forked from len0rd/rockbox
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
This commit is contained in:
parent
9216d0f16a
commit
0e98d7e315
2 changed files with 87 additions and 114 deletions
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
if (status != STREAM_STOPPED)
|
||||
{
|
||||
/* Keep clock from advancing while seeking */
|
||||
pcm_output_play_pause(false);
|
||||
}
|
||||
bool wb;
|
||||
|
||||
/* 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);
|
||||
wb = disk_buf_send_msg(STREAM_STOP, 0);
|
||||
|
||||
if (was_buffering != NULL)
|
||||
*was_buffering = wb;
|
||||
}
|
||||
|
||||
time = time_from_whence(time, whence);
|
||||
time = parser_seek_time(time);
|
||||
|
||||
if (status == STREAM_PLAYING)
|
||||
{
|
||||
/* 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);
|
||||
|
||||
/* Make sure streams are back in active pool */
|
||||
move_strl_to_actl();
|
||||
|
||||
/* Prepare the parser and associated streams */
|
||||
parser_prepare_streaming();
|
||||
|
||||
/* Start buffer using previous buffering status */
|
||||
disk_buf_send_msg(STREAM_PLAY, was_buffering);
|
||||
|
||||
/* 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);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Performed the seek - leave it at that until restarted */
|
||||
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);
|
||||
/* Prepare seek to start point */
|
||||
start = stream_seek_intl(start, SEEK_SET, STREAM_STOPPED, NULL);
|
||||
|
||||
/* 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();
|
||||
|
||||
/* 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)
|
||||
if (stream_mgr.status == STREAM_PLAYING)
|
||||
{
|
||||
cancel_cpu_boost();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
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;
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue