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/bind_to_current_loop.h" |
10 #include "base/callback_helpers.h" | 11 #include "base/callback_helpers.h" |
11 #include "base/location.h" | 12 #include "base/location.h" |
12 #include "base/logging.h" | 13 #include "base/logging.h" |
13 #include "base/single_thread_task_runner.h" | 14 #include "base/single_thread_task_runner.h" |
14 #include "media/base/audio_buffer.h" | 15 #include "media/base/audio_buffer.h" |
15 #include "media/base/audio_decoder_config.h" | 16 #include "media/base/audio_decoder_config.h" |
16 #include "media/base/audio_timestamp_helper.h" | 17 #include "media/base/audio_timestamp_helper.h" |
17 #include "media/base/bind_to_current_loop.h" | |
18 #include "media/base/buffers.h" | 18 #include "media/base/buffers.h" |
19 #include "media/base/decoder_buffer.h" | 19 #include "media/base/decoder_buffer.h" |
20 #include "media/base/decryptor.h" | 20 #include "media/base/decryptor.h" |
21 #include "media/base/demuxer_stream.h" | 21 #include "media/base/demuxer_stream.h" |
22 #include "media/base/pipeline.h" | 22 #include "media/base/pipeline.h" |
23 | 23 |
24 namespace media { | 24 namespace media { |
25 | 25 |
26 static inline bool IsOutOfSync(const base::TimeDelta& timestamp_1, | 26 static inline bool IsOutOfSync(const base::TimeDelta& timestamp_1, |
27 const base::TimeDelta& timestamp_2) { | 27 const base::TimeDelta& timestamp_2) { |
(...skipping 23 matching lines...) Expand all Loading... |
51 | 51 |
52 void DecryptingAudioDecoder::Initialize(const AudioDecoderConfig& config, | 52 void DecryptingAudioDecoder::Initialize(const AudioDecoderConfig& config, |
53 const PipelineStatusCB& status_cb, | 53 const PipelineStatusCB& status_cb, |
54 const OutputCB& output_cb) { | 54 const OutputCB& output_cb) { |
55 DVLOG(2) << "Initialize()"; | 55 DVLOG(2) << "Initialize()"; |
56 DCHECK(task_runner_->BelongsToCurrentThread()); | 56 DCHECK(task_runner_->BelongsToCurrentThread()); |
57 DCHECK(decode_cb_.is_null()); | 57 DCHECK(decode_cb_.is_null()); |
58 DCHECK(reset_cb_.is_null()); | 58 DCHECK(reset_cb_.is_null()); |
59 | 59 |
60 weak_this_ = weak_factory_.GetWeakPtr(); | 60 weak_this_ = weak_factory_.GetWeakPtr(); |
61 init_cb_ = BindToCurrentLoop(status_cb); | 61 init_cb_ = base::BindToCurrentLoop(status_cb); |
62 output_cb_ = BindToCurrentLoop(output_cb); | 62 output_cb_ = base::BindToCurrentLoop(output_cb); |
63 | 63 |
64 if (!config.IsValidConfig()) { | 64 if (!config.IsValidConfig()) { |
65 DLOG(ERROR) << "Invalid audio stream config."; | 65 DLOG(ERROR) << "Invalid audio stream config."; |
66 base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_DECODE); | 66 base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_DECODE); |
67 return; | 67 return; |
68 } | 68 } |
69 | 69 |
70 // DecryptingAudioDecoder only accepts potentially encrypted stream. | 70 // DecryptingAudioDecoder only accepts potentially encrypted stream. |
71 if (!config.is_encrypted()) { | 71 if (!config.is_encrypted()) { |
72 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED); | 72 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED); |
73 return; | 73 return; |
74 } | 74 } |
75 | 75 |
76 config_ = config; | 76 config_ = config; |
77 | 77 |
78 if (state_ == kUninitialized) { | 78 if (state_ == kUninitialized) { |
79 state_ = kDecryptorRequested; | 79 state_ = kDecryptorRequested; |
80 set_decryptor_ready_cb_.Run(BindToCurrentLoop( | 80 set_decryptor_ready_cb_.Run(base::BindToCurrentLoop( |
81 base::Bind(&DecryptingAudioDecoder::SetDecryptor, weak_this_))); | 81 base::Bind(&DecryptingAudioDecoder::SetDecryptor, weak_this_))); |
82 return; | 82 return; |
83 } | 83 } |
84 | 84 |
85 // Reinitialization (i.e. upon a config change) | 85 // Reinitialization (i.e. upon a config change) |
86 decryptor_->DeinitializeDecoder(Decryptor::kAudio); | 86 decryptor_->DeinitializeDecoder(Decryptor::kAudio); |
87 InitializeDecoder(); | 87 InitializeDecoder(); |
88 } | 88 } |
89 | 89 |
90 void DecryptingAudioDecoder::Decode(const scoped_refptr<DecoderBuffer>& buffer, | 90 void DecryptingAudioDecoder::Decode(const scoped_refptr<DecoderBuffer>& buffer, |
91 const DecodeCB& decode_cb) { | 91 const DecodeCB& decode_cb) { |
92 DVLOG(3) << "Decode()"; | 92 DVLOG(3) << "Decode()"; |
93 DCHECK(task_runner_->BelongsToCurrentThread()); | 93 DCHECK(task_runner_->BelongsToCurrentThread()); |
94 DCHECK(state_ == kIdle || state_ == kDecodeFinished) << state_; | 94 DCHECK(state_ == kIdle || state_ == kDecodeFinished) << state_; |
95 DCHECK(!decode_cb.is_null()); | 95 DCHECK(!decode_cb.is_null()); |
96 CHECK(decode_cb_.is_null()) << "Overlapping decodes are not supported."; | 96 CHECK(decode_cb_.is_null()) << "Overlapping decodes are not supported."; |
97 | 97 |
98 decode_cb_ = BindToCurrentLoop(decode_cb); | 98 decode_cb_ = base::BindToCurrentLoop(decode_cb); |
99 | 99 |
100 // Return empty (end-of-stream) frames if decoding has finished. | 100 // Return empty (end-of-stream) frames if decoding has finished. |
101 if (state_ == kDecodeFinished) { | 101 if (state_ == kDecodeFinished) { |
102 output_cb_.Run(AudioBuffer::CreateEOSBuffer()); | 102 output_cb_.Run(AudioBuffer::CreateEOSBuffer()); |
103 base::ResetAndReturn(&decode_cb_).Run(kOk); | 103 base::ResetAndReturn(&decode_cb_).Run(kOk); |
104 return; | 104 return; |
105 } | 105 } |
106 | 106 |
107 // Initialize the |next_output_timestamp_| to be the timestamp of the first | 107 // Initialize the |next_output_timestamp_| to be the timestamp of the first |
108 // non-EOS buffer. | 108 // non-EOS buffer. |
(...skipping 10 matching lines...) Expand all Loading... |
119 void DecryptingAudioDecoder::Reset(const base::Closure& closure) { | 119 void DecryptingAudioDecoder::Reset(const base::Closure& closure) { |
120 DVLOG(2) << "Reset() - state: " << state_; | 120 DVLOG(2) << "Reset() - state: " << state_; |
121 DCHECK(task_runner_->BelongsToCurrentThread()); | 121 DCHECK(task_runner_->BelongsToCurrentThread()); |
122 DCHECK(state_ == kIdle || | 122 DCHECK(state_ == kIdle || |
123 state_ == kPendingDecode || | 123 state_ == kPendingDecode || |
124 state_ == kWaitingForKey || | 124 state_ == kWaitingForKey || |
125 state_ == kDecodeFinished) << state_; | 125 state_ == kDecodeFinished) << state_; |
126 DCHECK(init_cb_.is_null()); // No Reset() during pending initialization. | 126 DCHECK(init_cb_.is_null()); // No Reset() during pending initialization. |
127 DCHECK(reset_cb_.is_null()); | 127 DCHECK(reset_cb_.is_null()); |
128 | 128 |
129 reset_cb_ = BindToCurrentLoop(closure); | 129 reset_cb_ = base::BindToCurrentLoop(closure); |
130 | 130 |
131 decryptor_->ResetDecoder(Decryptor::kAudio); | 131 decryptor_->ResetDecoder(Decryptor::kAudio); |
132 | 132 |
133 // Reset() cannot complete if the read callback is still pending. | 133 // Reset() cannot complete if the read callback is still pending. |
134 // Defer the resetting process in this case. The |reset_cb_| will be fired | 134 // Defer the resetting process in this case. The |reset_cb_| will be fired |
135 // after the read callback is fired - see DecryptAndDecodeBuffer() and | 135 // after the read callback is fired - see DecryptAndDecodeBuffer() and |
136 // DeliverFrame(). | 136 // DeliverFrame(). |
137 if (state_ == kPendingDecode) { | 137 if (state_ == kPendingDecode) { |
138 DCHECK(!decode_cb_.is_null()); | 138 DCHECK(!decode_cb_.is_null()); |
139 return; | 139 return; |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
192 decryptor_ = decryptor; | 192 decryptor_ = decryptor; |
193 | 193 |
194 InitializeDecoder(); | 194 InitializeDecoder(); |
195 decryptor_attached_cb.Run(true); | 195 decryptor_attached_cb.Run(true); |
196 } | 196 } |
197 | 197 |
198 void DecryptingAudioDecoder::InitializeDecoder() { | 198 void DecryptingAudioDecoder::InitializeDecoder() { |
199 state_ = kPendingDecoderInit; | 199 state_ = kPendingDecoderInit; |
200 decryptor_->InitializeAudioDecoder( | 200 decryptor_->InitializeAudioDecoder( |
201 config_, | 201 config_, |
202 BindToCurrentLoop(base::Bind( | 202 base::BindToCurrentLoop(base::Bind( |
203 &DecryptingAudioDecoder::FinishInitialization, weak_this_))); | 203 &DecryptingAudioDecoder::FinishInitialization, weak_this_))); |
204 } | 204 } |
205 | 205 |
206 void DecryptingAudioDecoder::FinishInitialization(bool success) { | 206 void DecryptingAudioDecoder::FinishInitialization(bool success) { |
207 DVLOG(2) << "FinishInitialization()"; | 207 DVLOG(2) << "FinishInitialization()"; |
208 DCHECK(task_runner_->BelongsToCurrentThread()); | 208 DCHECK(task_runner_->BelongsToCurrentThread()); |
209 DCHECK(state_ == kPendingDecoderInit) << state_; | 209 DCHECK(state_ == kPendingDecoderInit) << state_; |
210 DCHECK(!init_cb_.is_null()); | 210 DCHECK(!init_cb_.is_null()); |
211 DCHECK(reset_cb_.is_null()); // No Reset() before initialization finished. | 211 DCHECK(reset_cb_.is_null()); // No Reset() before initialization finished. |
212 DCHECK(decode_cb_.is_null()); // No Decode() before initialization finished. | 212 DCHECK(decode_cb_.is_null()); // No Decode() before initialization finished. |
213 | 213 |
214 if (!success) { | 214 if (!success) { |
215 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED); | 215 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED); |
216 decryptor_ = NULL; | 216 decryptor_ = NULL; |
217 state_ = kError; | 217 state_ = kError; |
218 return; | 218 return; |
219 } | 219 } |
220 | 220 |
221 // Success! | 221 // Success! |
222 timestamp_helper_.reset( | 222 timestamp_helper_.reset( |
223 new AudioTimestampHelper(config_.samples_per_second())); | 223 new AudioTimestampHelper(config_.samples_per_second())); |
224 | 224 |
225 decryptor_->RegisterNewKeyCB( | 225 decryptor_->RegisterNewKeyCB( |
226 Decryptor::kAudio, | 226 Decryptor::kAudio, |
227 BindToCurrentLoop( | 227 base::BindToCurrentLoop( |
228 base::Bind(&DecryptingAudioDecoder::OnKeyAdded, weak_this_))); | 228 base::Bind(&DecryptingAudioDecoder::OnKeyAdded, weak_this_))); |
229 | 229 |
230 state_ = kIdle; | 230 state_ = kIdle; |
231 base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK); | 231 base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK); |
232 } | 232 } |
233 | 233 |
234 void DecryptingAudioDecoder::DecodePendingBuffer() { | 234 void DecryptingAudioDecoder::DecodePendingBuffer() { |
235 DCHECK(task_runner_->BelongsToCurrentThread()); | 235 DCHECK(task_runner_->BelongsToCurrentThread()); |
236 DCHECK_EQ(state_, kPendingDecode) << state_; | 236 DCHECK_EQ(state_, kPendingDecode) << state_; |
237 | 237 |
238 int buffer_size = 0; | 238 int buffer_size = 0; |
239 if (!pending_buffer_to_decode_->end_of_stream()) { | 239 if (!pending_buffer_to_decode_->end_of_stream()) { |
240 buffer_size = pending_buffer_to_decode_->data_size(); | 240 buffer_size = pending_buffer_to_decode_->data_size(); |
241 } | 241 } |
242 | 242 |
243 decryptor_->DecryptAndDecodeAudio( | 243 decryptor_->DecryptAndDecodeAudio( |
244 pending_buffer_to_decode_, | 244 pending_buffer_to_decode_, |
245 BindToCurrentLoop(base::Bind( | 245 base::BindToCurrentLoop(base::Bind( |
246 &DecryptingAudioDecoder::DeliverFrame, weak_this_, buffer_size))); | 246 &DecryptingAudioDecoder::DeliverFrame, weak_this_, buffer_size))); |
247 } | 247 } |
248 | 248 |
249 void DecryptingAudioDecoder::DeliverFrame( | 249 void DecryptingAudioDecoder::DeliverFrame( |
250 int buffer_size, | 250 int buffer_size, |
251 Decryptor::Status status, | 251 Decryptor::Status status, |
252 const Decryptor::AudioFrames& frames) { | 252 const Decryptor::AudioFrames& frames) { |
253 DVLOG(3) << "DeliverFrame() - status: " << status; | 253 DVLOG(3) << "DeliverFrame() - status: " << status; |
254 DCHECK(task_runner_->BelongsToCurrentThread()); | 254 DCHECK(task_runner_->BelongsToCurrentThread()); |
255 DCHECK_EQ(state_, kPendingDecode) << state_; | 255 DCHECK_EQ(state_, kPendingDecode) << state_; |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
360 } | 360 } |
361 | 361 |
362 frame->set_timestamp(current_time); | 362 frame->set_timestamp(current_time); |
363 timestamp_helper_->AddFrames(frame->frame_count()); | 363 timestamp_helper_->AddFrames(frame->frame_count()); |
364 | 364 |
365 output_cb_.Run(frame); | 365 output_cb_.Run(frame); |
366 } | 366 } |
367 } | 367 } |
368 | 368 |
369 } // namespace media | 369 } // namespace media |
OLD | NEW |