From c89863027981c07b4ae58d0e1720ecda92dcddf3 Mon Sep 17 00:00:00 2001 From: Michael Sevakis Date: Fri, 4 Jan 2008 20:36:15 +0000 Subject: 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 --- apps/plugins/mpegplayer/mpeg_parser.c | 2 + apps/plugins/mpegplayer/stream_mgr.c | 38 ++++++++++------- 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) str_parser.start_pts = video_str.start_pts; str_parser.end_pts = video_str.end_pts; } + + str_parser.last_seek_time = str_parser.start_pts; } else { 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) /* Set the master clock */ set_stream_clock(time); + /* Make sure streams are back in active pool */ + move_strl_to_actl(); + /* Prepare the parser and associated streams */ parser_prepare_streaming(); @@ -489,6 +492,9 @@ static void stream_on_resume(void) /* Set the master clock */ set_stream_clock(str_parser.last_seek_time); + /* Make sure streams are back in active pool */ + move_strl_to_actl(); + /* Prepare the parser and associated streams */ parser_prepare_streaming(); } @@ -582,29 +588,29 @@ static void stream_on_seek(struct stream_seek_data *skd) stream_mgr_lock(); - if (!stream_can_seek()) - { - } - else if (stream_mgr.status != STREAM_STOPPED) + if (stream_can_seek()) { - if (stream_mgr.status != STREAM_PLAYING) + if (stream_mgr.status != STREAM_STOPPED) { - trigger_cpu_boost(); - } + if (stream_mgr.status != STREAM_PLAYING) + { + trigger_cpu_boost(); + } - stream_seek_intl(time, whence, stream_mgr.status); + stream_seek_intl(time, whence, stream_mgr.status); - if (stream_mgr.status != STREAM_PLAYING) + if (stream_mgr.status != STREAM_PLAYING) + { + cancel_cpu_boost(); + } + } + else { - cancel_cpu_boost(); + stream_mgr.seeked = true; + time = time_from_whence(time, whence); + parser_seek_time(time); } } - else - { - stream_mgr.seeked = true; - time = time_from_whence(time, whence); - parser_seek_time(time); - } stream_mgr_unlock(); 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 struct queue_event ev; /* Our event queue to receive commands */ int num_drawn; /* Number of frames drawn since reset */ int num_skipped; /* Number of frames skipped since reset */ - uint32_t curr_time; /* Current due time of frame */ - uint32_t period; /* Frame period in clock ticks */ uint32_t eta_stream; /* Current time of stream */ uint32_t eta_video; /* Time that frame has been scheduled for */ int32_t eta_early; /* How early has the frame been decoded? */ @@ -47,9 +45,9 @@ struct video_thread_data int skip_level; /* Skip severity */ long last_showfps; /* Last time the FPS display was updated */ long last_render; /* Last time a frame was drawn */ + uint32_t curr_time; /* Current due time of frame */ + uint32_t period; /* Frame period in clock ticks */ int syncf_perfect; /* Last sync fit result */ - uint32_t syncf_time; /* PTS of last synced frame */ - uint32_t syncf_period; /* TS duration of last synced frame */ }; /* 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) static bool check_needs_sync(struct video_thread_data *td, uint32_t time) { - uint32_t syncf_end; + uint32_t end_time; DEBUGF("check_needs_sync:\n"); 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) } time = clip_time(&video_str, time); - syncf_end = td->syncf_time + td->syncf_period; + end_time = td->curr_time + td->period; - DEBUGF(" sft:%u t:%u sfte:%u\n", (unsigned)td->syncf_time, - (unsigned)time, (unsigned)syncf_end); + DEBUGF(" sft:%u t:%u sfte:%u\n", (unsigned)td->curr_time, + (unsigned)time, (unsigned)end_time); - if (time < td->syncf_time) + if (time < td->curr_time) return true; - if (time >= syncf_end) - return time < video_str.end_pts || syncf_end < video_str.end_pts; + if (time >= end_time) + return time < video_str.end_pts || end_time < video_str.end_pts; return false; } @@ -260,8 +258,6 @@ static int sync_decoder(struct video_thread_data *td, uint32_t time = clip_time(&video_str, sd->time); td->syncf_perfect = 0; - td->syncf_time = 0; - td->syncf_period = 0; td->curr_time = 0; td->period = 0; @@ -358,7 +354,7 @@ static int sync_decoder(struct video_thread_data *td, case STATE_END: case STATE_INVALID_END: { - uint32_t syncf_end; + uint32_t end_time; if (td->info->display_picture == NULL) { @@ -371,36 +367,33 @@ static int sync_decoder(struct video_thread_data *td, if (td->info->display_picture->flags & PIC_FLAG_TAGS) { - td->syncf_time = td->info->display_picture->tag; - DEBUGF(" frame tagged:%u (%c%s)\n", (unsigned)td->syncf_time, + td->curr_time = td->info->display_picture->tag; + DEBUGF(" frame tagged:%u (%c%s)\n", (unsigned)td->curr_time, pic_coding_type_char(type), (td->info->display_picture->flags & PIC_FLAG_SKIP) ? " skipped" : ""); } else { - td->syncf_time += td->syncf_period; - DEBUGF(" add period:%u (%c%s)\n", (unsigned)td->syncf_time, + td->curr_time += td->period; + DEBUGF(" add period:%u (%c%s)\n", (unsigned)td->curr_time, pic_coding_type_char(type), (td->info->display_picture->flags & PIC_FLAG_SKIP) ? " skipped" : ""); } - td->syncf_period = TC_TO_TS(td->info->sequence->frame_period); - syncf_end = td->syncf_time + td->syncf_period; + td->period = TC_TO_TS(td->info->sequence->frame_period); + end_time = td->curr_time + td->period; DEBUGF(" ft:%u t:%u fe:%u (%c%s)", - (unsigned)td->syncf_time, + (unsigned)td->curr_time, (unsigned)time, - (unsigned)(td->syncf_time + td->syncf_period), + (unsigned)end_time, pic_coding_type_char(type), (td->info->display_picture->flags & PIC_FLAG_SKIP) ? " skipped" : ""); - td->curr_time = TS_TO_TICKS(td->syncf_time); - td->period = TS_TO_TICKS(td->syncf_period); - - if (syncf_end <= time && syncf_end < video_str.end_pts) + if (end_time <= time && end_time < video_str.end_pts) { /* Still too early and have not hit at EOS */ DEBUGF(" too early\n"); @@ -414,8 +407,8 @@ static int sync_decoder(struct video_thread_data *td, if (type == PIC_FLAG_CODING_TYPE_B) td->syncf_perfect &= ppic; - if ((td->syncf_time <= time && time < syncf_end) || - syncf_end >= video_str.end_pts) + if ((td->curr_time <= time && time < end_time) || + end_time >= video_str.end_pts) { /* One perfect point for matching time goal */ DEBUGF(" ft<=tdisplay_picture->flags & PIC_FLAG_TAGS) ? - TS_TO_TICKS(td.info->display_picture->tag) : - (td.curr_time + td.period); + td.info->display_picture->tag : (td.curr_time + td.period); - td.period = TC_TO_TICKS(td.info->sequence->frame_period); + td.period = TC_TO_TS(td.info->sequence->frame_period); /* No limiting => no dropping - draw this frame */ if (!settings.limitfps) @@ -826,7 +818,7 @@ static void video_thread(void) } td.eta_video = td.curr_time; - td.eta_stream = stream_get_time(); + td.eta_stream = TICKS_TO_TS(stream_get_time()); /* How early/late are we? > 0 = late, < 0 early */ offset = td.eta_stream - td.eta_video; @@ -932,19 +924,19 @@ static void video_thread(void) the next however */ td.skip_level = 0; - if (offset > CLOCK_RATE*110/1000) + if (offset > TS_SECOND*110/1000) { /* Decide which skip level is needed in order to catch up */ /* TODO: Calculate this rather than if...else - this is rather exponential though */ - if (offset > CLOCK_RATE*367/1000) + if (offset > TS_SECOND*367/1000) td.skip_level = 5; /* Decoder skip: I/D */ - if (offset > CLOCK_RATE*233/1000) + if (offset > TS_SECOND*233/1000) td.skip_level = 4; /* Decoder skip: P */ - else if (offset > CLOCK_RATE*167/1000) + else if (offset > TS_SECOND*167/1000) td.skip_level = 3; /* Render skip */ - else if (offset > CLOCK_RATE*133/1000) + else if (offset > TS_SECOND*133/1000) td.skip_level = 2; /* Decoder skip: B */ else td.skip_level = 1; /* Decoder skip: B */ @@ -958,10 +950,10 @@ static void video_thread(void) { /* Watch for messages while waiting for the frame time */ int32_t eta_remaining = td.eta_video - td.eta_stream; - if (eta_remaining > CLOCK_RATE/HZ) + if (eta_remaining > TS_SECOND/HZ) { /* Several ticks to wait - do some sleeping */ - int timeout = (eta_remaining - HZ) / (CLOCK_RATE/HZ); + int timeout = (eta_remaining - HZ) / (TS_SECOND/HZ); str_get_msg_w_tmo(&video_str, &td.ev, MAX(timeout, 1)); if (td.ev.id != SYS_TIMEOUT) goto message_process; @@ -974,7 +966,7 @@ static void video_thread(void) goto message_wait; } - td.eta_stream = stream_get_time(); + td.eta_stream = TICKS_TO_TS(stream_get_time()); } picture_draw: -- cgit v1.2.3