summaryrefslogtreecommitdiffstats
path: root/media
diff options
context:
space:
mode:
authortimav <timav@chromium.org>2016-03-18 13:34:44 -0700
committerCommit bot <commit-bot@chromium.org>2016-03-18 20:36:04 +0000
commitfdd853c71ec52b9020dddb9aea68695cc1d909f6 (patch)
treeebde3eff92e47b386ef7727c85970b2e9ff8743f /media
parent3563aaf9a36cabd63802f1a03976861269a32e51 (diff)
downloadchromium_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.cc144
-rw-r--r--media/mojo/services/mojo_audio_decoder.h35
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);
};