weak_factory_(this) {}
void DecryptingAudioDecoder::Initialize(const AudioDecoderConfig& config,
- const PipelineStatusCB& status_cb) {
+ const PipelineStatusCB& status_cb,
+ const OutputCB& output_cb) {
DVLOG(2) << "Initialize()";
DCHECK(task_runner_->BelongsToCurrentThread());
DCHECK(decode_cb_.is_null());
weak_this_ = weak_factory_.GetWeakPtr();
init_cb_ = BindToCurrentLoop(status_cb);
+ output_cb_ = BindToCurrentLoop(output_cb);
if (!config.IsValidConfig()) {
DLOG(ERROR) << "Invalid audio stream config.";
// Return empty (end-of-stream) frames if decoding has finished.
if (state_ == kDecodeFinished) {
- base::ResetAndReturn(&decode_cb_).Run(kOk, AudioBuffer::CreateEOSBuffer());
- return;
- }
-
- if (!queued_audio_frames_.empty()) {
- DCHECK(!buffer);
- base::ResetAndReturn(&decode_cb_).Run(kOk, queued_audio_frames_.front());
- queued_audio_frames_.pop_front();
+ output_cb_.Run(AudioBuffer::CreateEOSBuffer());
+ base::ResetAndReturn(&decode_cb_).Run(kOk);
return;
}
DecodePendingBuffer();
}
-scoped_refptr<AudioBuffer> DecryptingAudioDecoder::GetDecodeOutput() {
- if (queued_audio_frames_.empty())
- return NULL;
- 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());
if (state_ == kWaitingForKey) {
DCHECK(!decode_cb_.is_null());
pending_buffer_to_decode_ = NULL;
- base::ResetAndReturn(&decode_cb_).Run(kAborted, NULL);
+ base::ResetAndReturn(&decode_cb_).Run(kAborted);
}
DCHECK(decode_cb_.is_null());
DoReset();
}
-void DecryptingAudioDecoder::Stop(const base::Closure& closure) {
- DVLOG(2) << "Stop() - state: " << state_;
+DecryptingAudioDecoder::~DecryptingAudioDecoder() {
+ DVLOG(2) << __FUNCTION__;
DCHECK(task_runner_->BelongsToCurrentThread());
- // Invalidate all weak pointers so that pending callbacks won't be fired into
- // this object.
- weak_factory_.InvalidateWeakPtrs();
+ if (state_ == kUninitialized)
+ return;
if (decryptor_) {
decryptor_->DeinitializeDecoder(Decryptor::kAudio);
if (!init_cb_.is_null())
base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED);
if (!decode_cb_.is_null())
- base::ResetAndReturn(&decode_cb_).Run(kAborted, NULL);
+ base::ResetAndReturn(&decode_cb_).Run(kAborted);
if (!reset_cb_.is_null())
base::ResetAndReturn(&reset_cb_).Run();
-
- state_ = kStopped;
- task_runner_->PostTask(FROM_HERE, closure);
-}
-
-DecryptingAudioDecoder::~DecryptingAudioDecoder() {
- DCHECK(state_ == kUninitialized || state_ == kStopped) << state_;
}
-void DecryptingAudioDecoder::SetDecryptor(Decryptor* decryptor) {
+void DecryptingAudioDecoder::SetDecryptor(
+ Decryptor* decryptor,
+ const DecryptorAttachedCB& decryptor_attached_cb) {
DVLOG(2) << "SetDecryptor()";
DCHECK(task_runner_->BelongsToCurrentThread());
DCHECK_EQ(state_, kDecryptorRequested) << state_;
if (!decryptor) {
base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED);
- // TODO(xhwang): Add kError state. See http://crbug.com/251503
- state_ = kStopped;
+ state_ = kError;
+ decryptor_attached_cb.Run(false);
return;
}
decryptor_ = decryptor;
InitializeDecoder();
+ decryptor_attached_cb.Run(true);
}
void DecryptingAudioDecoder::InitializeDecoder() {
- // Force to use S16 due to limitations of the CDM. See b/13548512
- 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_,
if (!success) {
base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED);
- state_ = kStopped;
+ decryptor_ = NULL;
+ state_ = kError;
return;
}
DCHECK_EQ(state_, kPendingDecode) << state_;
DCHECK(!decode_cb_.is_null());
DCHECK(pending_buffer_to_decode_.get());
- DCHECK(queued_audio_frames_.empty());
bool need_to_try_again_if_nokey_is_returned = key_added_while_decode_pending_;
key_added_while_decode_pending_ = false;
pending_buffer_to_decode_ = NULL;
if (!reset_cb_.is_null()) {
- base::ResetAndReturn(&decode_cb_).Run(kAborted, NULL);
+ base::ResetAndReturn(&decode_cb_).Run(kAborted);
DoReset();
return;
}
if (status == Decryptor::kError) {
DVLOG(2) << "DeliverFrame() - kError";
state_ = kDecodeFinished; // TODO add kError state
- base::ResetAndReturn(&decode_cb_).Run(kDecodeError, NULL);
+ base::ResetAndReturn(&decode_cb_).Run(kDecodeError);
return;
}
if (status == Decryptor::kNeedMoreData) {
DVLOG(2) << "DeliverFrame() - kNeedMoreData";
- if (scoped_pending_buffer_to_decode->end_of_stream()) {
- state_ = kDecodeFinished;
- base::ResetAndReturn(&decode_cb_)
- .Run(kOk, AudioBuffer::CreateEOSBuffer());
- return;
- }
-
- state_ = kIdle;
- base::ResetAndReturn(&decode_cb_).Run(kNotEnoughData, NULL);
+ state_ = scoped_pending_buffer_to_decode->end_of_stream() ? kDecodeFinished
+ : kIdle;
+ base::ResetAndReturn(&decode_cb_).Run(kOk);
return;
}
DCHECK_EQ(status, Decryptor::kSuccess);
DCHECK(!frames.empty());
- EnqueueFrames(frames);
+ ProcessDecodedFrames(frames);
+
+ if (scoped_pending_buffer_to_decode->end_of_stream()) {
+ // Set |pending_buffer_to_decode_| back as we need to keep flushing the
+ // decryptor until kNeedMoreData is returned.
+ pending_buffer_to_decode_ = scoped_pending_buffer_to_decode;
+ DecodePendingBuffer();
+ return;
+ }
state_ = kIdle;
- base::ResetAndReturn(&decode_cb_).Run(kOk, queued_audio_frames_.front());
- queued_audio_frames_.pop_front();
+ base::ResetAndReturn(&decode_cb_).Run(kOk);
}
void DecryptingAudioDecoder::OnKeyAdded() {
base::ResetAndReturn(&reset_cb_).Run();
}
-void DecryptingAudioDecoder::EnqueueFrames(
+void DecryptingAudioDecoder::ProcessDecodedFrames(
const Decryptor::AudioBuffers& frames) {
- queued_audio_frames_ = frames;
-
- for (Decryptor::AudioBuffers::iterator iter = queued_audio_frames_.begin();
- iter != queued_audio_frames_.end();
+ for (Decryptor::AudioBuffers::const_iterator iter = frames.begin();
+ iter != frames.end();
++iter) {
- scoped_refptr<AudioBuffer>& frame = *iter;
+ scoped_refptr<AudioBuffer> frame = *iter;
DCHECK(!frame->end_of_stream()) << "EOS frame returned.";
DCHECK_GT(frame->frame_count(), 0) << "Empty frame returned.";
}
frame->set_timestamp(current_time);
- frame->set_duration(
- timestamp_helper_->GetFrameDuration(frame->frame_count()));
timestamp_helper_->AddFrames(frame->frame_count());
+
+ output_cb_.Run(frame);
}
}