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; |