diff options
Diffstat (limited to 'apps/plugins/mpegplayer')
-rw-r--r-- | apps/plugins/mpegplayer/mpegplayer.c | 65 |
1 files changed, 48 insertions, 17 deletions
diff --git a/apps/plugins/mpegplayer/mpegplayer.c b/apps/plugins/mpegplayer/mpegplayer.c index b61e76ce8a..7d97766c35 100644 --- a/apps/plugins/mpegplayer/mpegplayer.c +++ b/apps/plugins/mpegplayer/mpegplayer.c | |||
@@ -224,9 +224,28 @@ static Stream video_str IBSS_ATTR; | |||
224 | /* NOTE: Putting the following variables in IRAM cause audio corruption | 224 | /* NOTE: Putting the following variables in IRAM cause audio corruption |
225 | on the ipod (reason unknown) | 225 | on the ipod (reason unknown) |
226 | */ | 226 | */ |
227 | static uint8_t *disk_buf, *disk_buf_end; | 227 | static uint8_t *disk_buf IBSS_ATTR; |
228 | static uint8_t *disk_buf_end IBSS_ATTR; | ||
228 | static uint8_t *disk_buf_tail IBSS_ATTR; | 229 | static uint8_t *disk_buf_tail IBSS_ATTR; |
229 | static size_t buffer_size IBSS_ATTR; | 230 | static size_t buffer_size IBSS_ATTR; |
231 | #if NUM_CORES > 1 | ||
232 | /* Some stream variables are shared between cores */ | ||
233 | struct mutex stream_lock IBSS_ATTR; | ||
234 | static inline void init_stream_lock(void) | ||
235 | { rb->spinlock_init(&stream_lock); } | ||
236 | static inline void lock_stream(void) | ||
237 | { rb->spinlock_lock(&stream_lock); } | ||
238 | static inline void unlock_stream(void) | ||
239 | { rb->spinlock_unlock(&stream_lock); } | ||
240 | #else | ||
241 | /* No RMW issue here */ | ||
242 | static inline void init_stream_lock(void) | ||
243 | { } | ||
244 | static inline void lock_stream(void) | ||
245 | { } | ||
246 | static inline void unlock_stream(void) | ||
247 | { } | ||
248 | #endif | ||
230 | 249 | ||
231 | /* Events */ | 250 | /* Events */ |
232 | static struct event_queue msg_queue IBSS_ATTR; | 251 | static struct event_queue msg_queue IBSS_ATTR; |
@@ -558,7 +577,7 @@ static void get_next_data( Stream* str ) | |||
558 | /* Problem */ | 577 | /* Problem */ |
559 | //rb->splash( HZ*3, "missing packet start code prefix : %X%X at %X", *p, *(p+2), p-disk_buf ); | 578 | //rb->splash( HZ*3, "missing packet start code prefix : %X%X at %X", *p, *(p+2), p-disk_buf ); |
560 | str->curr_packet_end = str->curr_packet = NULL; | 579 | str->curr_packet_end = str->curr_packet = NULL; |
561 | return; | 580 | break; |
562 | //++p; | 581 | //++p; |
563 | //break; | 582 | //break; |
564 | } | 583 | } |
@@ -574,7 +593,7 @@ static void get_next_data( Stream* str ) | |||
574 | if (stream == 0xB9) | 593 | if (stream == 0xB9) |
575 | { | 594 | { |
576 | str->curr_packet_end = str->curr_packet = NULL; | 595 | str->curr_packet_end = str->curr_packet = NULL; |
577 | return; | 596 | break; |
578 | } | 597 | } |
579 | 598 | ||
580 | /* It's not the packet we're looking for, skip it */ | 599 | /* It's not the packet we're looking for, skip it */ |
@@ -667,6 +686,8 @@ static void get_next_data( Stream* str ) | |||
667 | 686 | ||
668 | if (str->curr_packet != NULL) | 687 | if (str->curr_packet != NULL) |
669 | { | 688 | { |
689 | lock_stream(); | ||
690 | |||
670 | if (str->curr_packet < str->prev_packet) | 691 | if (str->curr_packet < str->prev_packet) |
671 | { | 692 | { |
672 | str->buffer_remaining -= (disk_buf_end - str->prev_packet) + | 693 | str->buffer_remaining -= (disk_buf_end - str->prev_packet) + |
@@ -679,6 +700,8 @@ static void get_next_data( Stream* str ) | |||
679 | str->buffer_remaining -= (str->curr_packet - str->prev_packet); | 700 | str->buffer_remaining -= (str->curr_packet - str->prev_packet); |
680 | } | 701 | } |
681 | 702 | ||
703 | unlock_stream(); | ||
704 | |||
682 | str->prev_packet = str->curr_packet; | 705 | str->prev_packet = str->curr_packet; |
683 | } | 706 | } |
684 | 707 | ||
@@ -689,8 +712,6 @@ static void get_next_data( Stream* str ) | |||
689 | str->guard_bytes = str->curr_packet_end - disk_buf_end; | 712 | str->guard_bytes = str->curr_packet_end - disk_buf_end; |
690 | rb->memcpy(disk_buf_end, disk_buf, str->guard_bytes); | 713 | rb->memcpy(disk_buf_end, disk_buf, str->guard_bytes); |
691 | } | 714 | } |
692 | |||
693 | return; | ||
694 | } | 715 | } |
695 | 716 | ||
696 | break; | 717 | break; |
@@ -1250,9 +1271,9 @@ static void video_thread(void) | |||
1250 | mpeg2dec = mpeg2_init(); | 1271 | mpeg2dec = mpeg2_init(); |
1251 | if (mpeg2dec == NULL) | 1272 | if (mpeg2dec == NULL) |
1252 | { | 1273 | { |
1253 | videostatus = STREAM_ERROR; | ||
1254 | rb->splash(0, "mpeg2_init failed"); | 1274 | rb->splash(0, "mpeg2_init failed"); |
1255 | /* Commit suicide */ | 1275 | /* Commit suicide */ |
1276 | videostatus = THREAD_TERMINATED; | ||
1256 | rb->remove_thread(NULL); | 1277 | rb->remove_thread(NULL); |
1257 | } | 1278 | } |
1258 | 1279 | ||
@@ -1282,6 +1303,8 @@ static void video_thread(void) | |||
1282 | else if (videostatus == PLEASE_PAUSE) | 1303 | else if (videostatus == PLEASE_PAUSE) |
1283 | { | 1304 | { |
1284 | videostatus = STREAM_PAUSING; | 1305 | videostatus = STREAM_PAUSING; |
1306 | flush_icache(); | ||
1307 | |||
1285 | while (videostatus == STREAM_PAUSING) | 1308 | while (videostatus == STREAM_PAUSING) |
1286 | rb->sleep(HZ/10); | 1309 | rb->sleep(HZ/10); |
1287 | } | 1310 | } |
@@ -1533,6 +1556,8 @@ static void video_thread(void) | |||
1533 | } | 1556 | } |
1534 | 1557 | ||
1535 | done: | 1558 | done: |
1559 | flush_icache(); | ||
1560 | |||
1536 | videostatus = STREAM_DONE; | 1561 | videostatus = STREAM_DONE; |
1537 | 1562 | ||
1538 | while (videostatus != PLEASE_STOP) | 1563 | while (videostatus != PLEASE_STOP) |
@@ -1550,10 +1575,7 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter) | |||
1550 | int audiosize; | 1575 | int audiosize; |
1551 | int in_file; | 1576 | int in_file; |
1552 | uint8_t* buffer; | 1577 | uint8_t* buffer; |
1553 | size_t audio_remaining, video_remaining; | ||
1554 | size_t bytes_to_read; | ||
1555 | size_t file_remaining; | 1578 | size_t file_remaining; |
1556 | size_t n; | ||
1557 | size_t disk_buf_len; | 1579 | size_t disk_buf_len; |
1558 | #ifndef HAVE_LCD_COLOR | 1580 | #ifndef HAVE_LCD_COLOR |
1559 | long graysize; | 1581 | long graysize; |
@@ -1692,6 +1714,8 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter) | |||
1692 | gray_show(true); | 1714 | gray_show(true); |
1693 | #endif | 1715 | #endif |
1694 | 1716 | ||
1717 | init_stream_lock(); | ||
1718 | |||
1695 | /* We put the video thread on the second processor for multi-core targets. */ | 1719 | /* We put the video thread on the second processor for multi-core targets. */ |
1696 | if ((videothread_id = rb->create_thread(video_thread, | 1720 | if ((videothread_id = rb->create_thread(video_thread, |
1697 | (uint8_t*)video_stack,VIDEO_STACKSIZE,"mpgvideo" IF_PRIO(,PRIORITY_PLAYBACK) | 1721 | (uint8_t*)video_stack,VIDEO_STACKSIZE,"mpgvideo" IF_PRIO(,PRIORITY_PLAYBACK) |
@@ -1711,32 +1735,39 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter) | |||
1711 | rb->lcd_setfont(FONT_SYSFIXED); | 1735 | rb->lcd_setfont(FONT_SYSFIXED); |
1712 | 1736 | ||
1713 | /* Wait until both threads have finished their work */ | 1737 | /* Wait until both threads have finished their work */ |
1714 | while ((audiostatus != STREAM_DONE) || (videostatus != STREAM_DONE)) { | 1738 | while ((audiostatus != STREAM_DONE) || (videostatus != STREAM_DONE)) |
1715 | audio_remaining = audio_str.buffer_remaining; | 1739 | { |
1716 | video_remaining = video_str.buffer_remaining; | 1740 | size_t audio_remaining = audio_str.buffer_remaining; |
1741 | size_t video_remaining = video_str.buffer_remaining; | ||
1742 | |||
1717 | if (MIN(audio_remaining,video_remaining) < MPEG_LOW_WATERMARK) { | 1743 | if (MIN(audio_remaining,video_remaining) < MPEG_LOW_WATERMARK) { |
1718 | 1744 | ||
1719 | // TODO: Add mutex when updating the A/V buffer_remaining variables. | 1745 | size_t bytes_to_read = buffer_size - MPEG_GUARDBUF_SIZE - |
1720 | bytes_to_read = buffer_size - MPEG_GUARDBUF_SIZE - MAX(audio_remaining,video_remaining); | 1746 | MAX(audio_remaining,video_remaining); |
1721 | 1747 | ||
1722 | bytes_to_read = MIN(bytes_to_read,(size_t)(disk_buf_end-disk_buf_tail)); | 1748 | bytes_to_read = MIN(bytes_to_read,(size_t)(disk_buf_end-disk_buf_tail)); |
1723 | 1749 | ||
1724 | while (( bytes_to_read > 0) && (file_remaining > 0) && | 1750 | while (( bytes_to_read > 0) && (file_remaining > 0) && |
1725 | ((audiostatus != STREAM_DONE) || (videostatus != STREAM_DONE))) { | 1751 | ((audiostatus != STREAM_DONE) || (videostatus != STREAM_DONE))) { |
1726 | n = rb->read(in_file, disk_buf_tail, MIN(32*1024,bytes_to_read)); | 1752 | size_t n = rb->read(in_file, disk_buf_tail, MIN(32*1024,bytes_to_read)); |
1727 | 1753 | ||
1728 | bytes_to_read -= n; | 1754 | bytes_to_read -= n; |
1729 | file_remaining -= n; | 1755 | file_remaining -= n; |
1756 | |||
1757 | lock_stream(); | ||
1730 | audio_str.buffer_remaining += n; | 1758 | audio_str.buffer_remaining += n; |
1731 | video_str.buffer_remaining += n; | 1759 | video_str.buffer_remaining += n; |
1760 | unlock_stream(); | ||
1761 | |||
1732 | disk_buf_tail += n; | 1762 | disk_buf_tail += n; |
1763 | |||
1733 | rb->yield(); | 1764 | rb->yield(); |
1734 | } | 1765 | } |
1735 | 1766 | ||
1736 | if (disk_buf_tail == disk_buf_end) | 1767 | if (disk_buf_tail == disk_buf_end) |
1737 | disk_buf_tail = buffer; | 1768 | disk_buf_tail = buffer; |
1738 | |||
1739 | } | 1769 | } |
1770 | |||
1740 | rb->sleep(HZ/10); | 1771 | rb->sleep(HZ/10); |
1741 | } | 1772 | } |
1742 | 1773 | ||