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
),
41 state_(kUninitialized
),
42 set_decryptor_ready_cb_(set_decryptor_ready_cb
),
44 key_added_while_decode_pending_(false),
45 weak_factory_(this) {}
47 void DecryptingAudioDecoder::Initialize(const AudioDecoderConfig
& config
,
48 const PipelineStatusCB
& status_cb
,
49 const OutputCB
& output_cb
) {
50 DVLOG(2) << "Initialize()";
51 DCHECK(task_runner_
->BelongsToCurrentThread());
52 DCHECK(decode_cb_
.is_null());
53 DCHECK(reset_cb_
.is_null());
55 weak_this_
= weak_factory_
.GetWeakPtr();
56 init_cb_
= BindToCurrentLoop(status_cb
);
57 output_cb_
= BindToCurrentLoop(output_cb
);
59 if (!config
.IsValidConfig()) {
60 DLOG(ERROR
) << "Invalid audio stream config.";
61 base::ResetAndReturn(&init_cb_
).Run(PIPELINE_ERROR_DECODE
);
65 // DecryptingAudioDecoder only accepts potentially encrypted stream.
66 if (!config
.is_encrypted()) {
67 base::ResetAndReturn(&init_cb_
).Run(DECODER_ERROR_NOT_SUPPORTED
);
73 if (state_
== kUninitialized
) {
74 state_
= kDecryptorRequested
;
75 set_decryptor_ready_cb_
.Run(BindToCurrentLoop(
76 base::Bind(&DecryptingAudioDecoder::SetDecryptor
, weak_this_
)));
80 // Reinitialization (i.e. upon a config change)
81 decryptor_
->DeinitializeDecoder(Decryptor::kAudio
);
85 void DecryptingAudioDecoder::Decode(const scoped_refptr
<DecoderBuffer
>& buffer
,
86 const DecodeCB
& decode_cb
) {
87 DVLOG(3) << "Decode()";
88 DCHECK(task_runner_
->BelongsToCurrentThread());
89 DCHECK(state_
== kIdle
|| state_
== kDecodeFinished
) << state_
;
90 DCHECK(!decode_cb
.is_null());
91 CHECK(decode_cb_
.is_null()) << "Overlapping decodes are not supported.";
93 decode_cb_
= BindToCurrentLoop(decode_cb
);
95 // Return empty (end-of-stream) frames if decoding has finished.
96 if (state_
== kDecodeFinished
) {
97 output_cb_
.Run(AudioBuffer::CreateEOSBuffer());
98 base::ResetAndReturn(&decode_cb_
).Run(kOk
);
102 // Initialize the |next_output_timestamp_| to be the timestamp of the first
104 if (timestamp_helper_
->base_timestamp() == kNoTimestamp() &&
105 !buffer
->end_of_stream()) {
106 timestamp_helper_
->SetBaseTimestamp(buffer
->timestamp());
109 pending_buffer_to_decode_
= buffer
;
110 state_
= kPendingDecode
;
111 DecodePendingBuffer();
114 void DecryptingAudioDecoder::Reset(const base::Closure
& closure
) {
115 DVLOG(2) << "Reset() - state: " << state_
;
116 DCHECK(task_runner_
->BelongsToCurrentThread());
117 DCHECK(state_
== kIdle
||
118 state_
== kPendingDecode
||
119 state_
== kWaitingForKey
||
120 state_
== kDecodeFinished
) << state_
;
121 DCHECK(init_cb_
.is_null()); // No Reset() during pending initialization.
122 DCHECK(reset_cb_
.is_null());
124 reset_cb_
= BindToCurrentLoop(closure
);
126 decryptor_
->ResetDecoder(Decryptor::kAudio
);
128 // Reset() cannot complete if the read callback is still pending.
129 // Defer the resetting process in this case. The |reset_cb_| will be fired
130 // after the read callback is fired - see DecryptAndDecodeBuffer() and
132 if (state_
== kPendingDecode
) {
133 DCHECK(!decode_cb_
.is_null());
137 if (state_
== kWaitingForKey
) {
138 DCHECK(!decode_cb_
.is_null());
139 pending_buffer_to_decode_
= NULL
;
140 base::ResetAndReturn(&decode_cb_
).Run(kAborted
);
143 DCHECK(decode_cb_
.is_null());
147 void DecryptingAudioDecoder::Stop() {
148 DVLOG(2) << "Stop() - state: " << state_
;
149 DCHECK(task_runner_
->BelongsToCurrentThread());
151 // Invalidate all weak pointers so that pending callbacks won't be fired into
153 weak_factory_
.InvalidateWeakPtrs();
156 decryptor_
->DeinitializeDecoder(Decryptor::kAudio
);
159 if (!set_decryptor_ready_cb_
.is_null())
160 base::ResetAndReturn(&set_decryptor_ready_cb_
).Run(DecryptorReadyCB());
161 pending_buffer_to_decode_
= NULL
;
162 if (!init_cb_
.is_null())
163 base::ResetAndReturn(&init_cb_
).Run(DECODER_ERROR_NOT_SUPPORTED
);
164 if (!decode_cb_
.is_null())
165 base::ResetAndReturn(&decode_cb_
).Run(kAborted
);
166 if (!reset_cb_
.is_null())
167 base::ResetAndReturn(&reset_cb_
).Run();
172 DecryptingAudioDecoder::~DecryptingAudioDecoder() {
173 DCHECK(state_
== kUninitialized
|| state_
== kStopped
) << state_
;
176 void DecryptingAudioDecoder::SetDecryptor(Decryptor
* decryptor
) {
177 DVLOG(2) << "SetDecryptor()";
178 DCHECK(task_runner_
->BelongsToCurrentThread());
179 DCHECK_EQ(state_
, kDecryptorRequested
) << state_
;
180 DCHECK(!init_cb_
.is_null());
181 DCHECK(!set_decryptor_ready_cb_
.is_null());
183 set_decryptor_ready_cb_
.Reset();
186 base::ResetAndReturn(&init_cb_
).Run(DECODER_ERROR_NOT_SUPPORTED
);
187 // TODO(xhwang): Add kError state. See http://crbug.com/251503
192 decryptor_
= decryptor
;
197 void DecryptingAudioDecoder::InitializeDecoder() {
198 state_
= kPendingDecoderInit
;
199 decryptor_
->InitializeAudioDecoder(
201 BindToCurrentLoop(base::Bind(
202 &DecryptingAudioDecoder::FinishInitialization
, weak_this_
)));
205 void DecryptingAudioDecoder::FinishInitialization(bool success
) {
206 DVLOG(2) << "FinishInitialization()";
207 DCHECK(task_runner_
->BelongsToCurrentThread());
208 DCHECK(state_
== kPendingDecoderInit
) << state_
;
209 DCHECK(!init_cb_
.is_null());
210 DCHECK(reset_cb_
.is_null()); // No Reset() before initialization finished.
211 DCHECK(decode_cb_
.is_null()); // No Decode() before initialization finished.
214 base::ResetAndReturn(&init_cb_
).Run(DECODER_ERROR_NOT_SUPPORTED
);
220 timestamp_helper_
.reset(
221 new AudioTimestampHelper(config_
.samples_per_second()));
223 decryptor_
->RegisterNewKeyCB(
226 base::Bind(&DecryptingAudioDecoder::OnKeyAdded
, weak_this_
)));
229 base::ResetAndReturn(&init_cb_
).Run(PIPELINE_OK
);
232 void DecryptingAudioDecoder::DecodePendingBuffer() {
233 DCHECK(task_runner_
->BelongsToCurrentThread());
234 DCHECK_EQ(state_
, kPendingDecode
) << state_
;
237 if (!pending_buffer_to_decode_
->end_of_stream()) {
238 buffer_size
= pending_buffer_to_decode_
->data_size();
241 decryptor_
->DecryptAndDecodeAudio(
242 pending_buffer_to_decode_
,
243 BindToCurrentLoop(base::Bind(
244 &DecryptingAudioDecoder::DeliverFrame
, weak_this_
, buffer_size
)));
247 void DecryptingAudioDecoder::DeliverFrame(
249 Decryptor::Status status
,
250 const Decryptor::AudioBuffers
& frames
) {
251 DVLOG(3) << "DeliverFrame() - status: " << status
;
252 DCHECK(task_runner_
->BelongsToCurrentThread());
253 DCHECK_EQ(state_
, kPendingDecode
) << state_
;
254 DCHECK(!decode_cb_
.is_null());
255 DCHECK(pending_buffer_to_decode_
.get());
257 bool need_to_try_again_if_nokey_is_returned
= key_added_while_decode_pending_
;
258 key_added_while_decode_pending_
= false;
260 scoped_refptr
<DecoderBuffer
> scoped_pending_buffer_to_decode
=
261 pending_buffer_to_decode_
;
262 pending_buffer_to_decode_
= NULL
;
264 if (!reset_cb_
.is_null()) {
265 base::ResetAndReturn(&decode_cb_
).Run(kAborted
);
270 DCHECK_EQ(status
== Decryptor::kSuccess
, !frames
.empty());
272 if (status
== Decryptor::kError
) {
273 DVLOG(2) << "DeliverFrame() - kError";
274 state_
= kDecodeFinished
; // TODO add kError state
275 base::ResetAndReturn(&decode_cb_
).Run(kDecodeError
);
279 if (status
== Decryptor::kNoKey
) {
280 DVLOG(2) << "DeliverFrame() - kNoKey";
281 // Set |pending_buffer_to_decode_| back as we need to try decoding the
282 // pending buffer again when new key is added to the decryptor.
283 pending_buffer_to_decode_
= scoped_pending_buffer_to_decode
;
285 if (need_to_try_again_if_nokey_is_returned
) {
286 // The |state_| is still kPendingDecode.
287 DecodePendingBuffer();
291 state_
= kWaitingForKey
;
295 if (status
== Decryptor::kNeedMoreData
) {
296 DVLOG(2) << "DeliverFrame() - kNeedMoreData";
297 state_
= scoped_pending_buffer_to_decode
->end_of_stream() ? kDecodeFinished
299 base::ResetAndReturn(&decode_cb_
).Run(kOk
);
303 DCHECK_EQ(status
, Decryptor::kSuccess
);
304 DCHECK(!frames
.empty());
305 ProcessDecodedFrames(frames
);
307 if (scoped_pending_buffer_to_decode
->end_of_stream()) {
308 // Set |pending_buffer_to_decode_| back as we need to keep flushing the
309 // decryptor until kNeedMoreData is returned.
310 pending_buffer_to_decode_
= scoped_pending_buffer_to_decode
;
311 DecodePendingBuffer();
316 base::ResetAndReturn(&decode_cb_
).Run(kOk
);
319 void DecryptingAudioDecoder::OnKeyAdded() {
320 DCHECK(task_runner_
->BelongsToCurrentThread());
322 if (state_
== kPendingDecode
) {
323 key_added_while_decode_pending_
= true;
327 if (state_
== kWaitingForKey
) {
328 state_
= kPendingDecode
;
329 DecodePendingBuffer();
333 void DecryptingAudioDecoder::DoReset() {
334 DCHECK(init_cb_
.is_null());
335 DCHECK(decode_cb_
.is_null());
336 timestamp_helper_
->SetBaseTimestamp(kNoTimestamp());
338 base::ResetAndReturn(&reset_cb_
).Run();
341 void DecryptingAudioDecoder::ProcessDecodedFrames(
342 const Decryptor::AudioBuffers
& frames
) {
343 for (Decryptor::AudioBuffers::const_iterator iter
= frames
.begin();
344 iter
!= frames
.end();
346 scoped_refptr
<AudioBuffer
> frame
= *iter
;
348 DCHECK(!frame
->end_of_stream()) << "EOS frame returned.";
349 DCHECK_GT(frame
->frame_count(), 0) << "Empty frame returned.";
351 base::TimeDelta current_time
= timestamp_helper_
->GetTimestamp();
352 if (IsOutOfSync(current_time
, frame
->timestamp())) {
353 DVLOG(1) << "Timestamp returned by the decoder ("
354 << frame
->timestamp().InMilliseconds() << " ms)"
355 << " does not match the input timestamp and number of samples"
356 << " decoded (" << current_time
.InMilliseconds() << " ms).";
359 frame
->set_timestamp(current_time
);
360 timestamp_helper_
->AddFrames(frame
->frame_count());
362 output_cb_
.Run(frame
);