Chromium Code Reviews| 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" |
| 11 #include "base/message_loop_proxy.h" | 11 #include "base/message_loop_proxy.h" |
| 12 #include "media/base/audio_decoder_config.h" | 12 #include "media/base/audio_decoder_config.h" |
| 13 #include "media/base/video_decoder_config.h" | 13 #include "media/base/video_decoder_config.h" |
| 14 #include "media/base/bind_to_loop.h" | 14 #include "media/base/bind_to_loop.h" |
| 15 #include "media/base/decoder_buffer.h" | 15 #include "media/base/decoder_buffer.h" |
| 16 #include "media/base/decryptor.h" | 16 #include "media/base/decryptor.h" |
| 17 #include "media/base/demuxer_stream.h" | 17 #include "media/base/demuxer_stream.h" |
| 18 #include "media/base/pipeline.h" | 18 #include "media/base/pipeline.h" |
| 19 | 19 |
| 20 namespace media { | 20 namespace media { |
| 21 | 21 |
| 22 #define BIND_TO_LOOP(function) \ | 22 #define BIND_TO_LOOP(function) \ |
| 23 media::BindToLoop(message_loop_, base::Bind(function, this)) | 23 media::BindToLoop(message_loop_, base::Bind(function, this)) |
| 24 | 24 |
| 25 static bool IsStreamValidAndEncrytped( | |
|
acolwell GONE FROM CHROMIUM
2013/01/03 01:39:40
nit: s/Encrytped/Encrypted/
xhwang
2013/01/03 17:13:54
Done.
| |
| 26 const scoped_refptr<DemuxerStream>& stream) { | |
| 27 return ((stream->type() == DemuxerStream::AUDIO && | |
| 28 stream->audio_decoder_config().IsValidConfig() && | |
| 29 stream->audio_decoder_config().is_encrypted()) || | |
| 30 (stream->type() == DemuxerStream::VIDEO && | |
| 31 stream->video_decoder_config().IsValidConfig() && | |
| 32 stream->video_decoder_config().is_encrypted())); | |
| 33 } | |
| 34 | |
| 25 DecryptingDemuxerStream::DecryptingDemuxerStream( | 35 DecryptingDemuxerStream::DecryptingDemuxerStream( |
| 26 const scoped_refptr<base::MessageLoopProxy>& message_loop, | 36 const scoped_refptr<base::MessageLoopProxy>& message_loop, |
| 27 const SetDecryptorReadyCB& set_decryptor_ready_cb) | 37 const SetDecryptorReadyCB& set_decryptor_ready_cb) |
| 28 : message_loop_(message_loop), | 38 : message_loop_(message_loop), |
| 29 state_(kUninitialized), | 39 state_(kUninitialized), |
| 30 stream_type_(UNKNOWN), | 40 stream_type_(UNKNOWN), |
| 31 set_decryptor_ready_cb_(set_decryptor_ready_cb), | 41 set_decryptor_ready_cb_(set_decryptor_ready_cb), |
| 32 decryptor_(NULL), | 42 decryptor_(NULL), |
| 33 key_added_while_decrypt_pending_(false) { | 43 key_added_while_decrypt_pending_(false) { |
| 34 } | 44 } |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 115 | 125 |
| 116 DecryptingDemuxerStream::~DecryptingDemuxerStream() {} | 126 DecryptingDemuxerStream::~DecryptingDemuxerStream() {} |
| 117 | 127 |
| 118 void DecryptingDemuxerStream::DoInitialize( | 128 void DecryptingDemuxerStream::DoInitialize( |
| 119 const scoped_refptr<DemuxerStream>& stream, | 129 const scoped_refptr<DemuxerStream>& stream, |
| 120 const PipelineStatusCB& status_cb) { | 130 const PipelineStatusCB& status_cb) { |
| 121 DVLOG(2) << "DoInitialize()"; | 131 DVLOG(2) << "DoInitialize()"; |
| 122 DCHECK(message_loop_->BelongsToCurrentThread()); | 132 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 123 DCHECK_EQ(state_, kUninitialized) << state_; | 133 DCHECK_EQ(state_, kUninitialized) << state_; |
| 124 | 134 |
| 125 // Only valid potentially encrypted audio or video stream is accepted. | 135 // Decoder selector makes sure the stream is valid and potentially encrypted. |
| 126 if (!((stream->type() == AUDIO && | 136 DCHECK(IsStreamValidAndEncrytped(stream)); |
| 127 stream->audio_decoder_config().IsValidConfig() && | |
| 128 stream->audio_decoder_config().is_encrypted()) || | |
| 129 (stream->type() == VIDEO && | |
| 130 stream->video_decoder_config().IsValidConfig() && | |
| 131 stream->video_decoder_config().is_encrypted()))) { | |
| 132 status_cb.Run(DEMUXER_ERROR_NO_SUPPORTED_STREAMS); | |
| 133 return; | |
| 134 } | |
| 135 | 137 |
| 136 DCHECK(!demuxer_stream_); | 138 DCHECK(!demuxer_stream_); |
| 137 demuxer_stream_ = stream; | 139 demuxer_stream_ = stream; |
| 138 stream_type_ = stream->type(); | 140 stream_type_ = stream->type(); |
| 139 init_cb_ = status_cb; | 141 init_cb_ = status_cb; |
| 140 | 142 |
| 141 state_ = kDecryptorRequested; | 143 state_ = kDecryptorRequested; |
| 142 set_decryptor_ready_cb_.Run( | 144 set_decryptor_ready_cb_.Run( |
| 143 BIND_TO_LOOP(&DecryptingDemuxerStream::SetDecryptor)); | 145 BIND_TO_LOOP(&DecryptingDemuxerStream::SetDecryptor)); |
| 144 } | 146 } |
| 145 | 147 |
| 146 void DecryptingDemuxerStream::SetDecryptor(Decryptor* decryptor) { | 148 void DecryptingDemuxerStream::SetDecryptor(Decryptor* decryptor) { |
| 147 DVLOG(2) << "SetDecryptor()"; | 149 DVLOG(2) << "SetDecryptor()"; |
| 148 DCHECK(message_loop_->BelongsToCurrentThread()); | 150 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 149 DCHECK_EQ(state_, kDecryptorRequested) << state_; | 151 DCHECK_EQ(state_, kDecryptorRequested) << state_; |
| 150 DCHECK(!init_cb_.is_null()); | 152 DCHECK(!init_cb_.is_null()); |
| 151 DCHECK(!set_decryptor_ready_cb_.is_null()); | 153 DCHECK(!set_decryptor_ready_cb_.is_null()); |
| 152 | 154 |
| 153 set_decryptor_ready_cb_.Reset(); | 155 set_decryptor_ready_cb_.Reset(); |
| 154 decryptor_ = decryptor; | 156 decryptor_ = decryptor; |
| 155 | 157 |
| 156 switch (stream_type_) { | 158 SetDecoderConfig(); |
|
ddorwin
2013/01/03 01:45:36
Why was/is this done here instead of in DoInitiali
xhwang
2013/01/03 17:13:54
Good question. I don't see why not. Fixed.
| |
| 157 case AUDIO: { | |
| 158 const AudioDecoderConfig& input_audio_config = | |
| 159 demuxer_stream_->audio_decoder_config(); | |
| 160 audio_config_.reset(new AudioDecoderConfig()); | |
| 161 audio_config_->Initialize(input_audio_config.codec(), | |
| 162 input_audio_config.bits_per_channel(), | |
| 163 input_audio_config.channel_layout(), | |
| 164 input_audio_config.samples_per_second(), | |
| 165 input_audio_config.extra_data(), | |
| 166 input_audio_config.extra_data_size(), | |
| 167 false, // Output audio is not encrypted. | |
| 168 false); | |
| 169 break; | |
| 170 } | |
| 171 | |
| 172 case VIDEO: { | |
| 173 const VideoDecoderConfig& input_video_config = | |
| 174 demuxer_stream_->video_decoder_config(); | |
| 175 video_config_.reset(new VideoDecoderConfig()); | |
| 176 video_config_->Initialize(input_video_config.codec(), | |
| 177 input_video_config.profile(), | |
| 178 input_video_config.format(), | |
| 179 input_video_config.coded_size(), | |
| 180 input_video_config.visible_rect(), | |
| 181 input_video_config.natural_size(), | |
| 182 input_video_config.extra_data(), | |
| 183 input_video_config.extra_data_size(), | |
| 184 false, // Output video is not encrypted. | |
| 185 false); | |
| 186 break; | |
| 187 } | |
| 188 | |
| 189 default: | |
| 190 NOTREACHED(); | |
| 191 return; | |
| 192 } | |
| 193 | 159 |
| 194 decryptor_->RegisterNewKeyCB( | 160 decryptor_->RegisterNewKeyCB( |
| 195 GetDecryptorStreamType(), | 161 GetDecryptorStreamType(), |
| 196 BIND_TO_LOOP(&DecryptingDemuxerStream::OnKeyAdded)); | 162 BIND_TO_LOOP(&DecryptingDemuxerStream::OnKeyAdded)); |
| 197 | 163 |
| 198 state_ = kIdle; | 164 state_ = kIdle; |
| 199 base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK); | 165 base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK); |
| 200 } | 166 } |
| 201 | 167 |
| 202 void DecryptingDemuxerStream::DecryptBuffer( | 168 void DecryptingDemuxerStream::DecryptBuffer( |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 228 | 194 |
| 229 if (status == kAborted) { | 195 if (status == kAborted) { |
| 230 DVLOG(2) << "DoDecryptBuffer() - kAborted."; | 196 DVLOG(2) << "DoDecryptBuffer() - kAborted."; |
| 231 state_ = kIdle; | 197 state_ = kIdle; |
| 232 base::ResetAndReturn(&read_cb_).Run(kAborted, NULL); | 198 base::ResetAndReturn(&read_cb_).Run(kAborted, NULL); |
| 233 return; | 199 return; |
| 234 } | 200 } |
| 235 | 201 |
| 236 if (status == kConfigChanged) { | 202 if (status == kConfigChanged) { |
| 237 DVLOG(2) << "DoDecryptBuffer() - kConfigChanged."; | 203 DVLOG(2) << "DoDecryptBuffer() - kConfigChanged."; |
| 204 DCHECK_EQ(demuxer_stream_->type(), stream_type_); | |
| 205 // The demuxer should make sure the stream is still valid and potentially | |
| 206 // encrypted. | |
| 207 // TODO(xhwang): If needed, supported switching from encrypted stream to | |
|
acolwell GONE FROM CHROMIUM
2013/01/03 01:39:40
nit: s/supported/support
ddorwin
2013/01/03 01:45:36
Does this TODO belong in SourceBufferStream instea
xhwang
2013/01/03 17:13:54
Removed as I don't see any use case for that.
| |
| 208 // clear stream. | |
| 209 DCHECK(IsStreamValidAndEncrytped(demuxer_stream_)); | |
| 210 | |
| 211 SetDecoderConfig(); | |
| 238 state_ = kIdle; | 212 state_ = kIdle; |
| 239 // TODO(xhwang): Support kConfigChanged! | 213 base::ResetAndReturn(&read_cb_).Run(kConfigChanged, NULL); |
|
ddorwin
2013/01/03 01:45:36
Where does the config change take place? Does the
xhwang
2013/01/03 17:13:54
Added comment. The decoder will get notified of kC
| |
| 240 base::ResetAndReturn(&read_cb_).Run(kAborted, NULL); | |
| 241 return; | 214 return; |
| 242 } | 215 } |
| 243 | 216 |
| 244 if (buffer->IsEndOfStream()) { | 217 if (buffer->IsEndOfStream()) { |
| 245 DVLOG(2) << "DoDecryptBuffer() - EOS buffer."; | 218 DVLOG(2) << "DoDecryptBuffer() - EOS buffer."; |
| 246 state_ = kIdle; | 219 state_ = kIdle; |
| 247 base::ResetAndReturn(&read_cb_).Run(status, buffer); | 220 base::ResetAndReturn(&read_cb_).Run(status, buffer); |
| 248 return; | 221 return; |
| 249 } | 222 } |
| 250 | 223 |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 341 DCHECK(read_cb_.is_null()); | 314 DCHECK(read_cb_.is_null()); |
| 342 state_ = kIdle; | 315 state_ = kIdle; |
| 343 base::ResetAndReturn(&reset_cb_).Run(); | 316 base::ResetAndReturn(&reset_cb_).Run(); |
| 344 } | 317 } |
| 345 | 318 |
| 346 Decryptor::StreamType DecryptingDemuxerStream::GetDecryptorStreamType() const { | 319 Decryptor::StreamType DecryptingDemuxerStream::GetDecryptorStreamType() const { |
| 347 DCHECK(stream_type_ == AUDIO || stream_type_ == VIDEO); | 320 DCHECK(stream_type_ == AUDIO || stream_type_ == VIDEO); |
| 348 return stream_type_ == AUDIO ? Decryptor::kAudio : Decryptor::kVideo; | 321 return stream_type_ == AUDIO ? Decryptor::kAudio : Decryptor::kVideo; |
| 349 } | 322 } |
| 350 | 323 |
| 324 void DecryptingDemuxerStream::SetDecoderConfig() { | |
| 325 switch (stream_type_) { | |
| 326 case AUDIO: { | |
| 327 const AudioDecoderConfig& input_audio_config = | |
| 328 demuxer_stream_->audio_decoder_config(); | |
| 329 audio_config_.reset(new AudioDecoderConfig()); | |
| 330 audio_config_->Initialize(input_audio_config.codec(), | |
| 331 input_audio_config.bits_per_channel(), | |
| 332 input_audio_config.channel_layout(), | |
| 333 input_audio_config.samples_per_second(), | |
| 334 input_audio_config.extra_data(), | |
| 335 input_audio_config.extra_data_size(), | |
| 336 false, // Output audio is not encrypted. | |
| 337 false); | |
| 338 break; | |
| 339 } | |
| 340 | |
| 341 case VIDEO: { | |
| 342 const VideoDecoderConfig& input_video_config = | |
| 343 demuxer_stream_->video_decoder_config(); | |
| 344 video_config_.reset(new VideoDecoderConfig()); | |
| 345 video_config_->Initialize(input_video_config.codec(), | |
| 346 input_video_config.profile(), | |
| 347 input_video_config.format(), | |
| 348 input_video_config.coded_size(), | |
| 349 input_video_config.visible_rect(), | |
| 350 input_video_config.natural_size(), | |
| 351 input_video_config.extra_data(), | |
| 352 input_video_config.extra_data_size(), | |
| 353 false, // Output video is not encrypted. | |
| 354 false); | |
| 355 break; | |
| 356 } | |
| 357 | |
| 358 default: | |
| 359 NOTREACHED(); | |
| 360 return; | |
| 361 } | |
| 362 } | |
| 363 | |
| 351 } // namespace media | 364 } // namespace media |
| OLD | NEW |