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 static inline bool IsOutOfSync(const base::TimeDelta
& timestamp_1
,
27 const base::TimeDelta
& timestamp_2
) {
28 // Out of sync of 100ms would be pretty noticeable and we should keep any
30 const int64 kOutOfSyncThresholdInMilliseconds
= 100;
31 return std::abs(timestamp_1
.InMilliseconds() - timestamp_2
.InMilliseconds()) >
32 kOutOfSyncThresholdInMilliseconds
;
35 DecryptingAudioDecoder::DecryptingAudioDecoder(
36 const scoped_refptr
<base::SingleThreadTaskRunner
>& task_runner
,
37 const SetDecryptorReadyCB
& set_decryptor_ready_cb
)
38 : task_runner_(task_runner
),
39 state_(kUninitialized
),
40 set_decryptor_ready_cb_(set_decryptor_ready_cb
),
42 key_added_while_decode_pending_(false),
43 weak_factory_(this) {}
45 std::string
DecryptingAudioDecoder::GetDisplayName() const {
46 return "DecryptingAudioDecoder";
49 void DecryptingAudioDecoder::Initialize(const AudioDecoderConfig
& config
,
50 const PipelineStatusCB
& status_cb
,
51 const OutputCB
& output_cb
) {
52 DVLOG(2) << "Initialize()";
53 DCHECK(task_runner_
->BelongsToCurrentThread());
54 DCHECK(decode_cb_
.is_null());
55 DCHECK(reset_cb_
.is_null());
57 weak_this_
= weak_factory_
.GetWeakPtr();
58 init_cb_
= BindToCurrentLoop(status_cb
);
59 output_cb_
= BindToCurrentLoop(output_cb
);
61 if (!config
.IsValidConfig()) {
62 DLOG(ERROR
) << "Invalid audio stream config.";
63 base::ResetAndReturn(&init_cb_
).Run(PIPELINE_ERROR_DECODE
);
67 // DecryptingAudioDecoder only accepts potentially encrypted stream.
68 if (!config
.is_encrypted()) {
69 base::ResetAndReturn(&init_cb_
).Run(DECODER_ERROR_NOT_SUPPORTED
);
75 if (state_
== kUninitialized
) {
76 state_
= kDecryptorRequested
;
77 set_decryptor_ready_cb_
.Run(BindToCurrentLoop(
78 base::Bind(&DecryptingAudioDecoder::SetDecryptor
, weak_this_
)));
82 // Reinitialization (i.e. upon a config change)
83 decryptor_
->DeinitializeDecoder(Decryptor::kAudio
);
87 void DecryptingAudioDecoder::Decode(const scoped_refptr
<DecoderBuffer
>& buffer
,
88 const DecodeCB
& decode_cb
) {
89 DVLOG(3) << "Decode()";
90 DCHECK(task_runner_
->BelongsToCurrentThread());
91 DCHECK(state_
== kIdle
|| state_
== kDecodeFinished
) << state_
;
92 DCHECK(!decode_cb
.is_null());
93 CHECK(decode_cb_
.is_null()) << "Overlapping decodes are not supported.";
95 decode_cb_
= BindToCurrentLoop(decode_cb
);
97 // Return empty (end-of-stream) frames if decoding has finished.
98 if (state_
== kDecodeFinished
) {
99 output_cb_
.Run(AudioBuffer::CreateEOSBuffer());
100 base::ResetAndReturn(&decode_cb_
).Run(kOk
);
104 // Initialize the |next_output_timestamp_| to be the timestamp of the first
106 if (timestamp_helper_
->base_timestamp() == kNoTimestamp() &&
107 !buffer
->end_of_stream()) {
108 timestamp_helper_
->SetBaseTimestamp(buffer
->timestamp());
111 pending_buffer_to_decode_
= buffer
;
112 state_
= kPendingDecode
;
113 DecodePendingBuffer();
116 void DecryptingAudioDecoder::Reset(const base::Closure
& closure
) {
117 DVLOG(2) << "Reset() - state: " << state_
;
118 DCHECK(task_runner_
->BelongsToCurrentThread());
119 DCHECK(state_
== kIdle
||
120 state_
== kPendingDecode
||
121 state_
== kWaitingForKey
||
122 state_
== kDecodeFinished
) << state_
;
123 DCHECK(init_cb_
.is_null()); // No Reset() during pending initialization.
124 DCHECK(reset_cb_
.is_null());
126 reset_cb_
= BindToCurrentLoop(closure
);
128 decryptor_
->ResetDecoder(Decryptor::kAudio
);
130 // Reset() cannot complete if the read callback is still pending.
131 // Defer the resetting process in this case. The |reset_cb_| will be fired
132 // after the read callback is fired - see DecryptAndDecodeBuffer() and
134 if (state_
== kPendingDecode
) {
135 DCHECK(!decode_cb_
.is_null());
139 if (state_
== kWaitingForKey
) {
140 DCHECK(!decode_cb_
.is_null());
141 pending_buffer_to_decode_
= NULL
;
142 base::ResetAndReturn(&decode_cb_
).Run(kAborted
);
145 DCHECK(decode_cb_
.is_null());
149 DecryptingAudioDecoder::~DecryptingAudioDecoder() {
150 DVLOG(2) << __FUNCTION__
;
151 DCHECK(task_runner_
->BelongsToCurrentThread());
153 if (state_
== kUninitialized
)
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 (!decode_cb_
.is_null())
166 base::ResetAndReturn(&decode_cb_
).Run(kAborted
);
167 if (!reset_cb_
.is_null())
168 base::ResetAndReturn(&reset_cb_
).Run();
171 void DecryptingAudioDecoder::SetDecryptor(
172 Decryptor
* decryptor
,
173 const DecryptorAttachedCB
& decryptor_attached_cb
) {
174 DVLOG(2) << "SetDecryptor()";
175 DCHECK(task_runner_
->BelongsToCurrentThread());
176 DCHECK_EQ(state_
, kDecryptorRequested
) << state_
;
177 DCHECK(!init_cb_
.is_null());
178 DCHECK(!set_decryptor_ready_cb_
.is_null());
180 set_decryptor_ready_cb_
.Reset();
183 base::ResetAndReturn(&init_cb_
).Run(DECODER_ERROR_NOT_SUPPORTED
);
185 decryptor_attached_cb
.Run(false);
189 decryptor_
= decryptor
;
192 decryptor_attached_cb
.Run(true);
195 void DecryptingAudioDecoder::InitializeDecoder() {
196 state_
= kPendingDecoderInit
;
197 decryptor_
->InitializeAudioDecoder(
199 BindToCurrentLoop(base::Bind(
200 &DecryptingAudioDecoder::FinishInitialization
, weak_this_
)));
203 void DecryptingAudioDecoder::FinishInitialization(bool success
) {
204 DVLOG(2) << "FinishInitialization()";
205 DCHECK(task_runner_
->BelongsToCurrentThread());
206 DCHECK(state_
== kPendingDecoderInit
) << state_
;
207 DCHECK(!init_cb_
.is_null());
208 DCHECK(reset_cb_
.is_null()); // No Reset() before initialization finished.
209 DCHECK(decode_cb_
.is_null()); // No Decode() before initialization finished.
212 base::ResetAndReturn(&init_cb_
).Run(DECODER_ERROR_NOT_SUPPORTED
);
219 timestamp_helper_
.reset(
220 new AudioTimestampHelper(config_
.samples_per_second()));
222 decryptor_
->RegisterNewKeyCB(
225 base::Bind(&DecryptingAudioDecoder::OnKeyAdded
, weak_this_
)));
228 base::ResetAndReturn(&init_cb_
).Run(PIPELINE_OK
);
231 void DecryptingAudioDecoder::DecodePendingBuffer() {
232 DCHECK(task_runner_
->BelongsToCurrentThread());
233 DCHECK_EQ(state_
, kPendingDecode
) << state_
;
236 if (!pending_buffer_to_decode_
->end_of_stream()) {
237 buffer_size
= pending_buffer_to_decode_
->data_size();
240 decryptor_
->DecryptAndDecodeAudio(
241 pending_buffer_to_decode_
,
242 BindToCurrentLoop(base::Bind(
243 &DecryptingAudioDecoder::DeliverFrame
, weak_this_
, buffer_size
)));
246 void DecryptingAudioDecoder::DeliverFrame(
248 Decryptor::Status status
,
249 const Decryptor::AudioFrames
& frames
) {
250 DVLOG(3) << "DeliverFrame() - status: " << status
;
251 DCHECK(task_runner_
->BelongsToCurrentThread());
252 DCHECK_EQ(state_
, kPendingDecode
) << state_
;
253 DCHECK(!decode_cb_
.is_null());
254 DCHECK(pending_buffer_to_decode_
.get());
256 bool need_to_try_again_if_nokey_is_returned
= key_added_while_decode_pending_
;
257 key_added_while_decode_pending_
= false;
259 scoped_refptr
<DecoderBuffer
> scoped_pending_buffer_to_decode
=
260 pending_buffer_to_decode_
;
261 pending_buffer_to_decode_
= NULL
;
263 if (!reset_cb_
.is_null()) {
264 base::ResetAndReturn(&decode_cb_
).Run(kAborted
);
269 DCHECK_EQ(status
== Decryptor::kSuccess
, !frames
.empty());
271 if (status
== Decryptor::kError
) {
272 DVLOG(2) << "DeliverFrame() - kError";
273 state_
= kDecodeFinished
; // TODO add kError state
274 base::ResetAndReturn(&decode_cb_
).Run(kDecodeError
);
278 if (status
== Decryptor::kNoKey
) {
279 DVLOG(2) << "DeliverFrame() - kNoKey";
280 // Set |pending_buffer_to_decode_| back as we need to try decoding the
281 // pending buffer again when new key is added to the decryptor.
282 pending_buffer_to_decode_
= scoped_pending_buffer_to_decode
;
284 if (need_to_try_again_if_nokey_is_returned
) {
285 // The |state_| is still kPendingDecode.
286 DecodePendingBuffer();
290 state_
= kWaitingForKey
;
294 if (status
== Decryptor::kNeedMoreData
) {
295 DVLOG(2) << "DeliverFrame() - kNeedMoreData";
296 state_
= scoped_pending_buffer_to_decode
->end_of_stream() ? kDecodeFinished
298 base::ResetAndReturn(&decode_cb_
).Run(kOk
);
302 DCHECK_EQ(status
, Decryptor::kSuccess
);
303 DCHECK(!frames
.empty());
304 ProcessDecodedFrames(frames
);
306 if (scoped_pending_buffer_to_decode
->end_of_stream()) {
307 // Set |pending_buffer_to_decode_| back as we need to keep flushing the
308 // decryptor until kNeedMoreData is returned.
309 pending_buffer_to_decode_
= scoped_pending_buffer_to_decode
;
310 DecodePendingBuffer();
315 base::ResetAndReturn(&decode_cb_
).Run(kOk
);
318 void DecryptingAudioDecoder::OnKeyAdded() {
319 DCHECK(task_runner_
->BelongsToCurrentThread());
321 if (state_
== kPendingDecode
) {
322 key_added_while_decode_pending_
= true;
326 if (state_
== kWaitingForKey
) {
327 state_
= kPendingDecode
;
328 DecodePendingBuffer();
332 void DecryptingAudioDecoder::DoReset() {
333 DCHECK(init_cb_
.is_null());
334 DCHECK(decode_cb_
.is_null());
335 timestamp_helper_
->SetBaseTimestamp(kNoTimestamp());
337 base::ResetAndReturn(&reset_cb_
).Run();
340 void DecryptingAudioDecoder::ProcessDecodedFrames(
341 const Decryptor::AudioFrames
& frames
) {
342 for (Decryptor::AudioFrames::const_iterator iter
= frames
.begin();
343 iter
!= frames
.end();
345 scoped_refptr
<AudioBuffer
> frame
= *iter
;
347 DCHECK(!frame
->end_of_stream()) << "EOS frame returned.";
348 DCHECK_GT(frame
->frame_count(), 0) << "Empty frame returned.";
350 base::TimeDelta current_time
= timestamp_helper_
->GetTimestamp();
351 if (IsOutOfSync(current_time
, frame
->timestamp())) {
352 DVLOG(1) << "Timestamp returned by the decoder ("
353 << frame
->timestamp().InMilliseconds() << " ms)"
354 << " does not match the input timestamp and number of samples"
355 << " decoded (" << current_time
.InMilliseconds() << " ms).";
358 frame
->set_timestamp(current_time
);
359 timestamp_helper_
->AddFrames(frame
->frame_count());
361 output_cb_
.Run(frame
);