summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2008-01-04 20:36:15 +0000
committerMichael Sevakis <jethead71@rockbox.org>2008-01-04 20:36:15 +0000
commitc89863027981c07b4ae58d0e1720ecda92dcddf3 (patch)
treec5e4e34bf156b7a1949e351014bcce24686f9a2f
parentee71d8770ba0a64218111271d2f3f43ac4070461 (diff)
downloadrockbox-c89863027981c07b4ae58d0e1720ecda92dcddf3.tar.gz
rockbox-c89863027981c07b4ae58d0e1720ecda92dcddf3.zip
mpegplayer seek tweak: Have video keep the time and duration of the last decoded frame up to date at all times. Make sure streams that have reported and EOS condition are placed back on active list when seeking which it seems is the cause of a video glitch where the initial frame may be presented after a seek but video playback wouldn't restart. Set logical seek time to video start in the parser after after initial load.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@15995 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--apps/plugins/mpegplayer/mpeg_parser.c2
-rw-r--r--apps/plugins/mpegplayer/stream_mgr.c38
-rw-r--r--apps/plugins/mpegplayer/video_thread.c76
3 files changed, 58 insertions, 58 deletions
diff --git a/apps/plugins/mpegplayer/mpeg_parser.c b/apps/plugins/mpegplayer/mpeg_parser.c
index 5b863dabac..167f07da5c 100644
--- a/apps/plugins/mpegplayer/mpeg_parser.c
+++ b/apps/plugins/mpegplayer/mpeg_parser.c
@@ -1141,6 +1141,8 @@ int parser_init_stream(void)
1141 str_parser.start_pts = video_str.start_pts; 1141 str_parser.start_pts = video_str.start_pts;
1142 str_parser.end_pts = video_str.end_pts; 1142 str_parser.end_pts = video_str.end_pts;
1143 } 1143 }
1144
1145 str_parser.last_seek_time = str_parser.start_pts;
1144 } 1146 }
1145 else 1147 else
1146 { 1148 {
diff --git a/apps/plugins/mpegplayer/stream_mgr.c b/apps/plugins/mpegplayer/stream_mgr.c
index 1baa2032ec..8d2e42f62b 100644
--- a/apps/plugins/mpegplayer/stream_mgr.c
+++ b/apps/plugins/mpegplayer/stream_mgr.c
@@ -319,6 +319,9 @@ static uint32_t stream_seek_intl(uint32_t time, int whence, int status)
319 /* Set the master clock */ 319 /* Set the master clock */
320 set_stream_clock(time); 320 set_stream_clock(time);
321 321
322 /* Make sure streams are back in active pool */
323 move_strl_to_actl();
324
322 /* Prepare the parser and associated streams */ 325 /* Prepare the parser and associated streams */
323 parser_prepare_streaming(); 326 parser_prepare_streaming();
324 327
@@ -489,6 +492,9 @@ static void stream_on_resume(void)
489 /* Set the master clock */ 492 /* Set the master clock */
490 set_stream_clock(str_parser.last_seek_time); 493 set_stream_clock(str_parser.last_seek_time);
491 494
495 /* Make sure streams are back in active pool */
496 move_strl_to_actl();
497
492 /* Prepare the parser and associated streams */ 498 /* Prepare the parser and associated streams */
493 parser_prepare_streaming(); 499 parser_prepare_streaming();
494 } 500 }
@@ -582,29 +588,29 @@ static void stream_on_seek(struct stream_seek_data *skd)
582 588
583 stream_mgr_lock(); 589 stream_mgr_lock();
584 590
585 if (!stream_can_seek()) 591 if (stream_can_seek())
586 {
587 }
588 else if (stream_mgr.status != STREAM_STOPPED)
589 { 592 {
590 if (stream_mgr.status != STREAM_PLAYING) 593 if (stream_mgr.status != STREAM_STOPPED)
591 { 594 {
592 trigger_cpu_boost(); 595 if (stream_mgr.status != STREAM_PLAYING)
593 } 596 {
597 trigger_cpu_boost();
598 }
594 599
595 stream_seek_intl(time, whence, stream_mgr.status); 600 stream_seek_intl(time, whence, stream_mgr.status);
596 601
597 if (stream_mgr.status != STREAM_PLAYING) 602 if (stream_mgr.status != STREAM_PLAYING)
603 {
604 cancel_cpu_boost();
605 }
606 }
607 else
598 { 608 {
599 cancel_cpu_boost(); 609 stream_mgr.seeked = true;
610 time = time_from_whence(time, whence);
611 parser_seek_time(time);
600 } 612 }
601 } 613 }
602 else
603 {
604 stream_mgr.seeked = true;
605 time = time_from_whence(time, whence);
606 parser_seek_time(time);
607 }
608 614
609 stream_mgr_unlock(); 615 stream_mgr_unlock();
610 return; 616 return;
diff --git a/apps/plugins/mpegplayer/video_thread.c b/apps/plugins/mpegplayer/video_thread.c
index 950d49a935..6a54706942 100644
--- a/apps/plugins/mpegplayer/video_thread.c
+++ b/apps/plugins/mpegplayer/video_thread.c
@@ -37,8 +37,6 @@ struct video_thread_data
37 struct queue_event ev; /* Our event queue to receive commands */ 37 struct queue_event ev; /* Our event queue to receive commands */
38 int num_drawn; /* Number of frames drawn since reset */ 38 int num_drawn; /* Number of frames drawn since reset */
39 int num_skipped; /* Number of frames skipped since reset */ 39 int num_skipped; /* Number of frames skipped since reset */
40 uint32_t curr_time; /* Current due time of frame */
41 uint32_t period; /* Frame period in clock ticks */
42 uint32_t eta_stream; /* Current time of stream */ 40 uint32_t eta_stream; /* Current time of stream */
43 uint32_t eta_video; /* Time that frame has been scheduled for */ 41 uint32_t eta_video; /* Time that frame has been scheduled for */
44 int32_t eta_early; /* How early has the frame been decoded? */ 42 int32_t eta_early; /* How early has the frame been decoded? */
@@ -47,9 +45,9 @@ struct video_thread_data
47 int skip_level; /* Skip severity */ 45 int skip_level; /* Skip severity */
48 long last_showfps; /* Last time the FPS display was updated */ 46 long last_showfps; /* Last time the FPS display was updated */
49 long last_render; /* Last time a frame was drawn */ 47 long last_render; /* Last time a frame was drawn */
48 uint32_t curr_time; /* Current due time of frame */
49 uint32_t period; /* Frame period in clock ticks */
50 int syncf_perfect; /* Last sync fit result */ 50 int syncf_perfect; /* Last sync fit result */
51 uint32_t syncf_time; /* PTS of last synced frame */
52 uint32_t syncf_period; /* TS duration of last synced frame */
53}; 51};
54 52
55/* TODO: Check if 4KB is appropriate - it works for my test streams, 53/* TODO: Check if 4KB is appropriate - it works for my test streams,
@@ -221,7 +219,7 @@ static bool init_sequence(struct video_thread_data *td)
221 219
222static bool check_needs_sync(struct video_thread_data *td, uint32_t time) 220static bool check_needs_sync(struct video_thread_data *td, uint32_t time)
223{ 221{
224 uint32_t syncf_end; 222 uint32_t end_time;
225 223
226 DEBUGF("check_needs_sync:\n"); 224 DEBUGF("check_needs_sync:\n");
227 if (td->info == NULL || td->info->display_fbuf == NULL) 225 if (td->info == NULL || td->info->display_fbuf == NULL)
@@ -237,16 +235,16 @@ static bool check_needs_sync(struct video_thread_data *td, uint32_t time)
237 } 235 }
238 236
239 time = clip_time(&video_str, time); 237 time = clip_time(&video_str, time);
240 syncf_end = td->syncf_time + td->syncf_period; 238 end_time = td->curr_time + td->period;
241 239
242 DEBUGF(" sft:%u t:%u sfte:%u\n", (unsigned)td->syncf_time, 240 DEBUGF(" sft:%u t:%u sfte:%u\n", (unsigned)td->curr_time,
243 (unsigned)time, (unsigned)syncf_end); 241 (unsigned)time, (unsigned)end_time);
244 242
245 if (time < td->syncf_time) 243 if (time < td->curr_time)
246 return true; 244 return true;
247 245
248 if (time >= syncf_end) 246 if (time >= end_time)
249 return time < video_str.end_pts || syncf_end < video_str.end_pts; 247 return time < video_str.end_pts || end_time < video_str.end_pts;
250 248
251 return false; 249 return false;
252} 250}
@@ -260,8 +258,6 @@ static int sync_decoder(struct video_thread_data *td,
260 uint32_t time = clip_time(&video_str, sd->time); 258 uint32_t time = clip_time(&video_str, sd->time);
261 259
262 td->syncf_perfect = 0; 260 td->syncf_perfect = 0;
263 td->syncf_time = 0;
264 td->syncf_period = 0;
265 td->curr_time = 0; 261 td->curr_time = 0;
266 td->period = 0; 262 td->period = 0;
267 263
@@ -358,7 +354,7 @@ static int sync_decoder(struct video_thread_data *td,
358 case STATE_END: 354 case STATE_END:
359 case STATE_INVALID_END: 355 case STATE_INVALID_END:
360 { 356 {
361 uint32_t syncf_end; 357 uint32_t end_time;
362 358
363 if (td->info->display_picture == NULL) 359 if (td->info->display_picture == NULL)
364 { 360 {
@@ -371,36 +367,33 @@ static int sync_decoder(struct video_thread_data *td,
371 367
372 if (td->info->display_picture->flags & PIC_FLAG_TAGS) 368 if (td->info->display_picture->flags & PIC_FLAG_TAGS)
373 { 369 {
374 td->syncf_time = td->info->display_picture->tag; 370 td->curr_time = td->info->display_picture->tag;
375 DEBUGF(" frame tagged:%u (%c%s)\n", (unsigned)td->syncf_time, 371 DEBUGF(" frame tagged:%u (%c%s)\n", (unsigned)td->curr_time,
376 pic_coding_type_char(type), 372 pic_coding_type_char(type),
377 (td->info->display_picture->flags & PIC_FLAG_SKIP) ? 373 (td->info->display_picture->flags & PIC_FLAG_SKIP) ?
378 " skipped" : ""); 374 " skipped" : "");
379 } 375 }
380 else 376 else
381 { 377 {
382 td->syncf_time += td->syncf_period; 378 td->curr_time += td->period;
383 DEBUGF(" add period:%u (%c%s)\n", (unsigned)td->syncf_time, 379 DEBUGF(" add period:%u (%c%s)\n", (unsigned)td->curr_time,
384 pic_coding_type_char(type), 380 pic_coding_type_char(type),
385 (td->info->display_picture->flags & PIC_FLAG_SKIP) ? 381 (td->info->display_picture->flags & PIC_FLAG_SKIP) ?
386 " skipped" : ""); 382 " skipped" : "");
387 } 383 }
388 384
389 td->syncf_period = TC_TO_TS(td->info->sequence->frame_period); 385 td->period = TC_TO_TS(td->info->sequence->frame_period);
390 syncf_end = td->syncf_time + td->syncf_period; 386 end_time = td->curr_time + td->period;
391 387
392 DEBUGF(" ft:%u t:%u fe:%u (%c%s)", 388 DEBUGF(" ft:%u t:%u fe:%u (%c%s)",
393 (unsigned)td->syncf_time, 389 (unsigned)td->curr_time,
394 (unsigned)time, 390 (unsigned)time,
395 (unsigned)(td->syncf_time + td->syncf_period), 391 (unsigned)end_time,
396 pic_coding_type_char(type), 392 pic_coding_type_char(type),
397 (td->info->display_picture->flags & PIC_FLAG_SKIP) ? 393 (td->info->display_picture->flags & PIC_FLAG_SKIP) ?
398 " skipped" : ""); 394 " skipped" : "");
399 395
400 td->curr_time = TS_TO_TICKS(td->syncf_time); 396 if (end_time <= time && end_time < video_str.end_pts)
401 td->period = TS_TO_TICKS(td->syncf_period);
402
403 if (syncf_end <= time && syncf_end < video_str.end_pts)
404 { 397 {
405 /* Still too early and have not hit at EOS */ 398 /* Still too early and have not hit at EOS */
406 DEBUGF(" too early\n"); 399 DEBUGF(" too early\n");
@@ -414,8 +407,8 @@ static int sync_decoder(struct video_thread_data *td,
414 if (type == PIC_FLAG_CODING_TYPE_B) 407 if (type == PIC_FLAG_CODING_TYPE_B)
415 td->syncf_perfect &= ppic; 408 td->syncf_perfect &= ppic;
416 409
417 if ((td->syncf_time <= time && time < syncf_end) || 410 if ((td->curr_time <= time && time < end_time) ||
418 syncf_end >= video_str.end_pts) 411 end_time >= video_str.end_pts)
419 { 412 {
420 /* One perfect point for matching time goal */ 413 /* One perfect point for matching time goal */
421 DEBUGF(" ft<=t<fe\n"); 414 DEBUGF(" ft<=t<fe\n");
@@ -662,8 +655,8 @@ static void video_thread(void)
662 td.mpeg2dec = mpeg2_init(); 655 td.mpeg2dec = mpeg2_init();
663 td.info = NULL; 656 td.info = NULL;
664 td.syncf_perfect = 0; 657 td.syncf_perfect = 0;
665 td.syncf_time = 0; 658 td.curr_time = 0;
666 td.syncf_period = 0; 659 td.period = 0;
667 660
668 if (td.mpeg2dec == NULL) 661 if (td.mpeg2dec == NULL)
669 { 662 {
@@ -814,10 +807,9 @@ static void video_thread(void)
814 /* Get presentation times in audio samples - quite accurate 807 /* Get presentation times in audio samples - quite accurate
815 enough - add previous frame duration if not stamped */ 808 enough - add previous frame duration if not stamped */
816 td.curr_time = (td.info->display_picture->flags & PIC_FLAG_TAGS) ? 809 td.curr_time = (td.info->display_picture->flags & PIC_FLAG_TAGS) ?
817 TS_TO_TICKS(td.info->display_picture->tag) : 810 td.info->display_picture->tag : (td.curr_time + td.period);
818 (td.curr_time + td.period);
819 811
820 td.period = TC_TO_TICKS(td.info->sequence->frame_period); 812 td.period = TC_TO_TS(td.info->sequence->frame_period);
821 813
822 /* No limiting => no dropping - draw this frame */ 814 /* No limiting => no dropping - draw this frame */
823 if (!settings.limitfps) 815 if (!settings.limitfps)
@@ -826,7 +818,7 @@ static void video_thread(void)
826 } 818 }
827 819
828 td.eta_video = td.curr_time; 820 td.eta_video = td.curr_time;
829 td.eta_stream = stream_get_time(); 821 td.eta_stream = TICKS_TO_TS(stream_get_time());
830 822
831 /* How early/late are we? > 0 = late, < 0 early */ 823 /* How early/late are we? > 0 = late, < 0 early */
832 offset = td.eta_stream - td.eta_video; 824 offset = td.eta_stream - td.eta_video;
@@ -932,19 +924,19 @@ static void video_thread(void)
932 the next however */ 924 the next however */
933 td.skip_level = 0; 925 td.skip_level = 0;
934 926
935 if (offset > CLOCK_RATE*110/1000) 927 if (offset > TS_SECOND*110/1000)
936 { 928 {
937 /* Decide which skip level is needed in order to catch up */ 929 /* Decide which skip level is needed in order to catch up */
938 930
939 /* TODO: Calculate this rather than if...else - this is rather 931 /* TODO: Calculate this rather than if...else - this is rather
940 exponential though */ 932 exponential though */
941 if (offset > CLOCK_RATE*367/1000) 933 if (offset > TS_SECOND*367/1000)
942 td.skip_level = 5; /* Decoder skip: I/D */ 934 td.skip_level = 5; /* Decoder skip: I/D */
943 if (offset > CLOCK_RATE*233/1000) 935 if (offset > TS_SECOND*233/1000)
944 td.skip_level = 4; /* Decoder skip: P */ 936 td.skip_level = 4; /* Decoder skip: P */
945 else if (offset > CLOCK_RATE*167/1000) 937 else if (offset > TS_SECOND*167/1000)
946 td.skip_level = 3; /* Render skip */ 938 td.skip_level = 3; /* Render skip */
947 else if (offset > CLOCK_RATE*133/1000) 939 else if (offset > TS_SECOND*133/1000)
948 td.skip_level = 2; /* Decoder skip: B */ 940 td.skip_level = 2; /* Decoder skip: B */
949 else 941 else
950 td.skip_level = 1; /* Decoder skip: B */ 942 td.skip_level = 1; /* Decoder skip: B */
@@ -958,10 +950,10 @@ static void video_thread(void)
958 { 950 {
959 /* Watch for messages while waiting for the frame time */ 951 /* Watch for messages while waiting for the frame time */
960 int32_t eta_remaining = td.eta_video - td.eta_stream; 952 int32_t eta_remaining = td.eta_video - td.eta_stream;
961 if (eta_remaining > CLOCK_RATE/HZ) 953 if (eta_remaining > TS_SECOND/HZ)
962 { 954 {
963 /* Several ticks to wait - do some sleeping */ 955 /* Several ticks to wait - do some sleeping */
964 int timeout = (eta_remaining - HZ) / (CLOCK_RATE/HZ); 956 int timeout = (eta_remaining - HZ) / (TS_SECOND/HZ);
965 str_get_msg_w_tmo(&video_str, &td.ev, MAX(timeout, 1)); 957 str_get_msg_w_tmo(&video_str, &td.ev, MAX(timeout, 1));
966 if (td.ev.id != SYS_TIMEOUT) 958 if (td.ev.id != SYS_TIMEOUT)
967 goto message_process; 959 goto message_process;
@@ -974,7 +966,7 @@ static void video_thread(void)
974 goto message_wait; 966 goto message_wait;
975 } 967 }
976 968
977 td.eta_stream = stream_get_time(); 969 td.eta_stream = TICKS_TO_TS(stream_get_time());
978 } 970 }
979 971
980 picture_draw: 972 picture_draw: