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" |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
72 | 72 |
73 void DecryptingAudioDecoder::Reset(const base::Closure& closure) { | 73 void DecryptingAudioDecoder::Reset(const base::Closure& closure) { |
74 if (!message_loop_->BelongsToCurrentThread()) { | 74 if (!message_loop_->BelongsToCurrentThread()) { |
75 message_loop_->PostTask(FROM_HERE, base::Bind( | 75 message_loop_->PostTask(FROM_HERE, base::Bind( |
76 &DecryptingAudioDecoder::Reset, this, closure)); | 76 &DecryptingAudioDecoder::Reset, this, closure)); |
77 return; | 77 return; |
78 } | 78 } |
79 | 79 |
80 DVLOG(2) << "Reset() - state: " << state_; | 80 DVLOG(2) << "Reset() - state: " << state_; |
81 DCHECK(state_ == kIdle || | 81 DCHECK(state_ == kIdle || |
| 82 state_ == kPendingConfigChange || |
82 state_ == kPendingDemuxerRead || | 83 state_ == kPendingDemuxerRead || |
83 state_ == kPendingDecode || | 84 state_ == kPendingDecode || |
84 state_ == kWaitingForKey || | 85 state_ == kWaitingForKey || |
85 state_ == kDecodeFinished) << state_; | 86 state_ == kDecodeFinished) << state_; |
86 DCHECK(init_cb_.is_null()); // No Reset() during pending initialization. | 87 DCHECK(init_cb_.is_null()); // No Reset() during pending initialization. |
87 DCHECK(reset_cb_.is_null()); | 88 DCHECK(reset_cb_.is_null()); |
88 | 89 |
89 reset_cb_ = closure; | 90 reset_cb_ = closure; |
90 | 91 |
91 decryptor_->ResetDecoder(Decryptor::kAudio); | 92 decryptor_->ResetDecoder(Decryptor::kAudio); |
92 | 93 |
93 // Reset() cannot complete if the read callback is still pending. | 94 // Reset() cannot complete if the read callback is still pending. |
94 // Defer the resetting process in this case. The |reset_cb_| will be fired | 95 // Defer the resetting process in this case. The |reset_cb_| will be fired |
95 // after the read callback is fired - see DoDecryptAndDecodeBuffer() and | 96 // after the read callback is fired - see DoDecryptAndDecodeBuffer() and |
96 // DoDeliverFrame(). | 97 // DoDeliverFrame(). |
97 if (state_ == kPendingDemuxerRead || state_ == kPendingDecode) { | 98 if (state_ == kPendingConfigChange || |
| 99 state_ == kPendingDemuxerRead || |
| 100 state_ == kPendingDecode) { |
98 DCHECK(!read_cb_.is_null()); | 101 DCHECK(!read_cb_.is_null()); |
99 return; | 102 return; |
100 } | 103 } |
101 | 104 |
102 if (state_ == kWaitingForKey) { | 105 if (state_ == kWaitingForKey) { |
103 DCHECK(!read_cb_.is_null()); | 106 DCHECK(!read_cb_.is_null()); |
104 pending_buffer_to_decode_ = NULL; | 107 pending_buffer_to_decode_ = NULL; |
105 base::ResetAndReturn(&read_cb_).Run(kAborted, NULL); | 108 base::ResetAndReturn(&read_cb_).Run(kAborted, NULL); |
106 } | 109 } |
107 | 110 |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
199 bytes_per_sample_ = ChannelLayoutToChannelCount(channel_layout_) * | 202 bytes_per_sample_ = ChannelLayoutToChannelCount(channel_layout_) * |
200 bits_per_channel_ / kBitsPerByte; | 203 bits_per_channel_ / kBitsPerByte; |
201 | 204 |
202 decryptor_->RegisterNewKeyCB( | 205 decryptor_->RegisterNewKeyCB( |
203 Decryptor::kAudio, BIND_TO_LOOP(&DecryptingAudioDecoder::OnKeyAdded)); | 206 Decryptor::kAudio, BIND_TO_LOOP(&DecryptingAudioDecoder::OnKeyAdded)); |
204 | 207 |
205 state_ = kIdle; | 208 state_ = kIdle; |
206 base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK); | 209 base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK); |
207 } | 210 } |
208 | 211 |
| 212 void DecryptingAudioDecoder::FinishConfigChange(bool success) { |
| 213 DVLOG(2) << "FinishConfigChange()"; |
| 214 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 215 DCHECK_EQ(state_, kPendingConfigChange) << state_; |
| 216 DCHECK(!read_cb_.is_null()); |
| 217 |
| 218 if (!success) { |
| 219 base::ResetAndReturn(&read_cb_).Run(kDecodeError, NULL); |
| 220 state_ = kDecodeFinished; |
| 221 if (!reset_cb_.is_null()) |
| 222 base::ResetAndReturn(&reset_cb_).Run(); |
| 223 return; |
| 224 } |
| 225 |
| 226 // Config change succeeded. |
| 227 if (!reset_cb_.is_null()) { |
| 228 base::ResetAndReturn(&read_cb_).Run(kAborted, NULL); |
| 229 DoReset(); |
| 230 return; |
| 231 } |
| 232 |
| 233 state_ = kPendingDemuxerRead; |
| 234 ReadFromDemuxerStream(); |
| 235 } |
| 236 |
209 void DecryptingAudioDecoder::DoRead(const ReadCB& read_cb) { | 237 void DecryptingAudioDecoder::DoRead(const ReadCB& read_cb) { |
210 DVLOG(3) << "DoRead()"; | 238 DVLOG(3) << "DoRead()"; |
211 DCHECK(message_loop_->BelongsToCurrentThread()); | 239 DCHECK(message_loop_->BelongsToCurrentThread()); |
212 DCHECK(state_ == kIdle || state_ == kDecodeFinished) << state_; | 240 DCHECK(state_ == kIdle || state_ == kDecodeFinished) << state_; |
213 DCHECK(!read_cb.is_null()); | 241 DCHECK(!read_cb.is_null()); |
214 CHECK(read_cb_.is_null()) << "Overlapping decodes are not supported."; | 242 CHECK(read_cb_.is_null()) << "Overlapping decodes are not supported."; |
215 | 243 |
216 // Return empty (end-of-stream) frames if decoding has finished. | 244 // Return empty (end-of-stream) frames if decoding has finished. |
217 if (state_ == kDecodeFinished) { | 245 if (state_ == kDecodeFinished) { |
218 read_cb.Run(kOk, scoped_refptr<Buffer>(new DataBuffer(0))); | 246 read_cb.Run(kOk, scoped_refptr<Buffer>(new DataBuffer(0))); |
(...skipping 28 matching lines...) Expand all Loading... |
247 &DecryptingAudioDecoder::DoDecryptAndDecodeBuffer, this, | 275 &DecryptingAudioDecoder::DoDecryptAndDecodeBuffer, this, |
248 status, buffer)); | 276 status, buffer)); |
249 return; | 277 return; |
250 } | 278 } |
251 | 279 |
252 DVLOG(3) << "DoDecryptAndDecodeBuffer()"; | 280 DVLOG(3) << "DoDecryptAndDecodeBuffer()"; |
253 DCHECK_EQ(state_, kPendingDemuxerRead) << state_; | 281 DCHECK_EQ(state_, kPendingDemuxerRead) << state_; |
254 DCHECK(!read_cb_.is_null()); | 282 DCHECK(!read_cb_.is_null()); |
255 DCHECK_EQ(buffer != NULL, status == DemuxerStream::kOk) << status; | 283 DCHECK_EQ(buffer != NULL, status == DemuxerStream::kOk) << status; |
256 | 284 |
| 285 if (status == DemuxerStream::kConfigChanged) { |
| 286 DVLOG(2) << "DoDecryptAndDecodeBuffer() - kConfigChanged"; |
| 287 |
| 288 scoped_ptr<AudioDecoderConfig> scoped_config(new AudioDecoderConfig()); |
| 289 scoped_config->CopyFrom(demuxer_stream_->audio_decoder_config()); |
| 290 |
| 291 state_ = kPendingConfigChange; |
| 292 decryptor_->DeinitializeDecoder(Decryptor::kAudio); |
| 293 decryptor_->InitializeAudioDecoder( |
| 294 scoped_config.Pass(), BindToCurrentLoop(base::Bind( |
| 295 &DecryptingAudioDecoder::FinishConfigChange, this))); |
| 296 return; |
| 297 } |
| 298 |
257 if (!reset_cb_.is_null()) { | 299 if (!reset_cb_.is_null()) { |
258 base::ResetAndReturn(&read_cb_).Run(kAborted, NULL); | 300 base::ResetAndReturn(&read_cb_).Run(kAborted, NULL); |
259 DoReset(); | 301 DoReset(); |
260 return; | 302 return; |
261 } | 303 } |
262 | 304 |
263 if (status == DemuxerStream::kAborted) { | 305 if (status == DemuxerStream::kAborted) { |
264 DVLOG(2) << "DoDecryptAndDecodeBuffer() - kAborted"; | 306 DVLOG(2) << "DoDecryptAndDecodeBuffer() - kAborted"; |
265 state_ = kIdle; | 307 state_ = kIdle; |
266 base::ResetAndReturn(&read_cb_).Run(kAborted, NULL); | 308 base::ResetAndReturn(&read_cb_).Run(kAborted, NULL); |
267 return; | 309 return; |
268 } | 310 } |
269 | 311 |
270 if (status == DemuxerStream::kConfigChanged) { | |
271 // TODO(xhwang): Add config change support. | |
272 // The |state_| is chosen to be kDecodeFinished here to be consistent with | |
273 // the implementation of FFmpegVideoDecoder. | |
274 DVLOG(2) << "DoDecryptAndDecodeBuffer() - kConfigChanged"; | |
275 state_ = kDecodeFinished; | |
276 base::ResetAndReturn(&read_cb_).Run(kDecodeError, NULL); | |
277 return; | |
278 } | |
279 | |
280 DCHECK_EQ(status, DemuxerStream::kOk); | 312 DCHECK_EQ(status, DemuxerStream::kOk); |
281 | 313 |
282 // Initialize the |next_output_timestamp_| to be the timestamp of the first | 314 // Initialize the |next_output_timestamp_| to be the timestamp of the first |
283 // non-EOS buffer. | 315 // non-EOS buffer. |
284 if (output_timestamp_base_ == kNoTimestamp() && !buffer->IsEndOfStream()) { | 316 if (output_timestamp_base_ == kNoTimestamp() && !buffer->IsEndOfStream()) { |
285 DCHECK_EQ(total_samples_decoded_, 0); | 317 DCHECK_EQ(total_samples_decoded_, 0); |
286 output_timestamp_base_ = buffer->GetTimestamp(); | 318 output_timestamp_base_ = buffer->GetTimestamp(); |
287 } | 319 } |
288 | 320 |
289 pending_buffer_to_decode_ = buffer; | 321 pending_buffer_to_decode_ = buffer; |
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
452 | 484 |
453 base::TimeDelta DecryptingAudioDecoder::NumberOfSamplesToDuration( | 485 base::TimeDelta DecryptingAudioDecoder::NumberOfSamplesToDuration( |
454 int number_of_samples) const { | 486 int number_of_samples) const { |
455 DCHECK(samples_per_second_); | 487 DCHECK(samples_per_second_); |
456 return base::TimeDelta::FromMicroseconds(base::Time::kMicrosecondsPerSecond * | 488 return base::TimeDelta::FromMicroseconds(base::Time::kMicrosecondsPerSecond * |
457 number_of_samples / | 489 number_of_samples / |
458 samples_per_second_); | 490 samples_per_second_); |
459 } | 491 } |
460 | 492 |
461 } // namespace media | 493 } // namespace media |
OLD | NEW |