| 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/bind_to_current_loop.h" |
| 10 #include "base/callback_helpers.h" | 11 #include "base/callback_helpers.h" |
| 11 #include "base/location.h" | 12 #include "base/location.h" |
| 12 #include "base/logging.h" | 13 #include "base/logging.h" |
| 13 #include "base/single_thread_task_runner.h" | 14 #include "base/single_thread_task_runner.h" |
| 14 #include "media/base/audio_buffer.h" | 15 #include "media/base/audio_buffer.h" |
| 15 #include "media/base/audio_decoder_config.h" | 16 #include "media/base/audio_decoder_config.h" |
| 16 #include "media/base/audio_timestamp_helper.h" | 17 #include "media/base/audio_timestamp_helper.h" |
| 17 #include "media/base/bind_to_current_loop.h" | |
| 18 #include "media/base/buffers.h" | 18 #include "media/base/buffers.h" |
| 19 #include "media/base/decoder_buffer.h" | 19 #include "media/base/decoder_buffer.h" |
| 20 #include "media/base/decryptor.h" | 20 #include "media/base/decryptor.h" |
| 21 #include "media/base/demuxer_stream.h" | 21 #include "media/base/demuxer_stream.h" |
| 22 #include "media/base/pipeline.h" | 22 #include "media/base/pipeline.h" |
| 23 | 23 |
| 24 namespace media { | 24 namespace media { |
| 25 | 25 |
| 26 static inline bool IsOutOfSync(const base::TimeDelta& timestamp_1, | 26 static inline bool IsOutOfSync(const base::TimeDelta& timestamp_1, |
| 27 const base::TimeDelta& timestamp_2) { | 27 const base::TimeDelta& timestamp_2) { |
| (...skipping 23 matching lines...) Expand all Loading... |
| 51 | 51 |
| 52 void DecryptingAudioDecoder::Initialize(const AudioDecoderConfig& config, | 52 void DecryptingAudioDecoder::Initialize(const AudioDecoderConfig& config, |
| 53 const PipelineStatusCB& status_cb, | 53 const PipelineStatusCB& status_cb, |
| 54 const OutputCB& output_cb) { | 54 const OutputCB& output_cb) { |
| 55 DVLOG(2) << "Initialize()"; | 55 DVLOG(2) << "Initialize()"; |
| 56 DCHECK(task_runner_->BelongsToCurrentThread()); | 56 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 57 DCHECK(decode_cb_.is_null()); | 57 DCHECK(decode_cb_.is_null()); |
| 58 DCHECK(reset_cb_.is_null()); | 58 DCHECK(reset_cb_.is_null()); |
| 59 | 59 |
| 60 weak_this_ = weak_factory_.GetWeakPtr(); | 60 weak_this_ = weak_factory_.GetWeakPtr(); |
| 61 init_cb_ = BindToCurrentLoop(status_cb); | 61 init_cb_ = base::BindToCurrentLoop(status_cb); |
| 62 output_cb_ = BindToCurrentLoop(output_cb); | 62 output_cb_ = base::BindToCurrentLoop(output_cb); |
| 63 | 63 |
| 64 if (!config.IsValidConfig()) { | 64 if (!config.IsValidConfig()) { |
| 65 DLOG(ERROR) << "Invalid audio stream config."; | 65 DLOG(ERROR) << "Invalid audio stream config."; |
| 66 base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_DECODE); | 66 base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_DECODE); |
| 67 return; | 67 return; |
| 68 } | 68 } |
| 69 | 69 |
| 70 // DecryptingAudioDecoder only accepts potentially encrypted stream. | 70 // DecryptingAudioDecoder only accepts potentially encrypted stream. |
| 71 if (!config.is_encrypted()) { | 71 if (!config.is_encrypted()) { |
| 72 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED); | 72 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED); |
| 73 return; | 73 return; |
| 74 } | 74 } |
| 75 | 75 |
| 76 config_ = config; | 76 config_ = config; |
| 77 | 77 |
| 78 if (state_ == kUninitialized) { | 78 if (state_ == kUninitialized) { |
| 79 state_ = kDecryptorRequested; | 79 state_ = kDecryptorRequested; |
| 80 set_decryptor_ready_cb_.Run(BindToCurrentLoop( | 80 set_decryptor_ready_cb_.Run(base::BindToCurrentLoop( |
| 81 base::Bind(&DecryptingAudioDecoder::SetDecryptor, weak_this_))); | 81 base::Bind(&DecryptingAudioDecoder::SetDecryptor, weak_this_))); |
| 82 return; | 82 return; |
| 83 } | 83 } |
| 84 | 84 |
| 85 // Reinitialization (i.e. upon a config change) | 85 // Reinitialization (i.e. upon a config change) |
| 86 decryptor_->DeinitializeDecoder(Decryptor::kAudio); | 86 decryptor_->DeinitializeDecoder(Decryptor::kAudio); |
| 87 InitializeDecoder(); | 87 InitializeDecoder(); |
| 88 } | 88 } |
| 89 | 89 |
| 90 void DecryptingAudioDecoder::Decode(const scoped_refptr<DecoderBuffer>& buffer, | 90 void DecryptingAudioDecoder::Decode(const scoped_refptr<DecoderBuffer>& buffer, |
| 91 const DecodeCB& decode_cb) { | 91 const DecodeCB& decode_cb) { |
| 92 DVLOG(3) << "Decode()"; | 92 DVLOG(3) << "Decode()"; |
| 93 DCHECK(task_runner_->BelongsToCurrentThread()); | 93 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 94 DCHECK(state_ == kIdle || state_ == kDecodeFinished) << state_; | 94 DCHECK(state_ == kIdle || state_ == kDecodeFinished) << state_; |
| 95 DCHECK(!decode_cb.is_null()); | 95 DCHECK(!decode_cb.is_null()); |
| 96 CHECK(decode_cb_.is_null()) << "Overlapping decodes are not supported."; | 96 CHECK(decode_cb_.is_null()) << "Overlapping decodes are not supported."; |
| 97 | 97 |
| 98 decode_cb_ = BindToCurrentLoop(decode_cb); | 98 decode_cb_ = base::BindToCurrentLoop(decode_cb); |
| 99 | 99 |
| 100 // Return empty (end-of-stream) frames if decoding has finished. | 100 // Return empty (end-of-stream) frames if decoding has finished. |
| 101 if (state_ == kDecodeFinished) { | 101 if (state_ == kDecodeFinished) { |
| 102 output_cb_.Run(AudioBuffer::CreateEOSBuffer()); | 102 output_cb_.Run(AudioBuffer::CreateEOSBuffer()); |
| 103 base::ResetAndReturn(&decode_cb_).Run(kOk); | 103 base::ResetAndReturn(&decode_cb_).Run(kOk); |
| 104 return; | 104 return; |
| 105 } | 105 } |
| 106 | 106 |
| 107 // Initialize the |next_output_timestamp_| to be the timestamp of the first | 107 // Initialize the |next_output_timestamp_| to be the timestamp of the first |
| 108 // non-EOS buffer. | 108 // non-EOS buffer. |
| (...skipping 10 matching lines...) Expand all Loading... |
| 119 void DecryptingAudioDecoder::Reset(const base::Closure& closure) { | 119 void DecryptingAudioDecoder::Reset(const base::Closure& closure) { |
| 120 DVLOG(2) << "Reset() - state: " << state_; | 120 DVLOG(2) << "Reset() - state: " << state_; |
| 121 DCHECK(task_runner_->BelongsToCurrentThread()); | 121 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 122 DCHECK(state_ == kIdle || | 122 DCHECK(state_ == kIdle || |
| 123 state_ == kPendingDecode || | 123 state_ == kPendingDecode || |
| 124 state_ == kWaitingForKey || | 124 state_ == kWaitingForKey || |
| 125 state_ == kDecodeFinished) << state_; | 125 state_ == kDecodeFinished) << state_; |
| 126 DCHECK(init_cb_.is_null()); // No Reset() during pending initialization. | 126 DCHECK(init_cb_.is_null()); // No Reset() during pending initialization. |
| 127 DCHECK(reset_cb_.is_null()); | 127 DCHECK(reset_cb_.is_null()); |
| 128 | 128 |
| 129 reset_cb_ = BindToCurrentLoop(closure); | 129 reset_cb_ = base::BindToCurrentLoop(closure); |
| 130 | 130 |
| 131 decryptor_->ResetDecoder(Decryptor::kAudio); | 131 decryptor_->ResetDecoder(Decryptor::kAudio); |
| 132 | 132 |
| 133 // Reset() cannot complete if the read callback is still pending. | 133 // Reset() cannot complete if the read callback is still pending. |
| 134 // Defer the resetting process in this case. The |reset_cb_| will be fired | 134 // Defer the resetting process in this case. The |reset_cb_| will be fired |
| 135 // after the read callback is fired - see DecryptAndDecodeBuffer() and | 135 // after the read callback is fired - see DecryptAndDecodeBuffer() and |
| 136 // DeliverFrame(). | 136 // DeliverFrame(). |
| 137 if (state_ == kPendingDecode) { | 137 if (state_ == kPendingDecode) { |
| 138 DCHECK(!decode_cb_.is_null()); | 138 DCHECK(!decode_cb_.is_null()); |
| 139 return; | 139 return; |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 192 decryptor_ = decryptor; | 192 decryptor_ = decryptor; |
| 193 | 193 |
| 194 InitializeDecoder(); | 194 InitializeDecoder(); |
| 195 decryptor_attached_cb.Run(true); | 195 decryptor_attached_cb.Run(true); |
| 196 } | 196 } |
| 197 | 197 |
| 198 void DecryptingAudioDecoder::InitializeDecoder() { | 198 void DecryptingAudioDecoder::InitializeDecoder() { |
| 199 state_ = kPendingDecoderInit; | 199 state_ = kPendingDecoderInit; |
| 200 decryptor_->InitializeAudioDecoder( | 200 decryptor_->InitializeAudioDecoder( |
| 201 config_, | 201 config_, |
| 202 BindToCurrentLoop(base::Bind( | 202 base::BindToCurrentLoop(base::Bind( |
| 203 &DecryptingAudioDecoder::FinishInitialization, weak_this_))); | 203 &DecryptingAudioDecoder::FinishInitialization, weak_this_))); |
| 204 } | 204 } |
| 205 | 205 |
| 206 void DecryptingAudioDecoder::FinishInitialization(bool success) { | 206 void DecryptingAudioDecoder::FinishInitialization(bool success) { |
| 207 DVLOG(2) << "FinishInitialization()"; | 207 DVLOG(2) << "FinishInitialization()"; |
| 208 DCHECK(task_runner_->BelongsToCurrentThread()); | 208 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 209 DCHECK(state_ == kPendingDecoderInit) << state_; | 209 DCHECK(state_ == kPendingDecoderInit) << state_; |
| 210 DCHECK(!init_cb_.is_null()); | 210 DCHECK(!init_cb_.is_null()); |
| 211 DCHECK(reset_cb_.is_null()); // No Reset() before initialization finished. | 211 DCHECK(reset_cb_.is_null()); // No Reset() before initialization finished. |
| 212 DCHECK(decode_cb_.is_null()); // No Decode() before initialization finished. | 212 DCHECK(decode_cb_.is_null()); // No Decode() before initialization finished. |
| 213 | 213 |
| 214 if (!success) { | 214 if (!success) { |
| 215 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED); | 215 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED); |
| 216 decryptor_ = NULL; | 216 decryptor_ = NULL; |
| 217 state_ = kError; | 217 state_ = kError; |
| 218 return; | 218 return; |
| 219 } | 219 } |
| 220 | 220 |
| 221 // Success! | 221 // Success! |
| 222 timestamp_helper_.reset( | 222 timestamp_helper_.reset( |
| 223 new AudioTimestampHelper(config_.samples_per_second())); | 223 new AudioTimestampHelper(config_.samples_per_second())); |
| 224 | 224 |
| 225 decryptor_->RegisterNewKeyCB( | 225 decryptor_->RegisterNewKeyCB( |
| 226 Decryptor::kAudio, | 226 Decryptor::kAudio, |
| 227 BindToCurrentLoop( | 227 base::BindToCurrentLoop( |
| 228 base::Bind(&DecryptingAudioDecoder::OnKeyAdded, weak_this_))); | 228 base::Bind(&DecryptingAudioDecoder::OnKeyAdded, weak_this_))); |
| 229 | 229 |
| 230 state_ = kIdle; | 230 state_ = kIdle; |
| 231 base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK); | 231 base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK); |
| 232 } | 232 } |
| 233 | 233 |
| 234 void DecryptingAudioDecoder::DecodePendingBuffer() { | 234 void DecryptingAudioDecoder::DecodePendingBuffer() { |
| 235 DCHECK(task_runner_->BelongsToCurrentThread()); | 235 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 236 DCHECK_EQ(state_, kPendingDecode) << state_; | 236 DCHECK_EQ(state_, kPendingDecode) << state_; |
| 237 | 237 |
| 238 int buffer_size = 0; | 238 int buffer_size = 0; |
| 239 if (!pending_buffer_to_decode_->end_of_stream()) { | 239 if (!pending_buffer_to_decode_->end_of_stream()) { |
| 240 buffer_size = pending_buffer_to_decode_->data_size(); | 240 buffer_size = pending_buffer_to_decode_->data_size(); |
| 241 } | 241 } |
| 242 | 242 |
| 243 decryptor_->DecryptAndDecodeAudio( | 243 decryptor_->DecryptAndDecodeAudio( |
| 244 pending_buffer_to_decode_, | 244 pending_buffer_to_decode_, |
| 245 BindToCurrentLoop(base::Bind( | 245 base::BindToCurrentLoop(base::Bind( |
| 246 &DecryptingAudioDecoder::DeliverFrame, weak_this_, buffer_size))); | 246 &DecryptingAudioDecoder::DeliverFrame, weak_this_, buffer_size))); |
| 247 } | 247 } |
| 248 | 248 |
| 249 void DecryptingAudioDecoder::DeliverFrame( | 249 void DecryptingAudioDecoder::DeliverFrame( |
| 250 int buffer_size, | 250 int buffer_size, |
| 251 Decryptor::Status status, | 251 Decryptor::Status status, |
| 252 const Decryptor::AudioFrames& frames) { | 252 const Decryptor::AudioFrames& frames) { |
| 253 DVLOG(3) << "DeliverFrame() - status: " << status; | 253 DVLOG(3) << "DeliverFrame() - status: " << status; |
| 254 DCHECK(task_runner_->BelongsToCurrentThread()); | 254 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 255 DCHECK_EQ(state_, kPendingDecode) << state_; | 255 DCHECK_EQ(state_, kPendingDecode) << state_; |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 360 } | 360 } |
| 361 | 361 |
| 362 frame->set_timestamp(current_time); | 362 frame->set_timestamp(current_time); |
| 363 timestamp_helper_->AddFrames(frame->frame_count()); | 363 timestamp_helper_->AddFrames(frame->frame_count()); |
| 364 | 364 |
| 365 output_cb_.Run(frame); | 365 output_cb_.Run(frame); |
| 366 } | 366 } |
| 367 } | 367 } |
| 368 | 368 |
| 369 } // namespace media | 369 } // namespace media |
| OLD | NEW |