summaryrefslogtreecommitdiff
path: root/apps
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2007-04-16 03:34:56 +0000
committerMichael Sevakis <jethead71@rockbox.org>2007-04-16 03:34:56 +0000
commiteb4dcd80b7778d5765b5bcfc38982ee3d56e2cc1 (patch)
tree576130bebaf3eded62abafee5f9c61626dd6442a /apps
parent7a5d4011f56334c05b55bb511c2f1f6a4639c8c1 (diff)
downloadrockbox-eb4dcd80b7778d5765b5bcfc38982ee3d56e2cc1.tar.gz
rockbox-eb4dcd80b7778d5765b5bcfc38982ee3d56e2cc1.zip
mpegplayer: Better sync, smoother frames - corrected a few minor flaws. Keep timestamps 32-bit in stead of 33 - a 45kHz clock is good enough for humans. Increase pts queue size since the mpeg buffer is now filled when buffering the audio stream. Cleanup frame drop code a little too.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@13175 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps')
-rw-r--r--apps/plugins/mpegplayer/mpegplayer.c211
1 files changed, 119 insertions, 92 deletions
diff --git a/apps/plugins/mpegplayer/mpegplayer.c b/apps/plugins/mpegplayer/mpegplayer.c
index 7d97766c35..b4b3281225 100644
--- a/apps/plugins/mpegplayer/mpegplayer.c
+++ b/apps/plugins/mpegplayer/mpegplayer.c
@@ -108,10 +108,6 @@ FPS | 27Mhz | 100Hz | 44.1KHz | 48KHz
108#include "mpeg2.h" 108#include "mpeg2.h"
109#include "mpeg_settings.h" 109#include "mpeg_settings.h"
110#include "video_out.h" 110#include "video_out.h"
111#ifndef ATTR_ALIGN
112#define ATTR_ALIGN(a) __attribute__((aligned (a)))
113#endif
114#include "mpeg2_internal.h"
115#include "../../codecs/libmad/mad.h" 111#include "../../codecs/libmad/mad.h"
116 112
117PLUGIN_HEADER 113PLUGIN_HEADER
@@ -493,12 +489,13 @@ static void init_mad(void* mad_frame_overlap)
493#define SYSTEM_HEADER_START_CODE 0x000001bbul 489#define SYSTEM_HEADER_START_CODE 0x000001bbul
494 490
495/* p = base pointer, b0 - b4 = byte offsets from p */ 491/* p = base pointer, b0 - b4 = byte offsets from p */
492/* We only care about the MS 32 bits of the 33 and so the ticks are 45kHz */
496#define TS_FROM_HEADER(p, b0, b1, b2, b3, b4) \ 493#define TS_FROM_HEADER(p, b0, b1, b2, b3, b4) \
497 ((uint32_t)(((p)[b0] >> 1 << 30) | \ 494 ((uint32_t)(((p)[b0] >> 1 << 29) | \
498 ((p)[b1] << 22) | \ 495 ((p)[b1] << 21) | \
499 ((p)[b2] >> 1 << 15) | \ 496 ((p)[b2] >> 1 << 14) | \
500 ((p)[b3] << 7) | \ 497 ((p)[b3] << 6) | \
501 ((p)[b4] >> 1 ))) 498 ((p)[b4] >> 2 )))
502 499
503/* This function demuxes the streams and gives the next stream data pointer */ 500/* This function demuxes the streams and gives the next stream data pointer */
504static void get_next_data( Stream* str ) 501static void get_next_data( Stream* str )
@@ -612,10 +609,12 @@ static void get_next_data( Stream* str )
612 /* header points to the mpeg2 pes header */ 609 /* header points to the mpeg2 pes header */
613 if (header[7] & 0x80) 610 if (header[7] & 0x80)
614 { 611 {
612 /* header has a pts */
615 uint32_t pts = TS_FROM_HEADER(header, 9, 10, 11, 12, 13); 613 uint32_t pts = TS_FROM_HEADER(header, 9, 10, 11, 12, 13);
616 614
617 if (stream >= 0xe0) 615 if (stream >= 0xe0)
618 { 616 {
617 /* video stream - header may have a dts as well */
619 uint32_t dts = (header[7] & 0x40) == 0 ? 618 uint32_t dts = (header[7] & 0x40) == 0 ?
620 pts : TS_FROM_HEADER(header, 14, 15, 16, 17, 18); 619 pts : TS_FROM_HEADER(header, 14, 15, 16, 17, 18);
621 620
@@ -659,10 +658,12 @@ static void get_next_data( Stream* str )
659 658
660 if ((ptsbuf[-1] & 0xe0) == 0x20) 659 if ((ptsbuf[-1] & 0xe0) == 0x20)
661 { 660 {
661 /* header has a pts */
662 uint32_t pts = TS_FROM_HEADER(ptsbuf, -1, 0, 1, 2, 3); 662 uint32_t pts = TS_FROM_HEADER(ptsbuf, -1, 0, 1, 2, 3);
663 663
664 if (stream >= 0xe0) 664 if (stream >= 0xe0)
665 { 665 {
666 /* video stream - header may have a dts as well */
666 uint32_t dts = (ptsbuf[-1] & 0xf0) != 0x30 ? 667 uint32_t dts = (ptsbuf[-1] & 0xf0) != 0x30 ?
667 pts : TS_FROM_HEADER(ptsbuf, 4, 5, 6, 7, 18); 668 pts : TS_FROM_HEADER(ptsbuf, 4, 5, 6, 7, 18);
668 669
@@ -723,8 +724,8 @@ static void get_next_data( Stream* str )
723 724
724/* For simple lowpass filtering of sync variables */ 725/* For simple lowpass filtering of sync variables */
725#define AVERAGE(var, x, count) (((var) * (count-1) + (x)) / (count)) 726#define AVERAGE(var, x, count) (((var) * (count-1) + (x)) / (count))
726/* Convert 90kHz PTS/DTS ticks to our clock ticks */ 727/* Convert 45kHz PTS/DTS ticks to our clock ticks */
727#define TS_TO_TICKS(pts) ((uint64_t)CLOCK_RATE*(pts) / 90000) 728#define TS_TO_TICKS(pts) ((uint64_t)CLOCK_RATE*(pts) / 45000)
728/* Convert 27MHz ticks to our clock ticks */ 729/* Convert 27MHz ticks to our clock ticks */
729#define TIME_TO_TICKS(stamp) ((uint64_t)CLOCK_RATE*(stamp) / 27000000) 730#define TIME_TO_TICKS(stamp) ((uint64_t)CLOCK_RATE*(stamp) / 27000000)
730 731
@@ -737,14 +738,14 @@ static bool init_mpabuf(void)
737 return mpa_buffer != NULL; 738 return mpa_buffer != NULL;
738} 739}
739 740
740#define PTS_QUEUE_LEN (1 << 4) /* 16 should be way more than sufficient - 741#define PTS_QUEUE_LEN (1 << 5) /* 32 should be way more than sufficient -
741 if not, the case is handled */ 742 if not, the case is handled */
742#define PTS_QUEUE_MASK (PTS_QUEUE_LEN-1) 743#define PTS_QUEUE_MASK (PTS_QUEUE_LEN-1)
743struct pts_queue_slot 744struct pts_queue_slot
744{ 745{
745 uint32_t pts; /* Time stamp for packet */ 746 uint32_t pts; /* Time stamp for packet */
746 ssize_t size; /* Number of bytes left in packet */ 747 ssize_t size; /* Number of bytes left in packet */
747} pts_queue[PTS_QUEUE_MASK+1]; 748} pts_queue[PTS_QUEUE_LEN];
748 749
749 /* This starts out wr == rd but will never be emptied to zero during 750 /* This starts out wr == rd but will never be emptied to zero during
750 streaming again in order to support initializing the first packet's 751 streaming again in order to support initializing the first packet's
@@ -752,12 +753,6 @@ struct pts_queue_slot
752static unsigned pts_queue_rd; 753static unsigned pts_queue_rd;
753static unsigned pts_queue_wr; 754static unsigned pts_queue_wr;
754 755
755/* Resets the pts queue - call when starting and seeking */
756static void pts_queue_reset(void)
757{
758 pts_queue_rd = pts_queue_wr;
759}
760
761/* Increments the queue head postion - should be used to preincrement */ 756/* Increments the queue head postion - should be used to preincrement */
762static bool pts_queue_add_head(void) 757static bool pts_queue_add_head(void)
763{ 758{
@@ -790,6 +785,16 @@ static struct pts_queue_slot * pts_queue_tail(void)
790 return &pts_queue[pts_queue_rd & PTS_QUEUE_MASK]; 785 return &pts_queue[pts_queue_rd & PTS_QUEUE_MASK];
791} 786}
792 787
788/* Resets the pts queue - call when starting and seeking */
789static void pts_queue_reset(void)
790{
791 struct pts_queue_slot *pts;
792 pts_queue_rd = pts_queue_wr;
793 pts = pts_queue_tail();
794 pts->pts = 0;
795 pts->size = 0;
796}
797
793struct pcm_frame_header /* Header added to pcm data every time a decoded 798struct pcm_frame_header /* Header added to pcm data every time a decoded
794 mpa frame is sent out */ 799 mpa frame is sent out */
795{ 800{
@@ -992,6 +997,21 @@ static void audio_thread(void)
992 if (audiostatus == PLEASE_STOP) 997 if (audiostatus == PLEASE_STOP)
993 goto done; 998 goto done;
994 999
1000 if (pts->size <= 0)
1001 {
1002 /* Carry any overshoot to the next size since we're technically
1003 -pts->size bytes into it already. If size is negative an audio
1004 frame was split accross packets. Old has to be saved before
1005 moving the tail. */
1006 if (pts_queue_remove_tail())
1007 {
1008 struct pts_queue_slot *old = pts;
1009 pts = pts_queue_tail();
1010 pts->size += old->size;
1011 old->size = 0;
1012 }
1013 }
1014
995 /** Buffering **/ 1015 /** Buffering **/
996 if (mpabuf_used >= MPA_MAX_FRAME_SIZE + MAD_BUFFER_GUARD) 1016 if (mpabuf_used >= MPA_MAX_FRAME_SIZE + MAD_BUFFER_GUARD)
997 { 1017 {
@@ -999,46 +1019,53 @@ static void audio_thread(void)
999 } 1019 }
1000 else if (audio_str.curr_packet != NULL) 1020 else if (audio_str.curr_packet != NULL)
1001 { 1021 {
1002 /* Get data from next audio packet */ 1022 do
1003 len = audio_str.curr_packet_end - audio_str.curr_packet;
1004
1005 if (audio_str.tagged)
1006 { 1023 {
1007 struct pts_queue_slot *stamp = pts; 1024 /* Get data from next audio packet */
1025 len = audio_str.curr_packet_end - audio_str.curr_packet;
1026
1027 if (audio_str.tagged)
1028 {
1029 struct pts_queue_slot *stamp = pts;
1008 1030
1009 if (pts_queue_add_head()) 1031 if (pts_queue_add_head())
1032 {
1033 stamp = pts_queue_head();
1034 stamp->pts = TS_TO_TICKS(audio_str.curr_pts);
1035 /* pts->size should have been zeroed when slot was
1036 freed */
1037 }
1038 /* else queue full - just count up from the last to make
1039 it look like more data in the same packet */
1040 stamp->size += len;
1041 audio_str.tagged = 0;
1042 }
1043 else
1010 { 1044 {
1011 stamp = pts_queue_head(); 1045 /* Add to the one just behind the head - this may be the
1012 stamp->pts = TS_TO_TICKS(audio_str.curr_pts); 1046 tail or the previouly added head - whether or not we'll
1013 /* pts->size should have been zeroed when slot was freed */ 1047 ever reach this is quite in question since audio always
1048 seems to have every packet timestamped */
1049 pts_queue_head()->size += len;
1014 } 1050 }
1015 /* else queue full - just count up from the last to make it look
1016 like more data in the same packet */
1017 stamp->size += len;
1018 audio_str.tagged = 0;
1019 }
1020 else
1021 {
1022 /* Add to the one just behind the head - this may be the tail or
1023 the previouly added head - whether or not we'll ever reach this
1024 is quite in question since audio always seems to have every
1025 packet timestamped */
1026 pts_queue_head()->size += len;
1027 }
1028 1051
1029 /* Slide any remainder over to beginning - avoid function call overhead if 1052 /* Slide any remainder over to beginning - avoid function
1030 no data remaining as well */ 1053 call overhead if no data remaining as well */
1031 if (mpabuf > mpa_buffer && mpabuf_used > 0) 1054 if (mpabuf > mpa_buffer && mpabuf_used > 0)
1032 rb->memmove(mpa_buffer, mpabuf, mpabuf_used); 1055 rb->memmove(mpa_buffer, mpabuf, mpabuf_used);
1033 1056
1034 /* Splice this packet onto any remainder */ 1057 /* Splice this packet onto any remainder */
1035 rb->memcpy(mpa_buffer + mpabuf_used, audio_str.curr_packet, len); 1058 rb->memcpy(mpa_buffer + mpabuf_used, audio_str.curr_packet,
1059 len);
1036 1060
1037 mpabuf_used += len; 1061 mpabuf_used += len;
1038 mpabuf = mpa_buffer; 1062 mpabuf = mpa_buffer;
1039 1063
1040 /* Move stream position to the next packet */ 1064 /* Get data from next audio packet */
1041 get_next_data(&audio_str); 1065 get_next_data(&audio_str);
1066 }
1067 while (audio_str.curr_packet != NULL &&
1068 mpabuf_used < MPA_MAX_FRAME_SIZE + MAD_BUFFER_GUARD);
1042 } 1069 }
1043 else if (mpabuf_used <= 0) 1070 else if (mpabuf_used <= 0)
1044 { 1071 {
@@ -1051,6 +1078,13 @@ static void audio_thread(void)
1051 1078
1052 mad_stat = mad_frame_decode(&frame, &stream); 1079 mad_stat = mad_frame_decode(&frame, &stream);
1053 1080
1081 if (stream.next_frame == NULL)
1082 {
1083 /* What to do here? (This really is fatal) */
1084 DEBUGF("/* What to do here? */\n");
1085 break;
1086 }
1087
1054 /* Next mad stream buffer is the next frame postion */ 1088 /* Next mad stream buffer is the next frame postion */
1055 mpabuf = (uint8_t *)stream.next_frame; 1089 mpabuf = (uint8_t *)stream.next_frame;
1056 1090
@@ -1059,25 +1093,6 @@ static void audio_thread(void)
1059 mpabuf_used -= len; 1093 mpabuf_used -= len;
1060 pts->size -= len; 1094 pts->size -= len;
1061 1095
1062 if (pts->size <= 0)
1063 {
1064 /* Carry any overshoot to the next size since we're technically
1065 -pts->size bytes into it already. If size is negative an audio
1066 frame was split accross packets. Old has to be saved before
1067 moving the tail. */
1068 struct pts_queue_slot *old = pts;
1069
1070 if (pts_queue_remove_tail())
1071 {
1072 pts = pts_queue_tail();
1073 pts->size += old->size;
1074 }
1075
1076 /* Zero the size of the last slot to simplify stamping code and ensure
1077 that it is never negative if the tail didn't move */
1078 old->size = 0;
1079 }
1080
1081 if (mad_stat != 0) 1096 if (mad_stat != 0)
1082 { 1097 {
1083 DEBUGF("Audio stream error - %d\n", stream.error); 1098 DEBUGF("Audio stream error - %d\n", stream.error);
@@ -1113,13 +1128,6 @@ static void audio_thread(void)
1113 /* Generate the pcm samples */ 1128 /* Generate the pcm samples */
1114 mad_synth_frame(&synth, &frame); 1129 mad_synth_frame(&synth, &frame);
1115 1130
1116 if (stream.next_frame == NULL)
1117 {
1118 /* What to do here? */
1119 DEBUGF("/* What to do here? */\n");
1120 break;
1121 }
1122
1123 /** Output **/ 1131 /** Output **/
1124 1132
1125 /* TODO: Output through core dsp. We'll still use our own PCM buffer 1133 /* TODO: Output through core dsp. We'll still use our own PCM buffer
@@ -1257,6 +1265,7 @@ static void video_thread(void)
1257 char str[80]; 1265 char str[80];
1258 int dither_index = 0; 1266 int dither_index = 0;
1259 uint32_t curr_time = 0; 1267 uint32_t curr_time = 0;
1268 uint32_t period = 0; /* Frame period in clock ticks */
1260 uint32_t eta_audio = UINT_MAX, eta_video = 0; 1269 uint32_t eta_audio = UINT_MAX, eta_video = 0;
1261 int32_t eta_early = 0, eta_late = 0; 1270 int32_t eta_early = 0, eta_late = 0;
1262 int frame_drop_level = 0; 1271 int frame_drop_level = 0;
@@ -1307,6 +1316,8 @@ static void video_thread(void)
1307 1316
1308 while (videostatus == STREAM_PAUSING) 1317 while (videostatus == STREAM_PAUSING)
1309 rb->sleep(HZ/10); 1318 rb->sleep(HZ/10);
1319
1320 continue;
1310 } 1321 }
1311 1322
1312 state = mpeg2_parse (mpeg2dec); 1323 state = mpeg2_parse (mpeg2dec);
@@ -1336,7 +1347,6 @@ static void video_thread(void)
1336 case STATE_PICTURE: 1347 case STATE_PICTURE:
1337 { 1348 {
1338 /* A new picture is available - see if we should draw it */ 1349 /* A new picture is available - see if we should draw it */
1339 uint32_t period; /* Frame period in clock ticks */
1340 int32_t offset; /* Tick adjustment to keep sync */ 1350 int32_t offset; /* Tick adjustment to keep sync */
1341 1351
1342 /* No limiting => no dropping so simply make sure skipping is off 1352 /* No limiting => no dropping so simply make sure skipping is off
@@ -1344,12 +1354,12 @@ static void video_thread(void)
1344 if (!settings.limitfps) 1354 if (!settings.limitfps)
1345 goto picture_done; 1355 goto picture_done;
1346 1356
1347 period = TIME_TO_TICKS(info->sequence->frame_period);
1348
1349 /* Get presentation times in audio samples - quite accurate 1357 /* Get presentation times in audio samples - quite accurate
1350 enough */ 1358 enough - add previous frame duration if not stamped */
1351 curr_time = (info->current_picture->flags & PIC_FLAG_TAGS) ? 1359 curr_time = (info->display_picture->flags & PIC_FLAG_TAGS) ?
1352 TS_TO_TICKS(info->current_picture->tag) : (curr_time + period); 1360 TS_TO_TICKS(info->display_picture->tag) : (curr_time + period);
1361
1362 period = TIME_TO_TICKS(info->sequence->frame_period);
1353 1363
1354 eta_video = curr_time; 1364 eta_video = curr_time;
1355 eta_audio = get_stream_time(); 1365 eta_audio = get_stream_time();
@@ -1442,21 +1452,32 @@ static void video_thread(void)
1442 if (frame_drop_level > 1 || offset > CLOCK_RATE*167/1000) 1452 if (frame_drop_level > 1 || offset > CLOCK_RATE*167/1000)
1443 { 1453 {
1444 /* Frame type: I/P/B/D */ 1454 /* Frame type: I/P/B/D */
1445 int type = info->current_picture->flags & PIC_MASK_CODING_TYPE; 1455 int type = info->display_picture->flags & PIC_MASK_CODING_TYPE;
1446 1456
1447 /* Things are running a bit late or all frames are being 1457 /* Things are running a bit late or all frames are being
1448 dropped until a key frame */ 1458 dropped until a key frame */
1449 1459 if (frame_drop_level > 1)
1450 if (frame_drop_level > 1 && (type == I_TYPE || type == D_TYPE)) 1460 {
1451 frame_drop_level = 0; /* This frame can be drawn */ 1461 switch (type)
1462 {
1463 case PIC_FLAG_CODING_TYPE_I:
1464 case PIC_FLAG_CODING_TYPE_D:
1465 frame_drop_level = 0; /* This frame can be drawn */
1466 }
1467 }
1452 1468
1453 if (frame_drop_level <= 1 && offset > CLOCK_RATE*250/1000) 1469 if (frame_drop_level <= 1 && offset > CLOCK_RATE*250/1000)
1454 { 1470 {
1455 /* Things are very, very late. Resort to stronger measures 1471 /* Things are very, very late. Resort to stronger measures
1456 to keep sync by dropping a I/D/P frame. Drawing cannot 1472 to keep sync by dropping a I/D/P frame. Drawing cannot
1457 take place again until the next key frame. */ 1473 take place again until the next key frame. */
1458 if (type == I_TYPE || type == D_TYPE || type == P_TYPE) 1474 switch (type)
1475 {
1476 case PIC_FLAG_CODING_TYPE_I:
1477 case PIC_FLAG_CODING_TYPE_P:
1478 case PIC_FLAG_CODING_TYPE_D:
1459 frame_drop_level = 2; 1479 frame_drop_level = 2;
1480 }
1460 } 1481 }
1461 1482
1462 drop_frame = 1 << frame_drop_level; 1483 drop_frame = 1 << frame_drop_level;
@@ -1466,12 +1487,18 @@ static void video_thread(void)
1466 /* Timeout has expired and this frame will be drawn if it 1487 /* Timeout has expired and this frame will be drawn if it
1467 is available. This may reverse the decision to drop a 1488 is available. This may reverse the decision to drop a
1468 key frame above. */ 1489 key frame above. */
1469 if (frame_drop_level <= 1 || type == I_TYPE || type == D_TYPE) 1490 switch (type)
1470 { 1491 {
1471 drop_frame = 0; 1492 default:
1493 if (frame_drop_level <= 1)
1494 {
1495 case PIC_FLAG_CODING_TYPE_I:
1496 case PIC_FLAG_CODING_TYPE_D:
1497 drop_frame = 0;
1498 }
1472 } 1499 }
1473 } 1500 }
1474 else if (type == B_TYPE) 1501 else if (type == PIC_FLAG_CODING_TYPE_B)
1475 { 1502 {
1476 /* We want to drop something, so this B frame won't even be 1503 /* We want to drop something, so this B frame won't even be
1477 decoded. Drawing can happen on the next frame if so 1504 decoded. Drawing can happen on the next frame if so
@@ -1538,7 +1565,7 @@ static void video_thread(void)
1538 if (clock_ticks != 0) 1565 if (clock_ticks != 0)
1539 fps = num_drawn*CLOCK_RATE*10ll / clock_ticks; 1566 fps = num_drawn*CLOCK_RATE*10ll / clock_ticks;
1540 1567
1541 rb->snprintf(str, sizeof(str), "%d.%d %d %d", 1568 rb->snprintf(str, sizeof(str), "%d.%d %d %d ",
1542 fps / 10, fps % 10, num_skipped, 1569 fps / 10, fps % 10, num_skipped,
1543 info->display_picture->temporal_reference); 1570 info->display_picture->temporal_reference);
1544 rb->lcd_putsxy(0, 0, str); 1571 rb->lcd_putsxy(0, 0, str);