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 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
113 DCHECK(task_runner_->BelongsToCurrentThread()); | 113 DCHECK(task_runner_->BelongsToCurrentThread()); |
114 DCHECK(state_ == kIdle || | 114 DCHECK(state_ == kIdle || |
115 state_ == kPendingConfigChange || | 115 state_ == kPendingConfigChange || |
116 state_ == kPendingDemuxerRead || | 116 state_ == kPendingDemuxerRead || |
117 state_ == kPendingDecode || | 117 state_ == kPendingDecode || |
118 state_ == kWaitingForKey || | 118 state_ == kWaitingForKey || |
119 state_ == kDecodeFinished) << state_; | 119 state_ == kDecodeFinished) << state_; |
120 DCHECK(init_cb_.is_null()); // No Reset() during pending initialization. | 120 DCHECK(init_cb_.is_null()); // No Reset() during pending initialization. |
121 DCHECK(reset_cb_.is_null()); | 121 DCHECK(reset_cb_.is_null()); |
122 | 122 |
123 reset_cb_ = closure; | 123 reset_cb_ = BindToCurrentLoop(closure); |
xhwang
2014/01/10 18:58:51
Nice catch!
| |
124 | 124 |
125 decryptor_->ResetDecoder(Decryptor::kAudio); | 125 decryptor_->ResetDecoder(Decryptor::kAudio); |
126 | 126 |
127 // Reset() cannot complete if the read callback is still pending. | 127 // Reset() cannot complete if the read callback is still pending. |
128 // Defer the resetting process in this case. The |reset_cb_| will be fired | 128 // Defer the resetting process in this case. The |reset_cb_| will be fired |
129 // after the read callback is fired - see DecryptAndDecodeBuffer() and | 129 // after the read callback is fired - see DecryptAndDecodeBuffer() and |
130 // DeliverFrame(). | 130 // DeliverFrame(). |
131 if (state_ == kPendingConfigChange || | 131 if (state_ == kPendingConfigChange || |
132 state_ == kPendingDemuxerRead || | 132 state_ == kPendingDemuxerRead || |
133 state_ == kPendingDecode) { | 133 state_ == kPendingDecode) { |
134 DCHECK(!read_cb_.is_null()); | 134 DCHECK(!read_cb_.is_null()); |
135 return; | 135 return; |
136 } | 136 } |
137 | 137 |
138 if (state_ == kWaitingForKey) { | 138 if (state_ == kWaitingForKey) { |
139 DCHECK(!read_cb_.is_null()); | 139 DCHECK(!read_cb_.is_null()); |
140 pending_buffer_to_decode_ = NULL; | 140 pending_buffer_to_decode_ = NULL; |
141 base::ResetAndReturn(&read_cb_).Run(kAborted, NULL); | 141 base::ResetAndReturn(&read_cb_).Run(kAborted, NULL); |
142 } | 142 } |
143 | 143 |
144 DCHECK(read_cb_.is_null()); | 144 DCHECK(read_cb_.is_null()); |
145 DoReset(); | 145 DoReset(); |
146 } | 146 } |
147 | 147 |
148 void DecryptingAudioDecoder::Stop(const base::Closure& closure) { | |
149 DVLOG(2) << "Stop() - state: " << state_; | |
150 DCHECK(task_runner_->BelongsToCurrentThread()); | |
151 | |
152 if (decryptor_) { | |
153 decryptor_->RegisterNewKeyCB(Decryptor::kAudio, Decryptor::NewKeyCB()); | |
154 decryptor_->DeinitializeDecoder(Decryptor::kAudio); | |
155 decryptor_ = NULL; | |
156 } | |
157 if (!set_decryptor_ready_cb_.is_null()) | |
158 base::ResetAndReturn(&set_decryptor_ready_cb_).Run(DecryptorReadyCB()); | |
159 pending_buffer_to_decode_ = NULL; | |
160 if (!init_cb_.is_null()) | |
161 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED); | |
162 if (!read_cb_.is_null()) | |
163 base::ResetAndReturn(&read_cb_).Run(kAborted, NULL); | |
164 if (!reset_cb_.is_null()) | |
165 base::ResetAndReturn(&reset_cb_).Run(); | |
166 state_ = kStopped; | |
167 BindToCurrentLoop(closure).Run(); | |
DaleCurtis
2014/01/10 02:03:00
Instead of BTCL.Run(), just PostTask() to avoid un
| |
168 } | |
169 | |
148 int DecryptingAudioDecoder::bits_per_channel() { | 170 int DecryptingAudioDecoder::bits_per_channel() { |
149 DCHECK(task_runner_->BelongsToCurrentThread()); | 171 DCHECK(task_runner_->BelongsToCurrentThread()); |
150 return bits_per_channel_; | 172 return bits_per_channel_; |
151 } | 173 } |
152 | 174 |
153 ChannelLayout DecryptingAudioDecoder::channel_layout() { | 175 ChannelLayout DecryptingAudioDecoder::channel_layout() { |
154 DCHECK(task_runner_->BelongsToCurrentThread()); | 176 DCHECK(task_runner_->BelongsToCurrentThread()); |
155 return channel_layout_; | 177 return channel_layout_; |
156 } | 178 } |
157 | 179 |
158 int DecryptingAudioDecoder::samples_per_second() { | 180 int DecryptingAudioDecoder::samples_per_second() { |
159 DCHECK(task_runner_->BelongsToCurrentThread()); | 181 DCHECK(task_runner_->BelongsToCurrentThread()); |
160 return samples_per_second_; | 182 return samples_per_second_; |
161 } | 183 } |
162 | 184 |
163 DecryptingAudioDecoder::~DecryptingAudioDecoder() { | 185 DecryptingAudioDecoder::~DecryptingAudioDecoder() { |
186 DCHECK(state_ == kUninitialized || state_ == kStopped) << state_; | |
164 } | 187 } |
165 | 188 |
166 void DecryptingAudioDecoder::SetDecryptor(Decryptor* decryptor) { | 189 void DecryptingAudioDecoder::SetDecryptor(Decryptor* decryptor) { |
167 DVLOG(2) << "SetDecryptor()"; | 190 DVLOG(2) << "SetDecryptor()"; |
168 DCHECK(task_runner_->BelongsToCurrentThread()); | 191 DCHECK(task_runner_->BelongsToCurrentThread()); |
192 | |
193 if (state_ == kStopped) | |
194 return; | |
195 | |
169 DCHECK_EQ(state_, kDecryptorRequested) << state_; | 196 DCHECK_EQ(state_, kDecryptorRequested) << state_; |
170 DCHECK(!init_cb_.is_null()); | 197 DCHECK(!init_cb_.is_null()); |
171 DCHECK(!set_decryptor_ready_cb_.is_null()); | 198 DCHECK(!set_decryptor_ready_cb_.is_null()); |
172 | 199 |
173 set_decryptor_ready_cb_.Reset(); | 200 set_decryptor_ready_cb_.Reset(); |
174 | 201 |
175 if (!decryptor) { | 202 if (!decryptor) { |
176 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED); | 203 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED); |
177 // TODO(xhwang): Add kError state. See http://crbug.com/251503 | 204 // TODO(xhwang): Add kError state. See http://crbug.com/251503 |
178 state_ = kDecodeFinished; | 205 state_ = kStopped; |
179 return; | 206 return; |
180 } | 207 } |
181 | 208 |
182 decryptor_ = decryptor; | 209 decryptor_ = decryptor; |
183 | 210 |
184 const AudioDecoderConfig& input_config = | 211 const AudioDecoderConfig& input_config = |
185 demuxer_stream_->audio_decoder_config(); | 212 demuxer_stream_->audio_decoder_config(); |
186 AudioDecoderConfig config; | 213 AudioDecoderConfig config; |
187 config.Initialize(input_config.codec(), | 214 config.Initialize(input_config.codec(), |
188 kSampleFormatS16, | 215 kSampleFormatS16, |
189 input_config.channel_layout(), | 216 input_config.channel_layout(), |
190 input_config.samples_per_second(), | 217 input_config.samples_per_second(), |
191 input_config.extra_data(), | 218 input_config.extra_data(), |
192 input_config.extra_data_size(), | 219 input_config.extra_data_size(), |
193 input_config.is_encrypted(), | 220 input_config.is_encrypted(), |
194 false, | 221 false, |
195 base::TimeDelta(), | 222 base::TimeDelta(), |
196 base::TimeDelta()); | 223 base::TimeDelta()); |
197 | 224 |
198 state_ = kPendingDecoderInit; | 225 state_ = kPendingDecoderInit; |
199 decryptor_->InitializeAudioDecoder( | 226 decryptor_->InitializeAudioDecoder( |
200 config, | 227 config, |
201 BindToCurrentLoop(base::Bind( | 228 BindToCurrentLoop(base::Bind( |
202 &DecryptingAudioDecoder::FinishInitialization, weak_this_))); | 229 &DecryptingAudioDecoder::FinishInitialization, weak_this_))); |
203 } | 230 } |
204 | 231 |
205 void DecryptingAudioDecoder::FinishInitialization(bool success) { | 232 void DecryptingAudioDecoder::FinishInitialization(bool success) { |
206 DVLOG(2) << "FinishInitialization()"; | 233 DVLOG(2) << "FinishInitialization()"; |
207 DCHECK(task_runner_->BelongsToCurrentThread()); | 234 DCHECK(task_runner_->BelongsToCurrentThread()); |
235 | |
236 if (state_ == kStopped) | |
237 return; | |
238 | |
208 DCHECK_EQ(state_, kPendingDecoderInit) << state_; | 239 DCHECK_EQ(state_, kPendingDecoderInit) << state_; |
209 DCHECK(!init_cb_.is_null()); | 240 DCHECK(!init_cb_.is_null()); |
210 DCHECK(reset_cb_.is_null()); // No Reset() before initialization finished. | 241 DCHECK(reset_cb_.is_null()); // No Reset() before initialization finished. |
211 DCHECK(read_cb_.is_null()); // No Read() before initialization finished. | 242 DCHECK(read_cb_.is_null()); // No Read() before initialization finished. |
212 | 243 |
213 if (!success) { | 244 if (!success) { |
214 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED); | 245 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED); |
215 state_ = kDecodeFinished; | 246 state_ = kStopped; |
216 return; | 247 return; |
217 } | 248 } |
218 | 249 |
219 // Success! | 250 // Success! |
220 UpdateDecoderConfig(); | 251 UpdateDecoderConfig(); |
221 | 252 |
222 decryptor_->RegisterNewKeyCB( | 253 decryptor_->RegisterNewKeyCB( |
223 Decryptor::kAudio, BindToCurrentLoop(base::Bind( | 254 Decryptor::kAudio, BindToCurrentLoop(base::Bind( |
224 &DecryptingAudioDecoder::OnKeyAdded, weak_this_))); | 255 &DecryptingAudioDecoder::OnKeyAdded, weak_this_))); |
225 | 256 |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
337 BindToCurrentLoop(base::Bind( | 368 BindToCurrentLoop(base::Bind( |
338 &DecryptingAudioDecoder::DeliverFrame, weak_this_, buffer_size))); | 369 &DecryptingAudioDecoder::DeliverFrame, weak_this_, buffer_size))); |
339 } | 370 } |
340 | 371 |
341 void DecryptingAudioDecoder::DeliverFrame( | 372 void DecryptingAudioDecoder::DeliverFrame( |
342 int buffer_size, | 373 int buffer_size, |
343 Decryptor::Status status, | 374 Decryptor::Status status, |
344 const Decryptor::AudioBuffers& frames) { | 375 const Decryptor::AudioBuffers& frames) { |
345 DVLOG(3) << "DeliverFrame() - status: " << status; | 376 DVLOG(3) << "DeliverFrame() - status: " << status; |
346 DCHECK(task_runner_->BelongsToCurrentThread()); | 377 DCHECK(task_runner_->BelongsToCurrentThread()); |
378 | |
379 if (state_ == kStopped) | |
380 return; | |
381 | |
347 DCHECK_EQ(state_, kPendingDecode) << state_; | 382 DCHECK_EQ(state_, kPendingDecode) << state_; |
348 DCHECK(!read_cb_.is_null()); | 383 DCHECK(!read_cb_.is_null()); |
349 DCHECK(pending_buffer_to_decode_.get()); | 384 DCHECK(pending_buffer_to_decode_.get()); |
350 DCHECK(queued_audio_frames_.empty()); | 385 DCHECK(queued_audio_frames_.empty()); |
351 | 386 |
352 bool need_to_try_again_if_nokey_is_returned = key_added_while_decode_pending_; | 387 bool need_to_try_again_if_nokey_is_returned = key_added_while_decode_pending_; |
353 key_added_while_decode_pending_ = false; | 388 key_added_while_decode_pending_ = false; |
354 | 389 |
355 scoped_refptr<DecoderBuffer> scoped_pending_buffer_to_decode = | 390 scoped_refptr<DecoderBuffer> scoped_pending_buffer_to_decode = |
356 pending_buffer_to_decode_; | 391 pending_buffer_to_decode_; |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
467 } | 502 } |
468 | 503 |
469 frame->set_timestamp(current_time); | 504 frame->set_timestamp(current_time); |
470 frame->set_duration( | 505 frame->set_duration( |
471 timestamp_helper_->GetFrameDuration(frame->frame_count())); | 506 timestamp_helper_->GetFrameDuration(frame->frame_count())); |
472 timestamp_helper_->AddFrames(frame->frame_count()); | 507 timestamp_helper_->AddFrames(frame->frame_count()); |
473 } | 508 } |
474 } | 509 } |
475 | 510 |
476 } // namespace media | 511 } // namespace media |
OLD | NEW |