Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(334)

Side by Side Diff: media/filters/opus_audio_decoder.cc

Issue 23014009: media: Opus support for WebM in Media Source (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 232 matching lines...) Expand 10 before | Expand all | Expand 10 after
243 OpusAudioDecoder::OpusAudioDecoder( 243 OpusAudioDecoder::OpusAudioDecoder(
244 const scoped_refptr<base::MessageLoopProxy>& message_loop) 244 const scoped_refptr<base::MessageLoopProxy>& message_loop)
245 : message_loop_(message_loop), 245 : message_loop_(message_loop),
246 weak_factory_(this), 246 weak_factory_(this),
247 demuxer_stream_(NULL), 247 demuxer_stream_(NULL),
248 opus_decoder_(NULL), 248 opus_decoder_(NULL),
249 bits_per_channel_(0), 249 bits_per_channel_(0),
250 channel_layout_(CHANNEL_LAYOUT_NONE), 250 channel_layout_(CHANNEL_LAYOUT_NONE),
251 samples_per_second_(0), 251 samples_per_second_(0),
252 last_input_timestamp_(kNoTimestamp()), 252 last_input_timestamp_(kNoTimestamp()),
253 output_bytes_to_drop_(0),
254 skip_samples_(0) { 253 skip_samples_(0) {
255 } 254 }
256 255
257 void OpusAudioDecoder::Initialize( 256 void OpusAudioDecoder::Initialize(
258 DemuxerStream* stream, 257 DemuxerStream* stream,
259 const PipelineStatusCB& status_cb, 258 const PipelineStatusCB& status_cb,
260 const StatisticsCB& statistics_cb) { 259 const StatisticsCB& statistics_cb) {
261 DCHECK(message_loop_->BelongsToCurrentThread()); 260 DCHECK(message_loop_->BelongsToCurrentThread());
262 PipelineStatusCB initialize_cb = BindToCurrentLoop(status_cb); 261 PipelineStatusCB initialize_cb = BindToCurrentLoop(status_cb);
263 262
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after
450 // Allocate the output buffer if necessary. 449 // Allocate the output buffer if necessary.
451 if (!output_buffer_) 450 if (!output_buffer_)
452 output_buffer_.reset(new int16[kMaxOpusOutputPacketSizeSamples]); 451 output_buffer_.reset(new int16[kMaxOpusOutputPacketSizeSamples]);
453 452
454 // Parse the Opus header. 453 // Parse the Opus header.
455 OpusHeader opus_header; 454 OpusHeader opus_header;
456 ParseOpusHeader(config.extra_data(), config.extra_data_size(), 455 ParseOpusHeader(config.extra_data(), config.extra_data_size(),
457 config, 456 config,
458 &opus_header); 457 &opus_header);
459 458
460 skip_samples_ = opus_header.skip_samples; 459 if (!config.codec_delay()) {
461 460 skip_samples_ = opus_header.skip_samples;
fgalligan1 2013/08/26 21:10:06 Is this the same value as below? I.e. skipped_byte
vignesh 2013/08/26 21:44:23 No it is not. If you look below (Line 542 in the r
fgalligan1 2013/08/26 22:11:53 Sorry I was just asking if opus_header.skip_sample
vignesh 2013/08/26 23:55:48 No it does not. Neither does the skip_samples_ var
462 if (skip_samples_ > 0) 461 } else {
463 output_bytes_to_drop_ = skip_samples_ * config.bytes_per_frame(); 462 // WebM container stores codec delay in nanoseconds. Convert it to samples.
463 skip_samples_ = config.codec_delay() * config.samples_per_second() /
464 1000000000;
465 if (skip_samples_ != opus_header.skip_samples) {
466 DVLOG(1) << "Codec Delay in container does not match the value in Opus "
467 << "header. Using the value in container.";
468 }
469 }
464 470
465 uint8 channel_mapping[kMaxVorbisChannels]; 471 uint8 channel_mapping[kMaxVorbisChannels];
466 memcpy(&channel_mapping, 472 memcpy(&channel_mapping,
467 kDefaultOpusChannelLayout, 473 kDefaultOpusChannelLayout,
468 kMaxChannelsWithDefaultLayout); 474 kMaxChannelsWithDefaultLayout);
469 475
470 if (channel_count > kMaxChannelsWithDefaultLayout) { 476 if (channel_count > kMaxChannelsWithDefaultLayout) {
471 RemapOpusChannelLayout(opus_header.stream_map, 477 RemapOpusChannelLayout(opus_header.stream_map,
472 channel_count, 478 channel_count,
473 channel_mapping); 479 channel_mapping);
(...skipping 27 matching lines...) Expand all
501 void OpusAudioDecoder::CloseDecoder() { 507 void OpusAudioDecoder::CloseDecoder() {
502 if (opus_decoder_) { 508 if (opus_decoder_) {
503 opus_multistream_decoder_destroy(opus_decoder_); 509 opus_multistream_decoder_destroy(opus_decoder_);
504 opus_decoder_ = NULL; 510 opus_decoder_ = NULL;
505 } 511 }
506 } 512 }
507 513
508 void OpusAudioDecoder::ResetTimestampState() { 514 void OpusAudioDecoder::ResetTimestampState() {
509 output_timestamp_helper_->SetBaseTimestamp(kNoTimestamp()); 515 output_timestamp_helper_->SetBaseTimestamp(kNoTimestamp());
510 last_input_timestamp_ = kNoTimestamp(); 516 last_input_timestamp_ = kNoTimestamp();
511 output_bytes_to_drop_ = 0; 517 skip_samples_ = 0;
512 } 518 }
513 519
514 bool OpusAudioDecoder::Decode(const scoped_refptr<DecoderBuffer>& input, 520 bool OpusAudioDecoder::Decode(const scoped_refptr<DecoderBuffer>& input,
515 scoped_refptr<AudioBuffer>* output_buffer) { 521 scoped_refptr<AudioBuffer>* output_buffer) {
516 int samples_decoded = opus_multistream_decode(opus_decoder_, 522 int samples_decoded = opus_multistream_decode(opus_decoder_,
517 input->data(), 523 input->data(),
518 input->data_size(), 524 input->data_size(),
519 &output_buffer_[0], 525 &output_buffer_[0],
520 kMaxOpusOutputPacketSizeSamples, 526 kMaxOpusOutputPacketSizeSamples,
521 0); 527 0);
(...skipping 10 matching lines...) Expand all
532 int decoded_audio_size = samples_decoded * 538 int decoded_audio_size = samples_decoded *
533 demuxer_stream_->audio_decoder_config().bytes_per_frame(); 539 demuxer_stream_->audio_decoder_config().bytes_per_frame();
534 DCHECK_LE(decoded_audio_size, kMaxOpusOutputPacketSizeBytes); 540 DCHECK_LE(decoded_audio_size, kMaxOpusOutputPacketSizeBytes);
535 541
536 if (output_timestamp_helper_->base_timestamp() == kNoTimestamp() && 542 if (output_timestamp_helper_->base_timestamp() == kNoTimestamp() &&
537 !input->end_of_stream()) { 543 !input->end_of_stream()) {
538 DCHECK(input->timestamp() != kNoTimestamp()); 544 DCHECK(input->timestamp() != kNoTimestamp());
539 output_timestamp_helper_->SetBaseTimestamp(input->timestamp()); 545 output_timestamp_helper_->SetBaseTimestamp(input->timestamp());
540 } 546 }
541 547
542 if (decoded_audio_size > 0 && output_bytes_to_drop_ > 0) {
543 int dropped_size = std::min(decoded_audio_size, output_bytes_to_drop_);
544 DCHECK_EQ(dropped_size % kBytesPerChannel, 0);
545 decoded_audio_data += dropped_size;
546 decoded_audio_size -= dropped_size;
547 output_bytes_to_drop_ -= dropped_size;
548 samples_decoded = decoded_audio_size /
549 demuxer_stream_->audio_decoder_config().bytes_per_frame();
550 }
551
552 if (decoded_audio_size > 0) { 548 if (decoded_audio_size > 0) {
553 // Copy the audio samples into an output buffer. 549 // Copy the audio samples into an output buffer.
554 uint8* data[] = { decoded_audio_data }; 550 uint8* data[] = { decoded_audio_data };
555 *output_buffer = AudioBuffer::CopyFrom( 551 *output_buffer = AudioBuffer::CopyFrom(
556 kSampleFormatS16, 552 kSampleFormatS16,
557 ChannelLayoutToChannelCount(channel_layout_), 553 ChannelLayoutToChannelCount(channel_layout_),
558 samples_decoded, 554 samples_decoded,
559 data, 555 data,
560 output_timestamp_helper_->GetTimestamp(), 556 output_timestamp_helper_->GetTimestamp(),
561 output_timestamp_helper_->GetFrameDuration(samples_decoded)); 557 output_timestamp_helper_->GetFrameDuration(samples_decoded));
562 output_timestamp_helper_->AddFrames(samples_decoded); 558 output_timestamp_helper_->AddFrames(samples_decoded);
559 if (skip_samples_ > 0) {
560 int dropped_size = std::min(samples_decoded, skip_samples_);
561 output_buffer->get()->TrimStart(dropped_size);
fgalligan1 2013/08/26 21:10:06 I'm assuming this works on samples? Does it take i
vignesh 2013/08/26 21:44:23 Yes, it works on samples. I am unsure if it takes
vignesh 2013/08/26 23:55:48 As mentioned in the other comment in this file, th
562 skip_samples_ -= dropped_size;
563 samples_decoded -= dropped_size;
564 }
565 if (input->discard_padding() > 0) {
566 int discard_padding = input->discard_padding() * samples_per_second_ /
567 1000000000;
568 output_buffer->get()->TrimEnd(std::min(samples_decoded, discard_padding));
569 }
563 } 570 }
564 571
565 // Decoding finished successfully, update statistics. 572 // Decoding finished successfully, update statistics.
566 PipelineStatistics statistics; 573 PipelineStatistics statistics;
567 statistics.audio_bytes_decoded = decoded_audio_size; 574 statistics.audio_bytes_decoded = decoded_audio_size;
568 statistics_cb_.Run(statistics); 575 statistics_cb_.Run(statistics);
569 576
570 return true; 577 return true;
571 } 578 }
572 579
573 } // namespace media 580 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698