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

Unified Diff: media/filters/decrypting_audio_decoder.cc

Issue 11198017: Add DecryptingAudioDecoder. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Add unittests Created 8 years, 2 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/decrypting_audio_decoder.cc
diff --git a/media/filters/decrypting_video_decoder.cc b/media/filters/decrypting_audio_decoder.cc
similarity index 71%
copy from media/filters/decrypting_video_decoder.cc
copy to media/filters/decrypting_audio_decoder.cc
index 91b12ff0374c7f5947378845f7ce3a9763370f0d..633e2d9708a83bf68cd5a9fa60ef2579eaa7ac59 100644
--- a/media/filters/decrypting_video_decoder.cc
+++ b/media/filters/decrypting_audio_decoder.cc
@@ -2,26 +2,27 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "media/filters/decrypting_video_decoder.h"
+#include "media/filters/decrypting_audio_decoder.h"
#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/location.h"
#include "base/message_loop_proxy.h"
+#include "media/base/audio_decoder_config.h"
#include "media/base/bind_to_loop.h"
+#include "media/base/buffers.h"
+#include "media/base/data_buffer.h"
#include "media/base/decoder_buffer.h"
#include "media/base/decryptor.h"
#include "media/base/demuxer_stream.h"
#include "media/base/pipeline.h"
-#include "media/base/video_decoder_config.h"
-#include "media/base/video_frame.h"
namespace media {
#define BIND_TO_LOOP(function) \
media::BindToLoop(message_loop_, base::Bind(function, this))
-DecryptingVideoDecoder::DecryptingVideoDecoder(
+DecryptingAudioDecoder::DecryptingAudioDecoder(
const MessageLoopFactoryCB& message_loop_factory_cb,
const RequestDecryptorNotificationCB& request_decryptor_notification_cb)
: message_loop_factory_cb_(message_loop_factory_cb),
@@ -31,28 +32,28 @@ DecryptingVideoDecoder::DecryptingVideoDecoder(
key_added_while_pending_decode_(false) {
}
-void DecryptingVideoDecoder::Initialize(
+void DecryptingAudioDecoder::Initialize(
const scoped_refptr<DemuxerStream>& stream,
const PipelineStatusCB& status_cb,
const StatisticsCB& statistics_cb) {
DCHECK(!message_loop_);
message_loop_ = base::ResetAndReturn(&message_loop_factory_cb_).Run();
message_loop_->PostTask(FROM_HERE, base::Bind(
- &DecryptingVideoDecoder::DoInitialize, this,
+ &DecryptingAudioDecoder::DoInitialize, this,
stream, status_cb, statistics_cb));
}
-void DecryptingVideoDecoder::Read(const ReadCB& read_cb) {
+void DecryptingAudioDecoder::Read(const ReadCB& read_cb) {
// Complete operation asynchronously on different stack of execution as per
- // the API contract of VideoDecoder::Read()
+ // the API contract of AudioDecoder::Read()
message_loop_->PostTask(FROM_HERE, base::Bind(
- &DecryptingVideoDecoder::DoRead, this, read_cb));
+ &DecryptingAudioDecoder::DoRead, this, read_cb));
}
-void DecryptingVideoDecoder::Reset(const base::Closure& closure) {
+void DecryptingAudioDecoder::Reset(const base::Closure& closure) {
if (!message_loop_->BelongsToCurrentThread()) {
message_loop_->PostTask(FROM_HERE, base::Bind(
- &DecryptingVideoDecoder::Reset, this, closure));
+ &DecryptingAudioDecoder::Reset, this, closure));
return;
}
@@ -68,7 +69,7 @@ void DecryptingVideoDecoder::Reset(const base::Closure& closure) {
reset_cb_ = closure;
- decryptor_->ResetDecoder(Decryptor::kVideo);
+ decryptor_->ResetDecoder(Decryptor::kAudio);
// Reset() cannot complete if the read callback is still pending.
// Defer the resetting process in this case. The |reset_cb_| will be fired
@@ -89,10 +90,22 @@ void DecryptingVideoDecoder::Reset(const base::Closure& closure) {
DoReset();
}
-void DecryptingVideoDecoder::Stop(const base::Closure& closure) {
+int DecryptingAudioDecoder::bits_per_channel() {
+ return bits_per_channel_;
+}
+
+ChannelLayout DecryptingAudioDecoder::channel_layout() {
+ return channel_layout_;
+}
+
+int DecryptingAudioDecoder::samples_per_second() {
+ return samples_per_second_;
+}
+
+void DecryptingAudioDecoder::Stop(const base::Closure& closure) {
xhwang 2012/10/18 02:14:10 If we decided to have Stop(), this needs to be cha
if (!message_loop_->BelongsToCurrentThread()) {
message_loop_->PostTask(FROM_HERE, base::Bind(
- &DecryptingVideoDecoder::Stop, this, closure));
+ &DecryptingAudioDecoder::Stop, this, closure));
return;
}
@@ -100,15 +113,15 @@ void DecryptingVideoDecoder::Stop(const base::Closure& closure) {
DCHECK(stop_cb_.is_null());
stop_cb_ = closure;
- // We need to call Decryptor::DeinitializeDecoder(Decryptor::kVideo) if we
- // ever called Decryptor::InitializeVideoDecoder() to cancel the pending
- // initialization if the initialization is still pending, or to stop the video
- // decoder if the initialization has completed.
+ // We need to call Decryptor::DeinitializeDecoder(Decryptor::kAudio) if we
+ // ever called Decryptor::InitializeAudioDecoder() to cancel the pending
+ // initialization if the initialization is still pending, or to stop the
+ // audio decoder if the initialization has completed.
// When the state is kUninitialized and kDecryptorRequested,
- // InitializeVideoDecoder() has not been called, so we are okay.
- // When the state is kStopped, the video decoder should have already been
- // stopped, so no need to call DeinitializeDecoder(Decryptor::kVideo) either.
- // In all other cases, we need to call DeinitializeDecoder(Decryptor::kVideo)!
+ // InitializeAudioDecoder() has not been called, so we are okay.
+ // When the state is kStopped, the audio decoder should have already been
+ // stopped, so no need to call DeinitializeDecoder(Decryptor::kAudio) either.
+ // In all other cases, we need to call DeinitializeDecoder(Decryptor::kAudio)!
switch (state_) {
case kUninitialized:
case kStopped:
@@ -122,11 +135,11 @@ void DecryptingVideoDecoder::Stop(const base::Closure& closure) {
break;
case kIdle:
case kDecodeFinished:
- decryptor_->DeinitializeDecoder(Decryptor::kVideo);
+ decryptor_->DeinitializeDecoder(Decryptor::kAudio);
DoStop();
break;
case kWaitingForKey:
- decryptor_->DeinitializeDecoder(Decryptor::kVideo);
+ decryptor_->DeinitializeDecoder(Decryptor::kAudio);
DCHECK(!read_cb_.is_null());
pending_buffer_to_decode_ = NULL;
base::ResetAndReturn(&read_cb_).Run(kOk, NULL);
@@ -140,7 +153,7 @@ void DecryptingVideoDecoder::Stop(const base::Closure& closure) {
// fired after the init or read callback is fired - see
// FinishInitialization(), DoDecryptAndDecodeBuffer() and
// DoDeliverFrame(), respectively.
- decryptor_->DeinitializeDecoder(Decryptor::kVideo);
+ decryptor_->DeinitializeDecoder(Decryptor::kAudio);
DCHECK(!init_cb_.is_null() || !read_cb_.is_null());
break;
default:
@@ -148,28 +161,26 @@ void DecryptingVideoDecoder::Stop(const base::Closure& closure) {
}
}
-DecryptingVideoDecoder::~DecryptingVideoDecoder() {
+DecryptingAudioDecoder::~DecryptingAudioDecoder() {
DCHECK(state_ == kUninitialized || state_ == kStopped) << state_;
}
-void DecryptingVideoDecoder::DoInitialize(
+void DecryptingAudioDecoder::DoInitialize(
const scoped_refptr<DemuxerStream>& stream,
const PipelineStatusCB& status_cb,
const StatisticsCB& statistics_cb) {
- DVLOG(2) << "DoInitialize()";
DCHECK(message_loop_->BelongsToCurrentThread());
DCHECK_EQ(state_, kUninitialized) << state_;
DCHECK(stream);
- const VideoDecoderConfig& config = stream->video_decoder_config();
+ const AudioDecoderConfig& config = stream->audio_decoder_config();
if (!config.IsValidConfig()) {
- DLOG(ERROR) << "Invalid video stream config: "
- << config.AsHumanReadableString();
+ DLOG(ERROR) << "Invalid audio stream config.";
status_cb.Run(PIPELINE_ERROR_DECODE);
return;
}
- // DecryptingVideoDecoder only accepts potentially encrypted stream.
+ // DecryptingAudioDecoder only accepts potentially encrypted stream.
if (!config.is_encrypted()) {
status_cb.Run(DECODER_ERROR_NOT_SUPPORTED);
return;
@@ -183,10 +194,10 @@ void DecryptingVideoDecoder::DoInitialize(
state_ = kDecryptorRequested;
request_decryptor_notification_cb_.Run(
- BIND_TO_LOOP(&DecryptingVideoDecoder::SetDecryptor));
+ BIND_TO_LOOP(&DecryptingAudioDecoder::SetDecryptor));
}
-void DecryptingVideoDecoder::SetDecryptor(Decryptor* decryptor) {
+void DecryptingAudioDecoder::SetDecryptor(Decryptor* decryptor) {
DVLOG(2) << "SetDecryptor()";
DCHECK(message_loop_->BelongsToCurrentThread());
DCHECK_EQ(state_, kDecryptorRequested) << state_;
@@ -200,18 +211,17 @@ void DecryptingVideoDecoder::SetDecryptor(Decryptor* decryptor) {
decryptor_ = decryptor;
- scoped_ptr<VideoDecoderConfig> scoped_config(new VideoDecoderConfig());
- scoped_config->CopyFrom(demuxer_stream_->video_decoder_config());
+ scoped_ptr<AudioDecoderConfig> scoped_config(new AudioDecoderConfig());
+ scoped_config->CopyFrom(demuxer_stream_->audio_decoder_config());
state_ = kPendingDecoderInit;
- decryptor_->InitializeVideoDecoder(
+ decryptor_->InitializeAudioDecoder(
scoped_config.Pass(),
- BIND_TO_LOOP(&DecryptingVideoDecoder::FinishInitialization),
- BIND_TO_LOOP(&DecryptingVideoDecoder::OnKeyAdded));
+ BIND_TO_LOOP(&DecryptingAudioDecoder::FinishInitialization),
+ BIND_TO_LOOP(&DecryptingAudioDecoder::OnKeyAdded));
}
-void DecryptingVideoDecoder::FinishInitialization(bool success) {
- DVLOG(2) << "FinishInitialization()";
+void DecryptingAudioDecoder::FinishInitialization(bool success) {
DCHECK(message_loop_->BelongsToCurrentThread());
DCHECK_EQ(state_, kPendingDecoderInit) << state_;
DCHECK(!init_cb_.is_null());
@@ -231,20 +241,32 @@ void DecryptingVideoDecoder::FinishInitialization(bool success) {
}
// Success!
+ const AudioDecoderConfig& config = demuxer_stream_->audio_decoder_config();
+ bits_per_channel_ = config.bits_per_channel();
+ channel_layout_ = config.channel_layout();
+ samples_per_second_ = config.samples_per_second();
state_ = kIdle;
base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK);
}
-void DecryptingVideoDecoder::DoRead(const ReadCB& read_cb) {
+void DecryptingAudioDecoder::DoRead(const ReadCB& read_cb) {
DVLOG(3) << "DoRead()";
DCHECK(message_loop_->BelongsToCurrentThread());
DCHECK(state_ == kIdle || state_ == kDecodeFinished) << state_;
DCHECK(!read_cb.is_null());
CHECK(read_cb_.is_null()) << "Overlapping decodes are not supported.";
- // Return empty frames if decoding has finished.
+ // Return empty (end-of-stream) frames if decoding has finished.
if (state_ == kDecodeFinished) {
- read_cb.Run(kOk, VideoFrame::CreateEmptyFrame());
+ read_cb.Run(kOk, scoped_refptr<Buffer>(new DataBuffer(0)));
+ return;
+ }
+
+ if (!queued_audio_frames_.empty()) {
+ if (queued_audio_frames_.front()->IsEndOfStream())
+ state_ = kDecodeFinished;
+ read_cb.Run(kOk, queued_audio_frames_.front());
+ queued_audio_frames_.pop_front();
return;
}
@@ -253,16 +275,16 @@ void DecryptingVideoDecoder::DoRead(const ReadCB& read_cb) {
ReadFromDemuxerStream();
}
-void DecryptingVideoDecoder::ReadFromDemuxerStream() {
+void DecryptingAudioDecoder::ReadFromDemuxerStream() {
DCHECK(message_loop_->BelongsToCurrentThread());
DCHECK_EQ(state_, kPendingDemuxerRead) << state_;
DCHECK(!read_cb_.is_null());
demuxer_stream_->Read(
- base::Bind(&DecryptingVideoDecoder::DecryptAndDecodeBuffer, this));
+ base::Bind(&DecryptingAudioDecoder::DecryptAndDecodeBuffer, this));
}
-void DecryptingVideoDecoder::DecryptAndDecodeBuffer(
+void DecryptingAudioDecoder::DecryptAndDecodeBuffer(
DemuxerStream::Status status,
const scoped_refptr<DecoderBuffer>& buffer) {
// In theory, we don't need to force post the task here, because we do a
@@ -271,10 +293,10 @@ void DecryptingVideoDecoder::DecryptAndDecodeBuffer(
// stack we are still fine. But it looks like a force post task makes the
// logic more understandable and manageable, so why not?
message_loop_->PostTask(FROM_HERE, base::Bind(
- &DecryptingVideoDecoder::DoDecryptAndDecodeBuffer, this, status, buffer));
+ &DecryptingAudioDecoder::DoDecryptAndDecodeBuffer, this, status, buffer));
}
-void DecryptingVideoDecoder::DoDecryptAndDecodeBuffer(
+void DecryptingAudioDecoder::DoDecryptAndDecodeBuffer(
DemuxerStream::Status status,
const scoped_refptr<DecoderBuffer>& buffer) {
DVLOG(3) << "DoDecryptAndDecodeBuffer()";
@@ -302,7 +324,7 @@ void DecryptingVideoDecoder::DoDecryptAndDecodeBuffer(
if (status == DemuxerStream::kConfigChanged) {
// TODO(xhwang): Add config change support.
// The |state_| is chosen to be kDecodeFinished here to be consistent with
- // the implementation of FFmpegVideoDecoder.
+ // the implementation of FFmpegAudioDecoder.
DVLOG(2) << "DoDecryptAndDecodeBuffer() - kConfigChanged";
state_ = kDecodeFinished;
base::ResetAndReturn(&read_cb_).Run(kDecodeError, NULL);
@@ -315,37 +337,38 @@ void DecryptingVideoDecoder::DoDecryptAndDecodeBuffer(
DecodePendingBuffer();
}
-void DecryptingVideoDecoder::DecodePendingBuffer() {
+void DecryptingAudioDecoder::DecodePendingBuffer() {
DCHECK(message_loop_->BelongsToCurrentThread());
DCHECK_EQ(state_, kPendingDecode) << state_;
- decryptor_->DecryptAndDecodeVideo(
+ decryptor_->DecryptAndDecodeAudio(
pending_buffer_to_decode_,
- base::Bind(&DecryptingVideoDecoder::DeliverFrame, this,
+ base::Bind(&DecryptingAudioDecoder::DeliverFrame, this,
pending_buffer_to_decode_->GetDataSize()));
}
-void DecryptingVideoDecoder::DeliverFrame(
+void DecryptingAudioDecoder::DeliverFrame(
int buffer_size,
Decryptor::Status status,
- const scoped_refptr<VideoFrame>& frame) {
- // We need to force task post here because the VideoDecodeCB can be executed
+ const Decryptor::AudioBuffers& frames) {
+ // We need to force task post here because the AudioDecodeCB can be executed
// synchronously in Reset()/Stop(). Instead of using more complicated logic in
// those function to fix it, why not force task post here to make everything
// simple and clear?
message_loop_->PostTask(FROM_HERE, base::Bind(
- &DecryptingVideoDecoder::DoDeliverFrame, this,
- buffer_size, status, frame));
+ &DecryptingAudioDecoder::DoDeliverFrame, this,
+ buffer_size, status, frames));
}
-void DecryptingVideoDecoder::DoDeliverFrame(
+void DecryptingAudioDecoder::DoDeliverFrame(
int buffer_size,
Decryptor::Status status,
- const scoped_refptr<VideoFrame>& frame) {
+ const Decryptor::AudioBuffers& frames) {
DVLOG(3) << "DoDeliverFrame()";
DCHECK(message_loop_->BelongsToCurrentThread());
DCHECK_EQ(state_, kPendingDecode) << state_;
DCHECK(!read_cb_.is_null());
DCHECK(pending_buffer_to_decode_);
+ DCHECK(queued_audio_frames_.empty());
bool need_to_try_again_if_nokey_is_returned = key_added_while_pending_decode_;
key_added_while_pending_decode_ = false;
@@ -361,14 +384,14 @@ void DecryptingVideoDecoder::DoDeliverFrame(
}
if (status == Decryptor::kError) {
- DCHECK(!frame);
+ DCHECK(frames.empty());
state_ = kDecodeFinished;
base::ResetAndReturn(&read_cb_).Run(kDecodeError, NULL);
return;
}
if (status == Decryptor::kNoKey) {
- DCHECK(!frame);
+ DCHECK(frames.empty());
if (need_to_try_again_if_nokey_is_returned) {
// The |state_| is still kPendingDecode.
DecodePendingBuffer();
@@ -382,24 +405,29 @@ void DecryptingVideoDecoder::DoDeliverFrame(
// The buffer has been accepted by the decoder, let's report statistics.
if (buffer_size) {
PipelineStatistics statistics;
- statistics.video_bytes_decoded = buffer_size;
+ statistics.audio_bytes_decoded = buffer_size;
statistics_cb_.Run(statistics);
}
if (status == Decryptor::kNeedMoreData) {
- DCHECK(!frame);
+ DCHECK(frames.empty());
state_ = kPendingDemuxerRead;
ReadFromDemuxerStream();
return;
}
DCHECK_EQ(status, Decryptor::kSuccess);
- state_ = frame->IsEndOfStream() ? kDecodeFinished : kIdle;
- base::ResetAndReturn(&read_cb_).Run(kOk, frame);
+
+ DCHECK(!frames.empty());
+ queued_audio_frames_ = frames;
+
+ scoped_refptr<Buffer> first_frame = queued_audio_frames_.front();
+ queued_audio_frames_.pop_front();
+ state_ = first_frame->IsEndOfStream() ? kDecodeFinished : kIdle;
+ base::ResetAndReturn(&read_cb_).Run(kOk, first_frame);
}
-void DecryptingVideoDecoder::OnKeyAdded() {
- DVLOG(2) << "OnKeyAdded()";
+void DecryptingAudioDecoder::OnKeyAdded() {
DCHECK(message_loop_->BelongsToCurrentThread());
if (state_ == kPendingDecode) {
@@ -413,14 +441,14 @@ void DecryptingVideoDecoder::OnKeyAdded() {
}
}
-void DecryptingVideoDecoder::DoReset() {
+void DecryptingAudioDecoder::DoReset() {
DCHECK(init_cb_.is_null());
DCHECK(read_cb_.is_null());
state_ = kIdle;
base::ResetAndReturn(&reset_cb_).Run();
}
-void DecryptingVideoDecoder::DoStop() {
+void DecryptingAudioDecoder::DoStop() {
DCHECK(init_cb_.is_null());
DCHECK(read_cb_.is_null());
state_ = kStopped;

Powered by Google App Engine
This is Rietveld 408576698