Index: media/filters/opus_audio_decoder.cc |
diff --git a/media/filters/opus_audio_decoder.cc b/media/filters/opus_audio_decoder.cc |
index d4e2ec66794843755e95958363eb970b23352b1d..d63f4b249e5c6de4b3e91be16f8a7a57d5c1a8bc 100644 |
--- a/media/filters/opus_audio_decoder.cc |
+++ b/media/filters/opus_audio_decoder.cc |
@@ -256,7 +256,6 @@ OpusAudioDecoder::OpusAudioDecoder( |
const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) |
: task_runner_(task_runner), |
weak_factory_(this), |
- demuxer_stream_(NULL), |
opus_decoder_(NULL), |
channel_layout_(CHANNEL_LAYOUT_NONE), |
samples_per_second_(0), |
@@ -268,40 +267,28 @@ OpusAudioDecoder::OpusAudioDecoder( |
start_input_timestamp_(kNoTimestamp()) { |
} |
-void OpusAudioDecoder::Initialize( |
- DemuxerStream* stream, |
- const PipelineStatusCB& status_cb, |
- const StatisticsCB& statistics_cb) { |
+void OpusAudioDecoder::Initialize(const AudioDecoderConfig& config, |
+ const PipelineStatusCB& status_cb) { |
DCHECK(task_runner_->BelongsToCurrentThread()); |
PipelineStatusCB initialize_cb = BindToCurrentLoop(status_cb); |
- if (demuxer_stream_) { |
- // TODO(scherkus): initialization currently happens more than once in |
- // PipelineIntegrationTest.BasicPlayback. |
- DLOG(ERROR) << "Initialize has already been called."; |
- CHECK(false); |
- } |
- |
weak_this_ = weak_factory_.GetWeakPtr(); |
- demuxer_stream_ = stream; |
+ config_ = config; |
if (!ConfigureDecoder()) { |
initialize_cb.Run(DECODER_ERROR_NOT_SUPPORTED); |
return; |
} |
- statistics_cb_ = statistics_cb; |
initialize_cb.Run(PIPELINE_OK); |
} |
-void OpusAudioDecoder::Read(const ReadCB& read_cb) { |
+void OpusAudioDecoder::Decode(const scoped_refptr<DecoderBuffer>& buffer, |
+ const DecodeCB& decode_cb) { |
DCHECK(task_runner_->BelongsToCurrentThread()); |
- DCHECK(!read_cb.is_null()); |
- CHECK(read_cb_.is_null()) << "Overlapping decodes are not supported."; |
- DCHECK(stop_cb_.is_null()); |
- read_cb_ = BindToCurrentLoop(read_cb); |
+ DCHECK(!decode_cb.is_null()); |
- ReadFromDemuxerStream(); |
+ DecodeBuffer(buffer, BindToCurrentLoop(decode_cb)); |
} |
int OpusAudioDecoder::bits_per_channel() { |
@@ -321,108 +308,35 @@ int OpusAudioDecoder::samples_per_second() { |
void OpusAudioDecoder::Reset(const base::Closure& closure) { |
DCHECK(task_runner_->BelongsToCurrentThread()); |
- reset_cb_ = BindToCurrentLoop(closure); |
- |
- // A demuxer read is pending, we'll wait until it finishes. |
- if (!read_cb_.is_null()) |
- return; |
- |
- DoReset(); |
-} |
- |
-void OpusAudioDecoder::Stop(const base::Closure& closure) { |
- DCHECK(task_runner_->BelongsToCurrentThread()); |
- stop_cb_ = BindToCurrentLoop(closure); |
- |
- // A demuxer read is pending, we'll wait until it finishes. |
- if (!read_cb_.is_null()) |
- return; |
- |
- if (!reset_cb_.is_null()) { |
- DoReset(); |
- return; |
- } |
- |
- DoStop(); |
-} |
- |
-OpusAudioDecoder::~OpusAudioDecoder() {} |
- |
-void OpusAudioDecoder::DoReset() { |
- DCHECK(!reset_cb_.is_null()); |
opus_multistream_decoder_ctl(opus_decoder_, OPUS_RESET_STATE); |
ResetTimestampState(); |
- base::ResetAndReturn(&reset_cb_).Run(); |
- |
- if (!stop_cb_.is_null()) |
- DoStop(); |
+ task_runner_->PostTask(FROM_HERE, closure); |
} |
-void OpusAudioDecoder::DoStop() { |
- DCHECK(!stop_cb_.is_null()); |
+void OpusAudioDecoder::Stop(const base::Closure& closure) { |
+ DCHECK(task_runner_->BelongsToCurrentThread()); |
opus_multistream_decoder_ctl(opus_decoder_, OPUS_RESET_STATE); |
ResetTimestampState(); |
CloseDecoder(); |
- base::ResetAndReturn(&stop_cb_).Run(); |
+ task_runner_->PostTask(FROM_HERE, closure); |
xhwang
2014/03/05 00:40:46
Nice!
|
} |
-void OpusAudioDecoder::ReadFromDemuxerStream() { |
- DCHECK(!read_cb_.is_null()); |
- demuxer_stream_->Read(base::Bind(&OpusAudioDecoder::BufferReady, weak_this_)); |
-} |
+OpusAudioDecoder::~OpusAudioDecoder() {} |
-void OpusAudioDecoder::BufferReady( |
- DemuxerStream::Status status, |
- const scoped_refptr<DecoderBuffer>& input) { |
+void OpusAudioDecoder::DecodeBuffer( |
+ const scoped_refptr<DecoderBuffer>& input, |
+ const DecodeCB& decode_cb) { |
DCHECK(task_runner_->BelongsToCurrentThread()); |
- DCHECK(!read_cb_.is_null()); |
- DCHECK_EQ(status != DemuxerStream::kOk, !input.get()) << status; |
- |
- // Drop the buffer, fire |read_cb_| and complete the pending Reset(). |
- // If there happens to also be a pending Stop(), that will be handled at |
- // the end of DoReset(). |
- if (!reset_cb_.is_null()) { |
- base::ResetAndReturn(&read_cb_).Run(kAborted, NULL); |
- DoReset(); |
- return; |
- } |
- |
- // Drop the buffer, fire |read_cb_| and complete the pending Stop(). |
- if (!stop_cb_.is_null()) { |
- base::ResetAndReturn(&read_cb_).Run(kAborted, NULL); |
- DoStop(); |
- return; |
- } |
- |
- if (status == DemuxerStream::kAborted) { |
- DCHECK(!input.get()); |
- base::ResetAndReturn(&read_cb_).Run(kAborted, NULL); |
- return; |
- } |
- |
- if (status == DemuxerStream::kConfigChanged) { |
- DCHECK(!input.get()); |
- DVLOG(1) << "Config changed."; |
- |
- if (!ConfigureDecoder()) { |
- base::ResetAndReturn(&read_cb_).Run(kDecodeError, NULL); |
- return; |
- } |
+ DCHECK(!decode_cb.is_null()); |
- ResetTimestampState(); |
- ReadFromDemuxerStream(); |
- return; |
- } |
- |
- DCHECK_EQ(status, DemuxerStream::kOk); |
DCHECK(input.get()); |
// Libopus does not buffer output. Decoding is complete when an end of stream |
// input buffer is received. |
if (input->end_of_stream()) { |
- base::ResetAndReturn(&read_cb_).Run(kOk, AudioBuffer::CreateEOSBuffer()); |
+ decode_cb.Run(kOk, AudioBuffer::CreateEOSBuffer()); |
return; |
} |
@@ -431,7 +345,7 @@ void OpusAudioDecoder::BufferReady( |
if (input->timestamp() == kNoTimestamp() && |
output_timestamp_helper_->base_timestamp() == kNoTimestamp()) { |
DLOG(ERROR) << "Received a buffer without timestamps!"; |
- base::ResetAndReturn(&read_cb_).Run(kDecodeError, NULL); |
+ decode_cb.Run(kDecodeError, NULL); |
return; |
} |
@@ -442,7 +356,7 @@ void OpusAudioDecoder::BufferReady( |
DLOG(ERROR) << "Input timestamps are not monotonically increasing! " |
<< " ts " << input->timestamp().InMicroseconds() << " us" |
<< " diff " << diff.InMicroseconds() << " us"; |
- base::ResetAndReturn(&read_cb_).Run(kDecodeError, NULL); |
+ decode_cb.Run(kDecodeError, NULL); |
return; |
} |
@@ -459,53 +373,52 @@ void OpusAudioDecoder::BufferReady( |
scoped_refptr<AudioBuffer> output_buffer; |
if (!Decode(input, &output_buffer)) { |
- base::ResetAndReturn(&read_cb_).Run(kDecodeError, NULL); |
+ decode_cb.Run(kDecodeError, NULL); |
return; |
} |
if (output_buffer.get()) { |
// Execute callback to return the decoded audio. |
- base::ResetAndReturn(&read_cb_).Run(kOk, output_buffer); |
+ decode_cb.Run(kOk, output_buffer); |
} else { |
- // We exhausted the input data, but it wasn't enough for a frame. Ask for |
- // more data in order to fulfill this read. |
- ReadFromDemuxerStream(); |
+ // We exhausted the input data, but it wasn't enough for a frame. |
+ decode_cb.Run(kNotEnoughData, NULL); |
} |
} |
bool OpusAudioDecoder::ConfigureDecoder() { |
- const AudioDecoderConfig& config = demuxer_stream_->audio_decoder_config(); |
- |
- if (config.codec() != kCodecOpus) { |
+ if (config_.codec() != kCodecOpus) { |
DVLOG(1) << "Codec must be kCodecOpus."; |
return false; |
} |
const int channel_count = |
- ChannelLayoutToChannelCount(config.channel_layout()); |
- if (!config.IsValidConfig() || channel_count > kMaxVorbisChannels) { |
+ ChannelLayoutToChannelCount(config_.channel_layout()); |
+ if (!config_.IsValidConfig() || channel_count > kMaxVorbisChannels) { |
DLOG(ERROR) << "Invalid or unsupported audio stream -" |
- << " codec: " << config.codec() |
+ << " codec: " << config_.codec() |
<< " channel count: " << channel_count |
- << " channel layout: " << config.channel_layout() |
- << " bits per channel: " << config.bits_per_channel() |
- << " samples per second: " << config.samples_per_second(); |
+ << " channel layout: " << config_.channel_layout() |
+ << " bits per channel: " << config_.bits_per_channel() |
+ << " samples per second: " << config_.samples_per_second(); |
return false; |
} |
- if (config.is_encrypted()) { |
+ if (config_.is_encrypted()) { |
DLOG(ERROR) << "Encrypted audio stream not supported."; |
return false; |
} |
+ // TODO(rileya) Remove this check once we properly support midstream audio |
+ // config changes. |
if (opus_decoder_ && |
- (channel_layout_ != config.channel_layout() || |
- samples_per_second_ != config.samples_per_second())) { |
+ (channel_layout_ != config_.channel_layout() || |
+ samples_per_second_ != config_.samples_per_second())) { |
DLOG(ERROR) << "Unsupported config change -" |
<< ", channel_layout: " << channel_layout_ |
- << " -> " << config.channel_layout() |
+ << " -> " << config_.channel_layout() |
<< ", sample_rate: " << samples_per_second_ |
- << " -> " << config.samples_per_second(); |
+ << " -> " << config_.samples_per_second(); |
return false; |
} |
@@ -514,18 +427,18 @@ bool OpusAudioDecoder::ConfigureDecoder() { |
// Parse the Opus Extra Data. |
OpusExtraData opus_extra_data; |
- if (!ParseOpusExtraData(config.extra_data(), config.extra_data_size(), |
- config, |
+ if (!ParseOpusExtraData(config_.extra_data(), config_.extra_data_size(), |
+ config_, |
&opus_extra_data)) |
return false; |
// Convert from seconds to samples. |
- timestamp_offset_ = config.codec_delay(); |
- frame_delay_at_start_ = TimeDeltaToAudioFrames(config.codec_delay(), |
- config.samples_per_second()); |
+ timestamp_offset_ = config_.codec_delay(); |
+ frame_delay_at_start_ = TimeDeltaToAudioFrames(config_.codec_delay(), |
+ config_.samples_per_second()); |
if (timestamp_offset_ <= base::TimeDelta() || frame_delay_at_start_ < 0) { |
DLOG(ERROR) << "Invalid file. Incorrect value for codec delay: " |
- << config.codec_delay().InMicroseconds(); |
+ << config_.codec_delay().InMicroseconds(); |
return false; |
} |
@@ -548,7 +461,7 @@ bool OpusAudioDecoder::ConfigureDecoder() { |
// Init Opus. |
int status = OPUS_INVALID_STATE; |
- opus_decoder_ = opus_multistream_decoder_create(config.samples_per_second(), |
+ opus_decoder_ = opus_multistream_decoder_create(config_.samples_per_second(), |
channel_count, |
opus_extra_data.num_streams, |
opus_extra_data.num_coupled, |
@@ -568,10 +481,10 @@ bool OpusAudioDecoder::ConfigureDecoder() { |
return false; |
} |
- channel_layout_ = config.channel_layout(); |
- samples_per_second_ = config.samples_per_second(); |
+ channel_layout_ = config_.channel_layout(); |
+ samples_per_second_ = config_.samples_per_second(); |
output_timestamp_helper_.reset( |
- new AudioTimestampHelper(config.samples_per_second())); |
+ new AudioTimestampHelper(config_.samples_per_second())); |
start_input_timestamp_ = kNoTimestamp(); |
return true; |
} |
@@ -586,9 +499,8 @@ void OpusAudioDecoder::CloseDecoder() { |
void OpusAudioDecoder::ResetTimestampState() { |
output_timestamp_helper_->SetBaseTimestamp(kNoTimestamp()); |
last_input_timestamp_ = kNoTimestamp(); |
- frames_to_discard_ = TimeDeltaToAudioFrames( |
- demuxer_stream_->audio_decoder_config().seek_preroll(), |
- samples_per_second_); |
+ frames_to_discard_ = |
+ TimeDeltaToAudioFrames(config_.seek_preroll(), samples_per_second_); |
} |
bool OpusAudioDecoder::Decode(const scoped_refptr<DecoderBuffer>& input, |
@@ -657,11 +569,6 @@ bool OpusAudioDecoder::Decode(const scoped_refptr<DecoderBuffer>& input, |
frames_to_output = 0; |
} |
- // Decoding finished successfully, update statistics. |
- PipelineStatistics statistics; |
- statistics.audio_bytes_decoded = input->data_size(); |
- statistics_cb_.Run(statistics); |
- |
// Assign timestamp and duration to the buffer. |
output_buffer->get()->set_timestamp( |
output_timestamp_helper_->GetTimestamp() - timestamp_offset_); |