| 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_demuxer_stream.h" | 5 #include "media/filters/decrypting_demuxer_stream.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/callback_helpers.h" | 8 #include "base/callback_helpers.h" |
| 9 #include "base/location.h" | 9 #include "base/location.h" |
| 10 #include "base/logging.h" | 10 #include "base/logging.h" |
| (...skipping 25 matching lines...) Expand all Loading... |
| 36 demuxer_stream_(NULL), | 36 demuxer_stream_(NULL), |
| 37 decryptor_(NULL), | 37 decryptor_(NULL), |
| 38 key_added_while_decrypt_pending_(false), | 38 key_added_while_decrypt_pending_(false), |
| 39 weak_factory_(this) {} | 39 weak_factory_(this) {} |
| 40 | 40 |
| 41 std::string DecryptingDemuxerStream::GetDisplayName() const { | 41 std::string DecryptingDemuxerStream::GetDisplayName() const { |
| 42 return "DecryptingDemuxerStream"; | 42 return "DecryptingDemuxerStream"; |
| 43 } | 43 } |
| 44 | 44 |
| 45 void DecryptingDemuxerStream::Initialize(DemuxerStream* stream, | 45 void DecryptingDemuxerStream::Initialize(DemuxerStream* stream, |
| 46 const SetCdmReadyCB& set_cdm_ready_cb, | 46 CdmContext* cdm_context, |
| 47 const PipelineStatusCB& status_cb) { | 47 const PipelineStatusCB& status_cb) { |
| 48 DVLOG(2) << __FUNCTION__; | 48 DVLOG(2) << __FUNCTION__; |
| 49 DCHECK(task_runner_->BelongsToCurrentThread()); | 49 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 50 DCHECK_EQ(state_, kUninitialized) << state_; | 50 DCHECK_EQ(state_, kUninitialized) << state_; |
| 51 | 51 |
| 52 DCHECK(!demuxer_stream_); | 52 DCHECK(!demuxer_stream_); |
| 53 weak_this_ = weak_factory_.GetWeakPtr(); | 53 weak_this_ = weak_factory_.GetWeakPtr(); |
| 54 demuxer_stream_ = stream; | 54 demuxer_stream_ = stream; |
| 55 set_cdm_ready_cb_ = set_cdm_ready_cb; | |
| 56 init_cb_ = BindToCurrentLoop(status_cb); | 55 init_cb_ = BindToCurrentLoop(status_cb); |
| 57 | 56 |
| 58 InitializeDecoderConfig(); | 57 InitializeDecoderConfig(); |
| 59 | 58 |
| 60 state_ = kDecryptorRequested; | 59 DCHECK(cdm_context); |
| 61 set_cdm_ready_cb_.Run(BindToCurrentLoop( | 60 if (!cdm_context->GetDecryptor()) { |
| 62 base::Bind(&DecryptingDemuxerStream::SetCdm, weak_this_))); | 61 MEDIA_LOG(DEBUG, media_log_) << GetDisplayName() << ": no decryptor"; |
| 62 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED); |
| 63 return; |
| 64 } |
| 65 |
| 66 decryptor_ = cdm_context->GetDecryptor(); |
| 67 |
| 68 decryptor_->RegisterNewKeyCB( |
| 69 GetDecryptorStreamType(), |
| 70 BindToCurrentLoop( |
| 71 base::Bind(&DecryptingDemuxerStream::OnKeyAdded, weak_this_))); |
| 72 |
| 73 state_ = kIdle; |
| 74 base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK); |
| 63 } | 75 } |
| 64 | 76 |
| 65 void DecryptingDemuxerStream::Read(const ReadCB& read_cb) { | 77 void DecryptingDemuxerStream::Read(const ReadCB& read_cb) { |
| 66 DVLOG(3) << __FUNCTION__; | 78 DVLOG(3) << __FUNCTION__; |
| 67 DCHECK(task_runner_->BelongsToCurrentThread()); | 79 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 68 DCHECK_EQ(state_, kIdle) << state_; | 80 DCHECK_EQ(state_, kIdle) << state_; |
| 69 DCHECK(!read_cb.is_null()); | 81 DCHECK(!read_cb.is_null()); |
| 70 CHECK(read_cb_.is_null()) << "Overlapping reads are not supported."; | 82 CHECK(read_cb_.is_null()) << "Overlapping reads are not supported."; |
| 71 | 83 |
| 72 read_cb_ = BindToCurrentLoop(read_cb); | 84 read_cb_ = BindToCurrentLoop(read_cb); |
| 73 state_ = kPendingDemuxerRead; | 85 state_ = kPendingDemuxerRead; |
| 74 demuxer_stream_->Read( | 86 demuxer_stream_->Read( |
| 75 base::Bind(&DecryptingDemuxerStream::DecryptBuffer, weak_this_)); | 87 base::Bind(&DecryptingDemuxerStream::DecryptBuffer, weak_this_)); |
| 76 } | 88 } |
| 77 | 89 |
| 78 void DecryptingDemuxerStream::Reset(const base::Closure& closure) { | 90 void DecryptingDemuxerStream::Reset(const base::Closure& closure) { |
| 79 DVLOG(2) << __FUNCTION__ << " - state: " << state_; | 91 DVLOG(2) << __FUNCTION__ << " - state: " << state_; |
| 80 DCHECK(task_runner_->BelongsToCurrentThread()); | 92 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 81 DCHECK(state_ != kUninitialized) << state_; | 93 DCHECK(state_ != kUninitialized) << state_; |
| 82 DCHECK(reset_cb_.is_null()); | 94 DCHECK(reset_cb_.is_null()); |
| 83 | 95 |
| 84 reset_cb_ = BindToCurrentLoop(closure); | 96 reset_cb_ = BindToCurrentLoop(closure); |
| 85 | 97 |
| 86 // TODO(xhwang): This should not happen. Remove it, DCHECK against the | |
| 87 // condition and clean up related tests. | |
| 88 if (state_ == kDecryptorRequested) { | |
| 89 DCHECK(!init_cb_.is_null()); | |
| 90 set_cdm_ready_cb_.Run(CdmReadyCB()); | |
| 91 base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_ABORT); | |
| 92 DoReset(); | |
| 93 return; | |
| 94 } | |
| 95 | |
| 96 decryptor_->CancelDecrypt(GetDecryptorStreamType()); | 98 decryptor_->CancelDecrypt(GetDecryptorStreamType()); |
| 97 | 99 |
| 98 // Reset() cannot complete if the read callback is still pending. | 100 // Reset() cannot complete if the read callback is still pending. |
| 99 // Defer the resetting process in this case. The |reset_cb_| will be fired | 101 // Defer the resetting process in this case. The |reset_cb_| will be fired |
| 100 // after the read callback is fired - see DoDecryptBuffer() and | 102 // after the read callback is fired - see DoDecryptBuffer() and |
| 101 // DoDeliverBuffer(). | 103 // DoDeliverBuffer(). |
| 102 if (state_ == kPendingDemuxerRead || state_ == kPendingDecrypt) { | 104 if (state_ == kPendingDemuxerRead || state_ == kPendingDecrypt) { |
| 103 DCHECK(!read_cb_.is_null()); | 105 DCHECK(!read_cb_.is_null()); |
| 104 return; | 106 return; |
| 105 } | 107 } |
| 106 | 108 |
| 107 if (state_ == kWaitingForKey) { | 109 if (state_ == kWaitingForKey) { |
| 108 DCHECK(!read_cb_.is_null()); | 110 DCHECK(!read_cb_.is_null()); |
| 109 pending_buffer_to_decrypt_ = NULL; | 111 pending_buffer_to_decrypt_ = NULL; |
| 110 base::ResetAndReturn(&read_cb_).Run(kAborted, NULL); | 112 base::ResetAndReturn(&read_cb_).Run(kAborted, NULL); |
| 111 } | 113 } |
| 112 | 114 |
| 113 DCHECK(read_cb_.is_null()); | 115 DCHECK(read_cb_.is_null()); |
| 114 DoReset(); | 116 DoReset(); |
| 115 } | 117 } |
| 116 | 118 |
| 117 AudioDecoderConfig DecryptingDemuxerStream::audio_decoder_config() { | 119 AudioDecoderConfig DecryptingDemuxerStream::audio_decoder_config() { |
| 118 DCHECK(state_ != kUninitialized && state_ != kDecryptorRequested) << state_; | 120 DCHECK(state_ != kUninitialized) << state_; |
| 119 CHECK_EQ(demuxer_stream_->type(), AUDIO); | 121 CHECK_EQ(demuxer_stream_->type(), AUDIO); |
| 120 return audio_config_; | 122 return audio_config_; |
| 121 } | 123 } |
| 122 | 124 |
| 123 VideoDecoderConfig DecryptingDemuxerStream::video_decoder_config() { | 125 VideoDecoderConfig DecryptingDemuxerStream::video_decoder_config() { |
| 124 DCHECK(state_ != kUninitialized && state_ != kDecryptorRequested) << state_; | 126 DCHECK(state_ != kUninitialized) << state_; |
| 125 CHECK_EQ(demuxer_stream_->type(), VIDEO); | 127 CHECK_EQ(demuxer_stream_->type(), VIDEO); |
| 126 return video_config_; | 128 return video_config_; |
| 127 } | 129 } |
| 128 | 130 |
| 129 DemuxerStream::Type DecryptingDemuxerStream::type() const { | 131 DemuxerStream::Type DecryptingDemuxerStream::type() const { |
| 130 DCHECK(state_ != kUninitialized && state_ != kDecryptorRequested) << state_; | 132 DCHECK(state_ != kUninitialized) << state_; |
| 131 return demuxer_stream_->type(); | 133 return demuxer_stream_->type(); |
| 132 } | 134 } |
| 133 | 135 |
| 134 DemuxerStream::Liveness DecryptingDemuxerStream::liveness() const { | 136 DemuxerStream::Liveness DecryptingDemuxerStream::liveness() const { |
| 135 DCHECK(state_ != kUninitialized && state_ != kDecryptorRequested) << state_; | 137 DCHECK(state_ != kUninitialized) << state_; |
| 136 return demuxer_stream_->liveness(); | 138 return demuxer_stream_->liveness(); |
| 137 } | 139 } |
| 138 | 140 |
| 139 void DecryptingDemuxerStream::EnableBitstreamConverter() { | 141 void DecryptingDemuxerStream::EnableBitstreamConverter() { |
| 140 demuxer_stream_->EnableBitstreamConverter(); | 142 demuxer_stream_->EnableBitstreamConverter(); |
| 141 } | 143 } |
| 142 | 144 |
| 143 bool DecryptingDemuxerStream::SupportsConfigChanges() { | 145 bool DecryptingDemuxerStream::SupportsConfigChanges() { |
| 144 return demuxer_stream_->SupportsConfigChanges(); | 146 return demuxer_stream_->SupportsConfigChanges(); |
| 145 } | 147 } |
| 146 | 148 |
| 147 VideoRotation DecryptingDemuxerStream::video_rotation() { | 149 VideoRotation DecryptingDemuxerStream::video_rotation() { |
| 148 return demuxer_stream_->video_rotation(); | 150 return demuxer_stream_->video_rotation(); |
| 149 } | 151 } |
| 150 | 152 |
| 151 DecryptingDemuxerStream::~DecryptingDemuxerStream() { | 153 DecryptingDemuxerStream::~DecryptingDemuxerStream() { |
| 152 DVLOG(2) << __FUNCTION__ << " : state_ = " << state_; | 154 DVLOG(2) << __FUNCTION__ << " : state_ = " << state_; |
| 153 DCHECK(task_runner_->BelongsToCurrentThread()); | 155 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 154 | 156 |
| 155 if (state_ == kUninitialized) | 157 if (state_ == kUninitialized) |
| 156 return; | 158 return; |
| 157 | 159 |
| 158 if (decryptor_) { | 160 if (decryptor_) { |
| 159 decryptor_->CancelDecrypt(GetDecryptorStreamType()); | 161 decryptor_->CancelDecrypt(GetDecryptorStreamType()); |
| 160 decryptor_ = NULL; | 162 decryptor_ = NULL; |
| 161 } | 163 } |
| 162 if (!set_cdm_ready_cb_.is_null()) | |
| 163 base::ResetAndReturn(&set_cdm_ready_cb_).Run(CdmReadyCB()); | |
| 164 if (!init_cb_.is_null()) | 164 if (!init_cb_.is_null()) |
| 165 base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_ABORT); | 165 base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_ABORT); |
| 166 if (!read_cb_.is_null()) | 166 if (!read_cb_.is_null()) |
| 167 base::ResetAndReturn(&read_cb_).Run(kAborted, NULL); | 167 base::ResetAndReturn(&read_cb_).Run(kAborted, NULL); |
| 168 if (!reset_cb_.is_null()) | 168 if (!reset_cb_.is_null()) |
| 169 base::ResetAndReturn(&reset_cb_).Run(); | 169 base::ResetAndReturn(&reset_cb_).Run(); |
| 170 pending_buffer_to_decrypt_ = NULL; | 170 pending_buffer_to_decrypt_ = NULL; |
| 171 } | 171 } |
| 172 | 172 |
| 173 void DecryptingDemuxerStream::SetCdm(CdmContext* cdm_context, | |
| 174 const CdmAttachedCB& cdm_attached_cb) { | |
| 175 DVLOG(2) << __FUNCTION__; | |
| 176 DCHECK(task_runner_->BelongsToCurrentThread()); | |
| 177 DCHECK_EQ(state_, kDecryptorRequested) << state_; | |
| 178 DCHECK(!init_cb_.is_null()); | |
| 179 DCHECK(!set_cdm_ready_cb_.is_null()); | |
| 180 | |
| 181 set_cdm_ready_cb_.Reset(); | |
| 182 | |
| 183 if (!cdm_context || !cdm_context->GetDecryptor()) { | |
| 184 MEDIA_LOG(DEBUG, media_log_) << GetDisplayName() << ": decryptor not set"; | |
| 185 state_ = kUninitialized; | |
| 186 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED); | |
| 187 cdm_attached_cb.Run(false); | |
| 188 return; | |
| 189 } | |
| 190 | |
| 191 decryptor_ = cdm_context->GetDecryptor(); | |
| 192 | |
| 193 decryptor_->RegisterNewKeyCB( | |
| 194 GetDecryptorStreamType(), | |
| 195 BindToCurrentLoop( | |
| 196 base::Bind(&DecryptingDemuxerStream::OnKeyAdded, weak_this_))); | |
| 197 | |
| 198 state_ = kIdle; | |
| 199 base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK); | |
| 200 cdm_attached_cb.Run(true); | |
| 201 } | |
| 202 | |
| 203 void DecryptingDemuxerStream::DecryptBuffer( | 173 void DecryptingDemuxerStream::DecryptBuffer( |
| 204 DemuxerStream::Status status, | 174 DemuxerStream::Status status, |
| 205 const scoped_refptr<DecoderBuffer>& buffer) { | 175 const scoped_refptr<DecoderBuffer>& buffer) { |
| 206 DVLOG(3) << __FUNCTION__; | 176 DVLOG(3) << __FUNCTION__; |
| 207 DCHECK(task_runner_->BelongsToCurrentThread()); | 177 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 208 DCHECK_EQ(state_, kPendingDemuxerRead) << state_; | 178 DCHECK_EQ(state_, kPendingDemuxerRead) << state_; |
| 209 DCHECK(!read_cb_.is_null()); | 179 DCHECK(!read_cb_.is_null()); |
| 210 DCHECK_EQ(buffer.get() != NULL, status == kOk) << status; | 180 DCHECK_EQ(buffer.get() != NULL, status == kOk) << status; |
| 211 | 181 |
| 212 // Even when |!reset_cb_.is_null()|, we need to pass |kConfigChanged| back to | 182 // Even when |!reset_cb_.is_null()|, we need to pass |kConfigChanged| back to |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 346 state_ = kPendingDecrypt; | 316 state_ = kPendingDecrypt; |
| 347 DecryptPendingBuffer(); | 317 DecryptPendingBuffer(); |
| 348 } | 318 } |
| 349 } | 319 } |
| 350 | 320 |
| 351 void DecryptingDemuxerStream::DoReset() { | 321 void DecryptingDemuxerStream::DoReset() { |
| 352 DCHECK(state_ != kUninitialized); | 322 DCHECK(state_ != kUninitialized); |
| 353 DCHECK(init_cb_.is_null()); | 323 DCHECK(init_cb_.is_null()); |
| 354 DCHECK(read_cb_.is_null()); | 324 DCHECK(read_cb_.is_null()); |
| 355 | 325 |
| 356 if (state_ == kDecryptorRequested) | 326 state_ = kIdle; |
| 357 state_ = kUninitialized; | |
| 358 else | |
| 359 state_ = kIdle; | |
| 360 | |
| 361 base::ResetAndReturn(&reset_cb_).Run(); | 327 base::ResetAndReturn(&reset_cb_).Run(); |
| 362 } | 328 } |
| 363 | 329 |
| 364 Decryptor::StreamType DecryptingDemuxerStream::GetDecryptorStreamType() const { | 330 Decryptor::StreamType DecryptingDemuxerStream::GetDecryptorStreamType() const { |
| 365 if (demuxer_stream_->type() == AUDIO) | 331 if (demuxer_stream_->type() == AUDIO) |
| 366 return Decryptor::kAudio; | 332 return Decryptor::kAudio; |
| 367 | 333 |
| 368 DCHECK_EQ(demuxer_stream_->type(), VIDEO); | 334 DCHECK_EQ(demuxer_stream_->type(), VIDEO); |
| 369 return Decryptor::kVideo; | 335 return Decryptor::kVideo; |
| 370 } | 336 } |
| (...skipping 30 matching lines...) Expand all Loading... |
| 401 break; | 367 break; |
| 402 } | 368 } |
| 403 | 369 |
| 404 default: | 370 default: |
| 405 NOTREACHED(); | 371 NOTREACHED(); |
| 406 return; | 372 return; |
| 407 } | 373 } |
| 408 } | 374 } |
| 409 | 375 |
| 410 } // namespace media | 376 } // namespace media |
| OLD | NEW |