Update V8 to version 4.7.42.
[chromium-blink-merge.git] / media / filters / decrypting_audio_decoder.cc
blob52a85f1d25c8a4573a0f19d19e5f27244d279828
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"
7 #include <cstdlib>
9 #include "base/bind.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/decoder_buffer.h"
19 #include "media/base/media_log.h"
20 #include "media/base/pipeline.h"
21 #include "media/base/timestamp_constants.h"
23 namespace media {
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
28 // drift below that.
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),
44 decryptor_(NULL),
45 key_added_while_decode_pending_(false),
46 weak_factory_(this) {
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);
68 return;
71 // DecryptingAudioDecoder only accepts potentially encrypted stream.
72 if (!config.is_encrypted()) {
73 base::ResetAndReturn(&init_cb_).Run(false);
74 return;
77 config_ = config;
79 if (state_ == kUninitialized) {
80 state_ = kDecryptorRequested;
81 set_decryptor_ready_cb_.Run(BindToCurrentLoop(
82 base::Bind(&DecryptingAudioDecoder::SetDecryptor, weak_this_)));
83 return;
86 // Reinitialization (i.e. upon a config change)
87 decryptor_->DeinitializeDecoder(Decryptor::kAudio);
88 InitializeDecoder();
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);
105 return;
108 // Initialize the |next_output_timestamp_| to be the timestamp of the first
109 // non-EOS buffer.
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
137 // DeliverFrame().
138 if (state_ == kPendingDecode) {
139 DCHECK(!decode_cb_.is_null());
140 return;
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());
150 DoReset();
153 DecryptingAudioDecoder::~DecryptingAudioDecoder() {
154 DVLOG(2) << __FUNCTION__;
155 DCHECK(task_runner_->BelongsToCurrentThread());
157 if (state_ == kUninitialized)
158 return;
160 if (decryptor_) {
161 decryptor_->DeinitializeDecoder(Decryptor::kAudio);
162 decryptor_ = NULL;
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();
186 if (!decryptor) {
187 MEDIA_LOG(DEBUG, media_log_) << GetDisplayName() << ": no decryptor set";
188 base::ResetAndReturn(&init_cb_).Run(false);
189 state_ = kError;
190 decryptor_attached_cb.Run(false);
191 return;
194 decryptor_ = decryptor;
196 InitializeDecoder();
197 decryptor_attached_cb.Run(true);
200 void DecryptingAudioDecoder::InitializeDecoder() {
201 state_ = kPendingDecoderInit;
202 decryptor_->InitializeAudioDecoder(
203 config_,
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.
216 if (!success) {
217 MEDIA_LOG(DEBUG, media_log_) << GetDisplayName()
218 << ": failed to init decoder on decryptor";
219 base::ResetAndReturn(&init_cb_).Run(false);
220 decryptor_ = NULL;
221 state_ = kError;
222 return;
225 // Success!
226 timestamp_helper_.reset(
227 new AudioTimestampHelper(config_.samples_per_second()));
229 decryptor_->RegisterNewKeyCB(
230 Decryptor::kAudio,
231 BindToCurrentLoop(
232 base::Bind(&DecryptingAudioDecoder::OnKeyAdded, weak_this_)));
234 state_ = kIdle;
235 base::ResetAndReturn(&init_cb_).Run(true);
238 void DecryptingAudioDecoder::DecodePendingBuffer() {
239 DCHECK(task_runner_->BelongsToCurrentThread());
240 DCHECK_EQ(state_, kPendingDecode) << state_;
242 int buffer_size = 0;
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(
254 int buffer_size,
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);
272 DoReset();
273 return;
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);
283 return;
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();
297 return;
300 state_ = kWaitingForKey;
301 waiting_for_decryption_key_cb_.Run();
302 return;
305 if (status == Decryptor::kNeedMoreData) {
306 DVLOG(2) << "DeliverFrame() - kNeedMoreData";
307 state_ = scoped_pending_buffer_to_decode->end_of_stream() ? kDecodeFinished
308 : kIdle;
309 base::ResetAndReturn(&decode_cb_).Run(kOk);
310 return;
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();
322 return;
325 state_ = kIdle;
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;
334 return;
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());
347 state_ = kIdle;
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();
355 ++iter) {
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);
376 } // namespace media