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/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(stop_cb_.is_null()); | |
| 302 DCHECK(reset_cb_.is_null()); | |
|
xhwang
2014/01/10 22:14:15
nit: switch the order to these two
| |
| 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 if (read_cb_.is_null()) { | |
| 339 if (!reset_cb_.is_null()) | |
| 340 DoReset(); | |
| 341 else | |
| 342 DoStop(); | |
| 343 } | |
| 344 // Otherwise we have to wait for the pending demuxer read. | |
| 345 } | |
| 346 | |
| 347 OpusAudioDecoder::~OpusAudioDecoder() {} | |
| 348 | |
| 349 void OpusAudioDecoder::DoReset() { | |
| 350 DCHECK(task_runner_->BelongsToCurrentThread()); | |
| 351 DCHECK(!reset_cb_.is_null()); | |
| 352 DCHECK(read_cb_.is_null()); | |
| 324 | 353 |
| 325 opus_multistream_decoder_ctl(opus_decoder_, OPUS_RESET_STATE); | 354 opus_multistream_decoder_ctl(opus_decoder_, OPUS_RESET_STATE); |
| 326 ResetTimestampState(); | 355 ResetTimestampState(); |
| 327 reset_cb.Run(); | 356 base::ResetAndReturn(&reset_cb_).Run(); |
| 357 | |
| 358 if (!stop_cb_.is_null()) | |
| 359 DoStop(); | |
| 328 } | 360 } |
| 329 | 361 |
| 330 OpusAudioDecoder::~OpusAudioDecoder() { | 362 void OpusAudioDecoder::DoStop() { |
| 331 // TODO(scherkus): should we require Stop() to be called? this might end up | 363 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 332 // getting called on a random thread due to refcounting. | 364 DCHECK(!stop_cb_.is_null()); |
| 365 DCHECK(read_cb_.is_null()); | |
| 366 DCHECK(reset_cb_.is_null()); | |
| 367 | |
| 368 opus_multistream_decoder_ctl(opus_decoder_, OPUS_RESET_STATE); | |
| 369 ResetTimestampState(); | |
| 333 CloseDecoder(); | 370 CloseDecoder(); |
| 371 base::ResetAndReturn(&stop_cb_).Run(); | |
| 334 } | 372 } |
| 335 | 373 |
| 336 void OpusAudioDecoder::ReadFromDemuxerStream() { | 374 void OpusAudioDecoder::ReadFromDemuxerStream() { |
| 337 DCHECK(!read_cb_.is_null()); | 375 DCHECK(!read_cb_.is_null()); |
| 338 demuxer_stream_->Read(base::Bind(&OpusAudioDecoder::BufferReady, weak_this_)); | 376 demuxer_stream_->Read(base::Bind(&OpusAudioDecoder::BufferReady, weak_this_)); |
| 339 } | 377 } |
| 340 | 378 |
| 341 void OpusAudioDecoder::BufferReady( | 379 void OpusAudioDecoder::BufferReady( |
| 342 DemuxerStream::Status status, | 380 DemuxerStream::Status status, |
| 343 const scoped_refptr<DecoderBuffer>& input) { | 381 const scoped_refptr<DecoderBuffer>& input) { |
| 344 DCHECK(task_runner_->BelongsToCurrentThread()); | 382 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 345 DCHECK(!read_cb_.is_null()); | 383 DCHECK(!read_cb_.is_null()); |
| 346 DCHECK_EQ(status != DemuxerStream::kOk, !input.get()) << status; | 384 DCHECK_EQ(status != DemuxerStream::kOk, !input.get()) << status; |
| 347 | 385 |
| 386 // Drop the buffer, fire |read_cb_| and complete the pending Reset(). | |
| 387 if (!reset_cb_.is_null()) { | |
| 388 base::ResetAndReturn(&read_cb_).Run(kAborted, NULL); | |
| 389 DoReset(); | |
| 390 return; | |
| 391 } | |
| 392 | |
| 393 // Drop the buffer, fire |read_cb_| and complete the pending Stop(). | |
| 394 if (!stop_cb_.is_null()) { | |
| 395 base::ResetAndReturn(&read_cb_).Run(kAborted, NULL); | |
| 396 DoStop(); | |
| 397 return; | |
| 398 } | |
| 399 | |
| 348 if (status == DemuxerStream::kAborted) { | 400 if (status == DemuxerStream::kAborted) { |
| 349 DCHECK(!input.get()); | 401 DCHECK(!input.get()); |
| 350 base::ResetAndReturn(&read_cb_).Run(kAborted, NULL); | 402 base::ResetAndReturn(&read_cb_).Run(kAborted, NULL); |
| 351 return; | 403 return; |
| 352 } | 404 } |
| 353 | 405 |
| 354 if (status == DemuxerStream::kConfigChanged) { | 406 if (status == DemuxerStream::kConfigChanged) { |
| 355 DCHECK(!input.get()); | 407 DCHECK(!input.get()); |
| 356 DVLOG(1) << "Config changed."; | 408 DVLOG(1) << "Config changed."; |
| 357 | 409 |
| (...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 619 output_timestamp_helper_->AddFrames(frames_decoded); | 671 output_timestamp_helper_->AddFrames(frames_decoded); |
| 620 | 672 |
| 621 // Discard the buffer to indicate we need more data. | 673 // Discard the buffer to indicate we need more data. |
| 622 if (!frames_to_output) | 674 if (!frames_to_output) |
| 623 *output_buffer = NULL; | 675 *output_buffer = NULL; |
| 624 | 676 |
| 625 return true; | 677 return true; |
| 626 } | 678 } |
| 627 | 679 |
| 628 } // namespace media | 680 } // namespace media |
| OLD | NEW |