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/opus_audio_decoder.h" | 5 #include "media/filters/opus_audio_decoder.h" |
6 | 6 |
7 #include <cmath> | 7 #include <cmath> |
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 280 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
291 } | 291 } |
292 | 292 |
293 statistics_cb_ = statistics_cb; | 293 statistics_cb_ = statistics_cb; |
294 initialize_cb.Run(PIPELINE_OK); | 294 initialize_cb.Run(PIPELINE_OK); |
295 } | 295 } |
296 | 296 |
297 void OpusAudioDecoder::Read(const ReadCB& read_cb) { | 297 void OpusAudioDecoder::Read(const ReadCB& read_cb) { |
298 DCHECK(task_runner_->BelongsToCurrentThread()); | 298 DCHECK(task_runner_->BelongsToCurrentThread()); |
299 DCHECK(!read_cb.is_null()); | 299 DCHECK(!read_cb.is_null()); |
300 CHECK(read_cb_.is_null()) << "Overlapping decodes are not supported."; | 300 CHECK(read_cb_.is_null()) << "Overlapping decodes are not supported."; |
| 301 DCHECK(reset_cb_.is_null()); |
| 302 DCHECK(stop_cb_.is_null()); |
301 read_cb_ = BindToCurrentLoop(read_cb); | 303 read_cb_ = BindToCurrentLoop(read_cb); |
302 | 304 |
303 ReadFromDemuxerStream(); | 305 ReadFromDemuxerStream(); |
304 } | 306 } |
305 | 307 |
306 int OpusAudioDecoder::bits_per_channel() { | 308 int OpusAudioDecoder::bits_per_channel() { |
307 DCHECK(task_runner_->BelongsToCurrentThread()); | 309 DCHECK(task_runner_->BelongsToCurrentThread()); |
308 return bits_per_channel_; | 310 return bits_per_channel_; |
309 } | 311 } |
310 | 312 |
311 ChannelLayout OpusAudioDecoder::channel_layout() { | 313 ChannelLayout OpusAudioDecoder::channel_layout() { |
312 DCHECK(task_runner_->BelongsToCurrentThread()); | 314 DCHECK(task_runner_->BelongsToCurrentThread()); |
313 return channel_layout_; | 315 return channel_layout_; |
314 } | 316 } |
315 | 317 |
316 int OpusAudioDecoder::samples_per_second() { | 318 int OpusAudioDecoder::samples_per_second() { |
317 DCHECK(task_runner_->BelongsToCurrentThread()); | 319 DCHECK(task_runner_->BelongsToCurrentThread()); |
318 return samples_per_second_; | 320 return samples_per_second_; |
319 } | 321 } |
320 | 322 |
321 void OpusAudioDecoder::Reset(const base::Closure& closure) { | 323 void OpusAudioDecoder::Reset(const base::Closure& closure) { |
322 DCHECK(task_runner_->BelongsToCurrentThread()); | 324 DCHECK(task_runner_->BelongsToCurrentThread()); |
323 base::Closure reset_cb = BindToCurrentLoop(closure); | 325 DCHECK(reset_cb_.is_null()); |
| 326 reset_cb_ = BindToCurrentLoop(closure); |
| 327 |
| 328 if (read_cb_.is_null()) |
| 329 DoReset(); |
| 330 // Otherwise we have to wait for the pending demuxer read. |
| 331 } |
| 332 |
| 333 void OpusAudioDecoder::Stop(const base::Closure& closure) { |
| 334 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 335 DCHECK(stop_cb_.is_null()); |
| 336 stop_cb_ = BindToCurrentLoop(closure); |
| 337 |
| 338 // A demuxer read is pending, we'll wait until it finishes. |
| 339 if (!read_cb_.is_null()) |
| 340 return; |
| 341 |
| 342 if (!reset_cb_.is_null()) |
| 343 DoReset(); |
| 344 else |
| 345 DoStop(); |
| 346 } |
| 347 |
| 348 OpusAudioDecoder::~OpusAudioDecoder() {} |
| 349 |
| 350 void OpusAudioDecoder::DoReset() { |
| 351 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 352 DCHECK(!reset_cb_.is_null()); |
| 353 DCHECK(read_cb_.is_null()); |
324 | 354 |
325 opus_multistream_decoder_ctl(opus_decoder_, OPUS_RESET_STATE); | 355 opus_multistream_decoder_ctl(opus_decoder_, OPUS_RESET_STATE); |
326 ResetTimestampState(); | 356 ResetTimestampState(); |
327 reset_cb.Run(); | 357 base::ResetAndReturn(&reset_cb_).Run(); |
| 358 |
| 359 if (!stop_cb_.is_null()) |
| 360 DoStop(); |
328 } | 361 } |
329 | 362 |
330 OpusAudioDecoder::~OpusAudioDecoder() { | 363 void OpusAudioDecoder::DoStop() { |
331 // TODO(scherkus): should we require Stop() to be called? this might end up | 364 DCHECK(task_runner_->BelongsToCurrentThread()); |
332 // getting called on a random thread due to refcounting. | 365 DCHECK(!stop_cb_.is_null()); |
| 366 DCHECK(read_cb_.is_null()); |
| 367 DCHECK(reset_cb_.is_null()); |
| 368 |
| 369 opus_multistream_decoder_ctl(opus_decoder_, OPUS_RESET_STATE); |
| 370 ResetTimestampState(); |
333 CloseDecoder(); | 371 CloseDecoder(); |
| 372 base::ResetAndReturn(&stop_cb_).Run(); |
334 } | 373 } |
335 | 374 |
336 void OpusAudioDecoder::ReadFromDemuxerStream() { | 375 void OpusAudioDecoder::ReadFromDemuxerStream() { |
337 DCHECK(!read_cb_.is_null()); | 376 DCHECK(!read_cb_.is_null()); |
338 demuxer_stream_->Read(base::Bind(&OpusAudioDecoder::BufferReady, weak_this_)); | 377 demuxer_stream_->Read(base::Bind(&OpusAudioDecoder::BufferReady, weak_this_)); |
339 } | 378 } |
340 | 379 |
341 void OpusAudioDecoder::BufferReady( | 380 void OpusAudioDecoder::BufferReady( |
342 DemuxerStream::Status status, | 381 DemuxerStream::Status status, |
343 const scoped_refptr<DecoderBuffer>& input) { | 382 const scoped_refptr<DecoderBuffer>& input) { |
344 DCHECK(task_runner_->BelongsToCurrentThread()); | 383 DCHECK(task_runner_->BelongsToCurrentThread()); |
345 DCHECK(!read_cb_.is_null()); | 384 DCHECK(!read_cb_.is_null()); |
346 DCHECK_EQ(status != DemuxerStream::kOk, !input.get()) << status; | 385 DCHECK_EQ(status != DemuxerStream::kOk, !input.get()) << status; |
347 | 386 |
| 387 // Drop the buffer, fire |read_cb_| and complete the pending Reset(). |
| 388 // If there happens to also be a pending Stop(), that will be handled at |
| 389 // the end of DoReset(). |
| 390 if (!reset_cb_.is_null()) { |
| 391 base::ResetAndReturn(&read_cb_).Run(kAborted, NULL); |
| 392 DoReset(); |
| 393 return; |
| 394 } |
| 395 |
| 396 // Drop the buffer, fire |read_cb_| and complete the pending Stop(). |
| 397 if (!stop_cb_.is_null()) { |
| 398 base::ResetAndReturn(&read_cb_).Run(kAborted, NULL); |
| 399 DoStop(); |
| 400 return; |
| 401 } |
| 402 |
348 if (status == DemuxerStream::kAborted) { | 403 if (status == DemuxerStream::kAborted) { |
349 DCHECK(!input.get()); | 404 DCHECK(!input.get()); |
350 base::ResetAndReturn(&read_cb_).Run(kAborted, NULL); | 405 base::ResetAndReturn(&read_cb_).Run(kAborted, NULL); |
351 return; | 406 return; |
352 } | 407 } |
353 | 408 |
354 if (status == DemuxerStream::kConfigChanged) { | 409 if (status == DemuxerStream::kConfigChanged) { |
355 DCHECK(!input.get()); | 410 DCHECK(!input.get()); |
356 DVLOG(1) << "Config changed."; | 411 DVLOG(1) << "Config changed."; |
357 | 412 |
(...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
619 output_timestamp_helper_->AddFrames(frames_decoded); | 674 output_timestamp_helper_->AddFrames(frames_decoded); |
620 | 675 |
621 // Discard the buffer to indicate we need more data. | 676 // Discard the buffer to indicate we need more data. |
622 if (!frames_to_output) | 677 if (!frames_to_output) |
623 *output_buffer = NULL; | 678 *output_buffer = NULL; |
624 | 679 |
625 return true; | 680 return true; |
626 } | 681 } |
627 | 682 |
628 } // namespace media | 683 } // namespace media |
OLD | NEW |