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 3230e2360900bcf23a361cf2fe61fcf4fac684a3..33b48302b0ec8f7dc447318efe424f9bf5a7a157 100644 |
--- a/media/base/android/media_decoder_job.cc |
+++ b/media/base/android/media_decoder_job.cc |
@@ -29,6 +29,7 @@ MediaDecoderJob::MediaDecoderJob( |
weak_this_(this), |
request_data_cb_(request_data_cb), |
access_unit_index_(0), |
+ input_buf_index_(-1), |
stop_decode_pending_(false), |
destroy_pending_(false) { |
} |
@@ -36,6 +37,7 @@ MediaDecoderJob::MediaDecoderJob( |
MediaDecoderJob::~MediaDecoderJob() {} |
void MediaDecoderJob::OnDataReceived(const DemuxerData& data) { |
+ DVLOG(1) << __FUNCTION__ << ": " << data.access_units.size() << " units"; |
DCHECK(ui_loop_->BelongsToCurrentThread()); |
DCHECK(!on_data_received_cb_.is_null()); |
@@ -132,44 +134,59 @@ void MediaDecoderJob::Release() { |
delete this; |
} |
-MediaCodecStatus MediaDecoderJob::QueueInputBuffer( |
- const AccessUnit& unit) { |
- base::TimeDelta timeout = base::TimeDelta::FromMilliseconds( |
- kMediaCodecTimeoutInMilliseconds); |
- int input_buf_index = 0; |
- MediaCodecStatus status = |
- media_codec_bridge_->DequeueInputBuffer(timeout, &input_buf_index); |
- if (status != MEDIA_CODEC_OK) |
- return status; |
+MediaCodecStatus MediaDecoderJob::QueueInputBuffer(const AccessUnit& unit) { |
+ DVLOG(1) << __FUNCTION__; |
+ DCHECK(decoder_loop_->BelongsToCurrentThread()); |
+ |
+ int input_buf_index = input_buf_index_; |
+ input_buf_index_ = -1; |
+ |
+ // TODO(xhwang): Hide DequeueInputBuffer() and the index in MediaCodecBridge. |
+ if (input_buf_index == -1) { |
+ base::TimeDelta timeout = base::TimeDelta::FromMilliseconds( |
+ kMediaCodecTimeoutInMilliseconds); |
+ MediaCodecStatus status = |
+ media_codec_bridge_->DequeueInputBuffer(timeout, &input_buf_index); |
+ if (status != MEDIA_CODEC_OK) { |
+ DVLOG(1) << "DequeueInputBuffer fails: " << status; |
+ return status; |
+ } |
+ } |
// TODO(qinmin): skip frames if video is falling far behind. |
DCHECK_GE(input_buf_index, 0); |
if (unit.end_of_stream || unit.data.empty()) { |
- media_codec_bridge_->QueueEOS(input_buf_index); |
+ media_codec_bridge_->QueueEOS(input_buf_index_); |
return MEDIA_CODEC_INPUT_END_OF_STREAM; |
} |
if (unit.key_id.empty()) { |
- media_codec_bridge_->QueueInputBuffer( |
+ return media_codec_bridge_->QueueInputBuffer( |
input_buf_index, &unit.data[0], unit.data.size(), unit.timestamp); |
- return MEDIA_CODEC_OK; |
} |
if (unit.iv.empty() || unit.subsamples.empty()) { |
- LOG(ERROR) << "The access unit doesn't have iv or subsamples while it " |
+ DVLOG(1) << "The access unit doesn't have iv or subsamples while it " |
<< "has key IDs!"; |
return MEDIA_CODEC_ERROR; |
} |
- media_codec_bridge_->QueueSecureInputBuffer( |
+ MediaCodecStatus status = media_codec_bridge_->QueueSecureInputBuffer( |
input_buf_index, &unit.data[0], unit.data.size(), |
reinterpret_cast<const uint8*>(&unit.key_id[0]), unit.key_id.size(), |
reinterpret_cast<const uint8*>(&unit.iv[0]), unit.iv.size(), |
&unit.subsamples[0], unit.subsamples.size(), unit.timestamp); |
- return MEDIA_CODEC_OK; |
+ |
+ // In case of MEDIA_CODEC_NO_KEY, we must reuse the |input_buf_index_|. |
+ // Otherwise MediaDrm will report errors. |
+ if (status == MEDIA_CODEC_NO_KEY) |
+ input_buf_index_ = input_buf_index; |
+ |
+ return status; |
} |
void MediaDecoderJob::RequestData(const base::Closure& done_cb) { |
+ DVLOG(1) << __FUNCTION__; |
DCHECK(ui_loop_->BelongsToCurrentThread()); |
DCHECK(on_data_received_cb_.is_null()); |
@@ -201,6 +218,9 @@ void MediaDecoderJob::DecodeInternal( |
const base::TimeDelta& start_presentation_timestamp, |
bool needs_flush, |
const MediaDecoderJob::DecoderCallback& callback) { |
+ DVLOG(1) << __FUNCTION__; |
+ DCHECK(decoder_loop_->BelongsToCurrentThread()); |
+ |
if (needs_flush) { |
DVLOG(1) << "DecodeInternal needs flush."; |
input_eos_encountered_ = false; |
@@ -259,7 +279,7 @@ void MediaDecoderJob::DecodeInternal( |
// TODO(acolwell): Change to > since the else will never run for audio. |
if (time_to_render >= base::TimeDelta()) { |
- base::MessageLoop::current()->PostDelayedTask( |
+ decoder_loop_->PostDelayedTask( |
FROM_HERE, |
base::Bind(&MediaDecoderJob::ReleaseOutputBuffer, |
weak_this_.GetWeakPtr(), buffer_index, size, |
@@ -289,8 +309,9 @@ void MediaDecoderJob::OnDecodeCompleted( |
DCHECK(!decode_cb_.is_null()); |
if (status != MEDIA_CODEC_ERROR && |
- status != MEDIA_CODEC_ENQUEUE_INPUT_AGAIN_LATER && |
+ status != MEDIA_CODEC_DEQUEUE_INPUT_AGAIN_LATER && |
status != MEDIA_CODEC_INPUT_END_OF_STREAM && |
+ status != MEDIA_CODEC_NO_KEY && |
status != MEDIA_CODEC_STOPPED) { |
access_unit_index_++; |
} |