OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "media/filters/decrypting_audio_decoder.h" | 5 #include "media/filters/decrypting_audio_decoder.h" |
6 | 6 |
7 #include <cstdlib> | 7 #include <cstdlib> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/callback_helpers.h" | 10 #include "base/callback_helpers.h" |
(...skipping 27 matching lines...) Expand all Loading... |
38 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, | 38 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, |
39 const SetDecryptorReadyCB& set_decryptor_ready_cb) | 39 const SetDecryptorReadyCB& set_decryptor_ready_cb) |
40 : task_runner_(task_runner), | 40 : task_runner_(task_runner), |
41 state_(kUninitialized), | 41 state_(kUninitialized), |
42 set_decryptor_ready_cb_(set_decryptor_ready_cb), | 42 set_decryptor_ready_cb_(set_decryptor_ready_cb), |
43 decryptor_(NULL), | 43 decryptor_(NULL), |
44 key_added_while_decode_pending_(false), | 44 key_added_while_decode_pending_(false), |
45 weak_factory_(this) {} | 45 weak_factory_(this) {} |
46 | 46 |
47 void DecryptingAudioDecoder::Initialize(const AudioDecoderConfig& config, | 47 void DecryptingAudioDecoder::Initialize(const AudioDecoderConfig& config, |
48 const PipelineStatusCB& status_cb) { | 48 const PipelineStatusCB& status_cb, |
| 49 const OutputCB& output_cb) { |
49 DVLOG(2) << "Initialize()"; | 50 DVLOG(2) << "Initialize()"; |
50 DCHECK(task_runner_->BelongsToCurrentThread()); | 51 DCHECK(task_runner_->BelongsToCurrentThread()); |
51 DCHECK(decode_cb_.is_null()); | 52 DCHECK(decode_cb_.is_null()); |
52 DCHECK(reset_cb_.is_null()); | 53 DCHECK(reset_cb_.is_null()); |
53 | 54 |
54 weak_this_ = weak_factory_.GetWeakPtr(); | 55 weak_this_ = weak_factory_.GetWeakPtr(); |
55 init_cb_ = BindToCurrentLoop(status_cb); | 56 init_cb_ = BindToCurrentLoop(status_cb); |
| 57 output_cb_ = BindToCurrentLoop(output_cb); |
56 | 58 |
57 if (!config.IsValidConfig()) { | 59 if (!config.IsValidConfig()) { |
58 DLOG(ERROR) << "Invalid audio stream config."; | 60 DLOG(ERROR) << "Invalid audio stream config."; |
59 base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_DECODE); | 61 base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_DECODE); |
60 return; | 62 return; |
61 } | 63 } |
62 | 64 |
63 // DecryptingAudioDecoder only accepts potentially encrypted stream. | 65 // DecryptingAudioDecoder only accepts potentially encrypted stream. |
64 if (!config.is_encrypted()) { | 66 if (!config.is_encrypted()) { |
65 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED); | 67 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED); |
(...skipping 19 matching lines...) Expand all Loading... |
85 DVLOG(3) << "Decode()"; | 87 DVLOG(3) << "Decode()"; |
86 DCHECK(task_runner_->BelongsToCurrentThread()); | 88 DCHECK(task_runner_->BelongsToCurrentThread()); |
87 DCHECK(state_ == kIdle || state_ == kDecodeFinished) << state_; | 89 DCHECK(state_ == kIdle || state_ == kDecodeFinished) << state_; |
88 DCHECK(!decode_cb.is_null()); | 90 DCHECK(!decode_cb.is_null()); |
89 CHECK(decode_cb_.is_null()) << "Overlapping decodes are not supported."; | 91 CHECK(decode_cb_.is_null()) << "Overlapping decodes are not supported."; |
90 | 92 |
91 decode_cb_ = BindToCurrentLoop(decode_cb); | 93 decode_cb_ = BindToCurrentLoop(decode_cb); |
92 | 94 |
93 // Return empty (end-of-stream) frames if decoding has finished. | 95 // Return empty (end-of-stream) frames if decoding has finished. |
94 if (state_ == kDecodeFinished) { | 96 if (state_ == kDecodeFinished) { |
95 base::ResetAndReturn(&decode_cb_).Run(kOk, AudioBuffer::CreateEOSBuffer()); | 97 output_cb_.Run(AudioBuffer::CreateEOSBuffer()); |
| 98 base::ResetAndReturn(&decode_cb_).Run(kOk); |
96 return; | 99 return; |
97 } | 100 } |
98 | 101 |
99 if (!queued_audio_frames_.empty()) { | |
100 DCHECK(!buffer); | |
101 base::ResetAndReturn(&decode_cb_).Run(kOk, queued_audio_frames_.front()); | |
102 queued_audio_frames_.pop_front(); | |
103 return; | |
104 } | |
105 | |
106 // Initialize the |next_output_timestamp_| to be the timestamp of the first | 102 // Initialize the |next_output_timestamp_| to be the timestamp of the first |
107 // non-EOS buffer. | 103 // non-EOS buffer. |
108 if (timestamp_helper_->base_timestamp() == kNoTimestamp() && | 104 if (timestamp_helper_->base_timestamp() == kNoTimestamp() && |
109 !buffer->end_of_stream()) { | 105 !buffer->end_of_stream()) { |
110 timestamp_helper_->SetBaseTimestamp(buffer->timestamp()); | 106 timestamp_helper_->SetBaseTimestamp(buffer->timestamp()); |
111 } | 107 } |
112 | 108 |
113 pending_buffer_to_decode_ = buffer; | 109 pending_buffer_to_decode_ = buffer; |
114 state_ = kPendingDecode; | 110 state_ = kPendingDecode; |
115 DecodePendingBuffer(); | 111 DecodePendingBuffer(); |
116 } | 112 } |
117 | 113 |
118 scoped_refptr<AudioBuffer> DecryptingAudioDecoder::GetDecodeOutput() { | |
119 if (queued_audio_frames_.empty()) | |
120 return NULL; | |
121 scoped_refptr<AudioBuffer> out = queued_audio_frames_.front(); | |
122 queued_audio_frames_.pop_front(); | |
123 return out; | |
124 } | |
125 | |
126 void DecryptingAudioDecoder::Reset(const base::Closure& closure) { | 114 void DecryptingAudioDecoder::Reset(const base::Closure& closure) { |
127 DVLOG(2) << "Reset() - state: " << state_; | 115 DVLOG(2) << "Reset() - state: " << state_; |
128 DCHECK(task_runner_->BelongsToCurrentThread()); | 116 DCHECK(task_runner_->BelongsToCurrentThread()); |
129 DCHECK(state_ == kIdle || | 117 DCHECK(state_ == kIdle || |
130 state_ == kPendingDecode || | 118 state_ == kPendingDecode || |
131 state_ == kWaitingForKey || | 119 state_ == kWaitingForKey || |
132 state_ == kDecodeFinished) << state_; | 120 state_ == kDecodeFinished) << state_; |
133 DCHECK(init_cb_.is_null()); // No Reset() during pending initialization. | 121 DCHECK(init_cb_.is_null()); // No Reset() during pending initialization. |
134 DCHECK(reset_cb_.is_null()); | 122 DCHECK(reset_cb_.is_null()); |
135 | 123 |
136 reset_cb_ = BindToCurrentLoop(closure); | 124 reset_cb_ = BindToCurrentLoop(closure); |
137 | 125 |
138 decryptor_->ResetDecoder(Decryptor::kAudio); | 126 decryptor_->ResetDecoder(Decryptor::kAudio); |
139 | 127 |
140 // Reset() cannot complete if the read callback is still pending. | 128 // Reset() cannot complete if the read callback is still pending. |
141 // Defer the resetting process in this case. The |reset_cb_| will be fired | 129 // Defer the resetting process in this case. The |reset_cb_| will be fired |
142 // after the read callback is fired - see DecryptAndDecodeBuffer() and | 130 // after the read callback is fired - see DecryptAndDecodeBuffer() and |
143 // DeliverFrame(). | 131 // DeliverFrame(). |
144 if (state_ == kPendingDecode) { | 132 if (state_ == kPendingDecode) { |
145 DCHECK(!decode_cb_.is_null()); | 133 DCHECK(!decode_cb_.is_null()); |
146 return; | 134 return; |
147 } | 135 } |
148 | 136 |
149 if (state_ == kWaitingForKey) { | 137 if (state_ == kWaitingForKey) { |
150 DCHECK(!decode_cb_.is_null()); | 138 DCHECK(!decode_cb_.is_null()); |
151 pending_buffer_to_decode_ = NULL; | 139 pending_buffer_to_decode_ = NULL; |
152 base::ResetAndReturn(&decode_cb_).Run(kAborted, NULL); | 140 base::ResetAndReturn(&decode_cb_).Run(kAborted); |
153 } | 141 } |
154 | 142 |
155 DCHECK(decode_cb_.is_null()); | 143 DCHECK(decode_cb_.is_null()); |
156 DoReset(); | 144 DoReset(); |
157 } | 145 } |
158 | 146 |
159 void DecryptingAudioDecoder::Stop() { | 147 void DecryptingAudioDecoder::Stop() { |
160 DVLOG(2) << "Stop() - state: " << state_; | 148 DVLOG(2) << "Stop() - state: " << state_; |
161 DCHECK(task_runner_->BelongsToCurrentThread()); | 149 DCHECK(task_runner_->BelongsToCurrentThread()); |
162 | 150 |
163 // Invalidate all weak pointers so that pending callbacks won't be fired into | 151 // Invalidate all weak pointers so that pending callbacks won't be fired into |
164 // this object. | 152 // this object. |
165 weak_factory_.InvalidateWeakPtrs(); | 153 weak_factory_.InvalidateWeakPtrs(); |
166 | 154 |
167 if (decryptor_) { | 155 if (decryptor_) { |
168 decryptor_->DeinitializeDecoder(Decryptor::kAudio); | 156 decryptor_->DeinitializeDecoder(Decryptor::kAudio); |
169 decryptor_ = NULL; | 157 decryptor_ = NULL; |
170 } | 158 } |
171 if (!set_decryptor_ready_cb_.is_null()) | 159 if (!set_decryptor_ready_cb_.is_null()) |
172 base::ResetAndReturn(&set_decryptor_ready_cb_).Run(DecryptorReadyCB()); | 160 base::ResetAndReturn(&set_decryptor_ready_cb_).Run(DecryptorReadyCB()); |
173 pending_buffer_to_decode_ = NULL; | 161 pending_buffer_to_decode_ = NULL; |
174 if (!init_cb_.is_null()) | 162 if (!init_cb_.is_null()) |
175 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED); | 163 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED); |
176 if (!decode_cb_.is_null()) | 164 if (!decode_cb_.is_null()) |
177 base::ResetAndReturn(&decode_cb_).Run(kAborted, NULL); | 165 base::ResetAndReturn(&decode_cb_).Run(kAborted); |
178 if (!reset_cb_.is_null()) | 166 if (!reset_cb_.is_null()) |
179 base::ResetAndReturn(&reset_cb_).Run(); | 167 base::ResetAndReturn(&reset_cb_).Run(); |
180 | 168 |
181 state_ = kStopped; | 169 state_ = kStopped; |
182 } | 170 } |
183 | 171 |
184 DecryptingAudioDecoder::~DecryptingAudioDecoder() { | 172 DecryptingAudioDecoder::~DecryptingAudioDecoder() { |
185 DCHECK(state_ == kUninitialized || state_ == kStopped) << state_; | 173 DCHECK(state_ == kUninitialized || state_ == kStopped) << state_; |
186 } | 174 } |
187 | 175 |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
258 | 246 |
259 void DecryptingAudioDecoder::DeliverFrame( | 247 void DecryptingAudioDecoder::DeliverFrame( |
260 int buffer_size, | 248 int buffer_size, |
261 Decryptor::Status status, | 249 Decryptor::Status status, |
262 const Decryptor::AudioBuffers& frames) { | 250 const Decryptor::AudioBuffers& frames) { |
263 DVLOG(3) << "DeliverFrame() - status: " << status; | 251 DVLOG(3) << "DeliverFrame() - status: " << status; |
264 DCHECK(task_runner_->BelongsToCurrentThread()); | 252 DCHECK(task_runner_->BelongsToCurrentThread()); |
265 DCHECK_EQ(state_, kPendingDecode) << state_; | 253 DCHECK_EQ(state_, kPendingDecode) << state_; |
266 DCHECK(!decode_cb_.is_null()); | 254 DCHECK(!decode_cb_.is_null()); |
267 DCHECK(pending_buffer_to_decode_.get()); | 255 DCHECK(pending_buffer_to_decode_.get()); |
268 DCHECK(queued_audio_frames_.empty()); | |
269 | 256 |
270 bool need_to_try_again_if_nokey_is_returned = key_added_while_decode_pending_; | 257 bool need_to_try_again_if_nokey_is_returned = key_added_while_decode_pending_; |
271 key_added_while_decode_pending_ = false; | 258 key_added_while_decode_pending_ = false; |
272 | 259 |
273 scoped_refptr<DecoderBuffer> scoped_pending_buffer_to_decode = | 260 scoped_refptr<DecoderBuffer> scoped_pending_buffer_to_decode = |
274 pending_buffer_to_decode_; | 261 pending_buffer_to_decode_; |
275 pending_buffer_to_decode_ = NULL; | 262 pending_buffer_to_decode_ = NULL; |
276 | 263 |
277 if (!reset_cb_.is_null()) { | 264 if (!reset_cb_.is_null()) { |
278 base::ResetAndReturn(&decode_cb_).Run(kAborted, NULL); | 265 base::ResetAndReturn(&decode_cb_).Run(kAborted); |
279 DoReset(); | 266 DoReset(); |
280 return; | 267 return; |
281 } | 268 } |
282 | 269 |
283 DCHECK_EQ(status == Decryptor::kSuccess, !frames.empty()); | 270 DCHECK_EQ(status == Decryptor::kSuccess, !frames.empty()); |
284 | 271 |
285 if (status == Decryptor::kError) { | 272 if (status == Decryptor::kError) { |
286 DVLOG(2) << "DeliverFrame() - kError"; | 273 DVLOG(2) << "DeliverFrame() - kError"; |
287 state_ = kDecodeFinished; // TODO add kError state | 274 state_ = kDecodeFinished; // TODO add kError state |
288 base::ResetAndReturn(&decode_cb_).Run(kDecodeError, NULL); | 275 base::ResetAndReturn(&decode_cb_).Run(kDecodeError); |
289 return; | 276 return; |
290 } | 277 } |
291 | 278 |
292 if (status == Decryptor::kNoKey) { | 279 if (status == Decryptor::kNoKey) { |
293 DVLOG(2) << "DeliverFrame() - kNoKey"; | 280 DVLOG(2) << "DeliverFrame() - kNoKey"; |
294 // Set |pending_buffer_to_decode_| back as we need to try decoding the | 281 // Set |pending_buffer_to_decode_| back as we need to try decoding the |
295 // pending buffer again when new key is added to the decryptor. | 282 // pending buffer again when new key is added to the decryptor. |
296 pending_buffer_to_decode_ = scoped_pending_buffer_to_decode; | 283 pending_buffer_to_decode_ = scoped_pending_buffer_to_decode; |
297 | 284 |
298 if (need_to_try_again_if_nokey_is_returned) { | 285 if (need_to_try_again_if_nokey_is_returned) { |
299 // The |state_| is still kPendingDecode. | 286 // The |state_| is still kPendingDecode. |
300 DecodePendingBuffer(); | 287 DecodePendingBuffer(); |
301 return; | 288 return; |
302 } | 289 } |
303 | 290 |
304 state_ = kWaitingForKey; | 291 state_ = kWaitingForKey; |
305 return; | 292 return; |
306 } | 293 } |
307 | 294 |
308 if (status == Decryptor::kNeedMoreData) { | 295 if (status == Decryptor::kNeedMoreData) { |
309 DVLOG(2) << "DeliverFrame() - kNeedMoreData"; | 296 DVLOG(2) << "DeliverFrame() - kNeedMoreData"; |
310 if (scoped_pending_buffer_to_decode->end_of_stream()) { | 297 if (scoped_pending_buffer_to_decode->end_of_stream()) { |
311 state_ = kDecodeFinished; | 298 state_ = kDecodeFinished; |
312 base::ResetAndReturn(&decode_cb_) | 299 output_cb_.Run(AudioBuffer::CreateEOSBuffer()); |
313 .Run(kOk, AudioBuffer::CreateEOSBuffer()); | 300 base::ResetAndReturn(&decode_cb_).Run(kOk); |
314 return; | 301 return; |
315 } | 302 } |
316 | 303 |
317 state_ = kIdle; | 304 state_ = kIdle; |
318 base::ResetAndReturn(&decode_cb_).Run(kNotEnoughData, NULL); | 305 base::ResetAndReturn(&decode_cb_).Run(kOk); |
319 return; | 306 return; |
320 } | 307 } |
321 | 308 |
322 DCHECK_EQ(status, Decryptor::kSuccess); | 309 DCHECK_EQ(status, Decryptor::kSuccess); |
323 DCHECK(!frames.empty()); | 310 DCHECK(!frames.empty()); |
324 EnqueueFrames(frames); | 311 ProcessDecodedFrames(frames); |
325 | 312 |
326 state_ = kIdle; | 313 state_ = kIdle; |
327 base::ResetAndReturn(&decode_cb_).Run(kOk, queued_audio_frames_.front()); | 314 base::ResetAndReturn(&decode_cb_).Run(kOk); |
328 queued_audio_frames_.pop_front(); | |
329 } | 315 } |
330 | 316 |
331 void DecryptingAudioDecoder::OnKeyAdded() { | 317 void DecryptingAudioDecoder::OnKeyAdded() { |
332 DCHECK(task_runner_->BelongsToCurrentThread()); | 318 DCHECK(task_runner_->BelongsToCurrentThread()); |
333 | 319 |
334 if (state_ == kPendingDecode) { | 320 if (state_ == kPendingDecode) { |
335 key_added_while_decode_pending_ = true; | 321 key_added_while_decode_pending_ = true; |
336 return; | 322 return; |
337 } | 323 } |
338 | 324 |
339 if (state_ == kWaitingForKey) { | 325 if (state_ == kWaitingForKey) { |
340 state_ = kPendingDecode; | 326 state_ = kPendingDecode; |
341 DecodePendingBuffer(); | 327 DecodePendingBuffer(); |
342 } | 328 } |
343 } | 329 } |
344 | 330 |
345 void DecryptingAudioDecoder::DoReset() { | 331 void DecryptingAudioDecoder::DoReset() { |
346 DCHECK(init_cb_.is_null()); | 332 DCHECK(init_cb_.is_null()); |
347 DCHECK(decode_cb_.is_null()); | 333 DCHECK(decode_cb_.is_null()); |
348 timestamp_helper_->SetBaseTimestamp(kNoTimestamp()); | 334 timestamp_helper_->SetBaseTimestamp(kNoTimestamp()); |
349 state_ = kIdle; | 335 state_ = kIdle; |
350 base::ResetAndReturn(&reset_cb_).Run(); | 336 base::ResetAndReturn(&reset_cb_).Run(); |
351 } | 337 } |
352 | 338 |
353 void DecryptingAudioDecoder::EnqueueFrames( | 339 void DecryptingAudioDecoder::ProcessDecodedFrames( |
354 const Decryptor::AudioBuffers& frames) { | 340 const Decryptor::AudioBuffers& frames) { |
355 queued_audio_frames_ = frames; | 341 for (Decryptor::AudioBuffers::const_iterator iter = frames.begin(); |
356 | 342 iter != frames.end(); |
357 for (Decryptor::AudioBuffers::iterator iter = queued_audio_frames_.begin(); | |
358 iter != queued_audio_frames_.end(); | |
359 ++iter) { | 343 ++iter) { |
360 scoped_refptr<AudioBuffer>& frame = *iter; | 344 scoped_refptr<AudioBuffer> frame = *iter; |
361 | 345 |
362 DCHECK(!frame->end_of_stream()) << "EOS frame returned."; | 346 DCHECK(!frame->end_of_stream()) << "EOS frame returned."; |
363 DCHECK_GT(frame->frame_count(), 0) << "Empty frame returned."; | 347 DCHECK_GT(frame->frame_count(), 0) << "Empty frame returned."; |
364 | 348 |
365 base::TimeDelta current_time = timestamp_helper_->GetTimestamp(); | 349 base::TimeDelta current_time = timestamp_helper_->GetTimestamp(); |
366 if (IsOutOfSync(current_time, frame->timestamp())) { | 350 if (IsOutOfSync(current_time, frame->timestamp())) { |
367 DVLOG(1) << "Timestamp returned by the decoder (" | 351 DVLOG(1) << "Timestamp returned by the decoder (" |
368 << frame->timestamp().InMilliseconds() << " ms)" | 352 << frame->timestamp().InMilliseconds() << " ms)" |
369 << " does not match the input timestamp and number of samples" | 353 << " does not match the input timestamp and number of samples" |
370 << " decoded (" << current_time.InMilliseconds() << " ms)."; | 354 << " decoded (" << current_time.InMilliseconds() << " ms)."; |
371 } | 355 } |
372 | 356 |
373 frame->set_timestamp(current_time); | 357 frame->set_timestamp(current_time); |
374 timestamp_helper_->AddFrames(frame->frame_count()); | 358 timestamp_helper_->AddFrames(frame->frame_count()); |
| 359 |
| 360 output_cb_.Run(frame); |
375 } | 361 } |
376 } | 362 } |
377 | 363 |
378 } // namespace media | 364 } // namespace media |
OLD | NEW |