diff options
author | Michael Sevakis <jethead71@rockbox.org> | 2011-02-03 03:14:12 +0000 |
---|---|---|
committer | Michael Sevakis <jethead71@rockbox.org> | 2011-02-03 03:14:12 +0000 |
commit | 1bb3d61ef372e00986dd03672de944f756aeab4a (patch) | |
tree | af10850b35171fdcc4278c57c36139cf7ee6ffb4 /apps/plugins/mpegplayer/video_thread.c | |
parent | 38084784ad70a783ca1aae228007ed0b5abb31e4 (diff) | |
download | rockbox-1bb3d61ef372e00986dd03672de944f756aeab4a.tar.gz rockbox-1bb3d61ef372e00986dd03672de944f756aeab4a.zip |
MPEGPlayer: Try out a different frame drop scheme meant to skip in a more uniform way rather than running up late and jumping forward; will often drop more in long term to keep up in short term. Some other obscure fixes included: wait for 2 ref pics before decoding B-pics again after P or I frame drop or seeking (issue with open GOPs); draw the frame the decoder already has when beginning playback after a seek; rename a few vars.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@29198 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/plugins/mpegplayer/video_thread.c')
-rw-r--r-- | apps/plugins/mpegplayer/video_thread.c | 408 |
1 files changed, 216 insertions, 192 deletions
diff --git a/apps/plugins/mpegplayer/video_thread.c b/apps/plugins/mpegplayer/video_thread.c index aa88590b8e..2bfc5c680b 100644 --- a/apps/plugins/mpegplayer/video_thread.c +++ b/apps/plugins/mpegplayer/video_thread.c | |||
@@ -32,20 +32,26 @@ | |||
32 | /* Video thread data passed around to its various functions */ | 32 | /* Video thread data passed around to its various functions */ |
33 | struct video_thread_data | 33 | struct video_thread_data |
34 | { | 34 | { |
35 | /* Stream data */ | ||
35 | mpeg2dec_t *mpeg2dec; /* Our video decoder */ | 36 | mpeg2dec_t *mpeg2dec; /* Our video decoder */ |
36 | const mpeg2_info_t *info; /* Info about video stream */ | 37 | const mpeg2_info_t *info; /* Info about video stream */ |
37 | int state; /* Thread state */ | 38 | int state; /* Thread state */ |
38 | int status; /* Media status */ | 39 | int status; /* Media status */ |
39 | struct queue_event ev; /* Our event queue to receive commands */ | 40 | struct queue_event ev;/* Our event queue to receive commands */ |
40 | uint32_t eta_stream; /* Current time of stream */ | 41 | /* Operational info */ |
41 | uint32_t eta_video; /* Time that frame has been scheduled for */ | 42 | uint32_t stream_time; /* Current time from beginning of stream */ |
42 | int32_t eta_early; /* How early has the frame been decoded? */ | 43 | uint32_t goal_time; /* Scheduled time of current frame */ |
43 | int32_t eta_late; /* How late has the frame been decoded? */ | 44 | int32_t remain_time; /* T-minus value to frame_time (-:early, +:late) */ |
44 | int frame_drop_level; /* Drop severity */ | 45 | int skip_ref_pics; /* Severe skipping - wait for I-frame */ |
45 | int skip_level; /* Skip severity */ | 46 | int skip_level; /* Number of frames still to skip */ |
46 | long last_render; /* Last time a frame was drawn */ | 47 | int num_picture; /* Number of picture headers read */ |
47 | uint32_t curr_time; /* Current due time of frame */ | 48 | int num_intra; /* Number of I-picture headers read */ |
48 | uint32_t period; /* Frame period in clock ticks */ | 49 | int group_est; /* Estmated number remaining as of last I */ |
50 | long last_render; /* Last time a frame was drawn */ | ||
51 | /* Sync info */ | ||
52 | uint32_t frame_time; /* Current due time of frame (unadjusted) */ | ||
53 | uint32_t frame_period; /* Frame period in clock ticks */ | ||
54 | int num_ref_pics; /* Number of I and P frames since sync/skip */ | ||
49 | int syncf_perfect; /* Last sync fit result */ | 55 | int syncf_perfect; /* Last sync fit result */ |
50 | }; | 56 | }; |
51 | 57 | ||
@@ -62,6 +68,10 @@ static struct event_queue video_str_queue SHAREDBSS_ATTR; | |||
62 | static struct queue_sender_list video_str_queue_send SHAREDBSS_ATTR; | 68 | static struct queue_sender_list video_str_queue_send SHAREDBSS_ATTR; |
63 | struct stream video_str IBSS_ATTR; | 69 | struct stream video_str IBSS_ATTR; |
64 | 70 | ||
71 | #define DEFAULT_GOP_SIZE INT_MAX /* no I/P skips until it learns */ | ||
72 | #define DROP_THRESHOLD (100*TS_SECOND/1000) | ||
73 | #define MAX_EARLINESS (120*TS_SECOND/1000) | ||
74 | |||
65 | #if defined(DEBUG) || defined(SIMULATOR) | 75 | #if defined(DEBUG) || defined(SIMULATOR) |
66 | static unsigned char pic_coding_type_char(unsigned type) | 76 | static unsigned char pic_coding_type_char(unsigned type) |
67 | { | 77 | { |
@@ -217,12 +227,12 @@ static bool check_needs_sync(struct video_thread_data *td, uint32_t time) | |||
217 | } | 227 | } |
218 | 228 | ||
219 | time = clip_time(&video_str, time); | 229 | time = clip_time(&video_str, time); |
220 | end_time = td->curr_time + td->period; | 230 | end_time = td->frame_time + td->frame_period; |
221 | 231 | ||
222 | DEBUGF(" sft:%u t:%u sfte:%u\n", (unsigned)td->curr_time, | 232 | DEBUGF(" sft:%u t:%u sfte:%u\n", (unsigned)td->frame_time, |
223 | (unsigned)time, (unsigned)end_time); | 233 | (unsigned)time, (unsigned)end_time); |
224 | 234 | ||
225 | if (time < td->curr_time) | 235 | if (time < td->frame_time) |
226 | return true; | 236 | return true; |
227 | 237 | ||
228 | if (time >= end_time) | 238 | if (time >= end_time) |
@@ -236,12 +246,12 @@ static int sync_decoder(struct video_thread_data *td, | |||
236 | struct str_sync_data *sd) | 246 | struct str_sync_data *sd) |
237 | { | 247 | { |
238 | int retval = STREAM_ERROR; | 248 | int retval = STREAM_ERROR; |
239 | int ipic = 0, ppic = 0; | ||
240 | uint32_t time = clip_time(&video_str, sd->time); | 249 | uint32_t time = clip_time(&video_str, sd->time); |
241 | 250 | ||
242 | td->syncf_perfect = 0; | 251 | td->syncf_perfect = 0; |
243 | td->curr_time = 0; | 252 | td->frame_time = 0; |
244 | td->period = 0; | 253 | td->frame_period = 0; |
254 | td->num_ref_pics = 0; | ||
245 | 255 | ||
246 | /* Sometimes theres no sequence headers nearby and libmpeg2 may have reset | 256 | /* Sometimes theres no sequence headers nearby and libmpeg2 may have reset |
247 | * fully at some point */ | 257 | * fully at some point */ |
@@ -281,7 +291,6 @@ static int sync_decoder(struct video_thread_data *td, | |||
281 | case STREAM_OK: | 291 | case STREAM_OK: |
282 | if (video_str.pkt_flags & PKT_HAS_TS) | 292 | if (video_str.pkt_flags & PKT_HAS_TS) |
283 | mpeg2_tag_picture(td->mpeg2dec, video_str.pts, 0); | 293 | mpeg2_tag_picture(td->mpeg2dec, video_str.pts, 0); |
284 | |||
285 | mpeg2_buffer(td->mpeg2dec, video_str.curr_packet, | 294 | mpeg2_buffer(td->mpeg2dec, video_str.curr_packet, |
286 | video_str.curr_packet_end); | 295 | video_str.curr_packet_end); |
287 | td->info = mpeg2_info(td->mpeg2dec); | 296 | td->info = mpeg2_info(td->mpeg2dec); |
@@ -310,11 +319,13 @@ static int sync_decoder(struct video_thread_data *td, | |||
310 | case PIC_FLAG_CODING_TYPE_I: | 319 | case PIC_FLAG_CODING_TYPE_I: |
311 | /* I-frame; start decoding */ | 320 | /* I-frame; start decoding */ |
312 | mpeg2_skip(td->mpeg2dec, 0); | 321 | mpeg2_skip(td->mpeg2dec, 0); |
313 | ipic = 1; | 322 | td->num_ref_pics++; |
314 | break; | 323 | break; |
324 | |||
315 | case PIC_FLAG_CODING_TYPE_P: | 325 | case PIC_FLAG_CODING_TYPE_P: |
316 | /* P-frames don't count without I-frames */ | 326 | /* P-frames don't count without I-frames */ |
317 | ppic = ipic; | 327 | if (td->num_ref_pics > 0) |
328 | td->num_ref_pics++; | ||
318 | break; | 329 | break; |
319 | } | 330 | } |
320 | 331 | ||
@@ -348,26 +359,26 @@ static int sync_decoder(struct video_thread_data *td, | |||
348 | 359 | ||
349 | if (td->info->display_picture->flags & PIC_FLAG_TAGS) | 360 | if (td->info->display_picture->flags & PIC_FLAG_TAGS) |
350 | { | 361 | { |
351 | td->curr_time = td->info->display_picture->tag; | 362 | td->frame_time = td->info->display_picture->tag; |
352 | DEBUGF(" frame tagged:%u (%c%s)\n", (unsigned)td->curr_time, | 363 | DEBUGF(" frame tagged:%u (%c%s)\n", (unsigned)td->frame_time, |
353 | pic_coding_type_char(type), | 364 | pic_coding_type_char(type), |
354 | (td->info->display_picture->flags & PIC_FLAG_SKIP) ? | 365 | (td->info->display_picture->flags & PIC_FLAG_SKIP) ? |
355 | " skipped" : ""); | 366 | " skipped" : ""); |
356 | } | 367 | } |
357 | else | 368 | else |
358 | { | 369 | { |
359 | td->curr_time += td->period; | 370 | td->frame_time += td->frame_period; |
360 | DEBUGF(" add period:%u (%c%s)\n", (unsigned)td->curr_time, | 371 | DEBUGF(" add frame_period:%u (%c%s)\n", (unsigned)td->frame_time, |
361 | pic_coding_type_char(type), | 372 | pic_coding_type_char(type), |
362 | (td->info->display_picture->flags & PIC_FLAG_SKIP) ? | 373 | (td->info->display_picture->flags & PIC_FLAG_SKIP) ? |
363 | " skipped" : ""); | 374 | " skipped" : ""); |
364 | } | 375 | } |
365 | 376 | ||
366 | td->period = TC_TO_TS(td->info->sequence->frame_period); | 377 | td->frame_period = TC_TO_TS(td->info->sequence->frame_period); |
367 | end_time = td->curr_time + td->period; | 378 | end_time = td->frame_time + td->frame_period; |
368 | 379 | ||
369 | DEBUGF(" ft:%u t:%u fe:%u (%c%s)", | 380 | DEBUGF(" ft:%u t:%u fe:%u (%c%s)", |
370 | (unsigned)td->curr_time, | 381 | (unsigned)td->frame_time, |
371 | (unsigned)time, | 382 | (unsigned)time, |
372 | (unsigned)end_time, | 383 | (unsigned)end_time, |
373 | pic_coding_type_char(type), | 384 | pic_coding_type_char(type), |
@@ -383,12 +394,22 @@ static int sync_decoder(struct video_thread_data *td, | |||
383 | else if (!(td->info->display_picture->flags & PIC_FLAG_SKIP)) | 394 | else if (!(td->info->display_picture->flags & PIC_FLAG_SKIP)) |
384 | { | 395 | { |
385 | /* One perfect point if dependent frames were decoded */ | 396 | /* One perfect point if dependent frames were decoded */ |
386 | td->syncf_perfect = ipic; | 397 | switch (type) |
387 | 398 | { | |
388 | if (type == PIC_FLAG_CODING_TYPE_B) | 399 | case PIC_FLAG_CODING_TYPE_B: |
389 | td->syncf_perfect &= ppic; | 400 | if (td->num_ref_pics > 1) |
401 | { | ||
402 | case PIC_FLAG_CODING_TYPE_P: | ||
403 | if (td->num_ref_pics > 0) | ||
404 | { | ||
405 | case PIC_FLAG_CODING_TYPE_I: | ||
406 | td->syncf_perfect = 1; | ||
407 | break; | ||
408 | } | ||
409 | } | ||
410 | } | ||
390 | 411 | ||
391 | if ((td->curr_time <= time && time < end_time) || | 412 | if ((td->frame_time <= time && time < end_time) || |
392 | end_time >= video_str.end_pts) | 413 | end_time >= video_str.end_pts) |
393 | { | 414 | { |
394 | /* One perfect point for matching time goal */ | 415 | /* One perfect point for matching time goal */ |
@@ -464,20 +485,27 @@ static void video_thread_msg(struct video_thread_data *td) | |||
464 | 485 | ||
465 | switch (td->state) | 486 | switch (td->state) |
466 | { | 487 | { |
488 | case TSTATE_INIT: | ||
489 | /* Begin decoding state */ | ||
490 | td->state = TSTATE_DECODE; | ||
491 | /* */ | ||
492 | case TSTATE_DECODE: | ||
493 | if (td->syncf_perfect <= 0) | ||
494 | break; | ||
495 | /* There should be a frame already, just draw it */ | ||
496 | td->goal_time = td->frame_time; | ||
497 | td->state = TSTATE_RENDER_WAIT; | ||
498 | /* */ | ||
467 | case TSTATE_RENDER_WAIT: | 499 | case TSTATE_RENDER_WAIT: |
468 | /* Settings may have changed to nonlimited - just draw | 500 | /* Settings may have changed to nonlimited - just draw |
469 | * what was previously being waited for */ | 501 | * what was previously being waited for */ |
502 | td->stream_time = TICKS_TO_TS(stream_get_time()); | ||
470 | if (!settings.limitfps) | 503 | if (!settings.limitfps) |
471 | td->state = TSTATE_RENDER; | 504 | td->state = TSTATE_RENDER; |
472 | case TSTATE_DECODE: | 505 | /* */ |
473 | case TSTATE_RENDER: | 506 | case TSTATE_RENDER: |
474 | break; | 507 | break; |
475 | 508 | ||
476 | case TSTATE_INIT: | ||
477 | /* Begin decoding state */ | ||
478 | td->state = TSTATE_DECODE; | ||
479 | break; | ||
480 | |||
481 | case TSTATE_EOS: | 509 | case TSTATE_EOS: |
482 | /* At end of stream - no playback possible so fire the | 510 | /* At end of stream - no playback possible so fire the |
483 | * completion event */ | 511 | * completion event */ |
@@ -538,12 +566,14 @@ static void video_thread_msg(struct video_thread_data *td) | |||
538 | td->status = STREAM_STOPPED; | 566 | td->status = STREAM_STOPPED; |
539 | 567 | ||
540 | /* Reset operational info but not sync info */ | 568 | /* Reset operational info but not sync info */ |
541 | td->eta_stream = UINT32_MAX; | 569 | td->stream_time = UINT32_MAX; |
542 | td->eta_video = 0; | 570 | td->goal_time = 0; |
543 | td->eta_early = 0; | 571 | td->remain_time = 0; |
544 | td->eta_late = 0; | 572 | td->skip_ref_pics = 0; |
545 | td->frame_drop_level = 0; | ||
546 | td->skip_level = 0; | 573 | td->skip_level = 0; |
574 | td->num_picture = 0; | ||
575 | td->num_intra = 0; | ||
576 | td->group_est = DEFAULT_GOP_SIZE; | ||
547 | td->last_render = *rb->current_tick - HZ; | 577 | td->last_render = *rb->current_tick - HZ; |
548 | video_num_drawn = 0; | 578 | video_num_drawn = 0; |
549 | video_num_skipped = 0; | 579 | video_num_skipped = 0; |
@@ -639,13 +669,10 @@ static void video_thread(void) | |||
639 | { | 669 | { |
640 | struct video_thread_data td; | 670 | struct video_thread_data td; |
641 | 671 | ||
672 | memset(&td, 0, sizeof (td)); | ||
673 | td.mpeg2dec = mpeg2_init(); | ||
642 | td.status = STREAM_STOPPED; | 674 | td.status = STREAM_STOPPED; |
643 | td.state = TSTATE_EOS; | 675 | td.state = TSTATE_EOS; |
644 | td.mpeg2dec = mpeg2_init(); | ||
645 | td.info = NULL; | ||
646 | td.syncf_perfect = 0; | ||
647 | td.curr_time = 0; | ||
648 | td.period = 0; | ||
649 | 676 | ||
650 | if (td.mpeg2dec == NULL) | 677 | if (td.mpeg2dec == NULL) |
651 | { | 678 | { |
@@ -687,10 +714,7 @@ static void video_thread(void) | |||
687 | case TSTATE_RENDER: goto picture_draw; | 714 | case TSTATE_RENDER: goto picture_draw; |
688 | case TSTATE_RENDER_WAIT: goto picture_wait; | 715 | case TSTATE_RENDER_WAIT: goto picture_wait; |
689 | /* Anything else is interpreted as an exit */ | 716 | /* Anything else is interpreted as an exit */ |
690 | default: | 717 | default: goto video_exit; |
691 | vo_cleanup(); | ||
692 | mpeg2_close(td.mpeg2dec); | ||
693 | return; | ||
694 | } | 718 | } |
695 | } | 719 | } |
696 | 720 | ||
@@ -733,51 +757,72 @@ static void video_thread(void) | |||
733 | 757 | ||
734 | case STATE_PICTURE: | 758 | case STATE_PICTURE: |
735 | { | 759 | { |
736 | int skip = 0; /* Assume no skip */ | 760 | /* This is not in presentation order - do our best anyway */ |
761 | int skip = td.skip_ref_pics; | ||
737 | 762 | ||
738 | if (td.frame_drop_level >= 1 || td.skip_level > 0) | 763 | /* Frame type: I/P/B/D */ |
764 | switch (td.info->current_picture->flags & PIC_MASK_CODING_TYPE) | ||
739 | { | 765 | { |
740 | /* A frame will be dropped in the decoder */ | 766 | case PIC_FLAG_CODING_TYPE_I: |
767 | if (++td.num_intra >= 2) | ||
768 | td.group_est = td.num_picture / (td.num_intra - 1); | ||
741 | 769 | ||
742 | /* Frame type: I/P/B/D */ | 770 | /* Things are extremely late and all frames will be |
743 | int type = td.info->current_picture->flags | 771 | dropped until the next key frame */ |
744 | & PIC_MASK_CODING_TYPE; | 772 | if (td.skip_level > 0 && td.skip_level >= td.group_est) |
773 | { | ||
774 | td.skip_level--; /* skip frame */ | ||
775 | skip = td.skip_ref_pics = 1; /* wait for I-frame */ | ||
776 | td.num_ref_pics = 0; | ||
777 | } | ||
778 | else if (skip != 0) | ||
779 | { | ||
780 | skip = td.skip_ref_pics = 0; /* now, decode */ | ||
781 | td.num_ref_pics = 1; | ||
782 | } | ||
783 | break; | ||
745 | 784 | ||
746 | switch (type) | 785 | case PIC_FLAG_CODING_TYPE_P: |
786 | if (skip == 0) | ||
747 | { | 787 | { |
748 | case PIC_FLAG_CODING_TYPE_I: | 788 | td.num_ref_pics++; |
749 | case PIC_FLAG_CODING_TYPE_D: | 789 | |
750 | /* Level 5: Things are extremely late and all frames will | 790 | /* If skip_level at least the estimated number of frames |
751 | be dropped until the next key frame */ | 791 | left in I-I span, skip until next I-frame */ |
752 | if (td.frame_drop_level >= 1) | 792 | if (td.group_est > 0 && td.skip_level >= td.group_est) |
753 | td.frame_drop_level = 0; /* Key frame - reset drop level */ | ||
754 | if (td.skip_level >= 5) | ||
755 | { | ||
756 | td.frame_drop_level = 1; | ||
757 | td.skip_level = 0; /* reset */ | ||
758 | } | ||
759 | break; | ||
760 | case PIC_FLAG_CODING_TYPE_P: | ||
761 | /* Level 4: Things are very late and all frames will be | ||
762 | dropped until the next key frame */ | ||
763 | if (td.skip_level >= 4) | ||
764 | { | 793 | { |
765 | td.frame_drop_level = 1; | 794 | skip = td.skip_ref_pics = 1; /* wait for I-frame */ |
766 | td.skip_level = 0; /* reset */ | 795 | td.num_ref_pics = 0; |
767 | } | 796 | } |
768 | break; | 797 | } |
769 | case PIC_FLAG_CODING_TYPE_B: | 798 | |
770 | /* We want to drop something, so this B frame won't even | 799 | if (skip != 0) |
771 | be decoded. Drawing can happen on the next frame if so | 800 | td.skip_level--; |
772 | desired. Bring the level down as skips are done. */ | 801 | break; |
802 | |||
803 | case PIC_FLAG_CODING_TYPE_B: | ||
804 | /* We want to drop something, so this B-frame won't even be | ||
805 | decoded. Drawing can happen on the next frame if so desired | ||
806 | so long as the B-frames were not dependent upon those from | ||
807 | a previous open GOP where the needed reference frames were | ||
808 | skipped */ | ||
809 | if (td.skip_level > 0 || td.num_ref_pics < 2) | ||
810 | { | ||
773 | skip = 1; | 811 | skip = 1; |
774 | if (td.skip_level > 0) | 812 | td.skip_level--; |
775 | td.skip_level--; | ||
776 | } | 813 | } |
814 | break; | ||
777 | 815 | ||
778 | skip |= td.frame_drop_level; | 816 | default: |
817 | skip = 1; | ||
818 | break; | ||
779 | } | 819 | } |
780 | 820 | ||
821 | if (td.num_intra > 0) | ||
822 | td.num_picture++; | ||
823 | |||
824 | td.group_est--; | ||
825 | |||
781 | mpeg2_skip(td.mpeg2dec, skip); | 826 | mpeg2_skip(td.mpeg2dec, skip); |
782 | break; | 827 | break; |
783 | } | 828 | } |
@@ -788,47 +833,73 @@ static void video_thread(void) | |||
788 | { | 833 | { |
789 | int32_t offset; /* Tick adjustment to keep sync */ | 834 | int32_t offset; /* Tick adjustment to keep sync */ |
790 | 835 | ||
791 | /* draw current picture */ | ||
792 | if (td.info->display_fbuf == NULL) | 836 | if (td.info->display_fbuf == NULL) |
793 | break; /* No picture */ | 837 | break; /* No picture */ |
794 | 838 | ||
795 | td.syncf_perfect = 1; /* yes, a frame exists */ | ||
796 | |||
797 | /* Get presentation times in audio samples - quite accurate | 839 | /* Get presentation times in audio samples - quite accurate |
798 | enough - add previous frame duration if not stamped */ | 840 | enough - add previous frame duration if not stamped */ |
799 | td.curr_time = (td.info->display_picture->flags & PIC_FLAG_TAGS) ? | 841 | if (td.info->display_picture->flags & PIC_FLAG_TAGS) |
800 | td.info->display_picture->tag : (td.curr_time + td.period); | 842 | td.frame_time = td.info->display_picture->tag; |
843 | else | ||
844 | td.frame_time += td.frame_period; | ||
801 | 845 | ||
802 | td.period = TC_TO_TS(td.info->sequence->frame_period); | 846 | td.frame_period = TC_TO_TS(td.info->sequence->frame_period); |
803 | 847 | ||
804 | /* No limiting => no dropping - draw this frame */ | ||
805 | if (!settings.limitfps) | 848 | if (!settings.limitfps) |
806 | { | 849 | { |
850 | /* No limiting => no dropping or waiting - draw this frame */ | ||
851 | td.remain_time = 0; | ||
852 | td.skip_level = 0; | ||
853 | td.syncf_perfect = 1; /* have frame */ | ||
807 | goto picture_draw; | 854 | goto picture_draw; |
808 | } | 855 | } |
809 | 856 | ||
810 | td.eta_video = td.curr_time; | 857 | td.goal_time = td.frame_time; |
811 | td.eta_stream = TICKS_TO_TS(stream_get_time()); | 858 | td.stream_time = TICKS_TO_TS(stream_get_time()); |
812 | 859 | ||
813 | /* How early/late are we? > 0 = late, < 0 early */ | 860 | /* How early/late are we? > 0 = late, < 0 early */ |
814 | offset = td.eta_stream - td.eta_video; | 861 | offset = td.stream_time - td.goal_time; |
815 | 862 | ||
816 | if (!settings.skipframes) | 863 | if (offset >= 0) |
817 | { | 864 | { |
818 | /* Make no effort to determine whether this frame should be | 865 | /* Late or on-time */ |
819 | drawn or not since no action can be taken to correct the | 866 | if (td.remain_time < 0) |
820 | situation. We'll just wait if we're early and correct for | 867 | td.remain_time = 0; /* now, late */ |
821 | lateness as much as possible. */ | 868 | |
822 | if (offset < 0) | 869 | offset = AVERAGE(td.remain_time, offset, 4); |
823 | offset = 0; | 870 | td.remain_time = offset; |
871 | } | ||
872 | else | ||
873 | { | ||
874 | /* Early */ | ||
875 | if (td.remain_time >= 0) | ||
876 | td.remain_time = 0; /* now, early */ | ||
877 | else if (offset > td.remain_time) | ||
878 | td.remain_time = MAX(offset, -MAX_EARLINESS); /* less early */ | ||
879 | else if (td.remain_time != 0) | ||
880 | td.remain_time = AVERAGE(td.remain_time, 0, 8); /* earlier/same */ | ||
881 | /* else there's been no frame drop */ | ||
882 | |||
883 | offset = -td.remain_time; | ||
884 | } | ||
885 | |||
886 | /* Skip anything not decoded */ | ||
887 | if (td.info->display_picture->flags & PIC_FLAG_SKIP) | ||
888 | goto picture_skip; | ||
824 | 889 | ||
825 | td.eta_late = AVERAGE(td.eta_late, offset, 4); | 890 | td.syncf_perfect = 1; /* have frame (assume so from now on) */ |
826 | offset = td.eta_late; | ||
827 | 891 | ||
828 | if ((uint32_t)offset > td.eta_video) | 892 | /* Keep goal_time >= 0 */ |
829 | offset = td.eta_video; | 893 | if ((uint32_t)offset > td.goal_time) |
894 | offset = td.goal_time; | ||
830 | 895 | ||
831 | td.eta_video -= offset; | 896 | td.goal_time -= offset; |
897 | |||
898 | if (!settings.skipframes) | ||
899 | { | ||
900 | /* No skipping - just wait if we're early and correct for | ||
901 | lateness as much as possible. */ | ||
902 | td.skip_level = 0; | ||
832 | goto picture_wait; | 903 | goto picture_wait; |
833 | } | 904 | } |
834 | 905 | ||
@@ -838,112 +909,52 @@ static void video_thread(void) | |||
838 | * | 909 | * |
839 | * Frame Type Who Notes/Rationale | 910 | * Frame Type Who Notes/Rationale |
840 | * B decoder arbitrarily drop - no decode or draw | 911 | * B decoder arbitrarily drop - no decode or draw |
841 | * Any renderer arbitrarily drop - will be I/D/P | 912 | * Any renderer arbitrarily drop - I/P unless B decoded |
842 | * P decoder must wait for I/D-frame - choppy | 913 | * P decoder must wait for I-frame |
843 | * I/D decoder must wait for I/D-frame - choppy | 914 | * I decoder must wait for I-frame |
844 | * | 915 | * |
845 | * If a frame can be drawn and it has been at least 1/2 second, | 916 | * If a frame can be drawn and it has been at least 1/2 second, |
846 | * the image will be updated no matter how late it is just to | 917 | * the image will be updated no matter how late it is just to |
847 | * avoid looking stuck. | 918 | * avoid looking stuck. |
848 | */ | 919 | */ |
849 | 920 | if (td.skip_level > 0 && | |
850 | /* If we're late, set the eta to play the frame early so | ||
851 | we may catch up. If early, especially because of a drop, | ||
852 | mitigate a "snap" by moving back gradually. */ | ||
853 | if (offset >= 0) /* late or on time */ | ||
854 | { | ||
855 | td.eta_early = 0; /* Not early now :( */ | ||
856 | |||
857 | td.eta_late = AVERAGE(td.eta_late, offset, 4); | ||
858 | offset = td.eta_late; | ||
859 | |||
860 | if ((uint32_t)offset > td.eta_video) | ||
861 | offset = td.eta_video; | ||
862 | |||
863 | td.eta_video -= offset; | ||
864 | } | ||
865 | else | ||
866 | { | ||
867 | td.eta_late = 0; /* Not late now :) */ | ||
868 | |||
869 | if (offset > td.eta_early) | ||
870 | { | ||
871 | /* Just dropped a frame and we're now early or we're | ||
872 | coming back from being early */ | ||
873 | td.eta_early = offset; | ||
874 | if ((uint32_t)-offset > td.eta_video) | ||
875 | offset = -td.eta_video; | ||
876 | |||
877 | td.eta_video += offset; | ||
878 | } | ||
879 | else | ||
880 | { | ||
881 | /* Just early with an offset, do exponential drift back */ | ||
882 | if (td.eta_early != 0) | ||
883 | { | ||
884 | td.eta_early = AVERAGE(td.eta_early, 0, 8); | ||
885 | td.eta_video = ((uint32_t)-td.eta_early > td.eta_video) ? | ||
886 | 0 : (td.eta_video + td.eta_early); | ||
887 | } | ||
888 | |||
889 | offset = td.eta_early; | ||
890 | } | ||
891 | } | ||
892 | |||
893 | if (td.info->display_picture->flags & PIC_FLAG_SKIP) | ||
894 | { | ||
895 | /* This frame was set to skip so skip it after having updated | ||
896 | timing information */ | ||
897 | td.eta_early = INT32_MIN; | ||
898 | video_num_skipped++; | ||
899 | goto picture_skip; | ||
900 | } | ||
901 | |||
902 | if (td.skip_level == 3 && | ||
903 | TIME_BEFORE(*rb->current_tick, td.last_render + HZ/2)) | 921 | TIME_BEFORE(*rb->current_tick, td.last_render + HZ/2)) |
904 | { | 922 | { |
905 | /* Render drop was set previously but nothing was dropped in the | 923 | /* Frame skip was set previously but either there wasn't anything |
906 | decoder or it's been to long since drawing the last frame. */ | 924 | dropped yet or not dropped enough. So we quit at least rendering |
907 | td.skip_level = 0; | 925 | the actual frame to avoid further increase of a/v-drift. */ |
908 | td.eta_early = INT32_MIN; | 926 | td.skip_level--; |
909 | video_num_skipped++; | ||
910 | goto picture_skip; | 927 | goto picture_skip; |
911 | } | 928 | } |
912 | 929 | ||
913 | /* At this point a frame _will_ be drawn - a skip may happen on | 930 | /* At this point a frame _will_ be drawn - a skip may happen on |
914 | the next however */ | 931 | the next however */ |
915 | td.skip_level = 0; | ||
916 | 932 | ||
917 | if (offset > TS_SECOND*110/1000) | 933 | /* Calculate number of frames to drop/skip - allow brief periods |
934 | of lateness before producing skips */ | ||
935 | td.skip_level = 0; | ||
936 | if (td.remain_time > 0 && (uint32_t)offset > DROP_THRESHOLD) | ||
918 | { | 937 | { |
919 | /* Decide which skip level is needed in order to catch up */ | 938 | td.skip_level = (offset - DROP_THRESHOLD + td.frame_period) |
920 | 939 | / td.frame_period; | |
921 | /* TODO: Calculate this rather than if...else - this is rather | ||
922 | exponential though */ | ||
923 | if (offset > TS_SECOND*367/1000) | ||
924 | td.skip_level = 5; /* Decoder skip: I/D */ | ||
925 | if (offset > TS_SECOND*233/1000) | ||
926 | td.skip_level = 4; /* Decoder skip: P */ | ||
927 | else if (offset > TS_SECOND*167/1000) | ||
928 | td.skip_level = 3; /* Render skip */ | ||
929 | else if (offset > TS_SECOND*133/1000) | ||
930 | td.skip_level = 2; /* Decoder skip: B */ | ||
931 | else | ||
932 | td.skip_level = 1; /* Decoder skip: B */ | ||
933 | } | 940 | } |
934 | 941 | ||
935 | picture_wait: | 942 | picture_wait: |
936 | td.state = TSTATE_RENDER_WAIT; | 943 | td.state = TSTATE_RENDER_WAIT; |
937 | 944 | ||
938 | /* Wait until time catches up */ | 945 | /* Wait until time catches up */ |
939 | while (td.eta_video > td.eta_stream) | 946 | while (1) |
940 | { | 947 | { |
948 | int32_t twait = td.goal_time - td.stream_time; | ||
941 | /* Watch for messages while waiting for the frame time */ | 949 | /* Watch for messages while waiting for the frame time */ |
942 | int32_t eta_remaining = td.eta_video - td.eta_stream; | 950 | |
943 | if (eta_remaining > TS_SECOND/HZ) | 951 | if (twait <= 0) |
952 | break; | ||
953 | |||
954 | if (twait > TS_SECOND/HZ) | ||
944 | { | 955 | { |
945 | /* Several ticks to wait - do some sleeping */ | 956 | /* Several ticks to wait - do some sleeping */ |
946 | int timeout = (eta_remaining - HZ) / (TS_SECOND/HZ); | 957 | int timeout = (twait - HZ) / (TS_SECOND/HZ); |
947 | str_get_msg_w_tmo(&video_str, &td.ev, MAX(timeout, 1)); | 958 | str_get_msg_w_tmo(&video_str, &td.ev, MAX(timeout, 1)); |
948 | if (td.ev.id != SYS_TIMEOUT) | 959 | if (td.ev.id != SYS_TIMEOUT) |
949 | goto message_process; | 960 | goto message_process; |
@@ -956,7 +967,7 @@ static void video_thread(void) | |||
956 | goto message_wait; | 967 | goto message_wait; |
957 | } | 968 | } |
958 | 969 | ||
959 | td.eta_stream = TICKS_TO_TS(stream_get_time()); | 970 | td.stream_time = TICKS_TO_TS(stream_get_time()); |
960 | } | 971 | } |
961 | 972 | ||
962 | picture_draw: | 973 | picture_draw: |
@@ -965,8 +976,17 @@ static void video_thread(void) | |||
965 | 976 | ||
966 | vo_draw_frame(td.info->display_fbuf->buf); | 977 | vo_draw_frame(td.info->display_fbuf->buf); |
967 | video_num_drawn++; | 978 | video_num_drawn++; |
979 | break; | ||
968 | 980 | ||
969 | picture_skip: | 981 | picture_skip: |
982 | if (td.remain_time <= DROP_THRESHOLD) | ||
983 | { | ||
984 | td.skip_level = 0; | ||
985 | if (td.remain_time <= 0) | ||
986 | td.remain_time = INT32_MIN; | ||
987 | } | ||
988 | |||
989 | video_num_skipped++; | ||
970 | break; | 990 | break; |
971 | } | 991 | } |
972 | 992 | ||
@@ -976,6 +996,10 @@ static void video_thread(void) | |||
976 | 996 | ||
977 | rb->yield(); | 997 | rb->yield(); |
978 | } /* end while */ | 998 | } /* end while */ |
999 | |||
1000 | video_exit: | ||
1001 | vo_cleanup(); | ||
1002 | mpeg2_close(td.mpeg2dec); | ||
979 | } | 1003 | } |
980 | 1004 | ||
981 | /* Initializes the video thread */ | 1005 | /* Initializes the video thread */ |