From 0e98d7e315bcbdee35bcda4fd01a82da9185ed93 Mon Sep 17 00:00:00 2001 From: Michael Sevakis Date: Mon, 7 Jan 2008 14:58:23 +0000 Subject: mpegplayer: Misc seeking tweaks 1) Consolidate some code amongst functions. 2) Be sure times retured from stream_get_seek_time are never before the start of the movie 3) Stop PCM when clearing it so the current audio being sent to the audio device is also cleared. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@16014 a1c6a512-1295-4272-9138-f99709370657 --- apps/plugins/mpegplayer/pcm_output.c | 13 +++ apps/plugins/mpegplayer/stream_mgr.c | 184 ++++++++++++++--------------------- 2 files changed, 85 insertions(+), 112 deletions(-) diff --git a/apps/plugins/mpegplayer/pcm_output.c b/apps/plugins/mpegplayer/pcm_output.c index 281f7ddb72..ac89308af1 100644 --- a/apps/plugins/mpegplayer/pcm_output.c +++ b/apps/plugins/mpegplayer/pcm_output.c @@ -152,12 +152,25 @@ void pcm_output_add_data(void) /* Flushes the buffer - clock keeps counting */ void pcm_output_flush(void) { + bool playing, paused; + rb->pcm_play_lock(); + playing = rb->pcm_is_playing(); + paused = rb->pcm_is_paused(); + + /* Stop PCM to clear current buffer */ + if (playing) + rb->pcm_play_stop(); + pcmbuf_threshold = PCMOUT_PLAY_WM; pcmbuf_read = pcmbuf_written = 0; pcmbuf_head = pcmbuf_tail = pcm_buffer; + /* Restart if playing state was current */ + if (playing && !paused) + rb->pcm_play_data(get_more, NULL, 0); + rb->pcm_play_unlock(); } diff --git a/apps/plugins/mpegplayer/stream_mgr.c b/apps/plugins/mpegplayer/stream_mgr.c index c473db3ce3..dbc8ce9427 100644 --- a/apps/plugins/mpegplayer/stream_mgr.c +++ b/apps/plugins/mpegplayer/stream_mgr.c @@ -247,6 +247,37 @@ static void set_stream_clock(uint32_t time) pcm_output_set_clock(TS_TO_TICKS(time)); } +static void stream_start_playback(uint32_t time, bool fill_buffer) +{ + if (stream_mgr.seeked) + { + /* Clear any seeked status */ + stream_mgr.seeked = false; + + /* Flush old PCM data */ + pcm_output_flush(); + + /* 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(); + } + + /* Start buffer which optional force fill */ + disk_buf_send_msg(STREAM_PLAY, fill_buffer); + + /* Tell each stream to start - may generate end of stream signals + * now - we'll handle this when finished */ + actl_stream_broadcast(STREAM_PLAY, 0); + + /* Actually start the clock */ + pcm_output_play_pause(true); +} + /* Return the play time relative to the specified play time */ static uint32_t time_from_whence(uint32_t time, int whence) { @@ -286,62 +317,28 @@ static uint32_t time_from_whence(uint32_t time, int whence) } /* Handle seeking details if playing or paused */ -static uint32_t stream_seek_intl(uint32_t time, int whence, int status) +static uint32_t stream_seek_intl(uint32_t time, int whence, + int status, bool *was_buffering) { - /* seek start time */ - bool was_buffering; - - if (status == STREAM_PLAYING) - { - /* Keep clock from advancing while seeking */ - pcm_output_play_pause(false); - } - - /* Place streams in a non-running state - keep them on actl */ - actl_stream_broadcast(STREAM_STOP, 0); - - /* Stop all buffering or else risk clobbering random-access data */ - was_buffering = disk_buf_send_msg(STREAM_STOP, 0); - - time = time_from_whence(time, whence); - time = parser_seek_time(time); - - if (status == STREAM_PLAYING) + if (status != STREAM_STOPPED) { - /* Restart streams if currently playing */ - - /* Clear any seeked status */ - stream_mgr.seeked = false; - - /* Flush old PCM data */ - pcm_output_flush(); - - /* Set the master clock */ - set_stream_clock(time); + bool wb; - /* Make sure streams are back in active pool */ - move_strl_to_actl(); + /* Place streams in a non-running state - keep them on actl */ + actl_stream_broadcast(STREAM_STOP, 0); - /* Prepare the parser and associated streams */ - parser_prepare_streaming(); + /* Stop all buffering or else risk clobbering random-access data */ + wb = disk_buf_send_msg(STREAM_STOP, 0); - /* Start buffer using previous buffering status */ - disk_buf_send_msg(STREAM_PLAY, was_buffering); + if (was_buffering != NULL) + *was_buffering = wb; + } - /* Tell each stream to start - may generate end of stream signals - * now - we'll handle this when finished */ - actl_stream_broadcast(STREAM_PLAY, 0); + time = time_from_whence(time, whence); - /* Actually start the clock */ - pcm_output_play_pause(true); - } - else - { - /* Performed the seek - leave it at that until restarted */ - stream_mgr.seeked = true; - } + stream_mgr.seeked = true; - return time; + return parser_seek_time(time); } /* Handle STREAM_OPEN */ @@ -402,29 +399,11 @@ static void stream_on_play(void) start = str_parser.last_seek_time - str_parser.start_pts; stream_mgr.resume_time = start; - start = stream_seek_intl(start, SEEK_SET, STREAM_STOPPED); - - /* Fill list of all streams that will be playing */ - move_strl_to_actl(); - - /* Clear any seeked status */ - stream_mgr.seeked = false; - - /* Set the master clock */ - set_stream_clock(start); - - /* Prepare the parser and associated streams */ - parser_prepare_streaming(); + /* Prepare seek to start point */ + start = stream_seek_intl(start, SEEK_SET, STREAM_STOPPED, NULL); - /* Force buffering */ - disk_buf_send_msg(STREAM_PLAY, true); - - /* Tell each stream to start - may generate end of stream signals - * now - we'll handle this when finished */ - actl_stream_broadcast(STREAM_PLAY, 0); - - /* Actually start the clock */ - pcm_output_play_pause(true); + /* Sync and start - force buffer fill */ + stream_start_playback(start, true); } else { @@ -481,33 +460,8 @@ static void stream_on_resume(void) /* Boost the CPU */ trigger_cpu_boost(); - if (stream_mgr.seeked) - { - /* Have to give the parser notice to sync up streams */ - stream_mgr.seeked = false; - - /* Flush old PCM data */ - pcm_output_flush(); - - /* 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(); - } - - /* Don't force buffering */ - disk_buf_send_msg(STREAM_PLAY, false); - - /* Tell each stream to start - may generate end of stream signals - * now - we'll handle this when finished */ - actl_stream_broadcast(STREAM_PLAY, 0); - - /* Actually start the clock */ - pcm_output_play_pause(true); + /* Sync and start - no force buffering */ + stream_start_playback(str_parser.last_seek_time, false); /* Officially playing */ stream_mgr.status = STREAM_PLAYING; @@ -582,33 +536,30 @@ static void stream_on_seek(struct stream_seek_data *skd) if (stream_mgr.filename == NULL) break; + /* Keep things spinning if already doing so */ stream_keep_disk_active(); + /* Have data - reply in order to acquire lock */ stream_mgr_reply_msg(STREAM_OK); stream_mgr_lock(); if (stream_can_seek()) { - if (stream_mgr.status != STREAM_STOPPED) + bool buffer; + + if (stream_mgr.status == STREAM_PLAYING) { - if (stream_mgr.status != STREAM_PLAYING) - { - trigger_cpu_boost(); - } + /* Keep clock from advancing while seeking */ + pcm_output_play_pause(false); + } - stream_seek_intl(time, whence, stream_mgr.status); + time = stream_seek_intl(time, whence, stream_mgr.status, &buffer); - if (stream_mgr.status != STREAM_PLAYING) - { - cancel_cpu_boost(); - } - } - else + if (stream_mgr.status == STREAM_PLAYING) { - stream_mgr.seeked = true; - time = time_from_whence(time, whence); - parser_seek_time(time); + /* Sync and restart - no force buffering */ + stream_start_playback(time, buffer); } } @@ -616,6 +567,7 @@ static void stream_on_seek(struct stream_seek_data *skd) return; } + /* Invalid parameter or no file */ stream_mgr_reply_msg(STREAM_ERROR); } @@ -904,10 +856,18 @@ uint32_t stream_get_seek_time(uint32_t *start) stream_mgr_lock(); if (stream_mgr.seeked) + { time = str_parser.last_seek_time; + } else + { time = TICKS_TO_TS(pcm_output_get_clock()); + /* Clock can be start early so keep in range */ + if (time < str_parser.start_pts) + time = str_parser.start_pts; + } + if (start != NULL) *start = str_parser.start_pts; -- cgit v1.2.3