Chromium Code Reviews| Index: media/filters/decrypting_audio_decoder.cc |
| diff --git a/media/filters/decrypting_audio_decoder.cc b/media/filters/decrypting_audio_decoder.cc |
| index a96c9dba0c5f92c89184a231d512ce93be5657e3..f0fbc85ba3d846138a7da890313edd06440baa1e 100644 |
| --- a/media/filters/decrypting_audio_decoder.cc |
| +++ b/media/filters/decrypting_audio_decoder.cc |
| @@ -40,7 +40,6 @@ DecryptingAudioDecoder::DecryptingAudioDecoder( |
| : task_runner_(task_runner), |
| weak_factory_(this), |
| state_(kUninitialized), |
| - demuxer_stream_(NULL), |
| set_decryptor_ready_cb_(set_decryptor_ready_cb), |
| decryptor_(NULL), |
| key_added_while_decode_pending_(false), |
| @@ -49,19 +48,16 @@ DecryptingAudioDecoder::DecryptingAudioDecoder( |
| samples_per_second_(0) { |
| } |
| -void DecryptingAudioDecoder::Initialize( |
| - DemuxerStream* stream, |
| - const PipelineStatusCB& status_cb, |
| - const StatisticsCB& statistics_cb) { |
| +void DecryptingAudioDecoder::Initialize(const AudioDecoderConfig& config, |
| + const PipelineStatusCB& status_cb) { |
| DVLOG(2) << "Initialize()"; |
| DCHECK(task_runner_->BelongsToCurrentThread()); |
| - DCHECK_EQ(state_, kUninitialized) << state_; |
| - DCHECK(stream); |
| + DCHECK(decode_cb_.is_null()); |
| + DCHECK(reset_cb_.is_null()); |
| weak_this_ = weak_factory_.GetWeakPtr(); |
| init_cb_ = BindToCurrentLoop(status_cb); |
| - const AudioDecoderConfig& config = stream->audio_decoder_config(); |
| if (!config.IsValidConfig()) { |
| DLOG(ERROR) << "Invalid audio stream config."; |
| base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_DECODE); |
| @@ -74,47 +70,74 @@ void DecryptingAudioDecoder::Initialize( |
| return; |
| } |
| - DCHECK(!demuxer_stream_); |
| - demuxer_stream_ = stream; |
| - statistics_cb_ = statistics_cb; |
| + config_ = config; |
| - state_ = kDecryptorRequested; |
| - set_decryptor_ready_cb_.Run(BindToCurrentLoop( |
| - base::Bind(&DecryptingAudioDecoder::SetDecryptor, weak_this_))); |
| + if (state_ == kUninitialized) { |
| + state_ = kDecryptorRequested; |
| + set_decryptor_ready_cb_.Run(BindToCurrentLoop( |
| + base::Bind(&DecryptingAudioDecoder::SetDecryptor, weak_this_))); |
| + return; |
| + } |
| + |
| + // Reinitialization (i.e. upon a config change) |
| + decryptor_->DeinitializeDecoder(Decryptor::kAudio); |
| + state_ = kPendingConfigChange; |
|
xhwang
2014/03/05 00:40:46
In DVD, we use kPendingDecoderInit for this status
rileya (GONE FROM CHROMIUM)
2014/03/05 08:08:28
Not that I can see. Removed kPendingConfigChange e
|
| + decryptor_->InitializeAudioDecoder( |
| + config, |
| + BindToCurrentLoop(base::Bind( |
| + &DecryptingAudioDecoder::FinishInitialization, weak_this_))); |
| } |
| -void DecryptingAudioDecoder::Read(const ReadCB& read_cb) { |
| - DVLOG(3) << "Read()"; |
| +void DecryptingAudioDecoder::Decode(const scoped_refptr<DecoderBuffer>& buffer, |
| + const DecodeCB& decode_cb) { |
| + DVLOG(3) << "Decode()"; |
| DCHECK(task_runner_->BelongsToCurrentThread()); |
| DCHECK(state_ == kIdle || state_ == kDecodeFinished) << state_; |
| - DCHECK(!read_cb.is_null()); |
| - CHECK(read_cb_.is_null()) << "Overlapping decodes are not supported."; |
| + DCHECK(!decode_cb.is_null()); |
| + CHECK(decode_cb_.is_null()) << "Overlapping decodes are not supported."; |
| - read_cb_ = BindToCurrentLoop(read_cb); |
| + decode_cb_ = BindToCurrentLoop(decode_cb); |
| // Return empty (end-of-stream) frames if decoding has finished. |
| if (state_ == kDecodeFinished) { |
| - base::ResetAndReturn(&read_cb_).Run(kOk, AudioBuffer::CreateEOSBuffer()); |
| + base::ResetAndReturn(&decode_cb_).Run(kOk, AudioBuffer::CreateEOSBuffer()); |
| return; |
| } |
| if (!queued_audio_frames_.empty()) { |
| - base::ResetAndReturn(&read_cb_).Run(kOk, queued_audio_frames_.front()); |
| + DCHECK(!buffer); |
| + base::ResetAndReturn(&decode_cb_).Run(kOk, queued_audio_frames_.front()); |
| queued_audio_frames_.pop_front(); |
| return; |
| } |
| - state_ = kPendingDemuxerRead; |
| - ReadFromDemuxerStream(); |
| + // Initialize the |next_output_timestamp_| to be the timestamp of the first |
| + // non-EOS buffer. |
| + if (timestamp_helper_->base_timestamp() == kNoTimestamp() && |
| + !buffer->end_of_stream()) { |
| + timestamp_helper_->SetBaseTimestamp(buffer->timestamp()); |
| + } |
| + |
| + pending_buffer_to_decode_ = buffer; |
| + state_ = kPendingDecode; |
| + DecodePendingBuffer(); |
| +} |
| + |
| +scoped_refptr<AudioBuffer> DecryptingAudioDecoder::GetDecodeOutput() { |
| + if (queued_audio_frames_.empty()) { |
| + return NULL; |
| + } |
|
xhwang
2014/03/05 00:40:46
nit: no need for {}
rileya (GONE FROM CHROMIUM)
2014/03/05 08:08:28
Removed.
|
| + scoped_refptr<AudioBuffer> out = queued_audio_frames_.front(); |
| + queued_audio_frames_.pop_front(); |
| + return out; |
| } |
| void DecryptingAudioDecoder::Reset(const base::Closure& closure) { |
| DVLOG(2) << "Reset() - state: " << state_; |
| DCHECK(task_runner_->BelongsToCurrentThread()); |
| DCHECK(state_ == kIdle || |
| - state_ == kPendingConfigChange || |
| - state_ == kPendingDemuxerRead || |
| state_ == kPendingDecode || |
| + state_ == kPendingConfigChange || |
| state_ == kWaitingForKey || |
| state_ == kDecodeFinished) << state_; |
| DCHECK(init_cb_.is_null()); // No Reset() during pending initialization. |
| @@ -128,20 +151,18 @@ void DecryptingAudioDecoder::Reset(const base::Closure& closure) { |
| // Defer the resetting process in this case. The |reset_cb_| will be fired |
| // after the read callback is fired - see DecryptAndDecodeBuffer() and |
| // DeliverFrame(). |
| - if (state_ == kPendingConfigChange || |
| - state_ == kPendingDemuxerRead || |
| - state_ == kPendingDecode) { |
| - DCHECK(!read_cb_.is_null()); |
| + if (state_ == kPendingDecode) { |
| + DCHECK(!decode_cb_.is_null()); |
| return; |
| } |
| if (state_ == kWaitingForKey) { |
| - DCHECK(!read_cb_.is_null()); |
| + DCHECK(!decode_cb_.is_null()); |
| pending_buffer_to_decode_ = NULL; |
| - base::ResetAndReturn(&read_cb_).Run(kAborted, NULL); |
| + base::ResetAndReturn(&decode_cb_).Run(kAborted, NULL); |
| } |
| - DCHECK(read_cb_.is_null()); |
| + DCHECK(decode_cb_.is_null()); |
| DoReset(); |
| } |
| @@ -162,8 +183,8 @@ void DecryptingAudioDecoder::Stop(const base::Closure& closure) { |
| pending_buffer_to_decode_ = NULL; |
| if (!init_cb_.is_null()) |
| base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED); |
| - if (!read_cb_.is_null()) |
| - base::ResetAndReturn(&read_cb_).Run(kAborted, NULL); |
| + if (!decode_cb_.is_null()) |
| + base::ResetAndReturn(&decode_cb_).Run(kAborted, NULL); |
| if (!reset_cb_.is_null()) |
| base::ResetAndReturn(&reset_cb_).Run(); |
| @@ -208,23 +229,20 @@ void DecryptingAudioDecoder::SetDecryptor(Decryptor* decryptor) { |
| decryptor_ = decryptor; |
| - const AudioDecoderConfig& input_config = |
| - demuxer_stream_->audio_decoder_config(); |
| - AudioDecoderConfig config; |
| - config.Initialize(input_config.codec(), |
| - kSampleFormatS16, |
| - input_config.channel_layout(), |
| - input_config.samples_per_second(), |
| - input_config.extra_data(), |
| - input_config.extra_data_size(), |
| - input_config.is_encrypted(), |
| - false, |
| - base::TimeDelta(), |
| - base::TimeDelta()); |
| + config_.Initialize(config_.codec(), |
| + kSampleFormatS16, |
| + config_.channel_layout(), |
| + config_.samples_per_second(), |
| + config_.extra_data(), |
| + config_.extra_data_size(), |
| + config_.is_encrypted(), |
| + false, |
| + base::TimeDelta(), |
| + base::TimeDelta()); |
| state_ = kPendingDecoderInit; |
| decryptor_->InitializeAudioDecoder( |
| - config, |
| + config_, |
| BindToCurrentLoop(base::Bind( |
| &DecryptingAudioDecoder::FinishInitialization, weak_this_))); |
| } |
| @@ -232,10 +250,11 @@ void DecryptingAudioDecoder::SetDecryptor(Decryptor* decryptor) { |
| void DecryptingAudioDecoder::FinishInitialization(bool success) { |
| DVLOG(2) << "FinishInitialization()"; |
| DCHECK(task_runner_->BelongsToCurrentThread()); |
| - DCHECK_EQ(state_, kPendingDecoderInit) << state_; |
| + DCHECK(state_ == kPendingDecoderInit || state_ == kPendingConfigChange) |
| + << state_; |
| DCHECK(!init_cb_.is_null()); |
| DCHECK(reset_cb_.is_null()); // No Reset() before initialization finished. |
| - DCHECK(read_cb_.is_null()); // No Read() before initialization finished. |
| + DCHECK(decode_cb_.is_null()); // No Decode() before initialization finished. |
| if (!success) { |
| base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED); |
| @@ -255,102 +274,6 @@ void DecryptingAudioDecoder::FinishInitialization(bool success) { |
| base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK); |
| } |
| -void DecryptingAudioDecoder::FinishConfigChange(bool success) { |
| - DVLOG(2) << "FinishConfigChange()"; |
| - DCHECK(task_runner_->BelongsToCurrentThread()); |
| - DCHECK_EQ(state_, kPendingConfigChange) << state_; |
| - DCHECK(!read_cb_.is_null()); |
| - |
| - if (!success) { |
| - base::ResetAndReturn(&read_cb_).Run(kDecodeError, NULL); |
| - state_ = kDecodeFinished; |
| - if (!reset_cb_.is_null()) |
| - base::ResetAndReturn(&reset_cb_).Run(); |
| - return; |
| - } |
| - |
| - // Config change succeeded. |
| - UpdateDecoderConfig(); |
| - |
| - if (!reset_cb_.is_null()) { |
| - base::ResetAndReturn(&read_cb_).Run(kAborted, NULL); |
| - DoReset(); |
| - return; |
| - } |
| - |
| - state_ = kPendingDemuxerRead; |
| - ReadFromDemuxerStream(); |
| -} |
| - |
| -void DecryptingAudioDecoder::ReadFromDemuxerStream() { |
| - DCHECK_EQ(state_, kPendingDemuxerRead) << state_; |
| - DCHECK(!read_cb_.is_null()); |
| - |
| - demuxer_stream_->Read( |
| - base::Bind(&DecryptingAudioDecoder::DecryptAndDecodeBuffer, weak_this_)); |
| -} |
| - |
| -void DecryptingAudioDecoder::DecryptAndDecodeBuffer( |
| - DemuxerStream::Status status, |
| - const scoped_refptr<DecoderBuffer>& buffer) { |
| - DVLOG(3) << "DecryptAndDecodeBuffer()"; |
| - DCHECK(task_runner_->BelongsToCurrentThread()); |
| - DCHECK_EQ(state_, kPendingDemuxerRead) << state_; |
| - DCHECK(!read_cb_.is_null()); |
| - DCHECK_EQ(buffer.get() != NULL, status == DemuxerStream::kOk) << status; |
| - |
| - if (status == DemuxerStream::kConfigChanged) { |
| - DVLOG(2) << "DecryptAndDecodeBuffer() - kConfigChanged"; |
| - |
| - const AudioDecoderConfig& input_config = |
| - demuxer_stream_->audio_decoder_config(); |
| - AudioDecoderConfig config; |
| - config.Initialize(input_config.codec(), |
| - kSampleFormatS16, |
| - input_config.channel_layout(), |
| - input_config.samples_per_second(), |
| - input_config.extra_data(), |
| - input_config.extra_data_size(), |
| - input_config.is_encrypted(), |
| - false, |
| - base::TimeDelta(), |
| - base::TimeDelta()); |
| - |
| - state_ = kPendingConfigChange; |
| - decryptor_->DeinitializeDecoder(Decryptor::kAudio); |
| - decryptor_->InitializeAudioDecoder( |
| - config, BindToCurrentLoop(base::Bind( |
| - &DecryptingAudioDecoder::FinishConfigChange, weak_this_))); |
| - return; |
| - } |
| - |
| - if (!reset_cb_.is_null()) { |
| - base::ResetAndReturn(&read_cb_).Run(kAborted, NULL); |
| - DoReset(); |
| - return; |
| - } |
| - |
| - if (status == DemuxerStream::kAborted) { |
| - DVLOG(2) << "DecryptAndDecodeBuffer() - kAborted"; |
| - state_ = kIdle; |
| - base::ResetAndReturn(&read_cb_).Run(kAborted, NULL); |
| - return; |
| - } |
| - |
| - DCHECK_EQ(status, DemuxerStream::kOk); |
| - |
| - // Initialize the |next_output_timestamp_| to be the timestamp of the first |
| - // non-EOS buffer. |
| - if (timestamp_helper_->base_timestamp() == kNoTimestamp() && |
| - !buffer->end_of_stream()) { |
| - timestamp_helper_->SetBaseTimestamp(buffer->timestamp()); |
| - } |
| - |
| - pending_buffer_to_decode_ = buffer; |
| - state_ = kPendingDecode; |
| - DecodePendingBuffer(); |
| -} |
| - |
| void DecryptingAudioDecoder::DecodePendingBuffer() { |
| DCHECK(task_runner_->BelongsToCurrentThread()); |
| DCHECK_EQ(state_, kPendingDecode) << state_; |
| @@ -373,7 +296,7 @@ void DecryptingAudioDecoder::DeliverFrame( |
| DVLOG(3) << "DeliverFrame() - status: " << status; |
| DCHECK(task_runner_->BelongsToCurrentThread()); |
| DCHECK_EQ(state_, kPendingDecode) << state_; |
| - DCHECK(!read_cb_.is_null()); |
| + DCHECK(!decode_cb_.is_null()); |
| DCHECK(pending_buffer_to_decode_.get()); |
| DCHECK(queued_audio_frames_.empty()); |
| @@ -385,7 +308,7 @@ void DecryptingAudioDecoder::DeliverFrame( |
| pending_buffer_to_decode_ = NULL; |
| if (!reset_cb_.is_null()) { |
| - base::ResetAndReturn(&read_cb_).Run(kAborted, NULL); |
| + base::ResetAndReturn(&decode_cb_).Run(kAborted, NULL); |
| DoReset(); |
| return; |
| } |
| @@ -394,8 +317,8 @@ void DecryptingAudioDecoder::DeliverFrame( |
| if (status == Decryptor::kError) { |
| DVLOG(2) << "DeliverFrame() - kError"; |
| - state_ = kDecodeFinished; |
| - base::ResetAndReturn(&read_cb_).Run(kDecodeError, NULL); |
| + state_ = kDecodeFinished; // TODO add kError state |
| + base::ResetAndReturn(&decode_cb_).Run(kDecodeError, NULL); |
| return; |
| } |
| @@ -415,23 +338,17 @@ void DecryptingAudioDecoder::DeliverFrame( |
| return; |
| } |
| - // The buffer has been accepted by the decoder, let's report statistics. |
| - if (buffer_size) { |
| - PipelineStatistics statistics; |
| - statistics.audio_bytes_decoded = buffer_size; |
| - statistics_cb_.Run(statistics); |
| - } |
| - |
| if (status == Decryptor::kNeedMoreData) { |
| DVLOG(2) << "DeliverFrame() - kNeedMoreData"; |
| if (scoped_pending_buffer_to_decode->end_of_stream()) { |
| state_ = kDecodeFinished; |
| - base::ResetAndReturn(&read_cb_).Run(kOk, AudioBuffer::CreateEOSBuffer()); |
| + base::ResetAndReturn(&decode_cb_) |
| + .Run(kOk, AudioBuffer::CreateEOSBuffer()); |
| return; |
| } |
| - state_ = kPendingDemuxerRead; |
| - ReadFromDemuxerStream(); |
| + state_ = kIdle; |
| + base::ResetAndReturn(&decode_cb_).Run(kNotEnoughData, NULL); |
| return; |
| } |
| @@ -440,7 +357,7 @@ void DecryptingAudioDecoder::DeliverFrame( |
| EnqueueFrames(frames); |
| state_ = kIdle; |
| - base::ResetAndReturn(&read_cb_).Run(kOk, queued_audio_frames_.front()); |
| + base::ResetAndReturn(&decode_cb_).Run(kOk, queued_audio_frames_.front()); |
| queued_audio_frames_.pop_front(); |
| } |
| @@ -460,17 +377,16 @@ void DecryptingAudioDecoder::OnKeyAdded() { |
| void DecryptingAudioDecoder::DoReset() { |
| DCHECK(init_cb_.is_null()); |
| - DCHECK(read_cb_.is_null()); |
| + DCHECK(decode_cb_.is_null()); |
| timestamp_helper_->SetBaseTimestamp(kNoTimestamp()); |
| state_ = kIdle; |
| base::ResetAndReturn(&reset_cb_).Run(); |
| } |
| void DecryptingAudioDecoder::UpdateDecoderConfig() { |
| - const AudioDecoderConfig& config = demuxer_stream_->audio_decoder_config(); |
| bits_per_channel_ = kSupportedBitsPerChannel; |
| - channel_layout_ = config.channel_layout(); |
| - samples_per_second_ = config.samples_per_second(); |
| + channel_layout_ = config_.channel_layout(); |
| + samples_per_second_ = config_.samples_per_second(); |
| timestamp_helper_.reset(new AudioTimestampHelper(samples_per_second_)); |
| } |