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 99a619ecb2cb2c8eb9c73e0c46896f26b0ebef9f..e52d0e49fc2e651e0d6352b391a96432fc8cb6bc 100644 |
--- a/media/base/android/media_source_player.cc |
+++ b/media/base/android/media_source_player.cc |
@@ -63,6 +63,8 @@ MediaSourcePlayer::MediaSourcePlayer( |
reconfig_video_decoder_(false), |
drm_bridge_(NULL), |
is_waiting_for_key_(false), |
+ has_pending_audio_data_request_(false), |
+ has_pending_video_data_request_(false), |
weak_factory_(this) { |
demuxer_->Initialize(this); |
clock_.SetMaxTime(base::TimeDelta()); |
@@ -108,7 +110,7 @@ void MediaSourcePlayer::SetVideoSurface(gfx::ScopedJavaSurface surface) { |
} |
void MediaSourcePlayer::ScheduleSeekEventAndStopDecoding( |
- const base::TimeDelta& seek_time) { |
+ base::TimeDelta seek_time) { |
DVLOG(1) << __FUNCTION__ << "(" << seek_time.InSecondsF() << ")"; |
DCHECK(!IsEventPending(SEEK_EVENT_PENDING)); |
@@ -179,7 +181,7 @@ int MediaSourcePlayer::GetVideoHeight() { |
return height_; |
} |
-void MediaSourcePlayer::SeekTo(const base::TimeDelta& timestamp) { |
+void MediaSourcePlayer::SeekTo(base::TimeDelta timestamp) { |
DVLOG(1) << __FUNCTION__ << "(" << timestamp.InSecondsF() << ")"; |
if (IsEventPending(SEEK_EVENT_PENDING)) { |
@@ -224,7 +226,7 @@ void MediaSourcePlayer::Release() { |
// Clear all the pending events except seeks and config changes. |
pending_event_ &= (SEEK_EVENT_PENDING | CONFIG_CHANGE_EVENT_PENDING); |
is_surface_in_use_ = false; |
- audio_decoder_job_.reset(); |
+ ResetAudioDecoderJob(); |
ResetVideoDecoderJob(); |
// Prevent job re-creation attempts in OnDemuxerConfigsAvailable() |
@@ -347,6 +349,20 @@ void MediaSourcePlayer::OnDemuxerConfigsAvailable( |
void MediaSourcePlayer::OnDemuxerDataAvailable(const DemuxerData& data) { |
DVLOG(1) << __FUNCTION__ << "(" << data.type << ")"; |
DCHECK_LT(0u, data.access_units.size()); |
+ |
+ if (has_pending_audio_data_request_ && data.type == DemuxerStream::AUDIO) { |
+ has_pending_audio_data_request_ = false; |
+ ProcessPendingEvents(); |
+ return; |
+ } |
+ |
+ if (has_pending_video_data_request_ && data.type == DemuxerStream::VIDEO) { |
+ next_video_data_is_iframe_ = false; |
+ has_pending_video_data_request_ = false; |
+ ProcessPendingEvents(); |
+ return; |
+ } |
+ |
if (data.type == DemuxerStream::AUDIO && audio_decoder_job_) { |
audio_decoder_job_->OnDataReceived(data); |
} else if (data.type == DemuxerStream::VIDEO) { |
@@ -399,7 +415,7 @@ void MediaSourcePlayer::SetDrmBridge(MediaDrmBridge* drm_bridge) { |
} |
void MediaSourcePlayer::OnDemuxerSeekDone( |
- const base::TimeDelta& actual_browser_seek_time) { |
+ base::TimeDelta actual_browser_seek_time) { |
DVLOG(1) << __FUNCTION__; |
ClearPendingEvent(SEEK_EVENT_PENDING); |
@@ -421,14 +437,17 @@ void MediaSourcePlayer::OnDemuxerSeekDone( |
// player clock to the actual seek target. |
if (doing_browser_seek_) { |
DCHECK(actual_browser_seek_time != kNoTimestamp()); |
+ base::TimeDelta seek_time = actual_browser_seek_time; |
// A browser seek must not jump into the past. Ideally, it seeks to the |
// requested time, but it might jump into the future. |
- DCHECK(actual_browser_seek_time >= GetCurrentTime()); |
+ DCHECK(seek_time >= GetCurrentTime()); |
DVLOG(1) << __FUNCTION__ << " : setting clock to actual browser seek time: " |
- << actual_browser_seek_time.InSecondsF(); |
- clock_.SetTime(actual_browser_seek_time, actual_browser_seek_time); |
+ << seek_time.InSecondsF(); |
+ clock_.SetTime(seek_time, seek_time); |
if (audio_timestamp_helper_) |
- audio_timestamp_helper_->SetBaseTimestamp(actual_browser_seek_time); |
+ audio_timestamp_helper_->SetBaseTimestamp(seek_time); |
+ } else { |
+ DCHECK(actual_browser_seek_time == kNoTimestamp()); |
} |
reached_audio_eos_ = false; |
@@ -452,7 +471,7 @@ void MediaSourcePlayer::OnDemuxerSeekDone( |
} |
void MediaSourcePlayer::UpdateTimestamps( |
- const base::TimeDelta& presentation_timestamp, size_t audio_output_bytes) { |
+ base::TimeDelta presentation_timestamp, size_t audio_output_bytes) { |
base::TimeDelta new_max_time = presentation_timestamp; |
if (audio_output_bytes > 0) { |
@@ -478,6 +497,11 @@ void MediaSourcePlayer::ProcessPendingEvents() { |
return; |
} |
+ if (has_pending_audio_data_request_ || has_pending_video_data_request_) { |
+ DVLOG(1) << __FUNCTION__ << " : has pending data request."; |
+ return; |
+ } |
+ |
if (IsEventPending(PREFETCH_DONE_EVENT_PENDING)) { |
DVLOG(1) << __FUNCTION__ << " : PREFETCH_DONE still pending."; |
return; |
@@ -512,6 +536,14 @@ void MediaSourcePlayer::ProcessPendingEvents() { |
if (IsEventPending(PREFETCH_REQUEST_EVENT_PENDING)) { |
DVLOG(1) << __FUNCTION__ << " : Handling PREFETCH_REQUEST_EVENT."; |
+ // If one of the decoder is not initialized, cancel this event as it will be |
+ // called later when Start() is called again. |
+ if ((HasVideo() && !video_decoder_job_) || |
+ (HasAudio() && !audio_decoder_job_)) { |
+ ClearPendingEvent(PREFETCH_REQUEST_EVENT_PENDING); |
+ return; |
+ } |
+ |
DCHECK(audio_decoder_job_ || AudioFinished()); |
DCHECK(video_decoder_job_ || VideoFinished()); |
@@ -549,7 +581,7 @@ void MediaSourcePlayer::ProcessPendingEvents() { |
void MediaSourcePlayer::MediaDecoderCallback( |
bool is_audio, MediaCodecStatus status, |
- const base::TimeDelta& presentation_timestamp, size_t audio_output_bytes) { |
+ base::TimeDelta presentation_timestamp, size_t audio_output_bytes) { |
DVLOG(1) << __FUNCTION__ << ": " << is_audio << ", " << status; |
// TODO(xhwang): Drop IntToString() when http://crbug.com/303899 is fixed. |
@@ -755,7 +787,7 @@ bool MediaSourcePlayer::VideoFinished() { |
void MediaSourcePlayer::ConfigureAudioDecoderJob() { |
if (!HasAudio()) { |
- audio_decoder_job_.reset(); |
+ ResetAudioDecoderJob(); |
return; |
} |
@@ -769,8 +801,8 @@ void MediaSourcePlayer::ConfigureAudioDecoderJob() { |
DCHECK(!audio_decoder_job_ || !audio_decoder_job_->is_decoding()); |
+ ResetAudioDecoderJob(); |
DVLOG(1) << __FUNCTION__ << " : creating new audio decoder job"; |
- |
audio_decoder_job_.reset(AudioDecoderJob::Create( |
audio_codec_, sampling_rate_, num_channels_, &audio_extra_data_[0], |
audio_extra_data_.size(), media_crypto.obj(), |
@@ -785,6 +817,10 @@ void MediaSourcePlayer::ConfigureAudioDecoderJob() { |
} |
void MediaSourcePlayer::ResetVideoDecoderJob() { |
+ if (video_decoder_job_) { |
+ has_pending_video_data_request_ = |
+ video_decoder_job_->is_requesting_demuxer_data(); |
+ } |
video_decoder_job_.reset(); |
// Any eventual video decoder job re-creation will use the current |surface_|. |
@@ -792,6 +828,14 @@ void MediaSourcePlayer::ResetVideoDecoderJob() { |
ClearPendingEvent(SURFACE_CHANGE_EVENT_PENDING); |
} |
+void MediaSourcePlayer::ResetAudioDecoderJob() { |
+ if (audio_decoder_job_) { |
+ has_pending_audio_data_request_ = |
+ audio_decoder_job_->is_requesting_demuxer_data(); |
+ } |
+ audio_decoder_job_.reset(); |
+} |
+ |
void MediaSourcePlayer::ConfigureVideoDecoderJob() { |
if (!HasVideo() || surface_.IsEmpty()) { |
ResetVideoDecoderJob(); |
@@ -868,7 +912,7 @@ void MediaSourcePlayer::OnDecoderStarved() { |
} |
void MediaSourcePlayer::StartStarvationCallback( |
- const base::TimeDelta& presentation_timestamp) { |
+ base::TimeDelta presentation_timestamp) { |
// 20ms was chosen because it is the typical size of a compressed audio frame. |
// Anything smaller than this would likely cause unnecessary cycling in and |
// out of the prefetch state. |