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