Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(176)

Unified Diff: media/filters/android/media_codec_audio_decoder.cc

Issue 2016213003: Separate MediaCodecLoop from MediaCodecAudioDecoder (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: cl feedback. Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: media/filters/android/media_codec_audio_decoder.cc
diff --git a/media/filters/android/media_codec_audio_decoder.cc b/media/filters/android/media_codec_audio_decoder.cc
index d8f91dfda4cd091de88a9c0879f0ea012d83568f..914370cdf5884e6bb71039a265ab63363673078d 100644
--- a/media/filters/android/media_codec_audio_decoder.cc
+++ b/media/filters/android/media_codec_audio_decoder.cc
@@ -22,48 +22,10 @@ namespace {
// Android MediaCodec can only output 16bit PCM audio.
const int kBytesPerOutputSample = 2;
-// Valid MediaCodec buffer indexes are zero or positive.
-const int kInvalidBufferIndex = -1;
-
-inline const base::TimeDelta DecodePollDelay() {
- return base::TimeDelta::FromMilliseconds(10);
-}
-
-inline const base::TimeDelta NoWaitTimeout() {
- return base::TimeDelta::FromMicroseconds(0);
-}
-
-inline const base::TimeDelta IdleTimerTimeout() {
- return base::TimeDelta::FromSeconds(1);
-}
-
inline int GetChannelCount(const AudioDecoderConfig& config) {
return ChannelLayoutToChannelCount(config.channel_layout());
}
-std::unique_ptr<MediaCodecBridge> CreateMediaCodec(
- const AudioDecoderConfig& config,
- jobject media_crypto) {
- DVLOG(1) << __FUNCTION__ << ": config:" << config.AsHumanReadableString();
-
- std::unique_ptr<AudioCodecBridge> audio_codec_bridge(
- AudioCodecBridge::Create(config.codec()));
- if (!audio_codec_bridge) {
- DVLOG(0) << __FUNCTION__ << " failed: cannot create AudioCodecBridge";
- return nullptr;
- }
-
- const bool do_play = false; // Do not create AudioTrack object.
-
- if (!audio_codec_bridge->ConfigureAndStart(config, do_play, media_crypto)) {
- DVLOG(0) << __FUNCTION__ << " failed: cannot configure audio codec for "
- << config.AsHumanReadableString();
- return nullptr;
- }
-
- return std::move(audio_codec_bridge);
-}
-
// Converts interleaved data into planar data and writes it to |planes|.
// The planes are populated in the order of channels in the interleaved frame.
// If |channel_count| is less than the number of available planes the extra
@@ -94,7 +56,6 @@ MediaCodecAudioDecoder::MediaCodecAudioDecoder(
: task_runner_(task_runner),
state_(STATE_UNINITIALIZED),
channel_count_(0),
- pending_input_buf_index_(kInvalidBufferIndex),
media_drm_bridge_cdm_context_(nullptr),
cdm_registration_id_(0),
weak_factory_(this) {
@@ -104,7 +65,7 @@ MediaCodecAudioDecoder::MediaCodecAudioDecoder(
MediaCodecAudioDecoder::~MediaCodecAudioDecoder() {
DVLOG(1) << __FUNCTION__;
- media_codec_.reset();
+ codec_loop_.reset();
if (media_drm_bridge_cdm_context_) {
DCHECK(cdm_registration_id_);
@@ -156,8 +117,7 @@ void MediaCodecAudioDecoder::Initialize(const AudioDecoderConfig& config,
return;
}
- media_codec_ = CreateMediaCodec(config_, nullptr);
- if (!media_codec_) {
+ if (!CreateMediaCodecLoop()) {
bound_init_cb.Run(false);
return;
}
@@ -166,6 +126,32 @@ void MediaCodecAudioDecoder::Initialize(const AudioDecoderConfig& config,
bound_init_cb.Run(true);
}
+bool MediaCodecAudioDecoder::CreateMediaCodecLoop() {
+ DVLOG(1) << __FUNCTION__ << ": config:" << config_.AsHumanReadableString();
+
+ codec_loop_.reset();
+
+ std::unique_ptr<AudioCodecBridge> audio_codec_bridge(
+ AudioCodecBridge::Create(config_.codec()));
+ if (!audio_codec_bridge) {
+ DLOG(ERROR) << __FUNCTION__ << " failed: cannot create AudioCodecBridge";
+ return false;
+ }
+
+ jobject media_crypto_obj = media_crypto_ ? media_crypto_->obj() : nullptr;
+
+ if (!audio_codec_bridge->ConfigureAndStart(config_, false /* no AudioTrack */,
+ media_crypto_obj)) {
+ DLOG(ERROR) << __FUNCTION__ << " failed: cannot configure audio codec for "
+ << config_.AsHumanReadableString();
+ return false;
+ }
+
+ codec_loop_.reset(new MediaCodecLoop(this, std::move(audio_codec_bridge)));
+
+ return true;
+}
+
void MediaCodecAudioDecoder::Decode(const scoped_refptr<DecoderBuffer>& buffer,
const DecodeCB& decode_cb) {
DecodeCB bound_decode_cb = BindToCurrentLoop(decode_cb);
@@ -177,6 +163,7 @@ void MediaCodecAudioDecoder::Decode(const scoped_refptr<DecoderBuffer>& buffer,
return;
}
+ // Note that we transition to STATE_ERROR if |codec_loop_| does.
if (state_ == STATE_ERROR) {
// We get here if an error happens in DequeueOutput() or Reset().
DVLOG(2) << __FUNCTION__ << " " << buffer->AsHumanReadableString()
@@ -186,6 +173,8 @@ void MediaCodecAudioDecoder::Decode(const scoped_refptr<DecoderBuffer>& buffer,
return;
}
+ DCHECK(codec_loop_);
+
DVLOG(2) << __FUNCTION__ << " " << buffer->AsHumanReadableString();
DCHECK_EQ(state_, STATE_READY) << " unexpected state " << AsString(state_);
@@ -196,32 +185,22 @@ void MediaCodecAudioDecoder::Decode(const scoped_refptr<DecoderBuffer>& buffer,
input_queue_.push_back(std::make_pair(buffer, bound_decode_cb));
- DoIOTask();
+ codec_loop_->DoIOTask();
}
void MediaCodecAudioDecoder::Reset(const base::Closure& closure) {
DVLOG(1) << __FUNCTION__;
- io_timer_.Stop();
-
ClearInputQueue(DecodeStatus::ABORTED);
// Flush if we can, otherwise completely recreate and reconfigure the codec.
// Prior to JellyBean-MR2, flush() had several bugs (b/8125974, b/8347958) so
// we have to completely destroy and recreate the codec there.
- bool success = false;
- if (state_ != STATE_ERROR && state_ != STATE_DRAINED &&
- base::android::BuildInfo::GetInstance()->sdk_int() >= 18) {
- // media_codec_->Reset() calls MediaCodec.flush().
- success = (media_codec_->Reset() == MEDIA_CODEC_OK);
- }
+ bool success = codec_loop_->TryFlush();
- if (!success) {
- media_codec_.reset();
- jobject media_crypto_obj = media_crypto_ ? media_crypto_->obj() : nullptr;
- media_codec_ = CreateMediaCodec(config_, media_crypto_obj);
- success = !!media_codec_;
- }
+ // If the flush failed, then we have to re-create the codec.
+ if (!success)
+ success = CreateMediaCodecLoop();
// Reset AudioTimestampHelper.
timestamp_helper_->SetBaseTimestamp(kNoTimestamp());
@@ -263,6 +242,15 @@ void MediaCodecAudioDecoder::SetCdm(CdmContext* cdm_context,
weak_factory_.GetWeakPtr(), init_cb)));
}
+void MediaCodecAudioDecoder::OnKeyAdded() {
+ DVLOG(1) << __FUNCTION__;
+
+ // We don't register |codec_loop_| directly with the DRM bridge, since it's
+ // subject to replacement.
+ if (codec_loop_)
+ codec_loop_->OnKeyAdded();
+}
+
void MediaCodecAudioDecoder::OnMediaCryptoReady(
const InitCB& init_cb,
MediaDrmBridgeCdmContext::JavaObjectPtr media_crypto,
@@ -282,12 +270,10 @@ void MediaCodecAudioDecoder::OnMediaCryptoReady(
// We assume this is a part of the initialization process, thus MediaCodec
// is not created yet.
- DCHECK(!media_codec_);
+ DCHECK(!codec_loop_);
// After receiving |media_crypto_| we can configure MediaCodec.
-
- media_codec_ = CreateMediaCodec(config_, media_crypto->obj());
- if (!media_codec_) {
+ if (!CreateMediaCodecLoop()) {
SetState(STATE_UNINITIALIZED);
init_cb.Run(false);
return;
@@ -299,198 +285,40 @@ void MediaCodecAudioDecoder::OnMediaCryptoReady(
init_cb.Run(true);
}
-void MediaCodecAudioDecoder::OnKeyAdded() {
- DVLOG(1) << __FUNCTION__;
-
- if (state_ == STATE_WAITING_FOR_KEY)
- SetState(STATE_READY);
-
- DoIOTask();
-}
-
-void MediaCodecAudioDecoder::DoIOTask() {
- if (state_ == STATE_ERROR)
- return;
-
- const bool did_input = QueueInput();
- const bool did_output = DequeueOutput();
-
- ManageTimer(did_input || did_output);
-}
-
-bool MediaCodecAudioDecoder::QueueInput() {
- DVLOG(2) << __FUNCTION__;
-
- bool did_work = false;
- while (QueueOneInputBuffer())
- did_work = true;
-
- return did_work;
-}
-
-bool MediaCodecAudioDecoder::QueueOneInputBuffer() {
- DVLOG(2) << __FUNCTION__;
-
- if (input_queue_.empty())
- return false;
-
- if (state_ == STATE_WAITING_FOR_KEY || state_ == STATE_DRAINING ||
- state_ == STATE_DRAINED)
+bool MediaCodecAudioDecoder::IsAnyInputPending() const {
+ if (state_ != STATE_READY)
return false;
- // DequeueInputBuffer() may set STATE_ERROR.
- InputBufferInfo input_info = DequeueInputBuffer();
-
- if (input_info.buf_index == kInvalidBufferIndex) {
- if (state_ == STATE_ERROR)
- ClearInputQueue(DecodeStatus::DECODE_ERROR);
-
- return false;
- }
-
- // EnqueueInputBuffer() may set STATE_DRAINING, STATE_WAITING_FOR_KEY or
- // STATE_ERROR.
- bool did_work = EnqueueInputBuffer(input_info);
-
- switch (state_) {
- case STATE_READY: {
- const DecodeCB& decode_cb = input_queue_.front().second;
- decode_cb.Run(DecodeStatus::OK);
- input_queue_.pop_front();
- } break;
-
- case STATE_DRAINING:
- // After queueing EOS we need to flush decoder, i.e. receive this EOS at
- // the output, and then call corresponding decoder_cb.
- // Keep the EOS buffer in the input queue.
- break;
-
- case STATE_WAITING_FOR_KEY:
- // Keep trying to enqueue the same input buffer.
- // The buffer is owned by us (not the MediaCodec) and is filled with data.
- break;
-
- case STATE_ERROR:
- ClearInputQueue(DecodeStatus::DECODE_ERROR);
- break;
-
- default:
- NOTREACHED() << ": internal error, unexpected state " << AsString(state_);
- SetState(STATE_ERROR);
- ClearInputQueue(DecodeStatus::DECODE_ERROR);
- did_work = false;
- break;
- }
-
- return did_work;
+ return !input_queue_.empty();
}
-MediaCodecAudioDecoder::InputBufferInfo
-MediaCodecAudioDecoder::DequeueInputBuffer() {
+MediaCodecLoop::InputData MediaCodecAudioDecoder::ProvideInputData() {
DVLOG(2) << __FUNCTION__;
- // Do not dequeue a new input buffer if we failed with MEDIA_CODEC_NO_KEY.
- // That status does not return the input buffer back to the pool of
- // available input buffers. We have to reuse it in QueueSecureInputBuffer().
- if (pending_input_buf_index_ != kInvalidBufferIndex) {
- InputBufferInfo result(pending_input_buf_index_, true);
- pending_input_buf_index_ = kInvalidBufferIndex;
- return result;
- }
-
- int input_buf_index = kInvalidBufferIndex;
-
- media::MediaCodecStatus status =
- media_codec_->DequeueInputBuffer(NoWaitTimeout(), &input_buf_index);
- switch (status) {
- case media::MEDIA_CODEC_DEQUEUE_INPUT_AGAIN_LATER:
- DVLOG(2) << __FUNCTION__ << ": MEDIA_CODEC_DEQUEUE_INPUT_AGAIN_LATER";
- break;
-
- case media::MEDIA_CODEC_ERROR:
- DVLOG(1) << __FUNCTION__ << ": MEDIA_CODEC_ERROR from DequeInputBuffer";
- SetState(STATE_ERROR);
- break;
-
- case media::MEDIA_CODEC_OK:
- break;
-
- default:
- NOTREACHED() << "Unknown DequeueInputBuffer status " << status;
- SetState(STATE_ERROR);
- break;
- }
-
- return InputBufferInfo(input_buf_index, false);
-}
-
-bool MediaCodecAudioDecoder::EnqueueInputBuffer(
- const InputBufferInfo& input_info) {
- DVLOG(2) << __FUNCTION__ << ": index:" << input_info.buf_index;
-
- DCHECK_NE(input_info.buf_index, kInvalidBufferIndex);
-
scoped_refptr<DecoderBuffer> decoder_buffer = input_queue_.front().first;
+ MediaCodecLoop::InputData input_data;
if (decoder_buffer->end_of_stream()) {
- media_codec_->QueueEOS(input_info.buf_index);
-
- SetState(STATE_DRAINING);
- return true;
- }
-
- media::MediaCodecStatus status = MEDIA_CODEC_OK;
-
- const DecryptConfig* decrypt_config = decoder_buffer->decrypt_config();
- if (decrypt_config && decrypt_config->is_encrypted()) {
- // A pending buffer is already filled with data, no need to copy it again.
- const uint8_t* memory =
- input_info.is_pending ? nullptr : decoder_buffer->data();
-
- DVLOG(2) << __FUNCTION__ << ": QueueSecureInputBuffer:"
- << " index:" << input_info.buf_index
- << " pts:" << decoder_buffer->timestamp()
- << " size:" << decoder_buffer->data_size();
-
- status = media_codec_->QueueSecureInputBuffer(
- input_info.buf_index, memory, decoder_buffer->data_size(),
- decrypt_config->key_id(), decrypt_config->iv(),
- decrypt_config->subsamples(), decoder_buffer->timestamp());
-
+ input_data.is_eos = true;
+ // Note that for EOS, the completion callback will be delayed until the
+ // EOS actually arrives on the output queue.
} else {
- DVLOG(2) << __FUNCTION__ << ": QueueInputBuffer:"
- << " index:" << input_info.buf_index
- << " pts:" << decoder_buffer->timestamp()
- << " size:" << decoder_buffer->data_size();
-
- status = media_codec_->QueueInputBuffer(
- input_info.buf_index, decoder_buffer->data(),
- decoder_buffer->data_size(), decoder_buffer->timestamp());
+ input_data.memory = static_cast<const uint8_t*>(decoder_buffer->data());
+ input_data.length = decoder_buffer->data_size();
+ const DecryptConfig* decrypt_config = decoder_buffer->decrypt_config();
+ if (decrypt_config && decrypt_config->is_encrypted()) {
+ input_data.is_encrypted = true;
+ input_data.key_id = decrypt_config->key_id();
+ input_data.iv = decrypt_config->iv();
+ input_data.subsamples = decrypt_config->subsamples();
+ }
+ input_data.presentation_time = decoder_buffer->timestamp();
}
- bool did_work = false;
- switch (status) {
- case MEDIA_CODEC_ERROR:
- DVLOG(0) << __FUNCTION__ << ": MEDIA_CODEC_ERROR from QueueInputBuffer";
- SetState(STATE_ERROR);
- break;
-
- case MEDIA_CODEC_NO_KEY:
- DVLOG(1) << "QueueSecureInputBuffer failed: MEDIA_CODEC_NO_KEY";
- pending_input_buf_index_ = input_info.buf_index;
- SetState(STATE_WAITING_FOR_KEY);
- break;
-
- case MEDIA_CODEC_OK:
- did_work = true;
- break;
-
- default:
- NOTREACHED() << "Unknown Queue(Secure)InputBuffer status " << status;
- SetState(STATE_ERROR);
- break;
- }
- return did_work;
+ input_data.completion_cb = input_queue_.front().second;
+ input_queue_.pop_front();
+
+ return input_data;
}
void MediaCodecAudioDecoder::ClearInputQueue(DecodeStatus decode_status) {
@@ -502,123 +330,32 @@ void MediaCodecAudioDecoder::ClearInputQueue(DecodeStatus decode_status) {
input_queue_.clear();
}
-bool MediaCodecAudioDecoder::DequeueOutput() {
- DVLOG(2) << __FUNCTION__;
-
- MediaCodecStatus status;
- OutputBufferInfo out;
- bool did_work = false;
- do {
- status = media_codec_->DequeueOutputBuffer(NoWaitTimeout(), &out.buf_index,
- &out.offset, &out.size, &out.pts,
- &out.is_eos, &out.is_key_frame);
-
- switch (status) {
- case MEDIA_CODEC_OUTPUT_BUFFERS_CHANGED:
- // Output buffers are replaced in MediaCodecBridge, nothing to do.
- DVLOG(2) << __FUNCTION__ << " MEDIA_CODEC_OUTPUT_BUFFERS_CHANGED";
- did_work = true;
- break;
-
- case MEDIA_CODEC_OUTPUT_FORMAT_CHANGED:
- DVLOG(2) << __FUNCTION__ << " MEDIA_CODEC_OUTPUT_FORMAT_CHANGED";
- OnOutputFormatChanged();
- did_work = true;
- break;
-
- case MEDIA_CODEC_OK:
- // We got the decoded frame.
- if (out.is_eos)
- OnDecodedEos(out);
- else
- OnDecodedFrame(out);
-
- did_work = true;
- break;
-
- case MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER:
- // Nothing to do.
- DVLOG(2) << __FUNCTION__ << " MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER";
- break;
-
- case MEDIA_CODEC_ERROR:
- DVLOG(0) << __FUNCTION__
- << ": MEDIA_CODEC_ERROR from DequeueOutputBuffer";
-
- // Next Decode() will report the error to the pipeline.
- SetState(STATE_ERROR);
- break;
-
- default:
- NOTREACHED() << "Unknown DequeueOutputBuffer status " << status;
- // Next Decode() will report the error to the pipeline.
- SetState(STATE_ERROR);
- break;
- }
- } while (status != MEDIA_CODEC_DEQUEUE_OUTPUT_AGAIN_LATER &&
- status != MEDIA_CODEC_ERROR && !out.is_eos);
-
- return did_work;
-}
-
-void MediaCodecAudioDecoder::ManageTimer(bool did_work) {
- bool should_be_running = true;
-
- base::TimeTicks now = base::TimeTicks::Now();
- if (did_work || idle_time_begin_ == base::TimeTicks()) {
- idle_time_begin_ = now;
- } else {
- // Make sure that we have done work recently enough, else stop the timer.
- if (now - idle_time_begin_ > IdleTimerTimeout())
- should_be_running = false;
- }
-
- if (should_be_running && !io_timer_.IsRunning()) {
- io_timer_.Start(FROM_HERE, DecodePollDelay(), this,
- &MediaCodecAudioDecoder::DoIOTask);
- } else if (!should_be_running && io_timer_.IsRunning()) {
- io_timer_.Stop();
- }
-}
-
void MediaCodecAudioDecoder::SetState(State new_state) {
DVLOG(1) << __FUNCTION__ << ": " << AsString(state_) << "->"
<< AsString(new_state);
state_ = new_state;
}
-void MediaCodecAudioDecoder::OnDecodedEos(const OutputBufferInfo& out) {
- DVLOG(2) << __FUNCTION__ << " pts:" << out.pts;
-
- DCHECK_NE(out.buf_index, kInvalidBufferIndex);
- DCHECK(media_codec_);
-
- DCHECK_EQ(state_, STATE_DRAINING);
-
- media_codec_->ReleaseOutputBuffer(out.buf_index, false);
-
- // Report the end of decoding for EOS DecoderBuffer.
- DCHECK(!input_queue_.empty());
- DCHECK(input_queue_.front().first->end_of_stream());
-
- const DecodeCB& decode_cb = input_queue_.front().second;
- decode_cb.Run(DecodeStatus::OK);
-
- // Remove the EOS buffer from the input queue.
- input_queue_.pop_front();
+void MediaCodecAudioDecoder::OnCodecLoopError() {
+ // If the codec transitions into the error state, then so should we.
+ SetState(STATE_ERROR);
+ ClearInputQueue(DecodeStatus::DECODE_ERROR);
+}
- // Set state STATE_DRAINED after we have received EOS frame at the output.
- // media_decoder_job.cc says: once output EOS has occurred, we should
- // not be asked to decode again.
- SetState(STATE_DRAINED);
+void MediaCodecAudioDecoder::OnDecodedEos(
+ const MediaCodecLoop::OutputBuffer& out) {
+ DVLOG(2) << __FUNCTION__ << " pts:" << out.pts;
}
-void MediaCodecAudioDecoder::OnDecodedFrame(const OutputBufferInfo& out) {
+bool MediaCodecAudioDecoder::OnDecodedFrame(
+ const MediaCodecLoop::OutputBuffer& out) {
DVLOG(2) << __FUNCTION__ << " pts:" << out.pts;
DCHECK_NE(out.size, 0U);
- DCHECK_NE(out.buf_index, kInvalidBufferIndex);
- DCHECK(media_codec_);
+ DCHECK_NE(out.index, MediaCodecLoop::kInvalidBufferIndex);
+ DCHECK(codec_loop_);
+ MediaCodecBridge* media_codec = codec_loop_->GetCodec();
+ DCHECK(media_codec);
// For proper |frame_count| calculation we need to use the actual number
// of channels which can be different from |config_| value.
@@ -639,24 +376,26 @@ void MediaCodecAudioDecoder::OnDecodedFrame(const OutputBufferInfo& out) {
// Copy data into AudioBuffer.
CHECK_LE(out.size, audio_buffer->data_size());
- MediaCodecStatus status = media_codec_->CopyFromOutputBuffer(
- out.buf_index, out.offset, audio_buffer->channel_data()[0], out.size);
+ MediaCodecStatus status = media_codec->CopyFromOutputBuffer(
+ out.index, out.offset, audio_buffer->channel_data()[0], out.size);
- // TODO(timav,watk): This CHECK maintains the behavior of this call before
- // we started catching CodecException and returning it as MEDIA_CODEC_ERROR.
- // It needs to be handled some other way. http://crbug.com/585978
- CHECK_EQ(status, MEDIA_CODEC_OK);
+ if (status != MEDIA_CODEC_OK) {
+ media_codec->ReleaseOutputBuffer(out.index, false);
+ return false;
+ }
} else {
// Separate the planes while copying MediaCodec buffer into AudioBuffer.
DCHECK_LT(channel_count_, config_channel_count);
const uint8_t* interleaved_data = nullptr;
size_t interleaved_capacity = 0;
- MediaCodecStatus status = media_codec_->GetOutputBufferAddress(
- out.buf_index, out.offset, &interleaved_data, &interleaved_capacity);
+ MediaCodecStatus status = media_codec->GetOutputBufferAddress(
+ out.index, out.offset, &interleaved_data, &interleaved_capacity);
- // TODO(timav): Handle wrong status properly, http://crbug.com/585978.
- CHECK_EQ(status, MEDIA_CODEC_OK);
+ if (status != MEDIA_CODEC_OK) {
+ media_codec->ReleaseOutputBuffer(out.index, false);
+ return false;
+ }
DCHECK_LE(out.size, interleaved_capacity);
@@ -666,7 +405,7 @@ void MediaCodecAudioDecoder::OnDecodedFrame(const OutputBufferInfo& out) {
}
// Release MediaCodec output buffer.
- media_codec_->ReleaseOutputBuffer(out.buf_index, false);
+ media_codec->ReleaseOutputBuffer(out.index, false);
// Calculate and set buffer timestamp.
@@ -682,18 +421,23 @@ void MediaCodecAudioDecoder::OnDecodedFrame(const OutputBufferInfo& out) {
// Call the |output_cb_|.
output_cb_.Run(audio_buffer);
+
+ return true;
}
-void MediaCodecAudioDecoder::OnOutputFormatChanged() {
+bool MediaCodecAudioDecoder::OnOutputFormatChanged() {
DVLOG(2) << __FUNCTION__;
+ MediaCodecBridge* media_codec = codec_loop_->GetCodec();
+
+ // Note that if we return false to transition |codec_loop_| to the error
+ // state, then we'll also transition to the error state when it notifies us.
int new_sampling_rate = 0;
MediaCodecStatus status =
- media_codec_->GetOutputSamplingRate(&new_sampling_rate);
+ media_codec->GetOutputSamplingRate(&new_sampling_rate);
if (status != MEDIA_CODEC_OK) {
DLOG(ERROR) << "GetOutputSamplingRate failed.";
- SetState(STATE_ERROR);
- return;
+ return false;
}
if (new_sampling_rate != config_.samples_per_second()) {
// We do not support the change of sampling rate on the fly
@@ -701,15 +445,13 @@ void MediaCodecAudioDecoder::OnOutputFormatChanged() {
<< GetDisplayName() << " (detected change "
<< config_.samples_per_second() << "->" << new_sampling_rate
<< ")";
- SetState(STATE_ERROR);
- return;
+ return false;
}
- status = media_codec_->GetOutputChannelCount(&channel_count_);
+ status = media_codec->GetOutputChannelCount(&channel_count_);
if (status != MEDIA_CODEC_OK) {
DLOG(ERROR) << "GetOutputChannelCount failed.";
- SetState(STATE_ERROR);
- return;
+ return false;
}
const int config_channel_count = GetChannelCount(config_);
@@ -719,9 +461,10 @@ void MediaCodecAudioDecoder::OnOutputFormatChanged() {
if (channel_count_ > config_channel_count) {
DLOG(ERROR) << "Actual channel count " << channel_count_
<< " is greater than configured " << config_channel_count;
- SetState(STATE_ERROR);
- return;
+ return false;
}
+
+ return true;
}
#undef RETURN_STRING
@@ -735,9 +478,6 @@ const char* MediaCodecAudioDecoder::AsString(State state) {
RETURN_STRING(STATE_UNINITIALIZED);
RETURN_STRING(STATE_WAITING_FOR_MEDIA_CRYPTO);
RETURN_STRING(STATE_READY);
- RETURN_STRING(STATE_WAITING_FOR_KEY);
- RETURN_STRING(STATE_DRAINING);
- RETURN_STRING(STATE_DRAINED);
RETURN_STRING(STATE_ERROR);
}
NOTREACHED() << "Unknown state " << state;

Powered by Google App Engine
This is Rietveld 408576698