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 IsStreamValidAndEncrypted( | |
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(IsStreamValidAndEncrypted(stream)); |
ddorwin
2013/01/03 17:48:29
WDYT about moving this inside SetDecoderConfig() n
xhwang
2013/01/03 18:16:04
Done.
| |
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 |
143 SetDecoderConfig(); | |
144 | |
141 state_ = kDecryptorRequested; | 145 state_ = kDecryptorRequested; |
142 set_decryptor_ready_cb_.Run( | 146 set_decryptor_ready_cb_.Run( |
143 BIND_TO_LOOP(&DecryptingDemuxerStream::SetDecryptor)); | 147 BIND_TO_LOOP(&DecryptingDemuxerStream::SetDecryptor)); |
144 } | 148 } |
145 | 149 |
146 void DecryptingDemuxerStream::SetDecryptor(Decryptor* decryptor) { | 150 void DecryptingDemuxerStream::SetDecryptor(Decryptor* decryptor) { |
147 DVLOG(2) << "SetDecryptor()"; | 151 DVLOG(2) << "SetDecryptor()"; |
148 DCHECK(message_loop_->BelongsToCurrentThread()); | 152 DCHECK(message_loop_->BelongsToCurrentThread()); |
149 DCHECK_EQ(state_, kDecryptorRequested) << state_; | 153 DCHECK_EQ(state_, kDecryptorRequested) << state_; |
150 DCHECK(!init_cb_.is_null()); | 154 DCHECK(!init_cb_.is_null()); |
151 DCHECK(!set_decryptor_ready_cb_.is_null()); | 155 DCHECK(!set_decryptor_ready_cb_.is_null()); |
152 | 156 |
153 set_decryptor_ready_cb_.Reset(); | 157 set_decryptor_ready_cb_.Reset(); |
154 decryptor_ = decryptor; | 158 decryptor_ = decryptor; |
155 | 159 |
156 switch (stream_type_) { | |
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 | |
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( |
203 DemuxerStream::Status status, | 169 DemuxerStream::Status status, |
(...skipping 24 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 DCHECK(IsStreamValidAndEncrypted(demuxer_stream_)); | |
208 | |
209 // Update the decoder config with the new config. | |
ddorwin
2013/01/03 17:48:29
This comment doesn't really add anything that the
xhwang
2013/01/03 18:16:04
Done.
| |
210 SetDecoderConfig(); | |
ddorwin
2013/01/03 17:48:29
SetDecoderConfigFromDemuxerStream? Should Set be U
xhwang
2013/01/03 18:16:04
Done.
| |
238 state_ = kIdle; | 211 state_ = kIdle; |
239 // TODO(xhwang): Support kConfigChanged! | 212 base::ResetAndReturn(&read_cb_).Run(kConfigChanged, NULL); |
240 base::ResetAndReturn(&read_cb_).Run(kAborted, NULL); | |
241 return; | 213 return; |
242 } | 214 } |
243 | 215 |
244 if (buffer->IsEndOfStream()) { | 216 if (buffer->IsEndOfStream()) { |
245 DVLOG(2) << "DoDecryptBuffer() - EOS buffer."; | 217 DVLOG(2) << "DoDecryptBuffer() - EOS buffer."; |
246 state_ = kIdle; | 218 state_ = kIdle; |
247 base::ResetAndReturn(&read_cb_).Run(status, buffer); | 219 base::ResetAndReturn(&read_cb_).Run(status, buffer); |
248 return; | 220 return; |
249 } | 221 } |
250 | 222 |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
341 DCHECK(read_cb_.is_null()); | 313 DCHECK(read_cb_.is_null()); |
342 state_ = kIdle; | 314 state_ = kIdle; |
343 base::ResetAndReturn(&reset_cb_).Run(); | 315 base::ResetAndReturn(&reset_cb_).Run(); |
344 } | 316 } |
345 | 317 |
346 Decryptor::StreamType DecryptingDemuxerStream::GetDecryptorStreamType() const { | 318 Decryptor::StreamType DecryptingDemuxerStream::GetDecryptorStreamType() const { |
347 DCHECK(stream_type_ == AUDIO || stream_type_ == VIDEO); | 319 DCHECK(stream_type_ == AUDIO || stream_type_ == VIDEO); |
348 return stream_type_ == AUDIO ? Decryptor::kAudio : Decryptor::kVideo; | 320 return stream_type_ == AUDIO ? Decryptor::kAudio : Decryptor::kVideo; |
349 } | 321 } |
350 | 322 |
323 void DecryptingDemuxerStream::SetDecoderConfig() { | |
324 switch (stream_type_) { | |
325 case AUDIO: { | |
326 const AudioDecoderConfig& input_audio_config = | |
327 demuxer_stream_->audio_decoder_config(); | |
328 audio_config_.reset(new AudioDecoderConfig()); | |
329 audio_config_->Initialize(input_audio_config.codec(), | |
330 input_audio_config.bits_per_channel(), | |
331 input_audio_config.channel_layout(), | |
332 input_audio_config.samples_per_second(), | |
333 input_audio_config.extra_data(), | |
334 input_audio_config.extra_data_size(), | |
335 false, // Output audio is not encrypted. | |
336 false); | |
337 break; | |
338 } | |
339 | |
340 case VIDEO: { | |
341 const VideoDecoderConfig& input_video_config = | |
342 demuxer_stream_->video_decoder_config(); | |
343 video_config_.reset(new VideoDecoderConfig()); | |
344 video_config_->Initialize(input_video_config.codec(), | |
345 input_video_config.profile(), | |
346 input_video_config.format(), | |
347 input_video_config.coded_size(), | |
348 input_video_config.visible_rect(), | |
349 input_video_config.natural_size(), | |
350 input_video_config.extra_data(), | |
351 input_video_config.extra_data_size(), | |
352 false, // Output video is not encrypted. | |
353 false); | |
354 break; | |
355 } | |
356 | |
357 default: | |
358 NOTREACHED(); | |
359 return; | |
360 } | |
361 } | |
362 | |
351 } // namespace media | 363 } // namespace media |
OLD | NEW |