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

Unified Diff: media/filters/decrypting_audio_decoder.cc

Issue 11198017: Add DecryptingAudioDecoder. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebase 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
« no previous file with comments | « media/filters/decrypting_audio_decoder.h ('k') | media/filters/decrypting_audio_decoder_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 66%
copy from media/filters/decrypting_video_decoder.cc
copy to media/filters/decrypting_audio_decoder.cc
index 8ea96750b301cdd70b6c561d3fbff453393895b8..a6871b5335930fa5a2638ad96d4230d91de5edc6 100644
--- a/media/filters/decrypting_video_decoder.cc
+++ b/media/filters/decrypting_audio_decoder.cc
@@ -2,57 +2,61 @@
// 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),
state_(kUninitialized),
request_decryptor_notification_cb_(request_decryptor_notification_cb),
decryptor_(NULL),
- key_added_while_pending_decode_(false) {
+ key_added_while_pending_decode_(false),
+ bits_per_channel_(0),
+ channel_layout_(CHANNEL_LAYOUT_NONE),
+ samples_per_second_(0) {
}
-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;
}
@@ -67,7 +71,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
@@ -88,41 +92,22 @@ void DecryptingVideoDecoder::Reset(const base::Closure& closure) {
DoReset();
}
-void DecryptingVideoDecoder::Stop(const base::Closure& closure) {
- if (!message_loop_->BelongsToCurrentThread()) {
- message_loop_->PostTask(FROM_HERE, base::Bind(
- &DecryptingVideoDecoder::Stop, this, closure));
- return;
- }
+int DecryptingAudioDecoder::bits_per_channel() {
+ return bits_per_channel_;
+}
- DVLOG(2) << "Stop() - state: " << state_;
-
- // At this point the render thread is likely paused (in WebMediaPlayerImpl's
- // Destroy()), so running |closure| can't wait for anything that requires the
- // render thread to be processing messages to complete (such as PPAPI
- // callbacks).
- if (decryptor_)
- decryptor_->DeinitializeDecoder(Decryptor::kVideo);
- if (!request_decryptor_notification_cb_.is_null()) {
- base::ResetAndReturn(&request_decryptor_notification_cb_).Run(
- DecryptorNotificationCB());
- }
- 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(kOk, NULL);
- if (!reset_cb_.is_null())
- base::ResetAndReturn(&reset_cb_).Run();
- state_ = kStopped;
- closure.Run();
+ChannelLayout DecryptingAudioDecoder::channel_layout() {
+ return channel_layout_;
}
-DecryptingVideoDecoder::~DecryptingVideoDecoder() {
- DCHECK(state_ == kUninitialized || state_ == kStopped) << state_;
+int DecryptingAudioDecoder::samples_per_second() {
+ return samples_per_second_;
}
-void DecryptingVideoDecoder::DoInitialize(
+DecryptingAudioDecoder::~DecryptingAudioDecoder() {
+}
+
+void DecryptingAudioDecoder::DoInitialize(
const scoped_refptr<DemuxerStream>& stream,
const PipelineStatusCB& status_cb,
const StatisticsCB& statistics_cb) {
@@ -131,15 +116,14 @@ void DecryptingVideoDecoder::DoInitialize(
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;
@@ -153,40 +137,32 @@ 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());
-
- if (state_ == kStopped)
- return;
-
DCHECK_EQ(state_, kDecryptorRequested) << state_;
DCHECK(!init_cb_.is_null());
DCHECK(!request_decryptor_notification_cb_.is_null());
- request_decryptor_notification_cb_.Reset();
+ request_decryptor_notification_cb_.Reset();
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) {
+void DecryptingAudioDecoder::FinishInitialization(bool success) {
DVLOG(2) << "FinishInitialization()";
DCHECK(message_loop_->BelongsToCurrentThread());
-
- if (state_ == kStopped)
- return;
-
DCHECK_EQ(state_, kPendingDecoderInit) << state_;
DCHECK(!init_cb_.is_null());
DCHECK(reset_cb_.is_null()); // No Reset() before initialization finished.
@@ -194,25 +170,37 @@ void DecryptingVideoDecoder::FinishInitialization(bool success) {
if (!success) {
base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED);
- state_ = kStopped;
+ state_ = kDecodeFinished;
return;
}
// 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;
}
@@ -221,16 +209,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
@@ -239,26 +227,21 @@ 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()";
DCHECK(message_loop_->BelongsToCurrentThread());
-
- if (state_ == kStopped)
- return;
-
DCHECK_EQ(state_, kPendingDemuxerRead) << state_;
DCHECK(!read_cb_.is_null());
DCHECK_EQ(buffer != NULL, status == DemuxerStream::kOk) << status;
if (!reset_cb_.is_null()) {
base::ResetAndReturn(&read_cb_).Run(kOk, NULL);
- if (!reset_cb_.is_null())
- DoReset();
+ DoReset();
return;
}
@@ -285,41 +268,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
- // synchronously in Reset()/Stop(). Instead of using more complicated logic in
+ const Decryptor::AudioBuffers& frames) {
+ // We need to force task post here because the AudioDecodeCB can be executed
+ // synchronously in Reset(). 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());
-
- if (state_ == kStopped)
- return;
-
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;
@@ -327,20 +307,19 @@ void DecryptingVideoDecoder::DoDeliverFrame(
if (!reset_cb_.is_null()) {
pending_buffer_to_decode_ = NULL;
base::ResetAndReturn(&read_cb_).Run(kOk, NULL);
- if (!reset_cb_.is_null())
- DoReset();
+ DoReset();
return;
}
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();
@@ -354,24 +333,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) {
@@ -385,7 +369,7 @@ void DecryptingVideoDecoder::OnKeyAdded() {
}
}
-void DecryptingVideoDecoder::DoReset() {
+void DecryptingAudioDecoder::DoReset() {
DCHECK(init_cb_.is_null());
DCHECK(read_cb_.is_null());
state_ = kIdle;
« no previous file with comments | « media/filters/decrypting_audio_decoder.h ('k') | media/filters/decrypting_audio_decoder_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698