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