| Index: media/base/android/media_source_player.cc
|
| diff --git a/media/base/android/media_source_player.cc b/media/base/android/media_source_player.cc
|
| index 8e23a91629331fc6f8df18098a23ee69d37915d2..da4b55f47ed3d40cc5b2ee1494a34df58886217d 100644
|
| --- a/media/base/android/media_source_player.cc
|
| +++ b/media/base/android/media_source_player.cc
|
| @@ -11,6 +11,7 @@
|
| #include "base/barrier_closure.h"
|
| #include "base/basictypes.h"
|
| #include "base/bind.h"
|
| +#include "base/callback_helpers.h"
|
| #include "base/debug/trace_event.h"
|
| #include "base/logging.h"
|
| #include "base/strings/string_number_conversions.h"
|
| @@ -230,15 +231,39 @@ base::TimeDelta MediaSourcePlayer::GetDuration() {
|
|
|
| void MediaSourcePlayer::Release() {
|
| DVLOG(1) << __FUNCTION__;
|
| +
|
| + // Allow pending seeks and config changes to survive this Release().
|
| + // If previously pending a prefetch done event, or a job was still decoding,
|
| + // then at end of Release() we need to ProcessPendingEvents() to process any
|
| + // seek or config change that was blocked by the prefetch or decode.
|
| + // TODO(qinmin/wolenetz): Maintain channel state to not double-request data
|
| + // or drop data received across Release()+Start(). See http://crbug.com/306314
|
| + // and http://crbug.com/304234.
|
| + bool process_pending_events = false;
|
| + process_pending_events = IsEventPending(PREFETCH_DONE_EVENT_PENDING) ||
|
| + (audio_decoder_job_ && audio_decoder_job_->is_decoding()) ||
|
| + (video_decoder_job_ && video_decoder_job_->is_decoding());
|
| +
|
| + // Clear all the pending events except seeks and config changes.
|
| + pending_event_ &= (SEEK_EVENT_PENDING | CONFIG_CHANGE_EVENT_PENDING);
|
| +
|
| audio_decoder_job_.reset();
|
| video_decoder_job_.reset();
|
| +
|
| + // Prevent job re-creation attempts in OnDemuxerConfigsAvailable()
|
| reconfig_audio_decoder_ = false;
|
| reconfig_video_decoder_ = false;
|
| +
|
| + // Prevent player restart, including job re-creation attempts.
|
| playing_ = false;
|
| - pending_event_ = NO_EVENT_PENDING;
|
| +
|
| decoder_starvation_callback_.Cancel();
|
| surface_ = gfx::ScopedJavaSurface();
|
| manager()->ReleaseMediaResources(player_id());
|
| + if (process_pending_events) {
|
| + DVLOG(1) << __FUNCTION__ << " : Resuming seek or config change processing";
|
| + ProcessPendingEvents();
|
| + }
|
| }
|
|
|
| void MediaSourcePlayer::SetVolume(double volume) {
|
| @@ -549,12 +574,17 @@ void MediaSourcePlayer::MediaDecoderCallback(
|
| base::IntToString(status));
|
| }
|
|
|
| + // Let tests hook the completion of this decode cycle.
|
| + if (!decode_callback_for_testing_.is_null())
|
| + base::ResetAndReturn(&decode_callback_for_testing_).Run();
|
| +
|
| bool is_clock_manager = is_audio || !HasAudio();
|
|
|
| if (is_clock_manager)
|
| decoder_starvation_callback_.Cancel();
|
|
|
| if (status == MEDIA_CODEC_ERROR) {
|
| + DVLOG(1) << __FUNCTION__ << " : decode error";
|
| Release();
|
| manager()->OnError(player_id(), MEDIA_ERROR_DECODE);
|
| return;
|
| @@ -835,7 +865,17 @@ void MediaSourcePlayer::OnPrefetchDone() {
|
| DVLOG(1) << __FUNCTION__;
|
| DCHECK(!audio_decoder_job_ || !audio_decoder_job_->is_decoding());
|
| DCHECK(!video_decoder_job_ || !video_decoder_job_->is_decoding());
|
| - DCHECK(IsEventPending(PREFETCH_DONE_EVENT_PENDING));
|
| +
|
| + // A previously posted OnPrefetchDone() could race against a Release(). If
|
| + // Release() won the race, we should no longer have decoder jobs.
|
| + // TODO(qinmin/wolenetz): Maintain channel state to not double-request data
|
| + // or drop data received across Release()+Start(). See http://crbug.com/306314
|
| + // and http://crbug.com/304234.
|
| + if (!IsEventPending(PREFETCH_DONE_EVENT_PENDING)) {
|
| + DVLOG(1) << __FUNCTION__ << " : aborting";
|
| + DCHECK(!audio_decoder_job_ && !video_decoder_job_);
|
| + return;
|
| + }
|
|
|
| ClearPendingEvent(PREFETCH_DONE_EVENT_PENDING);
|
|
|
|
|