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/pipeline.h"
24 static inline bool IsOutOfSync(const base::TimeDelta
& timestamp_1
,
25 const base::TimeDelta
& timestamp_2
) {
26 // Out of sync of 100ms would be pretty noticeable and we should keep any
28 const int64 kOutOfSyncThresholdInMilliseconds
= 100;
29 return std::abs(timestamp_1
.InMilliseconds() - timestamp_2
.InMilliseconds()) >
30 kOutOfSyncThresholdInMilliseconds
;
33 DecryptingAudioDecoder::DecryptingAudioDecoder(
34 const scoped_refptr
<base::SingleThreadTaskRunner
>& task_runner
,
35 const SetDecryptorReadyCB
& set_decryptor_ready_cb
,
36 const base::Closure
& waiting_for_decryption_key_cb
)
37 : task_runner_(task_runner
),
38 state_(kUninitialized
),
39 waiting_for_decryption_key_cb_(waiting_for_decryption_key_cb
),
40 set_decryptor_ready_cb_(set_decryptor_ready_cb
),
42 key_added_while_decode_pending_(false),
46 std::string
DecryptingAudioDecoder::GetDisplayName() const {
47 return "DecryptingAudioDecoder";
50 void DecryptingAudioDecoder::Initialize(const AudioDecoderConfig
& config
,
51 const PipelineStatusCB
& status_cb
,
52 const OutputCB
& output_cb
) {
53 DVLOG(2) << "Initialize()";
54 DCHECK(task_runner_
->BelongsToCurrentThread());
55 DCHECK(decode_cb_
.is_null());
56 DCHECK(reset_cb_
.is_null());
58 weak_this_
= weak_factory_
.GetWeakPtr();
59 init_cb_
= BindToCurrentLoop(status_cb
);
60 output_cb_
= BindToCurrentLoop(output_cb
);
62 if (!config
.IsValidConfig()) {
63 DLOG(ERROR
) << "Invalid audio stream config.";
64 base::ResetAndReturn(&init_cb_
).Run(PIPELINE_ERROR_DECODE
);
68 // DecryptingAudioDecoder only accepts potentially encrypted stream.
69 if (!config
.is_encrypted()) {
70 base::ResetAndReturn(&init_cb_
).Run(DECODER_ERROR_NOT_SUPPORTED
);
76 if (state_
== kUninitialized
) {
77 state_
= kDecryptorRequested
;
78 set_decryptor_ready_cb_
.Run(BindToCurrentLoop(
79 base::Bind(&DecryptingAudioDecoder::SetDecryptor
, weak_this_
)));
83 // Reinitialization (i.e. upon a config change)
84 decryptor_
->DeinitializeDecoder(Decryptor::kAudio
);
88 void DecryptingAudioDecoder::Decode(const scoped_refptr
<DecoderBuffer
>& buffer
,
89 const DecodeCB
& decode_cb
) {
90 DVLOG(3) << "Decode()";
91 DCHECK(task_runner_
->BelongsToCurrentThread());
92 DCHECK(state_
== kIdle
|| state_
== kDecodeFinished
) << state_
;
93 DCHECK(!decode_cb
.is_null());
94 CHECK(decode_cb_
.is_null()) << "Overlapping decodes are not supported.";
96 decode_cb_
= BindToCurrentLoop(decode_cb
);
98 // Return empty (end-of-stream) frames if decoding has finished.
99 if (state_
== kDecodeFinished
) {
100 output_cb_
.Run(AudioBuffer::CreateEOSBuffer());
101 base::ResetAndReturn(&decode_cb_
).Run(kOk
);
105 // Initialize the |next_output_timestamp_| to be the timestamp of the first
107 if (timestamp_helper_
->base_timestamp() == kNoTimestamp() &&
108 !buffer
->end_of_stream()) {
109 timestamp_helper_
->SetBaseTimestamp(buffer
->timestamp());
112 pending_buffer_to_decode_
= buffer
;
113 state_
= kPendingDecode
;
114 DecodePendingBuffer();
117 void DecryptingAudioDecoder::Reset(const base::Closure
& closure
) {
118 DVLOG(2) << "Reset() - state: " << state_
;
119 DCHECK(task_runner_
->BelongsToCurrentThread());
120 DCHECK(state_
== kIdle
||
121 state_
== kPendingDecode
||
122 state_
== kWaitingForKey
||
123 state_
== kDecodeFinished
) << state_
;
124 DCHECK(init_cb_
.is_null()); // No Reset() during pending initialization.
125 DCHECK(reset_cb_
.is_null());
127 reset_cb_
= BindToCurrentLoop(closure
);
129 decryptor_
->ResetDecoder(Decryptor::kAudio
);
131 // Reset() cannot complete if the read callback is still pending.
132 // Defer the resetting process in this case. The |reset_cb_| will be fired
133 // after the read callback is fired - see DecryptAndDecodeBuffer() and
135 if (state_
== kPendingDecode
) {
136 DCHECK(!decode_cb_
.is_null());
140 if (state_
== kWaitingForKey
) {
141 DCHECK(!decode_cb_
.is_null());
142 pending_buffer_to_decode_
= NULL
;
143 base::ResetAndReturn(&decode_cb_
).Run(kAborted
);
146 DCHECK(decode_cb_
.is_null());
150 DecryptingAudioDecoder::~DecryptingAudioDecoder() {
151 DVLOG(2) << __FUNCTION__
;
152 DCHECK(task_runner_
->BelongsToCurrentThread());
154 if (state_
== kUninitialized
)
158 decryptor_
->DeinitializeDecoder(Decryptor::kAudio
);
161 if (!set_decryptor_ready_cb_
.is_null())
162 base::ResetAndReturn(&set_decryptor_ready_cb_
).Run(DecryptorReadyCB());
163 pending_buffer_to_decode_
= NULL
;
164 if (!init_cb_
.is_null())
165 base::ResetAndReturn(&init_cb_
).Run(DECODER_ERROR_NOT_SUPPORTED
);
166 if (!decode_cb_
.is_null())
167 base::ResetAndReturn(&decode_cb_
).Run(kAborted
);
168 if (!reset_cb_
.is_null())
169 base::ResetAndReturn(&reset_cb_
).Run();
172 void DecryptingAudioDecoder::SetDecryptor(
173 Decryptor
* decryptor
,
174 const DecryptorAttachedCB
& decryptor_attached_cb
) {
175 DVLOG(2) << "SetDecryptor()";
176 DCHECK(task_runner_
->BelongsToCurrentThread());
177 DCHECK_EQ(state_
, kDecryptorRequested
) << state_
;
178 DCHECK(!init_cb_
.is_null());
179 DCHECK(!set_decryptor_ready_cb_
.is_null());
181 set_decryptor_ready_cb_
.Reset();
184 base::ResetAndReturn(&init_cb_
).Run(DECODER_ERROR_NOT_SUPPORTED
);
186 decryptor_attached_cb
.Run(false);
190 decryptor_
= decryptor
;
193 decryptor_attached_cb
.Run(true);
196 void DecryptingAudioDecoder::InitializeDecoder() {
197 state_
= kPendingDecoderInit
;
198 decryptor_
->InitializeAudioDecoder(
200 BindToCurrentLoop(base::Bind(
201 &DecryptingAudioDecoder::FinishInitialization
, weak_this_
)));
204 void DecryptingAudioDecoder::FinishInitialization(bool success
) {
205 DVLOG(2) << "FinishInitialization()";
206 DCHECK(task_runner_
->BelongsToCurrentThread());
207 DCHECK(state_
== kPendingDecoderInit
) << state_
;
208 DCHECK(!init_cb_
.is_null());
209 DCHECK(reset_cb_
.is_null()); // No Reset() before initialization finished.
210 DCHECK(decode_cb_
.is_null()); // No Decode() before initialization finished.
213 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::AudioFrames
& 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
;
292 waiting_for_decryption_key_cb_
.Run();
296 if (status
== Decryptor::kNeedMoreData
) {
297 DVLOG(2) << "DeliverFrame() - kNeedMoreData";
298 state_
= scoped_pending_buffer_to_decode
->end_of_stream() ? kDecodeFinished
300 base::ResetAndReturn(&decode_cb_
).Run(kOk
);
304 DCHECK_EQ(status
, Decryptor::kSuccess
);
305 DCHECK(!frames
.empty());
306 ProcessDecodedFrames(frames
);
308 if (scoped_pending_buffer_to_decode
->end_of_stream()) {
309 // Set |pending_buffer_to_decode_| back as we need to keep flushing the
310 // decryptor until kNeedMoreData is returned.
311 pending_buffer_to_decode_
= scoped_pending_buffer_to_decode
;
312 DecodePendingBuffer();
317 base::ResetAndReturn(&decode_cb_
).Run(kOk
);
320 void DecryptingAudioDecoder::OnKeyAdded() {
321 DCHECK(task_runner_
->BelongsToCurrentThread());
323 if (state_
== kPendingDecode
) {
324 key_added_while_decode_pending_
= true;
328 if (state_
== kWaitingForKey
) {
329 state_
= kPendingDecode
;
330 DecodePendingBuffer();
334 void DecryptingAudioDecoder::DoReset() {
335 DCHECK(init_cb_
.is_null());
336 DCHECK(decode_cb_
.is_null());
337 timestamp_helper_
->SetBaseTimestamp(kNoTimestamp());
339 base::ResetAndReturn(&reset_cb_
).Run();
342 void DecryptingAudioDecoder::ProcessDecodedFrames(
343 const Decryptor::AudioFrames
& frames
) {
344 for (Decryptor::AudioFrames::const_iterator iter
= frames
.begin();
345 iter
!= frames
.end();
347 scoped_refptr
<AudioBuffer
> frame
= *iter
;
349 DCHECK(!frame
->end_of_stream()) << "EOS frame returned.";
350 DCHECK_GT(frame
->frame_count(), 0) << "Empty frame returned.";
352 base::TimeDelta current_time
= timestamp_helper_
->GetTimestamp();
353 if (IsOutOfSync(current_time
, frame
->timestamp())) {
354 DVLOG(1) << "Timestamp returned by the decoder ("
355 << frame
->timestamp().InMilliseconds() << " ms)"
356 << " does not match the input timestamp and number of samples"
357 << " decoded (" << current_time
.InMilliseconds() << " ms).";
360 frame
->set_timestamp(current_time
);
361 timestamp_helper_
->AddFrames(frame
->frame_count());
363 output_cb_
.Run(frame
);