1 #include "player.h"
2 #include "avifile.h"
3 #include "pwm_audio.h"
4
5 #include <dfs_file.h>
6 #include <unistd.h>
7 #include <sys/stat.h>
8 #include <sys/statfs.h>
9 #include "lv_demo_video.h"
10 #include "drv_jpeg.h"
11
12 #define DBG_TAG "player"
13 #define DBG_LVL DBG_INFO
14 #include <rtdbg.h>
15
16 #define T_vids _REV(0x30306463)
17 #define T_auds _REV(0x30317762)
18
19 #define __Map(x, in_min, in_max, out_min, out_max) \
20 (((x) - (in_min)) * ((out_max) - (out_min)) / ((in_max) - (in_min)) + (out_min))
21
22 struct avi_file_info
23 {
24 uint32_t Strsize;
25 uint32_t Strtype;
26 size_t BytesRD;
27 uint32_t cur_time;
28 uint32_t alltime;
29 } avi_file;
30
31 extern AVI_TypeDef AVI_file;
32 static uint8_t *v_pbuffer;
33
_REV(uint32_t value)34 static uint32_t _REV(uint32_t value)
35 {
36 return (value & 0x000000FFU) << 24 | (value & 0x0000FF00U) << 8 |
37 (value & 0x00FF0000U) >> 8 | (value & 0xFF000000U) >> 24;
38 }
39
audio_init(player_t player)40 static void audio_init(player_t player)
41 {
42 pwm_audio_config_t pac;
43 pac.duty_resolution = 10;
44 pac.gpio_num_left = 1;
45 pac.gpio_num_right = -1;
46 pac.ringbuf_len = 1024 * 8;
47
48 pwm_audio_init(&pac);
49
50 /* set default volume:-16 -- +16*/
51 pwm_audio_set_volume(player->volume);
52 }
53
read_video_frame(int fd,uint8_t * buffer,uint32_t length,uint32_t * fourcc)54 static uint32_t read_video_frame(int fd, uint8_t *buffer, uint32_t length, uint32_t *fourcc)
55 {
56 AVI_CHUNK_HEAD head;
57 read(fd, &head, sizeof(AVI_CHUNK_HEAD));
58 if (head.FourCC)
59 {
60 /* code */
61 }
62 *fourcc = head.FourCC;
63 if (head.size % 2)
64 {
65 head.size++;
66 }
67 if (length < head.size)
68 {
69 rt_kprintf("frame size too large\n");
70 return 0;
71 }
72
73 read(fd, buffer, head.size);
74 return head.size;
75 }
76
video_start_parser(player_t player,int fd,char * filename)77 static int video_start_parser(player_t player, int fd, char *filename)
78 {
79 int ret;
80 uint32_t alltime;
81
82 fd = open(filename, O_WRONLY);
83
84 avi_file.BytesRD = read(fd, v_pbuffer, 20480);
85 ret = AVI_Parser(v_pbuffer, avi_file.BytesRD);
86 if (0 > ret)
87 {
88 LOG_E("parse failed (%d)\n", ret);
89 return RT_ERROR;
90 }
91
92 /* Audio Init */
93 audio_init(player);
94 pwm_audio_set_param(AVI_file.auds_sample_rate, AVI_file.auds_bits, AVI_file.auds_channels);
95
96 alltime = (AVI_file.avi_hd.avih.us_per_frame / 1000) * AVI_file.avi_hd.avih.total_frames;
97 alltime /= 1000; /* s */
98 player->song_time_all = alltime;
99 LOG_I("video total time:%02d:%02d:%02d\n", alltime / 3600, (alltime % 3600) / 60, alltime % 60);
100
101 lseek(fd, AVI_file.movi_start, SEEK_SET);
102 avi_file.Strsize = read_video_frame(fd, v_pbuffer, DCODE_BUFFER_SIZE, &avi_file.Strtype);
103 avi_file.BytesRD = avi_file.Strsize + 8;
104
105 return fd;
106 }
107
search_files(player_t player,const char * dir_path,const char * ext)108 static void search_files(player_t player, const char *dir_path, const char *ext)
109 {
110 struct dirent *dirp;
111
112 DIR *dir = opendir(dir_path);
113 if (dir == NULL)
114 {
115 LOG_E("open directory error!");
116 return;
117 }
118 while ((dirp = readdir(dir)))
119 {
120 if (dirp->d_type == DT_DIR)
121 {
122 if (rt_strcmp(dirp->d_name, ".") == 0 || strcmp(dirp->d_name, "..") == 0)
123 {
124 continue;
125 }
126 char subdir_path[64];
127 rt_snprintf(subdir_path, sizeof(subdir_path), "%s/%s", dir_path, dirp->d_name);
128 search_files(player, subdir_path, ext);
129 }
130 else
131 {
132 char *file_ext = strrchr(dirp->d_name, '.');
133 if (file_ext != NULL && strcmp(file_ext, ext) == 0)
134 {
135 char file_path[64];
136 rt_snprintf(file_path, sizeof(file_path), "%s/%s", dir_path, dirp->d_name);
137 LOG_I("%s\n", file_path);
138
139 player->video_list[player->video_num] = rt_strdup(file_path);
140 LOG_E("video_list[%d]:%s", player->video_num, player->video_list[player->video_num]);
141 player->video_num ++;
142 }
143 }
144 }
145 closedir(dir);
146 }
147
add_video_player(player_t player)148 static uint8_t add_video_player(player_t player)
149 {
150 uint8_t video_index = 0;
151
152 if (player->video_num == 0)
153 {
154 player->video_list[player->song_current] = rt_strdup(player->video_name);
155 LOG_I("Add first res to player list:%s", player->video_list[player->song_current]);
156 player->song_current ++;
157 player->video_num++;
158 }
159 else
160 {
161 rt_bool_t flag = RT_FALSE;
162 /* find in list*/
163 for (int index = 0; index < player->video_num; index++)
164 {
165 char *video_name = player->video_list[index];
166 if (rt_strcmp(player->video_name, video_name))
167 {
168 flag = RT_TRUE;
169 }
170 else
171 {
172 flag = RT_FALSE;
173 video_index = index;
174 LOG_I("Find name to the list,index:%d", video_index);
175 break;
176 }
177 }
178 if (flag)
179 {
180 player->video_list[player->song_current] = rt_strdup(player->video_name);
181 LOG_I("Add [%s] to player list", player->video_list[player->song_current]);
182 player->song_current ++;
183 player->video_num ++;
184 /* free currnet player,to play next video */
185 player_delete(player);
186 }
187 }
188 /* show player */
189 player_show(player);
190
191 return video_index;
192 }
193
player_show(player_t player)194 int player_show(player_t player)
195 {
196 uint8_t i;
197 uint16_t percent;
198
199 rt_kprintf("*********** video Player ***********\n");
200
201 /* print now video */
202 for (i = 0; i < player->video_num; i++)
203 {
204 rt_kprintf("%02d. %s\n", i + 1, (char *)player->video_list[i]);
205 }
206
207 /* print now player status */
208 if (PLAYER_RUNNING == player->status)
209 {
210 rt_kprintf("<--- current player:");
211 }
212 else
213 {
214 rt_kprintf("<--- stop player:");
215 }
216
217 /* print current player */
218 rt_kprintf("%s", (char *)player->video_list[player->song_current]);
219 rt_kprintf("--->\n");
220
221 /* print player process */
222 percent = player->song_time_pass * 100 / player->song_time_all;
223 rt_kprintf("Player Progress:%02d%% Volume level:%02d%%\n", percent, player->volume);
224 rt_kprintf("***********************************\n");
225
226 return 0;
227 }
228
player_init(player_t player)229 static int player_init(player_t player)
230 {
231 rt_uint32_t level;
232
233 if (player->status != PLAYER_RUNNING)
234 {
235 level = rt_hw_interrupt_disable();
236
237 player->status = PLAYER_READY;
238
239 player->song_current = add_video_player(player) + 1;
240
241 rt_hw_interrupt_enable(level);
242
243 rt_sem_release(player->sem_play);
244 }
245
246 return 0;
247 }
248
player_play(player_t player)249 static int player_play(player_t player)
250 {
251 rt_uint32_t level;
252
253 if (player->status != PLAYER_RUNNING)
254 {
255 level = rt_hw_interrupt_disable();
256
257 player->status = PLAYER_RUNNING;
258
259 rt_hw_interrupt_enable(level);
260
261 rt_sem_release(player->sem_play);
262 }
263
264 return 0;
265 }
266
player_stop(player_t player)267 static int player_stop(player_t player)
268 {
269 rt_uint32_t level;
270
271 if (player->status == PLAYER_RUNNING)
272 {
273 level = rt_hw_interrupt_disable();
274
275 player->status = PLAYER_STOP;
276
277 rt_hw_interrupt_enable(level);
278 }
279
280 return 0;
281 }
282
player_delete(player_t player)283 int player_delete(player_t player)
284 {
285 rt_uint32_t level;
286
287 if (player->status == PLAYER_RUNNING)
288 {
289 level = rt_hw_interrupt_disable();
290
291 player->status = PLAYER_DELETE;
292
293 rt_hw_interrupt_enable(level);
294 }
295
296 return 0;
297 }
298
player_last(player_t player)299 static int player_last(player_t player)
300 {
301 rt_uint32_t level;
302
303 level = rt_hw_interrupt_disable();
304
305 if (player->song_current > 1)
306 {
307 player->song_current --;
308 }
309 else
310 {
311 player->song_current = player->video_num;
312 }
313
314 rt_hw_interrupt_enable(level);
315
316 player->status = PLAYER_LAST;
317
318 level = rt_hw_interrupt_disable();
319
320 rt_hw_interrupt_enable(level);
321
322 return 0;
323 }
324
player_next(player_t player)325 static int player_next(player_t player)
326 {
327 rt_uint32_t level;
328
329 level = rt_hw_interrupt_disable();
330
331 if (player->song_current < player->video_num)
332 {
333 player->song_current ++;
334 }
335 else
336 {
337 player->song_current = 1;
338 }
339
340 rt_hw_interrupt_enable(level);
341
342 player->status = PLAYER_NEXT;
343
344 level = rt_hw_interrupt_disable();
345
346 rt_hw_interrupt_enable(level);
347
348 return 0;
349 }
350
player_control(player_t player,int cmd,void * arg)351 int player_control(player_t player, int cmd, void *arg)
352 {
353 rt_uint32_t level;
354
355 switch (cmd)
356 {
357 case PLAYER_CMD_INIT:
358 LOG_I("Rec res name:%s len:%d", (char *)arg, rt_strlen(arg));
359 rt_memset(player->video_name, 0x00, rt_strlen(arg));
360 rt_strcpy(player->video_name, arg);
361 player_init(player);
362 break;
363 case PLAYER_CMD_PLAY:
364 player_play(player);
365 break;
366 case PLAYER_CMD_STOP:
367 player_stop(player);
368 break;
369 case PLAYER_CMD_LAST:
370 player_last(player);
371 break;
372 case PLAYER_CMD_NEXT:
373 player_next(player);
374 break;
375 case PLAYER_CMD_SET_VOL:
376 level = rt_hw_interrupt_disable();
377 player->volume = *(int16_t *)arg;
378 rt_hw_interrupt_enable(level);
379 pwm_audio_set_volume(player->volume);
380 break;
381 case PLAYER_CMD_GET_VOL:
382 *(uint8_t *)arg = player->volume;
383 break;
384 case PLAYER_CMD_GET_STATUS:
385 *(uint8_t *)arg = player->status;
386 break;
387 }
388 return 0;
389 }
390
player_entry(void * parameter)391 static void player_entry(void *parameter)
392 {
393 int fd = -1;
394 int32_t process;
395 player_t player = (player_t)parameter;
396
397 while (1)
398 {
399 if (player->status == PLAYER_READY)
400 {
401 fd = video_start_parser(player, fd, player->video_list[player->song_current - 1]);
402 LOG_I("Player:%s ready decode\n", player->video_list[player->song_current - 1]);
403
404 player->status = PLAYER_RUNNING;
405 }
406 if (player->status == PLAYER_RUNNING)
407 {
408 avi_file.cur_time = ((float)avi_file.BytesRD / AVI_file.movi_size) * avi_file.alltime;
409
410 if (avi_file.Strtype == T_vids)
411 {
412 JPEG_Draw_frame(player->decode, v_pbuffer, 0x00, 0x00);
413 }
414 /* audio output */
415 else if (avi_file.Strtype == T_auds)
416 {
417 size_t cnt;
418 pwm_audio_write((uint8_t *)v_pbuffer, avi_file.Strsize, &cnt, 500);
419 }
420 else
421 {
422 LOG_E("Unknow frame\n");
423 break;
424 }
425
426 /* read frame */
427 avi_file.Strsize = read_video_frame(fd, v_pbuffer, DCODE_BUFFER_SIZE, &avi_file.Strtype);
428 avi_file.BytesRD += avi_file.Strsize + 8;
429 player->song_time_pass = ((double)avi_file.BytesRD / AVI_file.movi_size) * player->song_time_all;
430
431 process = __Map((int32_t)player->song_time_pass, 0, player->song_time_all, 0, 100);
432 set_audio_wave_value(process);
433
434 /* if video was play over,play next video */
435 if (avi_file.BytesRD >= AVI_file.movi_size)
436 {
437 set_audio_wave_value(0);
438 player_show(player);
439 player_next(player);
440 }
441 }
442 if (player->status == PLAYER_STOP)
443 {
444 LOG_I("Stop player");
445
446 pwm_audio_stop();
447
448 rt_sem_take(player->sem_play, RT_WAITING_FOREVER);
449
450 pwm_audio_start();
451 }
452 if (player->status == PLAYER_DELETE)
453 {
454 close(fd);
455 pwm_audio_deinit();
456 player->status = PLAYER_IDLE;
457 LOG_I("Free %s resources", player->video_list[player->song_current - 1]);
458 }
459 if (player->status == PLAYER_LAST)
460 {
461 close(fd);
462 pwm_audio_deinit();
463 player->status = PLAYER_READY;
464 LOG_I("Free %s resources", player->video_list[player->song_current - 1]);
465 }
466 if (player->status == PLAYER_NEXT)
467 {
468 close(fd);
469 pwm_audio_deinit();
470 player->status = PLAYER_READY;
471 LOG_I("Free %s resources", player->video_list[player->song_current - 1]);
472 }
473 if (player->status == PLAYER_IDLE)
474 {
475 rt_sem_take(player->sem_play, RT_WAITING_FOREVER);
476 }
477 }
478 }
479
player_start(player_t player)480 int player_start(player_t player)
481 {
482 static rt_uint8_t inited = 0;
483
484 if (inited == 1)
485 {
486 return -RT_ERROR;
487 }
488
489 v_pbuffer = rt_malloc(DCODE_BUFFER_SIZE);
490 RT_ASSERT(v_pbuffer != NULL)
491 rt_memset(v_pbuffer, 0x00, DCODE_BUFFER_SIZE);
492
493 /* read filesystem */
494 search_files(player, "/", ".avi");
495
496 player->status = PLAYER_IDLE;
497 player->volume = PLAYER_SOUND_SIZE_DEFAULT;
498 player->song_current = 0;
499 player->song_time_pass = 0;
500
501 player->sem_play = rt_sem_create("sem_play", 0, RT_IPC_FLAG_FIFO);
502 if (player->sem_play == RT_NULL)
503 {
504 return -RT_ERROR;
505 }
506
507 player->play_thread = rt_thread_create("player",
508 player_entry, player,
509 2 * 1024, 18, 20);
510 if (player->play_thread != RT_NULL)
511 {
512 rt_thread_startup(player->play_thread);
513 }
514 else
515 {
516 rt_sem_delete(player->sem_play);
517 return -RT_ERROR;
518 }
519
520 inited = 1;
521
522 return 0;
523 }
524