diff options
author | timav <timav@chromium.org> | 2016-03-18 13:34:44 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-03-18 20:36:04 +0000 |
commit | fdd853c71ec52b9020dddb9aea68695cc1d909f6 (patch) | |
tree | ebde3eff92e47b386ef7727c85970b2e9ff8743f /media | |
parent | 3563aaf9a36cabd63802f1a03976861269a32e51 (diff) | |
download | chromium_src-fdd853c71ec52b9020dddb9aea68695cc1d909f6.zip chromium_src-fdd853c71ec52b9020dddb9aea68695cc1d909f6.tar.gz chromium_src-fdd853c71ec52b9020dddb9aea68695cc1d909f6.tar.bz2 |
Implement MojoAudioDecoder
Added MojoAudioDecoder implementation for Initialize(), Decode() and Reset(). It does not accept the decoded audio buffers yet.
BUG=542910
Review URL: https://codereview.chromium.org/1815553002
Cr-Commit-Position: refs/heads/master@{#382070}
Diffstat (limited to 'media')
-rw-r--r-- | media/mojo/services/mojo_audio_decoder.cc | 144 | ||||
-rw-r--r-- | media/mojo/services/mojo_audio_decoder.h | 35 |
2 files changed, 168 insertions, 11 deletions
diff --git a/media/mojo/services/mojo_audio_decoder.cc b/media/mojo/services/mojo_audio_decoder.cc index 1c6ad0c..ee6fe3c 100644 --- a/media/mojo/services/mojo_audio_decoder.cc +++ b/media/mojo/services/mojo_audio_decoder.cc @@ -5,17 +5,25 @@ #include "media/mojo/services/mojo_audio_decoder.h" #include "base/bind.h" +#include "base/bind_helpers.h" +#include "base/callback_helpers.h" #include "base/location.h" #include "base/logging.h" #include "base/single_thread_task_runner.h" #include "base/thread_task_runner_handle.h" +#include "media/base/cdm_context.h" +#include "media/mojo/common/media_type_converters.h" namespace media { MojoAudioDecoder::MojoAudioDecoder( scoped_refptr<base::SingleThreadTaskRunner> task_runner, interfaces::AudioDecoderPtr remote_decoder) - : task_runner_(task_runner), remote_decoder_(std::move(remote_decoder)) { + : task_runner_(task_runner), + remote_decoder_(std::move(remote_decoder)), + binding_(this), + has_connection_error_(false), + needs_bitstream_conversion_(false) { DVLOG(1) << __FUNCTION__; } @@ -34,10 +42,36 @@ void MojoAudioDecoder::Initialize(const AudioDecoderConfig& config, DVLOG(1) << __FUNCTION__; DCHECK(task_runner_->BelongsToCurrentThread()); - NOTIMPLEMENTED(); - - // Fail initialization while not implemented. - task_runner_->PostTask(FROM_HERE, base::Bind(init_cb, false)); + // Fail immediately if the stream is encrypted but |cdm_context| is invalid. + int cdm_id = (config.is_encrypted() && cdm_context) + ? cdm_context->GetCdmId() + : CdmContext::kInvalidCdmId; + + if (config.is_encrypted() && CdmContext::kInvalidCdmId == cdm_id) { + task_runner_->PostTask(FROM_HERE, base::Bind(init_cb, false)); + return; + } + + // If connection error has happened, fail immediately. + if (remote_decoder_.encountered_error()) { + task_runner_->PostTask(FROM_HERE, base::Bind(init_cb, false)); + return; + } + + // Otherwise, set an error handler to catch the connection error. + // Using base::Unretained(this) is safe because |this| owns |remote_decoder_|, + // and the error handler can't be invoked once |remote_decoder_| is destroyed. + remote_decoder_.set_connection_error_handler( + base::Bind(&MojoAudioDecoder::OnConnectionError, base::Unretained(this))); + + init_cb_ = init_cb; + + // Using base::Unretained(this) is safe because |this| owns |remote_decoder_|, + // and the callback won't be dispatched if |remote_decoder_| is destroyed. + remote_decoder_->Initialize( + binding_.CreateInterfacePtrAndBind(), + interfaces::AudioDecoderConfig::From(config), cdm_id, + base::Bind(&MojoAudioDecoder::OnInitialized, base::Unretained(this))); } void MojoAudioDecoder::Decode(const scoped_refptr<DecoderBuffer>& buffer, @@ -45,25 +79,115 @@ void MojoAudioDecoder::Decode(const scoped_refptr<DecoderBuffer>& buffer, DVLOG(3) << __FUNCTION__; DCHECK(task_runner_->BelongsToCurrentThread()); - NOTIMPLEMENTED(); + if (has_connection_error_) { + task_runner_->PostTask(FROM_HERE, base::Bind(decode_cb, kDecodeError)); + return; + } - // Actually we can't decode anything. - task_runner_->PostTask(FROM_HERE, base::Bind(decode_cb, kDecodeError)); + DCHECK(decode_cb_.is_null()); + decode_cb_ = decode_cb; + + // This code won't work because |buffer| is not serialized. + // TODO(timav): Serialize DecodeBuffer into data pipe. + remote_decoder_->Decode( + interfaces::DecoderBuffer::From(buffer), + base::Bind(&MojoAudioDecoder::OnDecodeStatus, base::Unretained(this))); } void MojoAudioDecoder::Reset(const base::Closure& closure) { DVLOG(2) << __FUNCTION__; DCHECK(task_runner_->BelongsToCurrentThread()); - NOTIMPLEMENTED(); + if (has_connection_error_) { + if (!decode_cb_.is_null()) { + task_runner_->PostTask( + FROM_HERE, + base::Bind(base::ResetAndReturn(&decode_cb_), kDecodeError)); + } + + task_runner_->PostTask(FROM_HERE, closure); + return; + } + + DCHECK(reset_cb_.is_null()); + reset_cb_ = closure; + remote_decoder_->Reset( + base::Bind(&MojoAudioDecoder::OnResetDone, base::Unretained(this))); } bool MojoAudioDecoder::NeedsBitstreamConversion() const { DVLOG(1) << __FUNCTION__; DCHECK(task_runner_->BelongsToCurrentThread()); + return needs_bitstream_conversion_; +} + +void MojoAudioDecoder::OnBufferDecoded(interfaces::AudioBufferPtr buffer) { + DVLOG(1) << __FUNCTION__; + DCHECK(task_runner_->BelongsToCurrentThread()); + NOTIMPLEMENTED(); - return false; +} + +void MojoAudioDecoder::OnConnectionError() { + DVLOG(1) << __FUNCTION__; + DCHECK(task_runner_->BelongsToCurrentThread()); + + has_connection_error_ = true; + + if (!init_cb_.is_null()) { + base::ResetAndReturn(&init_cb_).Run(false); + return; + } + + if (!decode_cb_.is_null()) + base::ResetAndReturn(&decode_cb_).Run(kDecodeError); + if (!reset_cb_.is_null()) + base::ResetAndReturn(&reset_cb_).Run(); +} + +void MojoAudioDecoder::OnInitialized(bool status, + bool needs_bitstream_conversion) { + DVLOG(1) << __FUNCTION__ << ": status:" << status; + DCHECK(task_runner_->BelongsToCurrentThread()); + + needs_bitstream_conversion_ = needs_bitstream_conversion; + + task_runner_->PostTask(FROM_HERE, base::Bind(init_cb_, status)); +} + +static media::AudioDecoder::Status ConvertDecodeStatus( + interfaces::AudioDecoder::DecodeStatus status) { + switch (status) { + case interfaces::AudioDecoder::DecodeStatus::OK: + return media::AudioDecoder::kOk; + case interfaces::AudioDecoder::DecodeStatus::ABORTED: + return media::AudioDecoder::kAborted; + case interfaces::AudioDecoder::DecodeStatus::DECODE_ERROR: + return media::AudioDecoder::kDecodeError; + } + NOTREACHED(); + return media::AudioDecoder::kDecodeError; +} + +void MojoAudioDecoder::OnDecodeStatus( + interfaces::AudioDecoder::DecodeStatus status) { + DVLOG(1) << __FUNCTION__ << ": status:" << status; + DCHECK(task_runner_->BelongsToCurrentThread()); + + DCHECK(!decode_cb_.is_null()); + base::ResetAndReturn(&decode_cb_).Run(ConvertDecodeStatus(status)); +} + +void MojoAudioDecoder::OnResetDone() { + DVLOG(1) << __FUNCTION__; + DCHECK(task_runner_->BelongsToCurrentThread()); + + // For pending decodes OnDecodeStatus() should arrive before OnResetDone(). + DCHECK(decode_cb_.is_null()); + + DCHECK(!reset_cb_.is_null()); + base::ResetAndReturn(&reset_cb_).Run(); } } // namespace media diff --git a/media/mojo/services/mojo_audio_decoder.h b/media/mojo/services/mojo_audio_decoder.h index eba5e75..6bfae6e 100644 --- a/media/mojo/services/mojo_audio_decoder.h +++ b/media/mojo/services/mojo_audio_decoder.h @@ -9,6 +9,7 @@ #include "base/memory/ref_counted.h" #include "media/base/audio_decoder.h" #include "media/mojo/interfaces/audio_decoder.mojom.h" +#include "mojo/public/cpp/bindings/binding.h" namespace base { class SingleThreadTaskRunner; @@ -17,7 +18,8 @@ class SingleThreadTaskRunner; namespace media { // An AudioDecoder that proxies to an interfaces::AudioDecoder. -class MojoAudioDecoder : public AudioDecoder { +class MojoAudioDecoder : public AudioDecoder, + public interfaces::AudioDecoderClient { public: MojoAudioDecoder(scoped_refptr<base::SingleThreadTaskRunner> task_runner, interfaces::AudioDecoderPtr remote_decoder); @@ -34,10 +36,41 @@ class MojoAudioDecoder : public AudioDecoder { void Reset(const base::Closure& closure) final; bool NeedsBitstreamConversion() const final; + // AudioDecoderClient implementation. + void OnBufferDecoded(interfaces::AudioBufferPtr buffer) final; + private: + // Callback for connection error on |remote_decoder_|. + void OnConnectionError(); + + // Called when |remote_decoder_| finished initialization. + void OnInitialized(bool status, bool needs_bitstream_conversion); + + // Called when |remote_decoder_| accepted or rejected DecoderBuffer. + void OnDecodeStatus(interfaces::AudioDecoder::DecodeStatus decode_status); + + // called when |remote_decoder_| finished Reset() sequence. + void OnResetDone(); + scoped_refptr<base::SingleThreadTaskRunner> task_runner_; + interfaces::AudioDecoderPtr remote_decoder_; + // Binding for AudioDecoderClient, bound to the |task_runner_|. + mojo::Binding<AudioDecoderClient> binding_; + + // We call these callbacks to pass the information to the pipeline. + InitCB init_cb_; + DecodeCB decode_cb_; + base::Closure reset_cb_; + + // Flag that is set if we got connection error. Never cleared. + bool has_connection_error_; + + // Flag telling whether this decoder requires bitstream conversion. + // Passed from |remote_decoder_| as a result of its initialization. + bool needs_bitstream_conversion_; + DISALLOW_COPY_AND_ASSIGN(MojoAudioDecoder); }; |