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 */
|
/* Flushes the buffer - clock keeps counting */
|
||||||
void pcm_output_flush(void)
|
void pcm_output_flush(void)
|
||||||
{
|
{
|
||||||
|
bool playing, paused;
|
||||||
|
|
||||||
rb->pcm_play_lock();
|
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_threshold = PCMOUT_PLAY_WM;
|
||||||
pcmbuf_read = pcmbuf_written = 0;
|
pcmbuf_read = pcmbuf_written = 0;
|
||||||
pcmbuf_head = pcmbuf_tail = pcm_buffer;
|
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();
|
rb->pcm_play_unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -247,6 +247,37 @@ static void set_stream_clock(uint32_t time)
|
||||||
pcm_output_set_clock(TS_TO_TICKS(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 */
|
/* Return the play time relative to the specified play time */
|
||||||
static uint32_t time_from_whence(uint32_t time, int whence)
|
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 */
|
/* 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 */
|
if (status != STREAM_STOPPED)
|
||||||
bool was_buffering;
|
|
||||||
|
|
||||||
if (status == STREAM_PLAYING)
|
|
||||||
{
|
{
|
||||||
/* Keep clock from advancing while seeking */
|
bool wb;
|
||||||
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 */
|
||||||
|
wb = disk_buf_send_msg(STREAM_STOP, 0);
|
||||||
|
|
||||||
|
if (was_buffering != NULL)
|
||||||
|
*was_buffering = 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);
|
|
||||||
|
|
||||||
time = time_from_whence(time, whence);
|
time = time_from_whence(time, whence);
|
||||||
time = parser_seek_time(time);
|
|
||||||
|
|
||||||
if (status == STREAM_PLAYING)
|
stream_mgr.seeked = true;
|
||||||
{
|
|
||||||
/* Restart streams if currently playing */
|
|
||||||
|
|
||||||
/* Clear any seeked status */
|
return parser_seek_time(time);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handle STREAM_OPEN */
|
/* Handle STREAM_OPEN */
|
||||||
|
@ -402,29 +399,11 @@ static void stream_on_play(void)
|
||||||
start = str_parser.last_seek_time - str_parser.start_pts;
|
start = str_parser.last_seek_time - str_parser.start_pts;
|
||||||
stream_mgr.resume_time = start;
|
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 */
|
/* Sync and start - force buffer fill */
|
||||||
move_strl_to_actl();
|
stream_start_playback(start, true);
|
||||||
|
|
||||||
/* 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);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -481,33 +460,8 @@ static void stream_on_resume(void)
|
||||||
/* Boost the CPU */
|
/* Boost the CPU */
|
||||||
trigger_cpu_boost();
|
trigger_cpu_boost();
|
||||||
|
|
||||||
if (stream_mgr.seeked)
|
/* Sync and start - no force buffering */
|
||||||
{
|
stream_start_playback(str_parser.last_seek_time, false);
|
||||||
/* 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);
|
|
||||||
|
|
||||||
/* Officially playing */
|
/* Officially playing */
|
||||||
stream_mgr.status = STREAM_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)
|
if (stream_mgr.filename == NULL)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
/* Keep things spinning if already doing so */
|
||||||
stream_keep_disk_active();
|
stream_keep_disk_active();
|
||||||
|
|
||||||
|
/* Have data - reply in order to acquire lock */
|
||||||
stream_mgr_reply_msg(STREAM_OK);
|
stream_mgr_reply_msg(STREAM_OK);
|
||||||
|
|
||||||
stream_mgr_lock();
|
stream_mgr_lock();
|
||||||
|
|
||||||
if (stream_can_seek())
|
if (stream_can_seek())
|
||||||
{
|
{
|
||||||
if (stream_mgr.status != STREAM_STOPPED)
|
bool buffer;
|
||||||
|
|
||||||
|
if (stream_mgr.status == STREAM_PLAYING)
|
||||||
{
|
{
|
||||||
if (stream_mgr.status != STREAM_PLAYING)
|
/* Keep clock from advancing while seeking */
|
||||||
{
|
pcm_output_play_pause(false);
|
||||||
trigger_cpu_boost();
|
|
||||||
}
|
|
||||||
|
|
||||||
stream_seek_intl(time, whence, stream_mgr.status);
|
|
||||||
|
|
||||||
if (stream_mgr.status != STREAM_PLAYING)
|
|
||||||
{
|
|
||||||
cancel_cpu_boost();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
time = stream_seek_intl(time, whence, stream_mgr.status, &buffer);
|
||||||
|
|
||||||
|
if (stream_mgr.status == STREAM_PLAYING)
|
||||||
{
|
{
|
||||||
stream_mgr.seeked = true;
|
/* Sync and restart - no force buffering */
|
||||||
time = time_from_whence(time, whence);
|
stream_start_playback(time, buffer);
|
||||||
parser_seek_time(time);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -616,6 +567,7 @@ static void stream_on_seek(struct stream_seek_data *skd)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Invalid parameter or no file */
|
||||||
stream_mgr_reply_msg(STREAM_ERROR);
|
stream_mgr_reply_msg(STREAM_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -904,10 +856,18 @@ uint32_t stream_get_seek_time(uint32_t *start)
|
||||||
stream_mgr_lock();
|
stream_mgr_lock();
|
||||||
|
|
||||||
if (stream_mgr.seeked)
|
if (stream_mgr.seeked)
|
||||||
|
{
|
||||||
time = str_parser.last_seek_time;
|
time = str_parser.last_seek_time;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
time = TICKS_TO_TS(pcm_output_get_clock());
|
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)
|
if (start != NULL)
|
||||||
*start = str_parser.start_pts;
|
*start = str_parser.start_pts;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue