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/single_thread_task_runner.h"
14 #include "media/base/audio_buffer.h"
15 #include "media/base/audio_decoder_config.h"
16 #include "media/base/audio_timestamp_helper.h"
17 #include "media/base/bind_to_current_loop.h"
18 #include "media/base/buffers.h"
19 #include "media/base/decoder_buffer.h"
20 #include "media/base/decryptor.h"
21 #include "media/base/demuxer_stream.h"
22 #include "media/base/pipeline.h"
26 const int DecryptingAudioDecoder::kSupportedBitsPerChannel
= 16;
28 static inline bool IsOutOfSync(const base::TimeDelta
& timestamp_1
,
29 const base::TimeDelta
& timestamp_2
) {
30 // Out of sync of 100ms would be pretty noticeable and we should keep any
32 const int64 kOutOfSyncThresholdInMilliseconds
= 100;
33 return std::abs(timestamp_1
.InMilliseconds() - timestamp_2
.InMilliseconds()) >
34 kOutOfSyncThresholdInMilliseconds
;
37 DecryptingAudioDecoder::DecryptingAudioDecoder(
38 const scoped_refptr
<base::SingleThreadTaskRunner
>& task_runner
,
39 const SetDecryptorReadyCB
& set_decryptor_ready_cb
)
40 : task_runner_(task_runner
),
42 state_(kUninitialized
),
43 demuxer_stream_(NULL
),
44 set_decryptor_ready_cb_(set_decryptor_ready_cb
),
46 key_added_while_decode_pending_(false),
48 channel_layout_(CHANNEL_LAYOUT_NONE
),
49 samples_per_second_(0) {
52 void DecryptingAudioDecoder::Initialize(
53 DemuxerStream
* stream
,
54 const PipelineStatusCB
& status_cb
,
55 const StatisticsCB
& statistics_cb
) {
56 DVLOG(2) << "Initialize()";
57 DCHECK(task_runner_
->BelongsToCurrentThread());
58 DCHECK_EQ(state_
, kUninitialized
) << state_
;
61 weak_this_
= weak_factory_
.GetWeakPtr();
62 init_cb_
= BindToCurrentLoop(status_cb
);
64 const AudioDecoderConfig
& config
= stream
->audio_decoder_config();
65 if (!config
.IsValidConfig()) {
66 DLOG(ERROR
) << "Invalid audio stream config.";
67 base::ResetAndReturn(&init_cb_
).Run(PIPELINE_ERROR_DECODE
);
71 // DecryptingAudioDecoder only accepts potentially encrypted stream.
72 if (!config
.is_encrypted()) {
73 base::ResetAndReturn(&init_cb_
).Run(DECODER_ERROR_NOT_SUPPORTED
);
77 DCHECK(!demuxer_stream_
);
78 demuxer_stream_
= stream
;
79 statistics_cb_
= statistics_cb
;
81 state_
= kDecryptorRequested
;
82 set_decryptor_ready_cb_
.Run(BindToCurrentLoop(
83 base::Bind(&DecryptingAudioDecoder::SetDecryptor
, weak_this_
)));
86 void DecryptingAudioDecoder::Read(const ReadCB
& read_cb
) {
88 DCHECK(task_runner_
->BelongsToCurrentThread());
89 DCHECK(state_
== kIdle
|| state_
== kDecodeFinished
) << state_
;
90 DCHECK(!read_cb
.is_null());
91 CHECK(read_cb_
.is_null()) << "Overlapping decodes are not supported.";
93 read_cb_
= BindToCurrentLoop(read_cb
);
95 // Return empty (end-of-stream) frames if decoding has finished.
96 if (state_
== kDecodeFinished
) {
97 base::ResetAndReturn(&read_cb_
).Run(kOk
, AudioBuffer::CreateEOSBuffer());
101 if (!queued_audio_frames_
.empty()) {
102 base::ResetAndReturn(&read_cb_
).Run(kOk
, queued_audio_frames_
.front());
103 queued_audio_frames_
.pop_front();
107 state_
= kPendingDemuxerRead
;
108 ReadFromDemuxerStream();
111 void DecryptingAudioDecoder::Reset(const base::Closure
& closure
) {
112 DVLOG(2) << "Reset() - state: " << state_
;
113 DCHECK(task_runner_
->BelongsToCurrentThread());
114 DCHECK(state_
== kIdle
||
115 state_
== kPendingConfigChange
||
116 state_
== kPendingDemuxerRead
||
117 state_
== kPendingDecode
||
118 state_
== kWaitingForKey
||
119 state_
== kDecodeFinished
) << state_
;
120 DCHECK(init_cb_
.is_null()); // No Reset() during pending initialization.
121 DCHECK(reset_cb_
.is_null());
123 reset_cb_
= BindToCurrentLoop(closure
);
125 decryptor_
->ResetDecoder(Decryptor::kAudio
);
127 // Reset() cannot complete if the read callback is still pending.
128 // Defer the resetting process in this case. The |reset_cb_| will be fired
129 // after the read callback is fired - see DecryptAndDecodeBuffer() and
131 if (state_
== kPendingConfigChange
||
132 state_
== kPendingDemuxerRead
||
133 state_
== kPendingDecode
) {
134 DCHECK(!read_cb_
.is_null());
138 if (state_
== kWaitingForKey
) {
139 DCHECK(!read_cb_
.is_null());
140 pending_buffer_to_decode_
= NULL
;
141 base::ResetAndReturn(&read_cb_
).Run(kAborted
, NULL
);
144 DCHECK(read_cb_
.is_null());
148 void DecryptingAudioDecoder::Stop(const base::Closure
& closure
) {
149 DVLOG(2) << "Stop() - state: " << state_
;
150 DCHECK(task_runner_
->BelongsToCurrentThread());
152 // Invalidate all weak pointers so that pending callbacks won't be fired into
154 weak_factory_
.InvalidateWeakPtrs();
157 decryptor_
->DeinitializeDecoder(Decryptor::kAudio
);
160 if (!set_decryptor_ready_cb_
.is_null())
161 base::ResetAndReturn(&set_decryptor_ready_cb_
).Run(DecryptorReadyCB());
162 pending_buffer_to_decode_
= NULL
;
163 if (!init_cb_
.is_null())
164 base::ResetAndReturn(&init_cb_
).Run(DECODER_ERROR_NOT_SUPPORTED
);
165 if (!read_cb_
.is_null())
166 base::ResetAndReturn(&read_cb_
).Run(kAborted
, NULL
);
167 if (!reset_cb_
.is_null())
168 base::ResetAndReturn(&reset_cb_
).Run();
171 task_runner_
->PostTask(FROM_HERE
, closure
);
174 int DecryptingAudioDecoder::bits_per_channel() {
175 DCHECK(task_runner_
->BelongsToCurrentThread());
176 return bits_per_channel_
;
179 ChannelLayout
DecryptingAudioDecoder::channel_layout() {
180 DCHECK(task_runner_
->BelongsToCurrentThread());
181 return channel_layout_
;
184 int DecryptingAudioDecoder::samples_per_second() {
185 DCHECK(task_runner_
->BelongsToCurrentThread());
186 return samples_per_second_
;
189 DecryptingAudioDecoder::~DecryptingAudioDecoder() {
190 DCHECK(state_
== kUninitialized
|| state_
== kStopped
) << state_
;
193 void DecryptingAudioDecoder::SetDecryptor(Decryptor
* decryptor
) {
194 DVLOG(2) << "SetDecryptor()";
195 DCHECK(task_runner_
->BelongsToCurrentThread());
196 DCHECK_EQ(state_
, kDecryptorRequested
) << state_
;
197 DCHECK(!init_cb_
.is_null());
198 DCHECK(!set_decryptor_ready_cb_
.is_null());
200 set_decryptor_ready_cb_
.Reset();
203 base::ResetAndReturn(&init_cb_
).Run(DECODER_ERROR_NOT_SUPPORTED
);
204 // TODO(xhwang): Add kError state. See http://crbug.com/251503
209 decryptor_
= decryptor
;
211 const AudioDecoderConfig
& input_config
=
212 demuxer_stream_
->audio_decoder_config();
213 AudioDecoderConfig config
;
214 config
.Initialize(input_config
.codec(),
216 input_config
.channel_layout(),
217 input_config
.samples_per_second(),
218 input_config
.extra_data(),
219 input_config
.extra_data_size(),
220 input_config
.is_encrypted(),
225 state_
= kPendingDecoderInit
;
226 decryptor_
->InitializeAudioDecoder(
228 BindToCurrentLoop(base::Bind(
229 &DecryptingAudioDecoder::FinishInitialization
, weak_this_
)));
232 void DecryptingAudioDecoder::FinishInitialization(bool success
) {
233 DVLOG(2) << "FinishInitialization()";
234 DCHECK(task_runner_
->BelongsToCurrentThread());
235 DCHECK_EQ(state_
, kPendingDecoderInit
) << state_
;
236 DCHECK(!init_cb_
.is_null());
237 DCHECK(reset_cb_
.is_null()); // No Reset() before initialization finished.
238 DCHECK(read_cb_
.is_null()); // No Read() before initialization finished.
241 base::ResetAndReturn(&init_cb_
).Run(DECODER_ERROR_NOT_SUPPORTED
);
247 UpdateDecoderConfig();
249 decryptor_
->RegisterNewKeyCB(
252 base::Bind(&DecryptingAudioDecoder::OnKeyAdded
, weak_this_
)));
255 base::ResetAndReturn(&init_cb_
).Run(PIPELINE_OK
);
258 void DecryptingAudioDecoder::FinishConfigChange(bool success
) {
259 DVLOG(2) << "FinishConfigChange()";
260 DCHECK(task_runner_
->BelongsToCurrentThread());
261 DCHECK_EQ(state_
, kPendingConfigChange
) << state_
;
262 DCHECK(!read_cb_
.is_null());
265 base::ResetAndReturn(&read_cb_
).Run(kDecodeError
, NULL
);
266 state_
= kDecodeFinished
;
267 if (!reset_cb_
.is_null())
268 base::ResetAndReturn(&reset_cb_
).Run();
272 // Config change succeeded.
273 UpdateDecoderConfig();
275 if (!reset_cb_
.is_null()) {
276 base::ResetAndReturn(&read_cb_
).Run(kAborted
, NULL
);
281 state_
= kPendingDemuxerRead
;
282 ReadFromDemuxerStream();
285 void DecryptingAudioDecoder::ReadFromDemuxerStream() {
286 DCHECK_EQ(state_
, kPendingDemuxerRead
) << state_
;
287 DCHECK(!read_cb_
.is_null());
289 demuxer_stream_
->Read(
290 base::Bind(&DecryptingAudioDecoder::DecryptAndDecodeBuffer
, weak_this_
));
293 void DecryptingAudioDecoder::DecryptAndDecodeBuffer(
294 DemuxerStream::Status status
,
295 const scoped_refptr
<DecoderBuffer
>& buffer
) {
296 DVLOG(3) << "DecryptAndDecodeBuffer()";
297 DCHECK(task_runner_
->BelongsToCurrentThread());
298 DCHECK_EQ(state_
, kPendingDemuxerRead
) << state_
;
299 DCHECK(!read_cb_
.is_null());
300 DCHECK_EQ(buffer
.get() != NULL
, status
== DemuxerStream::kOk
) << status
;
302 if (status
== DemuxerStream::kConfigChanged
) {
303 DVLOG(2) << "DecryptAndDecodeBuffer() - kConfigChanged";
305 const AudioDecoderConfig
& input_config
=
306 demuxer_stream_
->audio_decoder_config();
307 AudioDecoderConfig config
;
308 config
.Initialize(input_config
.codec(),
310 input_config
.channel_layout(),
311 input_config
.samples_per_second(),
312 input_config
.extra_data(),
313 input_config
.extra_data_size(),
314 input_config
.is_encrypted(),
319 state_
= kPendingConfigChange
;
320 decryptor_
->DeinitializeDecoder(Decryptor::kAudio
);
321 decryptor_
->InitializeAudioDecoder(
322 config
, BindToCurrentLoop(base::Bind(
323 &DecryptingAudioDecoder::FinishConfigChange
, weak_this_
)));
327 if (!reset_cb_
.is_null()) {
328 base::ResetAndReturn(&read_cb_
).Run(kAborted
, NULL
);
333 if (status
== DemuxerStream::kAborted
) {
334 DVLOG(2) << "DecryptAndDecodeBuffer() - kAborted";
336 base::ResetAndReturn(&read_cb_
).Run(kAborted
, NULL
);
340 DCHECK_EQ(status
, DemuxerStream::kOk
);
342 // Initialize the |next_output_timestamp_| to be the timestamp of the first
344 if (timestamp_helper_
->base_timestamp() == kNoTimestamp() &&
345 !buffer
->end_of_stream()) {
346 timestamp_helper_
->SetBaseTimestamp(buffer
->timestamp());
349 pending_buffer_to_decode_
= buffer
;
350 state_
= kPendingDecode
;
351 DecodePendingBuffer();
354 void DecryptingAudioDecoder::DecodePendingBuffer() {
355 DCHECK(task_runner_
->BelongsToCurrentThread());
356 DCHECK_EQ(state_
, kPendingDecode
) << state_
;
359 if (!pending_buffer_to_decode_
->end_of_stream()) {
360 buffer_size
= pending_buffer_to_decode_
->data_size();
363 decryptor_
->DecryptAndDecodeAudio(
364 pending_buffer_to_decode_
,
365 BindToCurrentLoop(base::Bind(
366 &DecryptingAudioDecoder::DeliverFrame
, weak_this_
, buffer_size
)));
369 void DecryptingAudioDecoder::DeliverFrame(
371 Decryptor::Status status
,
372 const Decryptor::AudioBuffers
& frames
) {
373 DVLOG(3) << "DeliverFrame() - status: " << status
;
374 DCHECK(task_runner_
->BelongsToCurrentThread());
375 DCHECK_EQ(state_
, kPendingDecode
) << state_
;
376 DCHECK(!read_cb_
.is_null());
377 DCHECK(pending_buffer_to_decode_
.get());
378 DCHECK(queued_audio_frames_
.empty());
380 bool need_to_try_again_if_nokey_is_returned
= key_added_while_decode_pending_
;
381 key_added_while_decode_pending_
= false;
383 scoped_refptr
<DecoderBuffer
> scoped_pending_buffer_to_decode
=
384 pending_buffer_to_decode_
;
385 pending_buffer_to_decode_
= NULL
;
387 if (!reset_cb_
.is_null()) {
388 base::ResetAndReturn(&read_cb_
).Run(kAborted
, NULL
);
393 DCHECK_EQ(status
== Decryptor::kSuccess
, !frames
.empty());
395 if (status
== Decryptor::kError
) {
396 DVLOG(2) << "DeliverFrame() - kError";
397 state_
= kDecodeFinished
;
398 base::ResetAndReturn(&read_cb_
).Run(kDecodeError
, NULL
);
402 if (status
== Decryptor::kNoKey
) {
403 DVLOG(2) << "DeliverFrame() - kNoKey";
404 // Set |pending_buffer_to_decode_| back as we need to try decoding the
405 // pending buffer again when new key is added to the decryptor.
406 pending_buffer_to_decode_
= scoped_pending_buffer_to_decode
;
408 if (need_to_try_again_if_nokey_is_returned
) {
409 // The |state_| is still kPendingDecode.
410 DecodePendingBuffer();
414 state_
= kWaitingForKey
;
418 // The buffer has been accepted by the decoder, let's report statistics.
420 PipelineStatistics statistics
;
421 statistics
.audio_bytes_decoded
= buffer_size
;
422 statistics_cb_
.Run(statistics
);
425 if (status
== Decryptor::kNeedMoreData
) {
426 DVLOG(2) << "DeliverFrame() - kNeedMoreData";
427 if (scoped_pending_buffer_to_decode
->end_of_stream()) {
428 state_
= kDecodeFinished
;
429 base::ResetAndReturn(&read_cb_
).Run(kOk
, AudioBuffer::CreateEOSBuffer());
433 state_
= kPendingDemuxerRead
;
434 ReadFromDemuxerStream();
438 DCHECK_EQ(status
, Decryptor::kSuccess
);
439 DCHECK(!frames
.empty());
440 EnqueueFrames(frames
);
443 base::ResetAndReturn(&read_cb_
).Run(kOk
, queued_audio_frames_
.front());
444 queued_audio_frames_
.pop_front();
447 void DecryptingAudioDecoder::OnKeyAdded() {
448 DCHECK(task_runner_
->BelongsToCurrentThread());
450 if (state_
== kPendingDecode
) {
451 key_added_while_decode_pending_
= true;
455 if (state_
== kWaitingForKey
) {
456 state_
= kPendingDecode
;
457 DecodePendingBuffer();
461 void DecryptingAudioDecoder::DoReset() {
462 DCHECK(init_cb_
.is_null());
463 DCHECK(read_cb_
.is_null());
464 timestamp_helper_
->SetBaseTimestamp(kNoTimestamp());
466 base::ResetAndReturn(&reset_cb_
).Run();
469 void DecryptingAudioDecoder::UpdateDecoderConfig() {
470 const AudioDecoderConfig
& config
= demuxer_stream_
->audio_decoder_config();
471 bits_per_channel_
= kSupportedBitsPerChannel
;
472 channel_layout_
= config
.channel_layout();
473 samples_per_second_
= config
.samples_per_second();
474 timestamp_helper_
.reset(new AudioTimestampHelper(samples_per_second_
));
477 void DecryptingAudioDecoder::EnqueueFrames(
478 const Decryptor::AudioBuffers
& frames
) {
479 queued_audio_frames_
= frames
;
481 for (Decryptor::AudioBuffers::iterator iter
= queued_audio_frames_
.begin();
482 iter
!= queued_audio_frames_
.end();
484 scoped_refptr
<AudioBuffer
>& frame
= *iter
;
486 DCHECK(!frame
->end_of_stream()) << "EOS frame returned.";
487 DCHECK_GT(frame
->frame_count(), 0) << "Empty frame returned.";
489 base::TimeDelta current_time
= timestamp_helper_
->GetTimestamp();
490 if (IsOutOfSync(current_time
, frame
->timestamp())) {
491 DVLOG(1) << "Timestamp returned by the decoder ("
492 << frame
->timestamp().InMilliseconds() << " ms)"
493 << " does not match the input timestamp and number of samples"
494 << " decoded (" << current_time
.InMilliseconds() << " ms).";
497 frame
->set_timestamp(current_time
);
499 timestamp_helper_
->GetFrameDuration(frame
->frame_count()));
500 timestamp_helper_
->AddFrames(frame
->frame_count());