diff options
author | Michael Sevakis <jethead71@rockbox.org> | 2008-01-07 14:58:23 +0000 |
---|---|---|
committer | Michael Sevakis <jethead71@rockbox.org> | 2008-01-07 14:58:23 +0000 |
commit | 0e98d7e315bcbdee35bcda4fd01a82da9185ed93 (patch) | |
tree | 937e05e7d7028706075adb27d4a8665163298e55 /apps/plugins/mpegplayer | |
parent | 9216d0f16a6c0c51bdae4fbfe9351d02beb1110c (diff) | |
download | rockbox-0e98d7e315bcbdee35bcda4fd01a82da9185ed93.tar.gz rockbox-0e98d7e315bcbdee35bcda4fd01a82da9185ed93.zip |
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
Diffstat (limited to 'apps/plugins/mpegplayer')
-rw-r--r-- | apps/plugins/mpegplayer/pcm_output.c | 13 | ||||
-rw-r--r-- | 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) | |||
152 | /* Flushes the buffer - clock keeps counting */ | 152 | /* Flushes the buffer - clock keeps counting */ |
153 | void pcm_output_flush(void) | 153 | void pcm_output_flush(void) |
154 | { | 154 | { |
155 | bool playing, paused; | ||
156 | |||
155 | rb->pcm_play_lock(); | 157 | rb->pcm_play_lock(); |
156 | 158 | ||
159 | playing = rb->pcm_is_playing(); | ||
160 | paused = rb->pcm_is_paused(); | ||
161 | |||
162 | /* Stop PCM to clear current buffer */ | ||
163 | if (playing) | ||
164 | rb->pcm_play_stop(); | ||
165 | |||
157 | pcmbuf_threshold = PCMOUT_PLAY_WM; | 166 | pcmbuf_threshold = PCMOUT_PLAY_WM; |
158 | pcmbuf_read = pcmbuf_written = 0; | 167 | pcmbuf_read = pcmbuf_written = 0; |
159 | pcmbuf_head = pcmbuf_tail = pcm_buffer; | 168 | pcmbuf_head = pcmbuf_tail = pcm_buffer; |
160 | 169 | ||
170 | /* Restart if playing state was current */ | ||
171 | if (playing && !paused) | ||
172 | rb->pcm_play_data(get_more, NULL, 0); | ||
173 | |||
161 | rb->pcm_play_unlock(); | 174 | rb->pcm_play_unlock(); |
162 | } | 175 | } |
163 | 176 | ||
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) | |||
247 | pcm_output_set_clock(TS_TO_TICKS(time)); | 247 | pcm_output_set_clock(TS_TO_TICKS(time)); |
248 | } | 248 | } |
249 | 249 | ||
250 | static void stream_start_playback(uint32_t time, bool fill_buffer) | ||
251 | { | ||
252 | if (stream_mgr.seeked) | ||
253 | { | ||
254 | /* Clear any seeked status */ | ||
255 | stream_mgr.seeked = false; | ||
256 | |||
257 | /* Flush old PCM data */ | ||
258 | pcm_output_flush(); | ||
259 | |||
260 | /* Set the master clock */ | ||
261 | set_stream_clock(time); | ||
262 | |||
263 | /* Make sure streams are back in active pool */ | ||
264 | move_strl_to_actl(); | ||
265 | |||
266 | /* Prepare the parser and associated streams */ | ||
267 | parser_prepare_streaming(); | ||
268 | } | ||
269 | |||
270 | /* Start buffer which optional force fill */ | ||
271 | disk_buf_send_msg(STREAM_PLAY, fill_buffer); | ||
272 | |||
273 | /* Tell each stream to start - may generate end of stream signals | ||
274 | * now - we'll handle this when finished */ | ||
275 | actl_stream_broadcast(STREAM_PLAY, 0); | ||
276 | |||
277 | /* Actually start the clock */ | ||
278 | pcm_output_play_pause(true); | ||
279 | } | ||
280 | |||
250 | /* Return the play time relative to the specified play time */ | 281 | /* Return the play time relative to the specified play time */ |
251 | static uint32_t time_from_whence(uint32_t time, int whence) | 282 | static uint32_t time_from_whence(uint32_t time, int whence) |
252 | { | 283 | { |
@@ -286,62 +317,28 @@ static uint32_t time_from_whence(uint32_t time, int whence) | |||
286 | } | 317 | } |
287 | 318 | ||
288 | /* Handle seeking details if playing or paused */ | 319 | /* Handle seeking details if playing or paused */ |
289 | static uint32_t stream_seek_intl(uint32_t time, int whence, int status) | 320 | static uint32_t stream_seek_intl(uint32_t time, int whence, |
321 | int status, bool *was_buffering) | ||
290 | { | 322 | { |
291 | /* seek start time */ | 323 | if (status != STREAM_STOPPED) |
292 | bool was_buffering; | ||
293 | |||
294 | if (status == STREAM_PLAYING) | ||
295 | { | ||
296 | /* Keep clock from advancing while seeking */ | ||
297 | pcm_output_play_pause(false); | ||
298 | } | ||
299 | |||
300 | /* Place streams in a non-running state - keep them on actl */ | ||
301 | actl_stream_broadcast(STREAM_STOP, 0); | ||
302 | |||
303 | /* Stop all buffering or else risk clobbering random-access data */ | ||
304 | was_buffering = disk_buf_send_msg(STREAM_STOP, 0); | ||
305 | |||
306 | time = time_from_whence(time, whence); | ||
307 | time = parser_seek_time(time); | ||
308 | |||
309 | if (status == STREAM_PLAYING) | ||
310 | { | 324 | { |
311 | /* Restart streams if currently playing */ | 325 | bool wb; |
312 | |||
313 | /* Clear any seeked status */ | ||
314 | stream_mgr.seeked = false; | ||
315 | |||
316 | /* Flush old PCM data */ | ||
317 | pcm_output_flush(); | ||
318 | |||
319 | /* Set the master clock */ | ||
320 | set_stream_clock(time); | ||
321 | 326 | ||
322 | /* Make sure streams are back in active pool */ | 327 | /* Place streams in a non-running state - keep them on actl */ |
323 | move_strl_to_actl(); | 328 | actl_stream_broadcast(STREAM_STOP, 0); |
324 | 329 | ||
325 | /* Prepare the parser and associated streams */ | 330 | /* Stop all buffering or else risk clobbering random-access data */ |
326 | parser_prepare_streaming(); | 331 | wb = disk_buf_send_msg(STREAM_STOP, 0); |
327 | 332 | ||
328 | /* Start buffer using previous buffering status */ | 333 | if (was_buffering != NULL) |
329 | disk_buf_send_msg(STREAM_PLAY, was_buffering); | 334 | *was_buffering = wb; |
335 | } | ||
330 | 336 | ||
331 | /* Tell each stream to start - may generate end of stream signals | 337 | time = time_from_whence(time, whence); |
332 | * now - we'll handle this when finished */ | ||
333 | actl_stream_broadcast(STREAM_PLAY, 0); | ||
334 | 338 | ||
335 | /* Actually start the clock */ | 339 | stream_mgr.seeked = true; |
336 | pcm_output_play_pause(true); | ||
337 | } | ||
338 | else | ||
339 | { | ||
340 | /* Performed the seek - leave it at that until restarted */ | ||
341 | stream_mgr.seeked = true; | ||
342 | } | ||
343 | 340 | ||
344 | return time; | 341 | return parser_seek_time(time); |
345 | } | 342 | } |
346 | 343 | ||
347 | /* Handle STREAM_OPEN */ | 344 | /* Handle STREAM_OPEN */ |
@@ -402,29 +399,11 @@ static void stream_on_play(void) | |||
402 | start = str_parser.last_seek_time - str_parser.start_pts; | 399 | start = str_parser.last_seek_time - str_parser.start_pts; |
403 | stream_mgr.resume_time = start; | 400 | stream_mgr.resume_time = start; |
404 | 401 | ||
405 | start = stream_seek_intl(start, SEEK_SET, STREAM_STOPPED); | 402 | /* Prepare seek to start point */ |
406 | 403 | start = stream_seek_intl(start, SEEK_SET, STREAM_STOPPED, NULL); | |
407 | /* Fill list of all streams that will be playing */ | ||
408 | move_strl_to_actl(); | ||
409 | |||
410 | /* Clear any seeked status */ | ||
411 | stream_mgr.seeked = false; | ||
412 | |||
413 | /* Set the master clock */ | ||
414 | set_stream_clock(start); | ||
415 | |||
416 | /* Prepare the parser and associated streams */ | ||
417 | parser_prepare_streaming(); | ||
418 | 404 | ||
419 | /* Force buffering */ | 405 | /* Sync and start - force buffer fill */ |
420 | disk_buf_send_msg(STREAM_PLAY, true); | 406 | stream_start_playback(start, true); |
421 | |||
422 | /* Tell each stream to start - may generate end of stream signals | ||
423 | * now - we'll handle this when finished */ | ||
424 | actl_stream_broadcast(STREAM_PLAY, 0); | ||
425 | |||
426 | /* Actually start the clock */ | ||
427 | pcm_output_play_pause(true); | ||
428 | } | 407 | } |
429 | else | 408 | else |
430 | { | 409 | { |
@@ -481,33 +460,8 @@ static void stream_on_resume(void) | |||
481 | /* Boost the CPU */ | 460 | /* Boost the CPU */ |
482 | trigger_cpu_boost(); | 461 | trigger_cpu_boost(); |
483 | 462 | ||
484 | if (stream_mgr.seeked) | 463 | /* Sync and start - no force buffering */ |
485 | { | 464 | stream_start_playback(str_parser.last_seek_time, false); |
486 | /* Have to give the parser notice to sync up streams */ | ||
487 | stream_mgr.seeked = false; | ||
488 | |||
489 | /* Flush old PCM data */ | ||
490 | pcm_output_flush(); | ||
491 | |||
492 | /* Set the master clock */ | ||
493 | set_stream_clock(str_parser.last_seek_time); | ||
494 | |||
495 | /* Make sure streams are back in active pool */ | ||
496 | move_strl_to_actl(); | ||
497 | |||
498 | /* Prepare the parser and associated streams */ | ||
499 | parser_prepare_streaming(); | ||
500 | } | ||
501 | |||
502 | /* Don't force buffering */ | ||
503 | disk_buf_send_msg(STREAM_PLAY, false); | ||
504 | |||
505 | /* Tell each stream to start - may generate end of stream signals | ||
506 | * now - we'll handle this when finished */ | ||
507 | actl_stream_broadcast(STREAM_PLAY, 0); | ||
508 | |||
509 | /* Actually start the clock */ | ||
510 | pcm_output_play_pause(true); | ||
511 | 465 | ||
512 | /* Officially playing */ | 466 | /* Officially playing */ |
513 | stream_mgr.status = STREAM_PLAYING; | 467 | stream_mgr.status = STREAM_PLAYING; |
@@ -582,33 +536,30 @@ static void stream_on_seek(struct stream_seek_data *skd) | |||
582 | if (stream_mgr.filename == NULL) | 536 | if (stream_mgr.filename == NULL) |
583 | break; | 537 | break; |
584 | 538 | ||
539 | /* Keep things spinning if already doing so */ | ||
585 | stream_keep_disk_active(); | 540 | stream_keep_disk_active(); |
586 | 541 | ||
542 | /* Have data - reply in order to acquire lock */ | ||
587 | stream_mgr_reply_msg(STREAM_OK); | 543 | stream_mgr_reply_msg(STREAM_OK); |
588 | 544 | ||
589 | stream_mgr_lock(); | 545 | stream_mgr_lock(); |
590 | 546 | ||
591 | if (stream_can_seek()) | 547 | if (stream_can_seek()) |
592 | { | 548 | { |
593 | if (stream_mgr.status != STREAM_STOPPED) | 549 | bool buffer; |
550 | |||
551 | if (stream_mgr.status == STREAM_PLAYING) | ||
594 | { | 552 | { |
595 | if (stream_mgr.status != STREAM_PLAYING) | 553 | /* Keep clock from advancing while seeking */ |
596 | { | 554 | pcm_output_play_pause(false); |
597 | trigger_cpu_boost(); | 555 | } |
598 | } | ||
599 | 556 | ||
600 | stream_seek_intl(time, whence, stream_mgr.status); | 557 | time = stream_seek_intl(time, whence, stream_mgr.status, &buffer); |
601 | 558 | ||
602 | if (stream_mgr.status != STREAM_PLAYING) | 559 | if (stream_mgr.status == STREAM_PLAYING) |
603 | { | ||
604 | cancel_cpu_boost(); | ||
605 | } | ||
606 | } | ||
607 | else | ||
608 | { | 560 | { |
609 | stream_mgr.seeked = true; | 561 | /* Sync and restart - no force buffering */ |
610 | time = time_from_whence(time, whence); | 562 | stream_start_playback(time, buffer); |
611 | parser_seek_time(time); | ||
612 | } | 563 | } |
613 | } | 564 | } |
614 | 565 | ||
@@ -616,6 +567,7 @@ static void stream_on_seek(struct stream_seek_data *skd) | |||
616 | return; | 567 | return; |
617 | } | 568 | } |
618 | 569 | ||
570 | /* Invalid parameter or no file */ | ||
619 | stream_mgr_reply_msg(STREAM_ERROR); | 571 | stream_mgr_reply_msg(STREAM_ERROR); |
620 | } | 572 | } |
621 | 573 | ||
@@ -904,10 +856,18 @@ uint32_t stream_get_seek_time(uint32_t *start) | |||
904 | stream_mgr_lock(); | 856 | stream_mgr_lock(); |
905 | 857 | ||
906 | if (stream_mgr.seeked) | 858 | if (stream_mgr.seeked) |
859 | { | ||
907 | time = str_parser.last_seek_time; | 860 | time = str_parser.last_seek_time; |
861 | } | ||
908 | else | 862 | else |
863 | { | ||
909 | time = TICKS_TO_TS(pcm_output_get_clock()); | 864 | time = TICKS_TO_TS(pcm_output_get_clock()); |
910 | 865 | ||
866 | /* Clock can be start early so keep in range */ | ||
867 | if (time < str_parser.start_pts) | ||
868 | time = str_parser.start_pts; | ||
869 | } | ||
870 | |||
911 | if (start != NULL) | 871 | if (start != NULL) |
912 | *start = str_parser.start_pts; | 872 | *start = str_parser.start_pts; |
913 | 873 | ||