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