diff options
author | Michael Sevakis <jethead71@rockbox.org> | 2008-01-04 20:36:15 +0000 |
---|---|---|
committer | Michael Sevakis <jethead71@rockbox.org> | 2008-01-04 20:36:15 +0000 |
commit | c89863027981c07b4ae58d0e1720ecda92dcddf3 (patch) | |
tree | c5e4e34bf156b7a1949e351014bcce24686f9a2f | |
parent | ee71d8770ba0a64218111271d2f3f43ac4070461 (diff) | |
download | rockbox-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.c | 2 | ||||
-rw-r--r-- | apps/plugins/mpegplayer/stream_mgr.c | 38 | ||||
-rw-r--r-- | apps/plugins/mpegplayer/video_thread.c | 76 |
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 | ||
222 | static bool check_needs_sync(struct video_thread_data *td, uint32_t time) | 220 | static 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: |