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/media_log.h"
21 #include "media/base/pipeline.h"
25 static inline bool IsOutOfSync(const base::TimeDelta
& timestamp_1
,
26 const base::TimeDelta
& timestamp_2
) {
27 // Out of sync of 100ms would be pretty noticeable and we should keep any
29 const int64 kOutOfSyncThresholdInMilliseconds
= 100;
30 return std::abs(timestamp_1
.InMilliseconds() - timestamp_2
.InMilliseconds()) >
31 kOutOfSyncThresholdInMilliseconds
;
34 DecryptingAudioDecoder::DecryptingAudioDecoder(
35 const scoped_refptr
<base::SingleThreadTaskRunner
>& task_runner
,
36 const scoped_refptr
<MediaLog
>& media_log
,
37 const SetDecryptorReadyCB
& set_decryptor_ready_cb
,
38 const base::Closure
& waiting_for_decryption_key_cb
)
39 : task_runner_(task_runner
),
40 media_log_(media_log
),
41 state_(kUninitialized
),
42 waiting_for_decryption_key_cb_(waiting_for_decryption_key_cb
),
43 set_decryptor_ready_cb_(set_decryptor_ready_cb
),
45 key_added_while_decode_pending_(false),
49 std::string
DecryptingAudioDecoder::GetDisplayName() const {
50 return "DecryptingAudioDecoder";
53 void DecryptingAudioDecoder::Initialize(const AudioDecoderConfig
& config
,
54 const InitCB
& init_cb
,
55 const OutputCB
& output_cb
) {
56 DVLOG(2) << "Initialize()";
57 DCHECK(task_runner_
->BelongsToCurrentThread());
58 DCHECK(decode_cb_
.is_null());
59 DCHECK(reset_cb_
.is_null());
61 weak_this_
= weak_factory_
.GetWeakPtr();
62 init_cb_
= BindToCurrentLoop(init_cb
);
63 output_cb_
= BindToCurrentLoop(output_cb
);
65 if (!config
.IsValidConfig()) {
66 DLOG(ERROR
) << "Invalid audio stream config.";
67 base::ResetAndReturn(&init_cb_
).Run(false);
71 // DecryptingAudioDecoder only accepts potentially encrypted stream.
72 if (!config
.is_encrypted()) {
73 base::ResetAndReturn(&init_cb_
).Run(false);
79 if (state_
== kUninitialized
) {
80 state_
= kDecryptorRequested
;
81 set_decryptor_ready_cb_
.Run(BindToCurrentLoop(
82 base::Bind(&DecryptingAudioDecoder::SetDecryptor
, weak_this_
)));
86 // Reinitialization (i.e. upon a config change)
87 decryptor_
->DeinitializeDecoder(Decryptor::kAudio
);
91 void DecryptingAudioDecoder::Decode(const scoped_refptr
<DecoderBuffer
>& buffer
,
92 const DecodeCB
& decode_cb
) {
93 DVLOG(3) << "Decode()";
94 DCHECK(task_runner_
->BelongsToCurrentThread());
95 DCHECK(state_
== kIdle
|| state_
== kDecodeFinished
) << state_
;
96 DCHECK(!decode_cb
.is_null());
97 CHECK(decode_cb_
.is_null()) << "Overlapping decodes are not supported.";
99 decode_cb_
= BindToCurrentLoop(decode_cb
);
101 // Return empty (end-of-stream) frames if decoding has finished.
102 if (state_
== kDecodeFinished
) {
103 output_cb_
.Run(AudioBuffer::CreateEOSBuffer());
104 base::ResetAndReturn(&decode_cb_
).Run(kOk
);
108 // Initialize the |next_output_timestamp_| to be the timestamp of the first
110 if (timestamp_helper_
->base_timestamp() == kNoTimestamp() &&
111 !buffer
->end_of_stream()) {
112 timestamp_helper_
->SetBaseTimestamp(buffer
->timestamp());
115 pending_buffer_to_decode_
= buffer
;
116 state_
= kPendingDecode
;
117 DecodePendingBuffer();
120 void DecryptingAudioDecoder::Reset(const base::Closure
& closure
) {
121 DVLOG(2) << "Reset() - state: " << state_
;
122 DCHECK(task_runner_
->BelongsToCurrentThread());
123 DCHECK(state_
== kIdle
||
124 state_
== kPendingDecode
||
125 state_
== kWaitingForKey
||
126 state_
== kDecodeFinished
) << state_
;
127 DCHECK(init_cb_
.is_null()); // No Reset() during pending initialization.
128 DCHECK(reset_cb_
.is_null());
130 reset_cb_
= BindToCurrentLoop(closure
);
132 decryptor_
->ResetDecoder(Decryptor::kAudio
);
134 // Reset() cannot complete if the read callback is still pending.
135 // Defer the resetting process in this case. The |reset_cb_| will be fired
136 // after the read callback is fired - see DecryptAndDecodeBuffer() and
138 if (state_
== kPendingDecode
) {
139 DCHECK(!decode_cb_
.is_null());
143 if (state_
== kWaitingForKey
) {
144 DCHECK(!decode_cb_
.is_null());
145 pending_buffer_to_decode_
= NULL
;
146 base::ResetAndReturn(&decode_cb_
).Run(kAborted
);
149 DCHECK(decode_cb_
.is_null());
153 DecryptingAudioDecoder::~DecryptingAudioDecoder() {
154 DVLOG(2) << __FUNCTION__
;
155 DCHECK(task_runner_
->BelongsToCurrentThread());
157 if (state_
== kUninitialized
)
161 decryptor_
->DeinitializeDecoder(Decryptor::kAudio
);
164 if (!set_decryptor_ready_cb_
.is_null())
165 base::ResetAndReturn(&set_decryptor_ready_cb_
).Run(DecryptorReadyCB());
166 pending_buffer_to_decode_
= NULL
;
167 if (!init_cb_
.is_null())
168 base::ResetAndReturn(&init_cb_
).Run(false);
169 if (!decode_cb_
.is_null())
170 base::ResetAndReturn(&decode_cb_
).Run(kAborted
);
171 if (!reset_cb_
.is_null())
172 base::ResetAndReturn(&reset_cb_
).Run();
175 void DecryptingAudioDecoder::SetDecryptor(
176 Decryptor
* decryptor
,
177 const DecryptorAttachedCB
& decryptor_attached_cb
) {
178 DVLOG(2) << "SetDecryptor()";
179 DCHECK(task_runner_
->BelongsToCurrentThread());
180 DCHECK_EQ(state_
, kDecryptorRequested
) << state_
;
181 DCHECK(!init_cb_
.is_null());
182 DCHECK(!set_decryptor_ready_cb_
.is_null());
184 set_decryptor_ready_cb_
.Reset();
187 MEDIA_LOG(DEBUG
, media_log_
) << GetDisplayName() << ": no decryptor set";
188 base::ResetAndReturn(&init_cb_
).Run(false);
190 decryptor_attached_cb
.Run(false);
194 decryptor_
= decryptor
;
197 decryptor_attached_cb
.Run(true);
200 void DecryptingAudioDecoder::InitializeDecoder() {
201 state_
= kPendingDecoderInit
;
202 decryptor_
->InitializeAudioDecoder(
204 BindToCurrentLoop(base::Bind(
205 &DecryptingAudioDecoder::FinishInitialization
, weak_this_
)));
208 void DecryptingAudioDecoder::FinishInitialization(bool success
) {
209 DVLOG(2) << "FinishInitialization()";
210 DCHECK(task_runner_
->BelongsToCurrentThread());
211 DCHECK(state_
== kPendingDecoderInit
) << state_
;
212 DCHECK(!init_cb_
.is_null());
213 DCHECK(reset_cb_
.is_null()); // No Reset() before initialization finished.
214 DCHECK(decode_cb_
.is_null()); // No Decode() before initialization finished.
217 MEDIA_LOG(DEBUG
, media_log_
) << GetDisplayName()
218 << ": failed to init decoder on decryptor";
219 base::ResetAndReturn(&init_cb_
).Run(false);
226 timestamp_helper_
.reset(
227 new AudioTimestampHelper(config_
.samples_per_second()));
229 decryptor_
->RegisterNewKeyCB(
232 base::Bind(&DecryptingAudioDecoder::OnKeyAdded
, weak_this_
)));
235 base::ResetAndReturn(&init_cb_
).Run(true);
238 void DecryptingAudioDecoder::DecodePendingBuffer() {
239 DCHECK(task_runner_
->BelongsToCurrentThread());
240 DCHECK_EQ(state_
, kPendingDecode
) << state_
;
243 if (!pending_buffer_to_decode_
->end_of_stream()) {
244 buffer_size
= pending_buffer_to_decode_
->data_size();
247 decryptor_
->DecryptAndDecodeAudio(
248 pending_buffer_to_decode_
,
249 BindToCurrentLoop(base::Bind(
250 &DecryptingAudioDecoder::DeliverFrame
, weak_this_
, buffer_size
)));
253 void DecryptingAudioDecoder::DeliverFrame(
255 Decryptor::Status status
,
256 const Decryptor::AudioFrames
& frames
) {
257 DVLOG(3) << "DeliverFrame() - status: " << status
;
258 DCHECK(task_runner_
->BelongsToCurrentThread());
259 DCHECK_EQ(state_
, kPendingDecode
) << state_
;
260 DCHECK(!decode_cb_
.is_null());
261 DCHECK(pending_buffer_to_decode_
.get());
263 bool need_to_try_again_if_nokey_is_returned
= key_added_while_decode_pending_
;
264 key_added_while_decode_pending_
= false;
266 scoped_refptr
<DecoderBuffer
> scoped_pending_buffer_to_decode
=
267 pending_buffer_to_decode_
;
268 pending_buffer_to_decode_
= NULL
;
270 if (!reset_cb_
.is_null()) {
271 base::ResetAndReturn(&decode_cb_
).Run(kAborted
);
276 DCHECK_EQ(status
== Decryptor::kSuccess
, !frames
.empty());
278 if (status
== Decryptor::kError
) {
279 DVLOG(2) << "DeliverFrame() - kError";
280 MEDIA_LOG(ERROR
, media_log_
) << GetDisplayName() << ": decode error";
281 state_
= kDecodeFinished
; // TODO add kError state
282 base::ResetAndReturn(&decode_cb_
).Run(kDecodeError
);
286 if (status
== Decryptor::kNoKey
) {
287 DVLOG(2) << "DeliverFrame() - kNoKey";
288 MEDIA_LOG(DEBUG
, media_log_
) << GetDisplayName() << ": no key";
290 // Set |pending_buffer_to_decode_| back as we need to try decoding the
291 // pending buffer again when new key is added to the decryptor.
292 pending_buffer_to_decode_
= scoped_pending_buffer_to_decode
;
294 if (need_to_try_again_if_nokey_is_returned
) {
295 // The |state_| is still kPendingDecode.
296 DecodePendingBuffer();
300 state_
= kWaitingForKey
;
301 waiting_for_decryption_key_cb_
.Run();
305 if (status
== Decryptor::kNeedMoreData
) {
306 DVLOG(2) << "DeliverFrame() - kNeedMoreData";
307 state_
= scoped_pending_buffer_to_decode
->end_of_stream() ? kDecodeFinished
309 base::ResetAndReturn(&decode_cb_
).Run(kOk
);
313 DCHECK_EQ(status
, Decryptor::kSuccess
);
314 DCHECK(!frames
.empty());
315 ProcessDecodedFrames(frames
);
317 if (scoped_pending_buffer_to_decode
->end_of_stream()) {
318 // Set |pending_buffer_to_decode_| back as we need to keep flushing the
319 // decryptor until kNeedMoreData is returned.
320 pending_buffer_to_decode_
= scoped_pending_buffer_to_decode
;
321 DecodePendingBuffer();
326 base::ResetAndReturn(&decode_cb_
).Run(kOk
);
329 void DecryptingAudioDecoder::OnKeyAdded() {
330 DCHECK(task_runner_
->BelongsToCurrentThread());
332 if (state_
== kPendingDecode
) {
333 key_added_while_decode_pending_
= true;
337 if (state_
== kWaitingForKey
) {
338 state_
= kPendingDecode
;
339 DecodePendingBuffer();
343 void DecryptingAudioDecoder::DoReset() {
344 DCHECK(init_cb_
.is_null());
345 DCHECK(decode_cb_
.is_null());
346 timestamp_helper_
->SetBaseTimestamp(kNoTimestamp());
348 base::ResetAndReturn(&reset_cb_
).Run();
351 void DecryptingAudioDecoder::ProcessDecodedFrames(
352 const Decryptor::AudioFrames
& frames
) {
353 for (Decryptor::AudioFrames::const_iterator iter
= frames
.begin();
354 iter
!= frames
.end();
356 scoped_refptr
<AudioBuffer
> frame
= *iter
;
358 DCHECK(!frame
->end_of_stream()) << "EOS frame returned.";
359 DCHECK_GT(frame
->frame_count(), 0) << "Empty frame returned.";
361 base::TimeDelta current_time
= timestamp_helper_
->GetTimestamp();
362 if (IsOutOfSync(current_time
, frame
->timestamp())) {
363 DVLOG(1) << "Timestamp returned by the decoder ("
364 << frame
->timestamp().InMilliseconds() << " ms)"
365 << " does not match the input timestamp and number of samples"
366 << " decoded (" << current_time
.InMilliseconds() << " ms).";
369 frame
->set_timestamp(current_time
);
370 timestamp_helper_
->AddFrames(frame
->frame_count());
372 output_cb_
.Run(frame
);