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