| 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 <stdint.h> | 7 #include <stdint.h> |
| 8 | 8 |
| 9 #include <cstdlib> | 9 #include <cstdlib> |
| 10 | 10 |
| 11 #include "base/bind.h" | 11 #include "base/bind.h" |
| 12 #include "base/callback_helpers.h" | 12 #include "base/callback_helpers.h" |
| 13 #include "base/location.h" | 13 #include "base/location.h" |
| 14 #include "base/logging.h" | 14 #include "base/logging.h" |
| 15 #include "base/single_thread_task_runner.h" | 15 #include "base/single_thread_task_runner.h" |
| 16 #include "media/base/audio_buffer.h" | 16 #include "media/base/audio_buffer.h" |
| 17 #include "media/base/audio_decoder_config.h" | 17 #include "media/base/audio_decoder_config.h" |
| 18 #include "media/base/audio_timestamp_helper.h" | 18 #include "media/base/audio_timestamp_helper.h" |
| 19 #include "media/base/bind_to_current_loop.h" | 19 #include "media/base/bind_to_current_loop.h" |
| 20 #include "media/base/cdm_context.h" |
| 20 #include "media/base/decoder_buffer.h" | 21 #include "media/base/decoder_buffer.h" |
| 21 #include "media/base/media_log.h" | 22 #include "media/base/media_log.h" |
| 22 #include "media/base/pipeline.h" | 23 #include "media/base/pipeline.h" |
| 23 #include "media/base/timestamp_constants.h" | 24 #include "media/base/timestamp_constants.h" |
| 24 | 25 |
| 25 namespace media { | 26 namespace media { |
| 26 | 27 |
| 27 static inline bool IsOutOfSync(const base::TimeDelta& timestamp_1, | 28 static inline bool IsOutOfSync(const base::TimeDelta& timestamp_1, |
| 28 const base::TimeDelta& timestamp_2) { | 29 const base::TimeDelta& timestamp_2) { |
| 29 // Out of sync of 100ms would be pretty noticeable and we should keep any | 30 // Out of sync of 100ms would be pretty noticeable and we should keep any |
| (...skipping 13 matching lines...) Expand all Loading... |
| 43 waiting_for_decryption_key_cb_(waiting_for_decryption_key_cb), | 44 waiting_for_decryption_key_cb_(waiting_for_decryption_key_cb), |
| 44 decryptor_(NULL), | 45 decryptor_(NULL), |
| 45 key_added_while_decode_pending_(false), | 46 key_added_while_decode_pending_(false), |
| 46 weak_factory_(this) {} | 47 weak_factory_(this) {} |
| 47 | 48 |
| 48 std::string DecryptingAudioDecoder::GetDisplayName() const { | 49 std::string DecryptingAudioDecoder::GetDisplayName() const { |
| 49 return "DecryptingAudioDecoder"; | 50 return "DecryptingAudioDecoder"; |
| 50 } | 51 } |
| 51 | 52 |
| 52 void DecryptingAudioDecoder::Initialize(const AudioDecoderConfig& config, | 53 void DecryptingAudioDecoder::Initialize(const AudioDecoderConfig& config, |
| 53 const SetCdmReadyCB& set_cdm_ready_cb, | 54 CdmContext* cdm_context, |
| 54 const InitCB& init_cb, | 55 const InitCB& init_cb, |
| 55 const OutputCB& output_cb) { | 56 const OutputCB& output_cb) { |
| 56 DVLOG(2) << "Initialize()"; | 57 DVLOG(2) << "Initialize()"; |
| 57 DCHECK(task_runner_->BelongsToCurrentThread()); | 58 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 58 DCHECK(decode_cb_.is_null()); | 59 DCHECK(decode_cb_.is_null()); |
| 59 DCHECK(reset_cb_.is_null()); | 60 DCHECK(reset_cb_.is_null()); |
| 60 | 61 |
| 61 weak_this_ = weak_factory_.GetWeakPtr(); | 62 weak_this_ = weak_factory_.GetWeakPtr(); |
| 62 init_cb_ = BindToCurrentLoop(init_cb); | 63 init_cb_ = BindToCurrentLoop(init_cb); |
| 63 output_cb_ = BindToCurrentLoop(output_cb); | 64 output_cb_ = BindToCurrentLoop(output_cb); |
| 64 | 65 |
| 66 // TODO(xhwang): We should be able to DCHECK config.IsValidConfig() and |
| 67 // config.is_encrypted(). |
| 65 if (!config.IsValidConfig()) { | 68 if (!config.IsValidConfig()) { |
| 66 DLOG(ERROR) << "Invalid audio stream config."; | 69 DLOG(ERROR) << "Invalid audio stream config."; |
| 67 base::ResetAndReturn(&init_cb_).Run(false); | 70 base::ResetAndReturn(&init_cb_).Run(false); |
| 68 return; | 71 return; |
| 69 } | 72 } |
| 70 | 73 |
| 71 // DecryptingAudioDecoder only accepts potentially encrypted stream. | 74 // DecryptingAudioDecoder only accepts potentially encrypted stream. |
| 72 if (!config.is_encrypted()) { | 75 if (!config.is_encrypted()) { |
| 73 base::ResetAndReturn(&init_cb_).Run(false); | 76 base::ResetAndReturn(&init_cb_).Run(false); |
| 74 return; | 77 return; |
| 75 } | 78 } |
| 76 | 79 |
| 77 config_ = config; | 80 config_ = config; |
| 78 | 81 |
| 79 if (state_ == kUninitialized) { | 82 if (state_ == kUninitialized) { |
| 80 DCHECK(!set_cdm_ready_cb.is_null()); | 83 DCHECK(cdm_context); |
| 81 state_ = kDecryptorRequested; | 84 if (!cdm_context->GetDecryptor()) { |
| 82 set_cdm_ready_cb_ = set_cdm_ready_cb; | 85 MEDIA_LOG(DEBUG, media_log_) << GetDisplayName() << ": no decryptor"; |
| 83 set_cdm_ready_cb_.Run(BindToCurrentLoop( | 86 base::ResetAndReturn(&init_cb_).Run(false); |
| 84 base::Bind(&DecryptingAudioDecoder::SetCdm, weak_this_))); | 87 return; |
| 85 return; | 88 } |
| 89 |
| 90 decryptor_ = cdm_context->GetDecryptor(); |
| 91 } else { |
| 92 // Reinitialization (i.e. upon a config change) |
| 93 decryptor_->DeinitializeDecoder(Decryptor::kAudio); |
| 86 } | 94 } |
| 87 | 95 |
| 88 // Reinitialization (i.e. upon a config change) | |
| 89 decryptor_->DeinitializeDecoder(Decryptor::kAudio); | |
| 90 InitializeDecoder(); | 96 InitializeDecoder(); |
| 91 } | 97 } |
| 92 | 98 |
| 93 void DecryptingAudioDecoder::Decode(const scoped_refptr<DecoderBuffer>& buffer, | 99 void DecryptingAudioDecoder::Decode(const scoped_refptr<DecoderBuffer>& buffer, |
| 94 const DecodeCB& decode_cb) { | 100 const DecodeCB& decode_cb) { |
| 95 DVLOG(3) << "Decode()"; | 101 DVLOG(3) << "Decode()"; |
| 96 DCHECK(task_runner_->BelongsToCurrentThread()); | 102 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 97 DCHECK(state_ == kIdle || state_ == kDecodeFinished) << state_; | 103 DCHECK(state_ == kIdle || state_ == kDecodeFinished) << state_; |
| 98 DCHECK(!decode_cb.is_null()); | 104 DCHECK(!decode_cb.is_null()); |
| 99 CHECK(decode_cb_.is_null()) << "Overlapping decodes are not supported."; | 105 CHECK(decode_cb_.is_null()) << "Overlapping decodes are not supported."; |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 156 DVLOG(2) << __FUNCTION__; | 162 DVLOG(2) << __FUNCTION__; |
| 157 DCHECK(task_runner_->BelongsToCurrentThread()); | 163 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 158 | 164 |
| 159 if (state_ == kUninitialized) | 165 if (state_ == kUninitialized) |
| 160 return; | 166 return; |
| 161 | 167 |
| 162 if (decryptor_) { | 168 if (decryptor_) { |
| 163 decryptor_->DeinitializeDecoder(Decryptor::kAudio); | 169 decryptor_->DeinitializeDecoder(Decryptor::kAudio); |
| 164 decryptor_ = NULL; | 170 decryptor_ = NULL; |
| 165 } | 171 } |
| 166 if (!set_cdm_ready_cb_.is_null()) | |
| 167 base::ResetAndReturn(&set_cdm_ready_cb_).Run(CdmReadyCB()); | |
| 168 pending_buffer_to_decode_ = NULL; | 172 pending_buffer_to_decode_ = NULL; |
| 169 if (!init_cb_.is_null()) | 173 if (!init_cb_.is_null()) |
| 170 base::ResetAndReturn(&init_cb_).Run(false); | 174 base::ResetAndReturn(&init_cb_).Run(false); |
| 171 if (!decode_cb_.is_null()) | 175 if (!decode_cb_.is_null()) |
| 172 base::ResetAndReturn(&decode_cb_).Run(kAborted); | 176 base::ResetAndReturn(&decode_cb_).Run(kAborted); |
| 173 if (!reset_cb_.is_null()) | 177 if (!reset_cb_.is_null()) |
| 174 base::ResetAndReturn(&reset_cb_).Run(); | 178 base::ResetAndReturn(&reset_cb_).Run(); |
| 175 } | 179 } |
| 176 | 180 |
| 177 void DecryptingAudioDecoder::SetCdm(CdmContext* cdm_context, | |
| 178 const CdmAttachedCB& cdm_attached_cb) { | |
| 179 DVLOG(2) << __FUNCTION__; | |
| 180 DCHECK(task_runner_->BelongsToCurrentThread()); | |
| 181 DCHECK_EQ(state_, kDecryptorRequested) << state_; | |
| 182 DCHECK(!init_cb_.is_null()); | |
| 183 DCHECK(!set_cdm_ready_cb_.is_null()); | |
| 184 | |
| 185 set_cdm_ready_cb_.Reset(); | |
| 186 | |
| 187 if (!cdm_context || !cdm_context->GetDecryptor()) { | |
| 188 MEDIA_LOG(DEBUG, media_log_) << GetDisplayName() << ": no decryptor set"; | |
| 189 base::ResetAndReturn(&init_cb_).Run(false); | |
| 190 state_ = kError; | |
| 191 cdm_attached_cb.Run(false); | |
| 192 return; | |
| 193 } | |
| 194 | |
| 195 decryptor_ = cdm_context->GetDecryptor(); | |
| 196 | |
| 197 InitializeDecoder(); | |
| 198 cdm_attached_cb.Run(true); | |
| 199 } | |
| 200 | |
| 201 void DecryptingAudioDecoder::InitializeDecoder() { | 181 void DecryptingAudioDecoder::InitializeDecoder() { |
| 202 state_ = kPendingDecoderInit; | 182 state_ = kPendingDecoderInit; |
| 203 decryptor_->InitializeAudioDecoder( | 183 decryptor_->InitializeAudioDecoder( |
| 204 config_, | 184 config_, |
| 205 BindToCurrentLoop(base::Bind( | 185 BindToCurrentLoop(base::Bind( |
| 206 &DecryptingAudioDecoder::FinishInitialization, weak_this_))); | 186 &DecryptingAudioDecoder::FinishInitialization, weak_this_))); |
| 207 } | 187 } |
| 208 | 188 |
| 209 void DecryptingAudioDecoder::FinishInitialization(bool success) { | 189 void DecryptingAudioDecoder::FinishInitialization(bool success) { |
| 210 DVLOG(2) << "FinishInitialization()"; | 190 DVLOG(2) << "FinishInitialization()"; |
| (...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 368 } | 348 } |
| 369 | 349 |
| 370 frame->set_timestamp(current_time); | 350 frame->set_timestamp(current_time); |
| 371 timestamp_helper_->AddFrames(frame->frame_count()); | 351 timestamp_helper_->AddFrames(frame->frame_count()); |
| 372 | 352 |
| 373 output_cb_.Run(frame); | 353 output_cb_.Run(frame); |
| 374 } | 354 } |
| 375 } | 355 } |
| 376 | 356 |
| 377 } // namespace media | 357 } // namespace media |
| OLD | NEW |