| 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 |