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_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 |