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/callback_helpers.h" | 10 #include "base/callback_helpers.h" |
11 #include "base/location.h" | 11 #include "base/location.h" |
12 #include "base/logging.h" | 12 #include "base/logging.h" |
13 #include "base/message_loop_proxy.h" | 13 #include "base/message_loop_proxy.h" |
14 #include "media/base/audio_decoder_config.h" | 14 #include "media/base/audio_decoder_config.h" |
15 #include "media/base/bind_to_loop.h" | 15 #include "media/base/bind_to_loop.h" |
16 #include "media/base/buffers.h" | 16 #include "media/base/buffers.h" |
17 #include "media/base/data_buffer.h" | 17 #include "media/base/data_buffer.h" |
18 #include "media/base/decoder_buffer.h" | 18 #include "media/base/decoder_buffer.h" |
19 #include "media/base/decryptor.h" | 19 #include "media/base/decryptor.h" |
20 #include "media/base/demuxer_stream.h" | 20 #include "media/base/demuxer_stream.h" |
21 #include "media/base/pipeline.h" | 21 #include "media/base/pipeline.h" |
22 | 22 |
23 namespace media { | 23 namespace media { |
24 | 24 |
25 #define BIND_TO_LOOP(function) \ | 25 #define BIND_TO_LOOP(function) \ |
26 media::BindToLoop(message_loop_, base::Bind(function, this)) | 26 media::BindToLoop(message_loop_, base::Bind(function, this)) |
27 | 27 |
28 const int DecryptingAudioDecoder::kSupportedBitsPerChannel = 16; | |
29 | |
28 static inline bool IsOutOfSync(const base::TimeDelta& timestamp_1, | 30 static inline bool IsOutOfSync(const base::TimeDelta& timestamp_1, |
29 const base::TimeDelta& timestamp_2) { | 31 const base::TimeDelta& timestamp_2) { |
30 // Out of sync of 100ms would be pretty noticeable and we should keep any | 32 // Out of sync of 100ms would be pretty noticeable and we should keep any |
31 // drift below that. | 33 // drift below that. |
32 const int64 kOutOfSyncThresholdInMicroseconds = 100000; | 34 const int64 kOutOfSyncThresholdInMicroseconds = 100000; |
33 return std::abs(timestamp_1.InMicroseconds() - timestamp_2.InMicroseconds()) > | 35 return std::abs(timestamp_1.InMicroseconds() - timestamp_2.InMicroseconds()) > |
34 kOutOfSyncThresholdInMicroseconds; | 36 kOutOfSyncThresholdInMicroseconds; |
35 } | 37 } |
36 | 38 |
37 DecryptingAudioDecoder::DecryptingAudioDecoder( | 39 DecryptingAudioDecoder::DecryptingAudioDecoder( |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
163 void DecryptingAudioDecoder::SetDecryptor(Decryptor* decryptor) { | 165 void DecryptingAudioDecoder::SetDecryptor(Decryptor* decryptor) { |
164 DVLOG(2) << "SetDecryptor()"; | 166 DVLOG(2) << "SetDecryptor()"; |
165 DCHECK(message_loop_->BelongsToCurrentThread()); | 167 DCHECK(message_loop_->BelongsToCurrentThread()); |
166 DCHECK_EQ(state_, kDecryptorRequested) << state_; | 168 DCHECK_EQ(state_, kDecryptorRequested) << state_; |
167 DCHECK(!init_cb_.is_null()); | 169 DCHECK(!init_cb_.is_null()); |
168 DCHECK(!set_decryptor_ready_cb_.is_null()); | 170 DCHECK(!set_decryptor_ready_cb_.is_null()); |
169 | 171 |
170 set_decryptor_ready_cb_.Reset(); | 172 set_decryptor_ready_cb_.Reset(); |
171 decryptor_ = decryptor; | 173 decryptor_ = decryptor; |
172 | 174 |
175 const AudioDecoderConfig& input_config = | |
176 demuxer_stream_->audio_decoder_config(); | |
173 scoped_ptr<AudioDecoderConfig> scoped_config(new AudioDecoderConfig()); | 177 scoped_ptr<AudioDecoderConfig> scoped_config(new AudioDecoderConfig()); |
174 scoped_config->CopyFrom(demuxer_stream_->audio_decoder_config()); | 178 scoped_config->Initialize(input_config.codec(), |
179 kSampleFormatS16, | |
180 input_config.channel_layout(), | |
181 input_config.samples_per_second(), | |
182 input_config.extra_data(), | |
183 input_config.extra_data_size(), | |
184 input_config.is_encrypted(), | |
185 false); | |
175 | 186 |
176 state_ = kPendingDecoderInit; | 187 state_ = kPendingDecoderInit; |
177 decryptor_->InitializeAudioDecoder( | 188 decryptor_->InitializeAudioDecoder( |
178 scoped_config.Pass(), | 189 scoped_config.Pass(), |
179 BIND_TO_LOOP(&DecryptingAudioDecoder::FinishInitialization)); | 190 BIND_TO_LOOP(&DecryptingAudioDecoder::FinishInitialization)); |
180 } | 191 } |
181 | 192 |
182 void DecryptingAudioDecoder::FinishInitialization(bool success) { | 193 void DecryptingAudioDecoder::FinishInitialization(bool success) { |
183 DVLOG(2) << "FinishInitialization()"; | 194 DVLOG(2) << "FinishInitialization()"; |
184 DCHECK(message_loop_->BelongsToCurrentThread()); | 195 DCHECK(message_loop_->BelongsToCurrentThread()); |
185 DCHECK_EQ(state_, kPendingDecoderInit) << state_; | 196 DCHECK_EQ(state_, kPendingDecoderInit) << state_; |
186 DCHECK(!init_cb_.is_null()); | 197 DCHECK(!init_cb_.is_null()); |
187 DCHECK(reset_cb_.is_null()); // No Reset() before initialization finished. | 198 DCHECK(reset_cb_.is_null()); // No Reset() before initialization finished. |
188 DCHECK(read_cb_.is_null()); // No Read() before initialization finished. | 199 DCHECK(read_cb_.is_null()); // No Read() before initialization finished. |
189 | 200 |
190 if (!success) { | 201 if (!success) { |
191 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED); | 202 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED); |
192 state_ = kDecodeFinished; | 203 state_ = kDecodeFinished; |
193 return; | 204 return; |
194 } | 205 } |
195 | 206 |
196 // Success! | 207 // Success! |
197 const AudioDecoderConfig& config = demuxer_stream_->audio_decoder_config(); | 208 SetDecoderConfig(); |
198 bits_per_channel_ = config.bits_per_channel(); | |
199 channel_layout_ = config.channel_layout(); | |
200 samples_per_second_ = config.samples_per_second(); | |
201 const int kBitsPerByte = 8; | |
202 bytes_per_sample_ = ChannelLayoutToChannelCount(channel_layout_) * | |
203 bits_per_channel_ / kBitsPerByte; | |
204 | 209 |
205 decryptor_->RegisterNewKeyCB( | 210 decryptor_->RegisterNewKeyCB( |
206 Decryptor::kAudio, BIND_TO_LOOP(&DecryptingAudioDecoder::OnKeyAdded)); | 211 Decryptor::kAudio, BIND_TO_LOOP(&DecryptingAudioDecoder::OnKeyAdded)); |
207 | 212 |
208 state_ = kIdle; | 213 state_ = kIdle; |
209 base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK); | 214 base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK); |
210 } | 215 } |
211 | 216 |
212 void DecryptingAudioDecoder::FinishConfigChange(bool success) { | 217 void DecryptingAudioDecoder::FinishConfigChange(bool success) { |
213 DVLOG(2) << "FinishConfigChange()"; | 218 DVLOG(2) << "FinishConfigChange()"; |
214 DCHECK(message_loop_->BelongsToCurrentThread()); | 219 DCHECK(message_loop_->BelongsToCurrentThread()); |
215 DCHECK_EQ(state_, kPendingConfigChange) << state_; | 220 DCHECK_EQ(state_, kPendingConfigChange) << state_; |
216 DCHECK(!read_cb_.is_null()); | 221 DCHECK(!read_cb_.is_null()); |
217 | 222 |
218 if (!success) { | 223 if (!success) { |
219 base::ResetAndReturn(&read_cb_).Run(kDecodeError, NULL); | 224 base::ResetAndReturn(&read_cb_).Run(kDecodeError, NULL); |
220 state_ = kDecodeFinished; | 225 state_ = kDecodeFinished; |
221 if (!reset_cb_.is_null()) | 226 if (!reset_cb_.is_null()) |
222 base::ResetAndReturn(&reset_cb_).Run(); | 227 base::ResetAndReturn(&reset_cb_).Run(); |
223 return; | 228 return; |
224 } | 229 } |
225 | 230 |
226 // Config change succeeded. | 231 // Config change succeeded. |
232 SetDecoderConfig(); | |
DaleCurtis
2013/01/10 01:24:35
Is this a bug fix?
xhwang
2013/01/10 18:17:23
Hmm, yes, filed bug and split this change to https
| |
233 | |
227 if (!reset_cb_.is_null()) { | 234 if (!reset_cb_.is_null()) { |
228 base::ResetAndReturn(&read_cb_).Run(kAborted, NULL); | 235 base::ResetAndReturn(&read_cb_).Run(kAborted, NULL); |
229 DoReset(); | 236 DoReset(); |
230 return; | 237 return; |
231 } | 238 } |
232 | 239 |
233 state_ = kPendingDemuxerRead; | 240 state_ = kPendingDemuxerRead; |
234 ReadFromDemuxerStream(); | 241 ReadFromDemuxerStream(); |
235 } | 242 } |
236 | 243 |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
278 } | 285 } |
279 | 286 |
280 DVLOG(3) << "DoDecryptAndDecodeBuffer()"; | 287 DVLOG(3) << "DoDecryptAndDecodeBuffer()"; |
281 DCHECK_EQ(state_, kPendingDemuxerRead) << state_; | 288 DCHECK_EQ(state_, kPendingDemuxerRead) << state_; |
282 DCHECK(!read_cb_.is_null()); | 289 DCHECK(!read_cb_.is_null()); |
283 DCHECK_EQ(buffer != NULL, status == DemuxerStream::kOk) << status; | 290 DCHECK_EQ(buffer != NULL, status == DemuxerStream::kOk) << status; |
284 | 291 |
285 if (status == DemuxerStream::kConfigChanged) { | 292 if (status == DemuxerStream::kConfigChanged) { |
286 DVLOG(2) << "DoDecryptAndDecodeBuffer() - kConfigChanged"; | 293 DVLOG(2) << "DoDecryptAndDecodeBuffer() - kConfigChanged"; |
287 | 294 |
288 scoped_ptr<AudioDecoderConfig> scoped_config(new AudioDecoderConfig()); | 295 const AudioDecoderConfig& input_config = |
289 scoped_config->CopyFrom(demuxer_stream_->audio_decoder_config()); | 296 demuxer_stream_->audio_decoder_config(); |
297 scoped_ptr<AudioDecoderConfig> scoped_config(new AudioDecoderConfig()); | |
298 scoped_config->Initialize(input_config.codec(), | |
299 kSampleFormatS16, | |
300 input_config.channel_layout(), | |
301 input_config.samples_per_second(), | |
302 input_config.extra_data(), | |
303 input_config.extra_data_size(), | |
304 input_config.is_encrypted(), | |
305 false); | |
290 | 306 |
291 state_ = kPendingConfigChange; | 307 state_ = kPendingConfigChange; |
292 decryptor_->DeinitializeDecoder(Decryptor::kAudio); | 308 decryptor_->DeinitializeDecoder(Decryptor::kAudio); |
293 decryptor_->InitializeAudioDecoder( | 309 decryptor_->InitializeAudioDecoder( |
294 scoped_config.Pass(), BindToCurrentLoop(base::Bind( | 310 scoped_config.Pass(), BindToCurrentLoop(base::Bind( |
295 &DecryptingAudioDecoder::FinishConfigChange, this))); | 311 &DecryptingAudioDecoder::FinishConfigChange, this))); |
296 return; | 312 return; |
297 } | 313 } |
298 | 314 |
299 if (!reset_cb_.is_null()) { | 315 if (!reset_cb_.is_null()) { |
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
440 | 456 |
441 void DecryptingAudioDecoder::DoReset() { | 457 void DecryptingAudioDecoder::DoReset() { |
442 DCHECK(init_cb_.is_null()); | 458 DCHECK(init_cb_.is_null()); |
443 DCHECK(read_cb_.is_null()); | 459 DCHECK(read_cb_.is_null()); |
444 output_timestamp_base_ = kNoTimestamp(); | 460 output_timestamp_base_ = kNoTimestamp(); |
445 total_samples_decoded_ = 0; | 461 total_samples_decoded_ = 0; |
446 state_ = kIdle; | 462 state_ = kIdle; |
447 base::ResetAndReturn(&reset_cb_).Run(); | 463 base::ResetAndReturn(&reset_cb_).Run(); |
448 } | 464 } |
449 | 465 |
466 void DecryptingAudioDecoder::SetDecoderConfig() { | |
467 const AudioDecoderConfig& config = demuxer_stream_->audio_decoder_config(); | |
468 bits_per_channel_ = kSupportedBitsPerChannel; | |
469 channel_layout_ = config.channel_layout(); | |
470 samples_per_second_ = config.samples_per_second(); | |
471 const int kBitsPerByte = 8; | |
472 bytes_per_sample_ = ChannelLayoutToChannelCount(channel_layout_) * | |
473 bits_per_channel_ / kBitsPerByte; | |
474 output_timestamp_base_ = kNoTimestamp(); | |
475 total_samples_decoded_ = 0; | |
476 } | |
477 | |
450 void DecryptingAudioDecoder::EnqueueFrames( | 478 void DecryptingAudioDecoder::EnqueueFrames( |
451 const Decryptor::AudioBuffers& frames) { | 479 const Decryptor::AudioBuffers& frames) { |
452 queued_audio_frames_ = frames; | 480 queued_audio_frames_ = frames; |
453 | 481 |
454 for (Decryptor::AudioBuffers::iterator iter = queued_audio_frames_.begin(); | 482 for (Decryptor::AudioBuffers::iterator iter = queued_audio_frames_.begin(); |
455 iter != queued_audio_frames_.end(); | 483 iter != queued_audio_frames_.end(); |
456 ++iter) { | 484 ++iter) { |
457 scoped_refptr<Buffer>& frame = *iter; | 485 scoped_refptr<Buffer>& frame = *iter; |
458 | 486 |
459 DCHECK(!frame->IsEndOfStream()) << "EOS frame returned."; | 487 DCHECK(!frame->IsEndOfStream()) << "EOS frame returned."; |
(...skipping 24 matching lines...) Expand all Loading... | |
484 | 512 |
485 base::TimeDelta DecryptingAudioDecoder::NumberOfSamplesToDuration( | 513 base::TimeDelta DecryptingAudioDecoder::NumberOfSamplesToDuration( |
486 int number_of_samples) const { | 514 int number_of_samples) const { |
487 DCHECK(samples_per_second_); | 515 DCHECK(samples_per_second_); |
488 return base::TimeDelta::FromMicroseconds(base::Time::kMicrosecondsPerSecond * | 516 return base::TimeDelta::FromMicroseconds(base::Time::kMicrosecondsPerSecond * |
489 number_of_samples / | 517 number_of_samples / |
490 samples_per_second_); | 518 samples_per_second_); |
491 } | 519 } |
492 | 520 |
493 } // namespace media | 521 } // namespace media |
OLD | NEW |