Index: media/base/android/media_decoder_job.cc |
diff --git a/media/base/android/media_decoder_job.cc b/media/base/android/media_decoder_job.cc |
index 41b74a08e5100dc69147db854f4c987d5157911e..90094439605c4380a35021bf59ab8daa763c06ce 100644 |
--- a/media/base/android/media_decoder_job.cc |
+++ b/media/base/android/media_decoder_job.cc |
@@ -110,7 +110,7 @@ void MediaDecoderJob::Prefetch(const base::Closure& prefetch_cb) { |
RequestData(prefetch_cb); |
} |
-bool MediaDecoderJob::Decode( |
+MediaDecoderJob::MediaDecoderJobStatus MediaDecoderJob::Decode( |
base::TimeTicks start_time_ticks, |
base::TimeDelta start_presentation_timestamp, |
const DecoderCallback& callback) { |
@@ -120,10 +120,11 @@ bool MediaDecoderJob::Decode( |
if (!media_codec_bridge_ || need_to_reconfig_decoder_job_) { |
if (drain_decoder_) |
OnDecoderDrained(); |
- need_to_reconfig_decoder_job_ = !CreateMediaCodecBridge(); |
+ MediaDecoderJobStatus status = CreateMediaCodecBridge(); |
+ need_to_reconfig_decoder_job_ = (status != STATUS_SUCCESS); |
skip_eos_enqueue_ = true; |
if (need_to_reconfig_decoder_job_) |
- return false; |
+ return status; |
} |
decode_cb_ = callback; |
@@ -133,11 +134,11 @@ bool MediaDecoderJob::Decode( |
base::Unretained(this), |
start_time_ticks, |
start_presentation_timestamp)); |
- return true; |
+ return STATUS_SUCCESS; |
} |
DecodeCurrentAccessUnit(start_time_ticks, start_presentation_timestamp); |
- return true; |
+ return STATUS_SUCCESS; |
} |
void MediaDecoderJob::StopDecode() { |
@@ -205,6 +206,32 @@ base::android::ScopedJavaLocalRef<jobject> MediaDecoderJob::GetMediaCrypto() { |
return media_crypto; |
} |
+bool MediaDecoderJob::SetCurrentFrameToPreviouslyCachedKeyFrame() { |
+ const std::vector<AccessUnit>& access_units = |
+ received_data_[current_demuxer_data_index_].access_units; |
+ // If the current data chunk is empty, the player must be in an initial or |
+ // seek state. The next access unit will always be a key frame. |
+ if (access_units.size() == 0) |
+ return true; |
+ |
+ // Find key frame in all the access units the decoder have decoded, |
+ // or is about to decode. |
+ int i = std::min(access_unit_index_[current_demuxer_data_index_], |
+ access_units.size() - 1); |
+ for (; i >= 0; --i) { |
+ // Config change is always the last access unit, and it always come with |
+ // a key frame afterwards. |
+ if (access_units[i].status == DemuxerStream::kConfigChanged) |
+ return true; |
+ if (access_units[i].is_key_frame) { |
+ access_unit_index_[current_demuxer_data_index_] = i; |
+ return true; |
+ } |
+ } |
+ return false; |
+} |
+ |
+ |
void MediaDecoderJob::Release() { |
DCHECK(ui_task_runner_->BelongsToCurrentThread()); |
DVLOG(1) << __FUNCTION__; |
@@ -518,11 +545,8 @@ void MediaDecoderJob::OnDecodeCompleted( |
case MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER: |
case MEDIA_CODEC_OUTPUT_FORMAT_CHANGED: |
case MEDIA_CODEC_OUTPUT_END_OF_STREAM: |
- if (!input_eos_encountered_) { |
- CurrentDataConsumed( |
- CurrentAccessUnit().status == DemuxerStream::kConfigChanged); |
+ if (!input_eos_encountered_) |
access_unit_index_[current_demuxer_data_index_]++; |
- } |
break; |
case MEDIA_CODEC_DEQUEUE_INPUT_AGAIN_LATER: |
@@ -589,7 +613,7 @@ void MediaDecoderJob::RequestCurrentChunkIfEmpty() { |
// Requests new data if the the last access unit of the next chunk is not EOS. |
current_demuxer_data_index_ = inactive_demuxer_data_index(); |
- const AccessUnit last_access_unit = |
+ const AccessUnit& last_access_unit = |
received_data_[current_demuxer_data_index_].access_units.back(); |
if (!last_access_unit.is_end_of_stream && |
last_access_unit.status != DemuxerStream::kAborted) { |
@@ -616,26 +640,26 @@ void MediaDecoderJob::OnDecoderDrained() { |
// Increase the access unit index so that the new decoder will not handle |
// the config change again. |
access_unit_index_[current_demuxer_data_index_]++; |
- CurrentDataConsumed(true); |
} |
-bool MediaDecoderJob::CreateMediaCodecBridge() { |
+MediaDecoderJob::MediaDecoderJobStatus |
+ MediaDecoderJob::CreateMediaCodecBridge() { |
DVLOG(1) << __FUNCTION__; |
DCHECK(ui_task_runner_->BelongsToCurrentThread()); |
DCHECK(decode_cb_.is_null()); |
if (!HasStream()) { |
ReleaseMediaCodecBridge(); |
- return false; |
+ return STATUS_FAILURE; |
} |
// Create |media_codec_bridge_| only if config changes. |
if (media_codec_bridge_ && !need_to_reconfig_decoder_job_) |
- return true; |
+ return STATUS_SUCCESS; |
base::android::ScopedJavaLocalRef<jobject> media_crypto = GetMediaCrypto(); |
if (is_content_encrypted_ && media_crypto.is_null()) |
- return false; |
+ return STATUS_FAILURE; |
ReleaseMediaCodecBridge(); |
DVLOG(1) << __FUNCTION__ << " : creating new media codec bridge"; |