1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "media/filters/decrypting_audio_decoder.h"
10 #include "base/callback_helpers.h"
11 #include "base/location.h"
12 #include "base/logging.h"
13 #include "base/message_loop_proxy.h"
14 #include "media/base/audio_decoder_config.h"
15 #include "media/base/bind_to_loop.h"
16 #include "media/base/buffers.h"
17 #include "media/base/data_buffer.h"
18 #include "media/base/decoder_buffer.h"
19 #include "media/base/decryptor.h"
20 #include "media/base/demuxer_stream.h"
21 #include "media/base/pipeline.h"
25 const int DecryptingAudioDecoder::kSupportedBitsPerChannel
= 16;
27 static inline bool IsOutOfSync(const base::TimeDelta
& timestamp_1
,
28 const base::TimeDelta
& timestamp_2
) {
29 // Out of sync of 100ms would be pretty noticeable and we should keep any
31 const int64 kOutOfSyncThresholdInMicroseconds
= 100000;
32 return std::abs(timestamp_1
.InMicroseconds() - timestamp_2
.InMicroseconds()) >
33 kOutOfSyncThresholdInMicroseconds
;
36 DecryptingAudioDecoder::DecryptingAudioDecoder(
37 const scoped_refptr
<base::MessageLoopProxy
>& message_loop
,
38 const SetDecryptorReadyCB
& set_decryptor_ready_cb
)
39 : message_loop_(message_loop
),
40 state_(kUninitialized
),
41 set_decryptor_ready_cb_(set_decryptor_ready_cb
),
43 key_added_while_decode_pending_(false),
45 channel_layout_(CHANNEL_LAYOUT_NONE
),
46 samples_per_second_(0),
48 output_timestamp_base_(kNoTimestamp()),
49 total_samples_decoded_(0) {
52 void DecryptingAudioDecoder::Initialize(
53 const scoped_refptr
<DemuxerStream
>& stream
,
54 const PipelineStatusCB
& status_cb
,
55 const StatisticsCB
& statistics_cb
) {
56 DVLOG(2) << "Initialize()";
57 DCHECK(message_loop_
->BelongsToCurrentThread());
58 DCHECK_EQ(state_
, kUninitialized
) << state_
;
61 init_cb_
= BindToCurrentLoop(status_cb
);
63 const AudioDecoderConfig
& config
= stream
->audio_decoder_config();
64 if (!config
.IsValidConfig()) {
65 DLOG(ERROR
) << "Invalid audio stream config.";
66 base::ResetAndReturn(&init_cb_
).Run(PIPELINE_ERROR_DECODE
);
70 // DecryptingAudioDecoder only accepts potentially encrypted stream.
71 if (!config
.is_encrypted()) {
72 base::ResetAndReturn(&init_cb_
).Run(DECODER_ERROR_NOT_SUPPORTED
);
76 DCHECK(!demuxer_stream_
);
77 demuxer_stream_
= stream
;
78 statistics_cb_
= statistics_cb
;
80 state_
= kDecryptorRequested
;
81 set_decryptor_ready_cb_
.Run(BindToCurrentLoop(
82 base::Bind(&DecryptingAudioDecoder::SetDecryptor
, this)));
85 void DecryptingAudioDecoder::Read(const ReadCB
& read_cb
) {
87 DCHECK(message_loop_
->BelongsToCurrentThread());
88 DCHECK(state_
== kIdle
|| state_
== kDecodeFinished
) << state_
;
89 DCHECK(!read_cb
.is_null());
90 CHECK(read_cb_
.is_null()) << "Overlapping decodes are not supported.";
92 read_cb_
= BindToCurrentLoop(read_cb
);
94 // Return empty (end-of-stream) frames if decoding has finished.
95 if (state_
== kDecodeFinished
) {
96 base::ResetAndReturn(&read_cb_
).Run(kOk
, DataBuffer::CreateEOSBuffer());
100 if (!queued_audio_frames_
.empty()) {
101 base::ResetAndReturn(&read_cb_
).Run(kOk
, queued_audio_frames_
.front());
102 queued_audio_frames_
.pop_front();
106 state_
= kPendingDemuxerRead
;
107 ReadFromDemuxerStream();
110 void DecryptingAudioDecoder::Reset(const base::Closure
& closure
) {
111 DVLOG(2) << "Reset() - state: " << state_
;
112 DCHECK(message_loop_
->BelongsToCurrentThread());
113 DCHECK(state_
== kIdle
||
114 state_
== kPendingConfigChange
||
115 state_
== kPendingDemuxerRead
||
116 state_
== kPendingDecode
||
117 state_
== kWaitingForKey
||
118 state_
== kDecodeFinished
) << state_
;
119 DCHECK(init_cb_
.is_null()); // No Reset() during pending initialization.
120 DCHECK(reset_cb_
.is_null());
124 decryptor_
->ResetDecoder(Decryptor::kAudio
);
126 // Reset() cannot complete if the read callback is still pending.
127 // Defer the resetting process in this case. The |reset_cb_| will be fired
128 // after the read callback is fired - see DoDecryptAndDecodeBuffer() and
130 if (state_
== kPendingConfigChange
||
131 state_
== kPendingDemuxerRead
||
132 state_
== kPendingDecode
) {
133 DCHECK(!read_cb_
.is_null());
137 if (state_
== kWaitingForKey
) {
138 DCHECK(!read_cb_
.is_null());
139 pending_buffer_to_decode_
= NULL
;
140 base::ResetAndReturn(&read_cb_
).Run(kAborted
, NULL
);
143 DCHECK(read_cb_
.is_null());
147 int DecryptingAudioDecoder::bits_per_channel() {
148 DCHECK(message_loop_
->BelongsToCurrentThread());
149 return bits_per_channel_
;
152 ChannelLayout
DecryptingAudioDecoder::channel_layout() {
153 DCHECK(message_loop_
->BelongsToCurrentThread());
154 return channel_layout_
;
157 int DecryptingAudioDecoder::samples_per_second() {
158 DCHECK(message_loop_
->BelongsToCurrentThread());
159 return samples_per_second_
;
162 DecryptingAudioDecoder::~DecryptingAudioDecoder() {
165 void DecryptingAudioDecoder::SetDecryptor(Decryptor
* decryptor
) {
166 DVLOG(2) << "SetDecryptor()";
167 DCHECK(message_loop_
->BelongsToCurrentThread());
168 DCHECK_EQ(state_
, kDecryptorRequested
) << state_
;
169 DCHECK(!init_cb_
.is_null());
170 DCHECK(!set_decryptor_ready_cb_
.is_null());
172 set_decryptor_ready_cb_
.Reset();
173 decryptor_
= decryptor
;
175 const AudioDecoderConfig
& input_config
=
176 demuxer_stream_
->audio_decoder_config();
177 scoped_ptr
<AudioDecoderConfig
> scoped_config(new AudioDecoderConfig());
178 scoped_config
->Initialize(input_config
.codec(),
180 input_config
.channel_layout(),
181 input_config
.samples_per_second(),
182 input_config
.extra_data(),
183 input_config
.extra_data_size(),
184 input_config
.is_encrypted(),
187 state_
= kPendingDecoderInit
;
188 decryptor_
->InitializeAudioDecoder(
189 scoped_config
.Pass(),
190 BindToCurrentLoop(base::Bind(
191 &DecryptingAudioDecoder::FinishInitialization
, this)));
194 void DecryptingAudioDecoder::FinishInitialization(bool success
) {
195 DVLOG(2) << "FinishInitialization()";
196 DCHECK(message_loop_
->BelongsToCurrentThread());
197 DCHECK_EQ(state_
, kPendingDecoderInit
) << state_
;
198 DCHECK(!init_cb_
.is_null());
199 DCHECK(reset_cb_
.is_null()); // No Reset() before initialization finished.
200 DCHECK(read_cb_
.is_null()); // No Read() before initialization finished.
203 base::ResetAndReturn(&init_cb_
).Run(DECODER_ERROR_NOT_SUPPORTED
);
204 state_
= kDecodeFinished
;
209 UpdateDecoderConfig();
211 decryptor_
->RegisterNewKeyCB(
212 Decryptor::kAudio
, BindToCurrentLoop(base::Bind(
213 &DecryptingAudioDecoder::OnKeyAdded
, this)));
216 base::ResetAndReturn(&init_cb_
).Run(PIPELINE_OK
);
219 void DecryptingAudioDecoder::FinishConfigChange(bool success
) {
220 DVLOG(2) << "FinishConfigChange()";
221 DCHECK(message_loop_
->BelongsToCurrentThread());
222 DCHECK_EQ(state_
, kPendingConfigChange
) << state_
;
223 DCHECK(!read_cb_
.is_null());
226 base::ResetAndReturn(&read_cb_
).Run(kDecodeError
, NULL
);
227 state_
= kDecodeFinished
;
228 if (!reset_cb_
.is_null())
229 base::ResetAndReturn(&reset_cb_
).Run();
233 // Config change succeeded.
234 UpdateDecoderConfig();
236 if (!reset_cb_
.is_null()) {
237 base::ResetAndReturn(&read_cb_
).Run(kAborted
, NULL
);
242 state_
= kPendingDemuxerRead
;
243 ReadFromDemuxerStream();
246 void DecryptingAudioDecoder::ReadFromDemuxerStream() {
247 DCHECK_EQ(state_
, kPendingDemuxerRead
) << state_
;
248 DCHECK(!read_cb_
.is_null());
250 demuxer_stream_
->Read(
251 base::Bind(&DecryptingAudioDecoder::DecryptAndDecodeBuffer
, this));
254 void DecryptingAudioDecoder::DecryptAndDecodeBuffer(
255 DemuxerStream::Status status
,
256 const scoped_refptr
<DecoderBuffer
>& buffer
) {
257 DVLOG(3) << "DecryptAndDecodeBuffer()";
258 DCHECK(message_loop_
->BelongsToCurrentThread());
259 DCHECK_EQ(state_
, kPendingDemuxerRead
) << state_
;
260 DCHECK(!read_cb_
.is_null());
261 DCHECK_EQ(buffer
!= NULL
, status
== DemuxerStream::kOk
) << status
;
263 if (status
== DemuxerStream::kConfigChanged
) {
264 DVLOG(2) << "DecryptAndDecodeBuffer() - kConfigChanged";
266 const AudioDecoderConfig
& input_config
=
267 demuxer_stream_
->audio_decoder_config();
268 scoped_ptr
<AudioDecoderConfig
> scoped_config(new AudioDecoderConfig());
269 scoped_config
->Initialize(input_config
.codec(),
271 input_config
.channel_layout(),
272 input_config
.samples_per_second(),
273 input_config
.extra_data(),
274 input_config
.extra_data_size(),
275 input_config
.is_encrypted(),
278 state_
= kPendingConfigChange
;
279 decryptor_
->DeinitializeDecoder(Decryptor::kAudio
);
280 decryptor_
->InitializeAudioDecoder(
281 scoped_config
.Pass(), BindToCurrentLoop(base::Bind(
282 &DecryptingAudioDecoder::FinishConfigChange
, this)));
286 if (!reset_cb_
.is_null()) {
287 base::ResetAndReturn(&read_cb_
).Run(kAborted
, NULL
);
292 if (status
== DemuxerStream::kAborted
) {
293 DVLOG(2) << "DecryptAndDecodeBuffer() - kAborted";
295 base::ResetAndReturn(&read_cb_
).Run(kAborted
, NULL
);
299 DCHECK_EQ(status
, DemuxerStream::kOk
);
301 // Initialize the |next_output_timestamp_| to be the timestamp of the first
303 if (output_timestamp_base_
== kNoTimestamp() && !buffer
->IsEndOfStream()) {
304 DCHECK_EQ(total_samples_decoded_
, 0);
305 output_timestamp_base_
= buffer
->GetTimestamp();
308 pending_buffer_to_decode_
= buffer
;
309 state_
= kPendingDecode
;
310 DecodePendingBuffer();
313 void DecryptingAudioDecoder::DecodePendingBuffer() {
314 DCHECK(message_loop_
->BelongsToCurrentThread());
315 DCHECK_EQ(state_
, kPendingDecode
) << state_
;
318 if (!pending_buffer_to_decode_
->IsEndOfStream()) {
319 buffer_size
= pending_buffer_to_decode_
->GetDataSize();
322 decryptor_
->DecryptAndDecodeAudio(
323 pending_buffer_to_decode_
,
324 base::Bind(&DecryptingAudioDecoder::DeliverFrame
, this, buffer_size
));
327 void DecryptingAudioDecoder::DeliverFrame(
329 Decryptor::Status status
,
330 const Decryptor::AudioBuffers
& frames
) {
331 // We need to force task post here because the AudioDecodeCB can be executed
332 // synchronously in Reset(). Instead of using more complicated logic in
333 // those function to fix it, why not force task post here to make everything
335 message_loop_
->PostTask(FROM_HERE
, base::Bind(
336 &DecryptingAudioDecoder::DoDeliverFrame
, this,
337 buffer_size
, status
, frames
));
340 void DecryptingAudioDecoder::DoDeliverFrame(
342 Decryptor::Status status
,
343 const Decryptor::AudioBuffers
& frames
) {
344 DVLOG(3) << "DoDeliverFrame() - status: " << status
;
345 DCHECK(message_loop_
->BelongsToCurrentThread());
346 DCHECK_EQ(state_
, kPendingDecode
) << state_
;
347 DCHECK(!read_cb_
.is_null());
348 DCHECK(pending_buffer_to_decode_
);
349 DCHECK(queued_audio_frames_
.empty());
351 bool need_to_try_again_if_nokey_is_returned
= key_added_while_decode_pending_
;
352 key_added_while_decode_pending_
= false;
354 scoped_refptr
<DecoderBuffer
> scoped_pending_buffer_to_decode
=
355 pending_buffer_to_decode_
;
356 pending_buffer_to_decode_
= NULL
;
358 if (!reset_cb_
.is_null()) {
359 base::ResetAndReturn(&read_cb_
).Run(kAborted
, NULL
);
364 DCHECK_EQ(status
== Decryptor::kSuccess
, !frames
.empty());
366 if (status
== Decryptor::kError
) {
367 DVLOG(2) << "DoDeliverFrame() - kError";
368 state_
= kDecodeFinished
;
369 base::ResetAndReturn(&read_cb_
).Run(kDecodeError
, NULL
);
373 if (status
== Decryptor::kNoKey
) {
374 DVLOG(2) << "DoDeliverFrame() - kNoKey";
375 // Set |pending_buffer_to_decode_| back as we need to try decoding the
376 // pending buffer again when new key is added to the decryptor.
377 pending_buffer_to_decode_
= scoped_pending_buffer_to_decode
;
379 if (need_to_try_again_if_nokey_is_returned
) {
380 // The |state_| is still kPendingDecode.
381 DecodePendingBuffer();
385 state_
= kWaitingForKey
;
389 // The buffer has been accepted by the decoder, let's report statistics.
391 PipelineStatistics statistics
;
392 statistics
.audio_bytes_decoded
= buffer_size
;
393 statistics_cb_
.Run(statistics
);
396 if (status
== Decryptor::kNeedMoreData
) {
397 DVLOG(2) << "DoDeliverFrame() - kNeedMoreData";
398 if (scoped_pending_buffer_to_decode
->IsEndOfStream()) {
399 state_
= kDecodeFinished
;
400 base::ResetAndReturn(&read_cb_
).Run(kOk
, DataBuffer::CreateEOSBuffer());
404 state_
= kPendingDemuxerRead
;
405 ReadFromDemuxerStream();
409 DCHECK_EQ(status
, Decryptor::kSuccess
);
410 DCHECK(!frames
.empty());
411 EnqueueFrames(frames
);
414 base::ResetAndReturn(&read_cb_
).Run(kOk
, queued_audio_frames_
.front());
415 queued_audio_frames_
.pop_front();
418 void DecryptingAudioDecoder::OnKeyAdded() {
419 DCHECK(message_loop_
->BelongsToCurrentThread());
421 if (state_
== kPendingDecode
) {
422 key_added_while_decode_pending_
= true;
426 if (state_
== kWaitingForKey
) {
427 state_
= kPendingDecode
;
428 DecodePendingBuffer();
432 void DecryptingAudioDecoder::DoReset() {
433 DCHECK(init_cb_
.is_null());
434 DCHECK(read_cb_
.is_null());
435 output_timestamp_base_
= kNoTimestamp();
436 total_samples_decoded_
= 0;
438 base::ResetAndReturn(&reset_cb_
).Run();
441 void DecryptingAudioDecoder::UpdateDecoderConfig() {
442 const AudioDecoderConfig
& config
= demuxer_stream_
->audio_decoder_config();
443 bits_per_channel_
= kSupportedBitsPerChannel
;
444 channel_layout_
= config
.channel_layout();
445 samples_per_second_
= config
.samples_per_second();
446 const int kBitsPerByte
= 8;
447 bytes_per_sample_
= ChannelLayoutToChannelCount(channel_layout_
) *
448 bits_per_channel_
/ kBitsPerByte
;
449 output_timestamp_base_
= kNoTimestamp();
450 total_samples_decoded_
= 0;
453 void DecryptingAudioDecoder::EnqueueFrames(
454 const Decryptor::AudioBuffers
& frames
) {
455 queued_audio_frames_
= frames
;
457 for (Decryptor::AudioBuffers::iterator iter
= queued_audio_frames_
.begin();
458 iter
!= queued_audio_frames_
.end();
460 scoped_refptr
<DataBuffer
>& frame
= *iter
;
462 DCHECK(!frame
->IsEndOfStream()) << "EOS frame returned.";
463 DCHECK_GT(frame
->GetDataSize(), 0) << "Empty frame returned.";
465 base::TimeDelta cur_timestamp
= output_timestamp_base_
+
466 NumberOfSamplesToDuration(total_samples_decoded_
);
467 if (IsOutOfSync(cur_timestamp
, frame
->GetTimestamp())) {
468 DVLOG(1) << "Timestamp returned by the decoder ("
469 << frame
->GetTimestamp().InMilliseconds() << " ms)"
470 << " does not match the input timestamp and number of samples"
471 << " decoded (" << cur_timestamp
.InMilliseconds() << " ms).";
473 frame
->SetTimestamp(cur_timestamp
);
475 int frame_size
= frame
->GetDataSize();
476 DCHECK_EQ(frame_size
% bytes_per_sample_
, 0) <<
477 "Decoder didn't output full samples";
478 int samples_decoded
= frame_size
/ bytes_per_sample_
;
479 total_samples_decoded_
+= samples_decoded
;
481 base::TimeDelta next_timestamp
= output_timestamp_base_
+
482 NumberOfSamplesToDuration(total_samples_decoded_
);
483 base::TimeDelta duration
= next_timestamp
- cur_timestamp
;
484 frame
->SetDuration(duration
);
488 base::TimeDelta
DecryptingAudioDecoder::NumberOfSamplesToDuration(
489 int number_of_samples
) const {
490 DCHECK(samples_per_second_
);
491 return base::TimeDelta::FromMicroseconds(base::Time::kMicrosecondsPerSecond
*
493 samples_per_second_
);