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 "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/callback_helpers.h" | 8 #include "base/callback_helpers.h" |
9 #include "base/location.h" | 9 #include "base/location.h" |
10 #include "base/message_loop/message_loop_proxy.h" | 10 #include "base/message_loop/message_loop_proxy.h" |
(...skipping 18 matching lines...) Expand all Loading... |
29 memcpy(&value, data + read_offset, sizeof(value)); | 29 memcpy(&value, data + read_offset, sizeof(value)); |
30 return base::ByteSwapToLE16(value); | 30 return base::ByteSwapToLE16(value); |
31 } | 31 } |
32 | 32 |
33 // Returns true if the decode result was end of stream. | 33 // Returns true if the decode result was end of stream. |
34 static inline bool IsEndOfStream(int decoded_size, | 34 static inline bool IsEndOfStream(int decoded_size, |
35 const scoped_refptr<DecoderBuffer>& input) { | 35 const scoped_refptr<DecoderBuffer>& input) { |
36 // Two conditions to meet to declare end of stream for this decoder: | 36 // Two conditions to meet to declare end of stream for this decoder: |
37 // 1. Opus didn't output anything. | 37 // 1. Opus didn't output anything. |
38 // 2. An end of stream buffer is received. | 38 // 2. An end of stream buffer is received. |
39 return decoded_size == 0 && input->IsEndOfStream(); | 39 return decoded_size == 0 && input->end_of_stream(); |
40 } | 40 } |
41 | 41 |
42 // The Opus specification is part of IETF RFC 6716: | 42 // The Opus specification is part of IETF RFC 6716: |
43 // http://tools.ietf.org/html/rfc6716 | 43 // http://tools.ietf.org/html/rfc6716 |
44 | 44 |
45 // Opus uses Vorbis channel mapping, and Vorbis channel mapping specifies | 45 // Opus uses Vorbis channel mapping, and Vorbis channel mapping specifies |
46 // mappings for up to 8 channels. This information is part of the Vorbis I | 46 // mappings for up to 8 channels. This information is part of the Vorbis I |
47 // Specification: | 47 // Specification: |
48 // http://www.xiph.org/vorbis/doc/Vorbis_I_spec.html | 48 // http://www.xiph.org/vorbis/doc/Vorbis_I_spec.html |
49 static const int kMaxVorbisChannels = 8; | 49 static const int kMaxVorbisChannels = 8; |
(...skipping 299 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
349 ResetTimestampState(); | 349 ResetTimestampState(); |
350 ReadFromDemuxerStream(); | 350 ReadFromDemuxerStream(); |
351 return; | 351 return; |
352 } | 352 } |
353 | 353 |
354 DCHECK_EQ(status, DemuxerStream::kOk); | 354 DCHECK_EQ(status, DemuxerStream::kOk); |
355 DCHECK(input.get()); | 355 DCHECK(input.get()); |
356 | 356 |
357 // Libopus does not buffer output. Decoding is complete when an end of stream | 357 // Libopus does not buffer output. Decoding is complete when an end of stream |
358 // input buffer is received. | 358 // input buffer is received. |
359 if (input->IsEndOfStream()) { | 359 if (input->end_of_stream()) { |
360 base::ResetAndReturn(&read_cb_).Run(kOk, AudioBuffer::CreateEOSBuffer()); | 360 base::ResetAndReturn(&read_cb_).Run(kOk, AudioBuffer::CreateEOSBuffer()); |
361 return; | 361 return; |
362 } | 362 } |
363 | 363 |
364 // Make sure we are notified if http://crbug.com/49709 returns. Issue also | 364 // Make sure we are notified if http://crbug.com/49709 returns. Issue also |
365 // occurs with some damaged files. | 365 // occurs with some damaged files. |
366 if (input->GetTimestamp() == kNoTimestamp() && | 366 if (input->timestamp() == kNoTimestamp() && |
367 output_timestamp_helper_->base_timestamp() == kNoTimestamp()) { | 367 output_timestamp_helper_->base_timestamp() == kNoTimestamp()) { |
368 DVLOG(1) << "Received a buffer without timestamps!"; | 368 DVLOG(1) << "Received a buffer without timestamps!"; |
369 base::ResetAndReturn(&read_cb_).Run(kDecodeError, NULL); | 369 base::ResetAndReturn(&read_cb_).Run(kDecodeError, NULL); |
370 return; | 370 return; |
371 } | 371 } |
372 | 372 |
373 if (last_input_timestamp_ != kNoTimestamp() && | 373 if (last_input_timestamp_ != kNoTimestamp() && |
374 input->GetTimestamp() != kNoTimestamp() && | 374 input->timestamp() != kNoTimestamp() && |
375 input->GetTimestamp() < last_input_timestamp_) { | 375 input->timestamp() < last_input_timestamp_) { |
376 base::TimeDelta diff = input->GetTimestamp() - last_input_timestamp_; | 376 base::TimeDelta diff = input->timestamp() - last_input_timestamp_; |
377 DVLOG(1) << "Input timestamps are not monotonically increasing! " | 377 DVLOG(1) << "Input timestamps are not monotonically increasing! " |
378 << " ts " << input->GetTimestamp().InMicroseconds() << " us" | 378 << " ts " << input->timestamp().InMicroseconds() << " us" |
379 << " diff " << diff.InMicroseconds() << " us"; | 379 << " diff " << diff.InMicroseconds() << " us"; |
380 base::ResetAndReturn(&read_cb_).Run(kDecodeError, NULL); | 380 base::ResetAndReturn(&read_cb_).Run(kDecodeError, NULL); |
381 return; | 381 return; |
382 } | 382 } |
383 | 383 |
384 last_input_timestamp_ = input->GetTimestamp(); | 384 last_input_timestamp_ = input->timestamp(); |
385 | 385 |
386 scoped_refptr<AudioBuffer> output_buffer; | 386 scoped_refptr<AudioBuffer> output_buffer; |
387 | 387 |
388 if (!Decode(input, &output_buffer)) { | 388 if (!Decode(input, &output_buffer)) { |
389 base::ResetAndReturn(&read_cb_).Run(kDecodeError, NULL); | 389 base::ResetAndReturn(&read_cb_).Run(kDecodeError, NULL); |
390 return; | 390 return; |
391 } | 391 } |
392 | 392 |
393 if (output_buffer.get()) { | 393 if (output_buffer.get()) { |
394 // Execute callback to return the decoded audio. | 394 // Execute callback to return the decoded audio. |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
507 | 507 |
508 void OpusAudioDecoder::ResetTimestampState() { | 508 void OpusAudioDecoder::ResetTimestampState() { |
509 output_timestamp_helper_->SetBaseTimestamp(kNoTimestamp()); | 509 output_timestamp_helper_->SetBaseTimestamp(kNoTimestamp()); |
510 last_input_timestamp_ = kNoTimestamp(); | 510 last_input_timestamp_ = kNoTimestamp(); |
511 output_bytes_to_drop_ = 0; | 511 output_bytes_to_drop_ = 0; |
512 } | 512 } |
513 | 513 |
514 bool OpusAudioDecoder::Decode(const scoped_refptr<DecoderBuffer>& input, | 514 bool OpusAudioDecoder::Decode(const scoped_refptr<DecoderBuffer>& input, |
515 scoped_refptr<AudioBuffer>* output_buffer) { | 515 scoped_refptr<AudioBuffer>* output_buffer) { |
516 int samples_decoded = opus_multistream_decode(opus_decoder_, | 516 int samples_decoded = opus_multistream_decode(opus_decoder_, |
517 input->GetData(), | 517 input->data(), |
518 input->GetDataSize(), | 518 input->data_size(), |
519 &output_buffer_[0], | 519 &output_buffer_[0], |
520 kMaxOpusOutputPacketSizeSamples, | 520 kMaxOpusOutputPacketSizeSamples, |
521 0); | 521 0); |
522 if (samples_decoded < 0) { | 522 if (samples_decoded < 0) { |
523 LOG(ERROR) << "opus_multistream_decode failed for" | 523 LOG(ERROR) << "opus_multistream_decode failed for" |
524 << " timestamp: " << input->GetTimestamp().InMicroseconds() | 524 << " timestamp: " << input->timestamp().InMicroseconds() |
525 << " us, duration: " << input->GetDuration().InMicroseconds() | 525 << " us, duration: " << input->duration().InMicroseconds() |
526 << " us, packet size: " << input->GetDataSize() << " bytes with" | 526 << " us, packet size: " << input->data_size() << " bytes with" |
527 << " status: " << opus_strerror(samples_decoded); | 527 << " status: " << opus_strerror(samples_decoded); |
528 return false; | 528 return false; |
529 } | 529 } |
530 | 530 |
531 uint8* decoded_audio_data = reinterpret_cast<uint8*>(&output_buffer_[0]); | 531 uint8* decoded_audio_data = reinterpret_cast<uint8*>(&output_buffer_[0]); |
532 int decoded_audio_size = samples_decoded * | 532 int decoded_audio_size = samples_decoded * |
533 demuxer_stream_->audio_decoder_config().bytes_per_frame(); | 533 demuxer_stream_->audio_decoder_config().bytes_per_frame(); |
534 DCHECK_LE(decoded_audio_size, kMaxOpusOutputPacketSizeBytes); | 534 DCHECK_LE(decoded_audio_size, kMaxOpusOutputPacketSizeBytes); |
535 | 535 |
536 if (output_timestamp_helper_->base_timestamp() == kNoTimestamp() && | 536 if (output_timestamp_helper_->base_timestamp() == kNoTimestamp() && |
537 !input->IsEndOfStream()) { | 537 !input->end_of_stream()) { |
538 DCHECK(input->GetTimestamp() != kNoTimestamp()); | 538 DCHECK(input->timestamp() != kNoTimestamp()); |
539 output_timestamp_helper_->SetBaseTimestamp(input->GetTimestamp()); | 539 output_timestamp_helper_->SetBaseTimestamp(input->timestamp()); |
540 } | 540 } |
541 | 541 |
542 if (decoded_audio_size > 0 && output_bytes_to_drop_ > 0) { | 542 if (decoded_audio_size > 0 && output_bytes_to_drop_ > 0) { |
543 int dropped_size = std::min(decoded_audio_size, output_bytes_to_drop_); | 543 int dropped_size = std::min(decoded_audio_size, output_bytes_to_drop_); |
544 DCHECK_EQ(dropped_size % kBytesPerChannel, 0); | 544 DCHECK_EQ(dropped_size % kBytesPerChannel, 0); |
545 decoded_audio_data += dropped_size; | 545 decoded_audio_data += dropped_size; |
546 decoded_audio_size -= dropped_size; | 546 decoded_audio_size -= dropped_size; |
547 output_bytes_to_drop_ -= dropped_size; | 547 output_bytes_to_drop_ -= dropped_size; |
548 samples_decoded = decoded_audio_size / | 548 samples_decoded = decoded_audio_size / |
549 demuxer_stream_->audio_decoder_config().bytes_per_frame(); | 549 demuxer_stream_->audio_decoder_config().bytes_per_frame(); |
(...skipping 14 matching lines...) Expand all Loading... |
564 | 564 |
565 // Decoding finished successfully, update statistics. | 565 // Decoding finished successfully, update statistics. |
566 PipelineStatistics statistics; | 566 PipelineStatistics statistics; |
567 statistics.audio_bytes_decoded = decoded_audio_size; | 567 statistics.audio_bytes_decoded = decoded_audio_size; |
568 statistics_cb_.Run(statistics); | 568 statistics_cb_.Run(statistics); |
569 | 569 |
570 return true; | 570 return true; |
571 } | 571 } |
572 | 572 |
573 } // namespace media | 573 } // namespace media |
OLD | NEW |