| 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 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 83 // 8 Channels (7.1) | 83 // 8 Channels (7.1) |
| 84 // Front L, Center, Front R, Side L, Side R, Back L, Back R, LFE | 84 // Front L, Center, Front R, Side L, Side R, Back L, Back R, LFE |
| 85 // | 85 // |
| 86 // Channel ordering information is taken from section 4.3.9 of the Vorbis I | 86 // Channel ordering information is taken from section 4.3.9 of the Vorbis I |
| 87 // Specification: | 87 // Specification: |
| 88 // http://xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-800004.3.9 | 88 // http://xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-800004.3.9 |
| 89 | 89 |
| 90 // These are the FFmpeg channel layouts expressed using the position of each | 90 // These are the FFmpeg channel layouts expressed using the position of each |
| 91 // channel in the output stream from libopus. | 91 // channel in the output stream from libopus. |
| 92 const uint8 kFFmpegChannelLayouts[num_layouts][num_layout_values] = { | 92 const uint8 kFFmpegChannelLayouts[num_layouts][num_layout_values] = { |
| 93 { 0 }, | 93 {0}, |
| 94 | 94 |
| 95 // Stereo: No reorder. | 95 // Stereo: No reorder. |
| 96 { 0, 1 }, | 96 {0, 1}, |
| 97 | 97 |
| 98 // 3 Channels, from Vorbis order to: | 98 // 3 Channels, from Vorbis order to: |
| 99 // L, R, Center | 99 // L, R, Center |
| 100 { 0, 2, 1 }, | 100 {0, 2, 1}, |
| 101 | 101 |
| 102 // 4 Channels: No reorder. | 102 // 4 Channels: No reorder. |
| 103 { 0, 1, 2, 3 }, | 103 {0, 1, 2, 3}, |
| 104 | 104 |
| 105 // 5 Channels, from Vorbis order to: | 105 // 5 Channels, from Vorbis order to: |
| 106 // Front L, Front R, Center, Back L, Back R | 106 // Front L, Front R, Center, Back L, Back R |
| 107 { 0, 2, 1, 3, 4 }, | 107 {0, 2, 1, 3, 4}, |
| 108 | 108 |
| 109 // 6 Channels (5.1), from Vorbis order to: | 109 // 6 Channels (5.1), from Vorbis order to: |
| 110 // Front L, Front R, Center, LFE, Back L, Back R | 110 // Front L, Front R, Center, LFE, Back L, Back R |
| 111 { 0, 2, 1, 5, 3, 4 }, | 111 {0, 2, 1, 5, 3, 4}, |
| 112 | 112 |
| 113 // 7 Channels (6.1), from Vorbis order to: | 113 // 7 Channels (6.1), from Vorbis order to: |
| 114 // Front L, Front R, Front Center, LFE, Side L, Side R, Back Center | 114 // Front L, Front R, Front Center, LFE, Side L, Side R, Back Center |
| 115 { 0, 2, 1, 6, 3, 4, 5 }, | 115 {0, 2, 1, 6, 3, 4, 5}, |
| 116 | 116 |
| 117 // 8 Channels (7.1), from Vorbis order to: | 117 // 8 Channels (7.1), from Vorbis order to: |
| 118 // Front L, Front R, Center, LFE, Back L, Back R, Side L, Side R | 118 // Front L, Front R, Center, LFE, Back L, Back R, Side L, Side R |
| 119 { 0, 2, 1, 7, 5, 6, 3, 4 }, | 119 {0, 2, 1, 7, 5, 6, 3, 4}, |
| 120 }; | 120 }; |
| 121 | 121 |
| 122 // Reorder the channels to produce the same ordering as FFmpeg, which is | 122 // Reorder the channels to produce the same ordering as FFmpeg, which is |
| 123 // what the pipeline expects. | 123 // what the pipeline expects. |
| 124 const uint8* vorbis_layout_offset = kFFmpegChannelLayouts[num_channels - 1]; | 124 const uint8* vorbis_layout_offset = kFFmpegChannelLayouts[num_channels - 1]; |
| 125 for (int channel = 0; channel < num_channels; ++channel) | 125 for (int channel = 0; channel < num_channels; ++channel) |
| 126 channel_layout[channel] = opus_mapping[vorbis_layout_offset[channel]]; | 126 channel_layout[channel] = opus_mapping[vorbis_layout_offset[channel]]; |
| 127 } | 127 } |
| 128 | 128 |
| 129 // Opus Header contents: | 129 // Opus Header contents: |
| (...skipping 18 matching lines...) Expand all Loading... |
| 148 // - right | 148 // - right |
| 149 // - else | 149 // - else |
| 150 // - stream = byte-M | 150 // - stream = byte-M |
| 151 | 151 |
| 152 // Default audio output channel layout. Used to initialize |stream_map| in | 152 // Default audio output channel layout. Used to initialize |stream_map| in |
| 153 // OpusHeader, and passed to opus_multistream_decoder_create() when the header | 153 // OpusHeader, and passed to opus_multistream_decoder_create() when the header |
| 154 // does not contain mapping information. The values are valid only for mono and | 154 // does not contain mapping information. The values are valid only for mono and |
| 155 // stereo output: Opus streams with more than 2 channels require a stream map. | 155 // stereo output: Opus streams with more than 2 channels require a stream map. |
| 156 static const int kMaxChannelsWithDefaultLayout = 2; | 156 static const int kMaxChannelsWithDefaultLayout = 2; |
| 157 static const uint8 kDefaultOpusChannelLayout[kMaxChannelsWithDefaultLayout] = { | 157 static const uint8 kDefaultOpusChannelLayout[kMaxChannelsWithDefaultLayout] = { |
| 158 0, 1 }; | 158 0, 1 |
| 159 }; |
| 159 | 160 |
| 160 // Size of the Opus header excluding optional mapping information. | 161 // Size of the Opus header excluding optional mapping information. |
| 161 static const int kOpusHeaderSize = 19; | 162 static const int kOpusHeaderSize = 19; |
| 162 | 163 |
| 163 // Offset to the channel count byte in the Opus header. | 164 // Offset to the channel count byte in the Opus header. |
| 164 static const int kOpusHeaderChannelsOffset = 9; | 165 static const int kOpusHeaderChannelsOffset = 9; |
| 165 | 166 |
| 166 // Offset to the pre-skip value in the Opus header. | 167 // Offset to the pre-skip value in the Opus header. |
| 167 static const int kOpusHeaderSkipSamplesOffset = 10; | 168 static const int kOpusHeaderSkipSamplesOffset = 10; |
| 168 | 169 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 179 static const int kOpusHeaderNumCoupledOffset = kOpusHeaderNumStreamsOffset + 1; | 180 static const int kOpusHeaderNumCoupledOffset = kOpusHeaderNumStreamsOffset + 1; |
| 180 static const int kOpusHeaderStreamMapOffset = kOpusHeaderNumStreamsOffset + 2; | 181 static const int kOpusHeaderStreamMapOffset = kOpusHeaderNumStreamsOffset + 2; |
| 181 | 182 |
| 182 struct OpusHeader { | 183 struct OpusHeader { |
| 183 OpusHeader() | 184 OpusHeader() |
| 184 : channels(0), | 185 : channels(0), |
| 185 skip_samples(0), | 186 skip_samples(0), |
| 186 channel_mapping(0), | 187 channel_mapping(0), |
| 187 num_streams(0), | 188 num_streams(0), |
| 188 num_coupled(0) { | 189 num_coupled(0) { |
| 189 memcpy(stream_map, | 190 memcpy( |
| 190 kDefaultOpusChannelLayout, | 191 stream_map, kDefaultOpusChannelLayout, kMaxChannelsWithDefaultLayout); |
| 191 kMaxChannelsWithDefaultLayout); | |
| 192 } | 192 } |
| 193 int channels; | 193 int channels; |
| 194 int skip_samples; | 194 int skip_samples; |
| 195 int channel_mapping; | 195 int channel_mapping; |
| 196 int num_streams; | 196 int num_streams; |
| 197 int num_coupled; | 197 int num_coupled; |
| 198 uint8 stream_map[kMaxVorbisChannels]; | 198 uint8 stream_map[kMaxVorbisChannels]; |
| 199 }; | 199 }; |
| 200 | 200 |
| 201 // Returns true when able to successfully parse and store Opus header data in | 201 // Returns true when able to successfully parse and store Opus header data in |
| 202 // data parsed in |header|. Based on opus header parsing code in libopusdec | 202 // data parsed in |header|. Based on opus header parsing code in libopusdec |
| 203 // from FFmpeg, and opus_header from Xiph's opus-tools project. | 203 // from FFmpeg, and opus_header from Xiph's opus-tools project. |
| 204 static void ParseOpusHeader(const uint8* data, int data_size, | 204 static void ParseOpusHeader(const uint8* data, |
| 205 int data_size, |
| 205 const AudioDecoderConfig& config, | 206 const AudioDecoderConfig& config, |
| 206 OpusHeader* header) { | 207 OpusHeader* header) { |
| 207 CHECK_GE(data_size, kOpusHeaderSize); | 208 CHECK_GE(data_size, kOpusHeaderSize); |
| 208 | 209 |
| 209 header->channels = *(data + kOpusHeaderChannelsOffset); | 210 header->channels = *(data + kOpusHeaderChannelsOffset); |
| 210 | 211 |
| 211 CHECK(header->channels > 0 && header->channels <= kMaxVorbisChannels) | 212 CHECK(header->channels > 0 && header->channels <= kMaxVorbisChannels) |
| 212 << "invalid channel count in header: " << header->channels; | 213 << "invalid channel count in header: " << header->channels; |
| 213 | 214 |
| 214 header->skip_samples = | 215 header->skip_samples = |
| (...skipping 29 matching lines...) Expand all Loading... |
| 244 const scoped_refptr<base::MessageLoopProxy>& message_loop) | 245 const scoped_refptr<base::MessageLoopProxy>& message_loop) |
| 245 : message_loop_(message_loop), | 246 : message_loop_(message_loop), |
| 246 weak_factory_(this), | 247 weak_factory_(this), |
| 247 demuxer_stream_(NULL), | 248 demuxer_stream_(NULL), |
| 248 opus_decoder_(NULL), | 249 opus_decoder_(NULL), |
| 249 bits_per_channel_(0), | 250 bits_per_channel_(0), |
| 250 channel_layout_(CHANNEL_LAYOUT_NONE), | 251 channel_layout_(CHANNEL_LAYOUT_NONE), |
| 251 samples_per_second_(0), | 252 samples_per_second_(0), |
| 252 last_input_timestamp_(kNoTimestamp()), | 253 last_input_timestamp_(kNoTimestamp()), |
| 253 output_bytes_to_drop_(0), | 254 output_bytes_to_drop_(0), |
| 254 skip_samples_(0) { | 255 skip_samples_(0) {} |
| 255 } | |
| 256 | 256 |
| 257 void OpusAudioDecoder::Initialize( | 257 void OpusAudioDecoder::Initialize(DemuxerStream* stream, |
| 258 DemuxerStream* stream, | 258 const PipelineStatusCB& status_cb, |
| 259 const PipelineStatusCB& status_cb, | 259 const StatisticsCB& statistics_cb) { |
| 260 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 |
| 264 if (demuxer_stream_) { | 263 if (demuxer_stream_) { |
| 265 // TODO(scherkus): initialization currently happens more than once in | 264 // TODO(scherkus): initialization currently happens more than once in |
| 266 // PipelineIntegrationTest.BasicPlayback. | 265 // PipelineIntegrationTest.BasicPlayback. |
| 267 LOG(ERROR) << "Initialize has already been called."; | 266 LOG(ERROR) << "Initialize has already been called."; |
| 268 CHECK(false); | 267 CHECK(false); |
| 269 } | 268 } |
| 270 | 269 |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 317 // TODO(scherkus): should we require Stop() to be called? this might end up | 316 // TODO(scherkus): should we require Stop() to be called? this might end up |
| 318 // getting called on a random thread due to refcounting. | 317 // getting called on a random thread due to refcounting. |
| 319 CloseDecoder(); | 318 CloseDecoder(); |
| 320 } | 319 } |
| 321 | 320 |
| 322 void OpusAudioDecoder::ReadFromDemuxerStream() { | 321 void OpusAudioDecoder::ReadFromDemuxerStream() { |
| 323 DCHECK(!read_cb_.is_null()); | 322 DCHECK(!read_cb_.is_null()); |
| 324 demuxer_stream_->Read(base::Bind(&OpusAudioDecoder::BufferReady, weak_this_)); | 323 demuxer_stream_->Read(base::Bind(&OpusAudioDecoder::BufferReady, weak_this_)); |
| 325 } | 324 } |
| 326 | 325 |
| 327 void OpusAudioDecoder::BufferReady( | 326 void OpusAudioDecoder::BufferReady(DemuxerStream::Status status, |
| 328 DemuxerStream::Status status, | 327 const scoped_refptr<DecoderBuffer>& input) { |
| 329 const scoped_refptr<DecoderBuffer>& input) { | |
| 330 DCHECK(message_loop_->BelongsToCurrentThread()); | 328 DCHECK(message_loop_->BelongsToCurrentThread()); |
| 331 DCHECK(!read_cb_.is_null()); | 329 DCHECK(!read_cb_.is_null()); |
| 332 DCHECK_EQ(status != DemuxerStream::kOk, !input.get()) << status; | 330 DCHECK_EQ(status != DemuxerStream::kOk, !input.get()) << status; |
| 333 | 331 |
| 334 if (status == DemuxerStream::kAborted) { | 332 if (status == DemuxerStream::kAborted) { |
| 335 DCHECK(!input.get()); | 333 DCHECK(!input.get()); |
| 336 base::ResetAndReturn(&read_cb_).Run(kAborted, NULL); | 334 base::ResetAndReturn(&read_cb_).Run(kAborted, NULL); |
| 337 return; | 335 return; |
| 338 } | 336 } |
| 339 | 337 |
| 340 if (status == DemuxerStream::kConfigChanged) { | 338 if (status == DemuxerStream::kConfigChanged) { |
| 341 DCHECK(!input.get()); | 339 DCHECK(!input.get()); |
| 342 DVLOG(1) << "Config changed."; | 340 DVLOG(1) << "Config changed."; |
| 343 | 341 |
| 344 if (!ConfigureDecoder()) { | 342 if (!ConfigureDecoder()) { |
| 345 base::ResetAndReturn(&read_cb_).Run(kDecodeError, NULL); | 343 base::ResetAndReturn(&read_cb_).Run(kDecodeError, NULL); |
| 346 return; | 344 return; |
| 347 } | 345 } |
| 348 | 346 |
| 349 ResetTimestampState(); | 347 ResetTimestampState(); |
| 350 ReadFromDemuxerStream(); | 348 ReadFromDemuxerStream(); |
| 351 return; | 349 return; |
| 352 } | 350 } |
| 353 | 351 |
| 354 DCHECK_EQ(status, DemuxerStream::kOk); | 352 DCHECK_EQ(status, DemuxerStream::kOk); |
| 355 DCHECK(input.get()); | 353 DCHECK(input.get()); |
| 356 | 354 |
| 357 // Libopus does not buffer output. Decoding is complete when an end of stream | 355 // Libopus does not buffer output. Decoding is complete when an end of stream |
| 358 // input buffer is received. | 356 // input buffer is received. |
| 359 if (input->IsEndOfStream()) { | 357 if (input->end_of_stream()) { |
| 360 base::ResetAndReturn(&read_cb_).Run(kOk, DataBuffer::CreateEOSBuffer()); | 358 base::ResetAndReturn(&read_cb_).Run(kOk, DataBuffer::CreateEOSBuffer()); |
| 361 return; | 359 return; |
| 362 } | 360 } |
| 363 | 361 |
| 364 // Make sure we are notified if http://crbug.com/49709 returns. Issue also | 362 // Make sure we are notified if http://crbug.com/49709 returns. Issue also |
| 365 // occurs with some damaged files. | 363 // occurs with some damaged files. |
| 366 if (input->GetTimestamp() == kNoTimestamp() && | 364 if (input->timestamp() == kNoTimestamp() && |
| 367 output_timestamp_helper_->base_timestamp() == kNoTimestamp()) { | 365 output_timestamp_helper_->base_timestamp() == kNoTimestamp()) { |
| 368 DVLOG(1) << "Received a buffer without timestamps!"; | 366 DVLOG(1) << "Received a buffer without timestamps!"; |
| 369 base::ResetAndReturn(&read_cb_).Run(kDecodeError, NULL); | 367 base::ResetAndReturn(&read_cb_).Run(kDecodeError, NULL); |
| 370 return; | 368 return; |
| 371 } | 369 } |
| 372 | 370 |
| 373 if (last_input_timestamp_ != kNoTimestamp() && | 371 if (last_input_timestamp_ != kNoTimestamp() && |
| 374 input->GetTimestamp() != kNoTimestamp() && | 372 input->timestamp() != kNoTimestamp() && |
| 375 input->GetTimestamp() < last_input_timestamp_) { | 373 input->timestamp() < last_input_timestamp_) { |
| 376 base::TimeDelta diff = input->GetTimestamp() - last_input_timestamp_; | 374 base::TimeDelta diff = input->timestamp() - last_input_timestamp_; |
| 377 DVLOG(1) << "Input timestamps are not monotonically increasing! " | 375 DVLOG(1) << "Input timestamps are not monotonically increasing! " |
| 378 << " ts " << input->GetTimestamp().InMicroseconds() << " us" | 376 << " ts " << input->timestamp().InMicroseconds() << " us" |
| 379 << " diff " << diff.InMicroseconds() << " us"; | 377 << " diff " << diff.InMicroseconds() << " us"; |
| 380 base::ResetAndReturn(&read_cb_).Run(kDecodeError, NULL); | 378 base::ResetAndReturn(&read_cb_).Run(kDecodeError, NULL); |
| 381 return; | 379 return; |
| 382 } | 380 } |
| 383 | 381 |
| 384 last_input_timestamp_ = input->GetTimestamp(); | 382 last_input_timestamp_ = input->timestamp(); |
| 385 | 383 |
| 386 scoped_refptr<DataBuffer> output_buffer; | 384 scoped_refptr<DataBuffer> output_buffer; |
| 387 | 385 |
| 388 if (!Decode(input, &output_buffer)) { | 386 if (!Decode(input, &output_buffer)) { |
| 389 base::ResetAndReturn(&read_cb_).Run(kDecodeError, NULL); | 387 base::ResetAndReturn(&read_cb_).Run(kDecodeError, NULL); |
| 390 return; | 388 return; |
| 391 } | 389 } |
| 392 | 390 |
| 393 if (output_buffer.get()) { | 391 if (output_buffer.get()) { |
| 394 // Execute callback to return the decoded audio. | 392 // Execute callback to return the decoded audio. |
| (...skipping 28 matching lines...) Expand all Loading... |
| 423 if (config.bits_per_channel() != kBitsPerChannel) { | 421 if (config.bits_per_channel() != kBitsPerChannel) { |
| 424 DLOG(ERROR) << "16 bit samples required."; | 422 DLOG(ERROR) << "16 bit samples required."; |
| 425 return false; | 423 return false; |
| 426 } | 424 } |
| 427 | 425 |
| 428 if (config.is_encrypted()) { | 426 if (config.is_encrypted()) { |
| 429 DLOG(ERROR) << "Encrypted audio stream not supported."; | 427 DLOG(ERROR) << "Encrypted audio stream not supported."; |
| 430 return false; | 428 return false; |
| 431 } | 429 } |
| 432 | 430 |
| 433 if (opus_decoder_ && | 431 if (opus_decoder_ && (bits_per_channel_ != config.bits_per_channel() || |
| 434 (bits_per_channel_ != config.bits_per_channel() || | 432 channel_layout_ != config.channel_layout() || |
| 435 channel_layout_ != config.channel_layout() || | 433 samples_per_second_ != config.samples_per_second())) { |
| 436 samples_per_second_ != config.samples_per_second())) { | |
| 437 DVLOG(1) << "Unsupported config change :"; | 434 DVLOG(1) << "Unsupported config change :"; |
| 438 DVLOG(1) << "\tbits_per_channel : " << bits_per_channel_ | 435 DVLOG(1) << "\tbits_per_channel : " << bits_per_channel_ << " -> " |
| 439 << " -> " << config.bits_per_channel(); | 436 << config.bits_per_channel(); |
| 440 DVLOG(1) << "\tchannel_layout : " << channel_layout_ | 437 DVLOG(1) << "\tchannel_layout : " << channel_layout_ << " -> " |
| 441 << " -> " << config.channel_layout(); | 438 << config.channel_layout(); |
| 442 DVLOG(1) << "\tsample_rate : " << samples_per_second_ | 439 DVLOG(1) << "\tsample_rate : " << samples_per_second_ << " -> " |
| 443 << " -> " << config.samples_per_second(); | 440 << config.samples_per_second(); |
| 444 return false; | 441 return false; |
| 445 } | 442 } |
| 446 | 443 |
| 447 // Clean up existing decoder if necessary. | 444 // Clean up existing decoder if necessary. |
| 448 CloseDecoder(); | 445 CloseDecoder(); |
| 449 | 446 |
| 450 // Allocate the output buffer if necessary. | 447 // Allocate the output buffer if necessary. |
| 451 if (!output_buffer_) | 448 if (!output_buffer_) |
| 452 output_buffer_.reset(new int16[kMaxOpusOutputPacketSizeSamples]); | 449 output_buffer_.reset(new int16[kMaxOpusOutputPacketSizeSamples]); |
| 453 | 450 |
| 454 // Parse the Opus header. | 451 // Parse the Opus header. |
| 455 OpusHeader opus_header; | 452 OpusHeader opus_header; |
| 456 ParseOpusHeader(config.extra_data(), config.extra_data_size(), | 453 ParseOpusHeader( |
| 457 config, | 454 config.extra_data(), config.extra_data_size(), config, &opus_header); |
| 458 &opus_header); | |
| 459 | 455 |
| 460 skip_samples_ = opus_header.skip_samples; | 456 skip_samples_ = opus_header.skip_samples; |
| 461 | 457 |
| 462 if (skip_samples_ > 0) | 458 if (skip_samples_ > 0) |
| 463 output_bytes_to_drop_ = skip_samples_ * config.bytes_per_frame(); | 459 output_bytes_to_drop_ = skip_samples_ * config.bytes_per_frame(); |
| 464 | 460 |
| 465 uint8 channel_mapping[kMaxVorbisChannels]; | 461 uint8 channel_mapping[kMaxVorbisChannels]; |
| 466 memcpy(&channel_mapping, | 462 memcpy(&channel_mapping, |
| 467 kDefaultOpusChannelLayout, | 463 kDefaultOpusChannelLayout, |
| 468 kMaxChannelsWithDefaultLayout); | 464 kMaxChannelsWithDefaultLayout); |
| 469 | 465 |
| 470 if (channel_count > kMaxChannelsWithDefaultLayout) { | 466 if (channel_count > kMaxChannelsWithDefaultLayout) { |
| 471 RemapOpusChannelLayout(opus_header.stream_map, | 467 RemapOpusChannelLayout( |
| 472 channel_count, | 468 opus_header.stream_map, channel_count, channel_mapping); |
| 473 channel_mapping); | |
| 474 } | 469 } |
| 475 | 470 |
| 476 // Init Opus. | 471 // Init Opus. |
| 477 int status = OPUS_INVALID_STATE; | 472 int status = OPUS_INVALID_STATE; |
| 478 opus_decoder_ = opus_multistream_decoder_create(config.samples_per_second(), | 473 opus_decoder_ = opus_multistream_decoder_create(config.samples_per_second(), |
| 479 channel_count, | 474 channel_count, |
| 480 opus_header.num_streams, | 475 opus_header.num_streams, |
| 481 opus_header.num_coupled, | 476 opus_header.num_coupled, |
| 482 channel_mapping, | 477 channel_mapping, |
| 483 &status); | 478 &status); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 508 void OpusAudioDecoder::ResetTimestampState() { | 503 void OpusAudioDecoder::ResetTimestampState() { |
| 509 output_timestamp_helper_->SetBaseTimestamp(kNoTimestamp()); | 504 output_timestamp_helper_->SetBaseTimestamp(kNoTimestamp()); |
| 510 last_input_timestamp_ = kNoTimestamp(); | 505 last_input_timestamp_ = kNoTimestamp(); |
| 511 output_bytes_to_drop_ = 0; | 506 output_bytes_to_drop_ = 0; |
| 512 } | 507 } |
| 513 | 508 |
| 514 bool OpusAudioDecoder::Decode(const scoped_refptr<DecoderBuffer>& input, | 509 bool OpusAudioDecoder::Decode(const scoped_refptr<DecoderBuffer>& input, |
| 515 scoped_refptr<DataBuffer>* output_buffer) { | 510 scoped_refptr<DataBuffer>* output_buffer) { |
| 516 const int samples_decoded = | 511 const int samples_decoded = |
| 517 opus_multistream_decode(opus_decoder_, | 512 opus_multistream_decode(opus_decoder_, |
| 518 input->GetData(), input->GetDataSize(), | 513 input->data(), |
| 514 input->data_size(), |
| 519 &output_buffer_[0], | 515 &output_buffer_[0], |
| 520 kMaxOpusOutputPacketSizeSamples, | 516 kMaxOpusOutputPacketSizeSamples, |
| 521 0); | 517 0); |
| 522 if (samples_decoded < 0) { | 518 if (samples_decoded < 0) { |
| 523 LOG(ERROR) << "opus_multistream_decode failed for" | 519 LOG(ERROR) << "opus_multistream_decode failed for" |
| 524 << " timestamp: " << input->GetTimestamp().InMicroseconds() | 520 << " timestamp: " << input->timestamp().InMicroseconds() |
| 525 << " us, duration: " << input->GetDuration().InMicroseconds() | 521 << " us, duration: " << input->duration().InMicroseconds() |
| 526 << " us, packet size: " << input->GetDataSize() << " bytes with" | 522 << " us, packet size: " << input->data_size() << " bytes with" |
| 527 << " status: " << opus_strerror(samples_decoded); | 523 << " status: " << opus_strerror(samples_decoded); |
| 528 return false; | 524 return false; |
| 529 } | 525 } |
| 530 | 526 |
| 531 uint8* decoded_audio_data = reinterpret_cast<uint8*>(&output_buffer_[0]); | 527 uint8* decoded_audio_data = reinterpret_cast<uint8*>(&output_buffer_[0]); |
| 532 int decoded_audio_size = samples_decoded * | 528 int decoded_audio_size = |
| 529 samples_decoded * |
| 533 demuxer_stream_->audio_decoder_config().bytes_per_frame(); | 530 demuxer_stream_->audio_decoder_config().bytes_per_frame(); |
| 534 DCHECK_LE(decoded_audio_size, kMaxOpusOutputPacketSizeBytes); | 531 DCHECK_LE(decoded_audio_size, kMaxOpusOutputPacketSizeBytes); |
| 535 | 532 |
| 536 if (output_timestamp_helper_->base_timestamp() == kNoTimestamp() && | 533 if (output_timestamp_helper_->base_timestamp() == kNoTimestamp() && |
| 537 !input->IsEndOfStream()) { | 534 !input->end_of_stream()) { |
| 538 DCHECK(input->GetTimestamp() != kNoTimestamp()); | 535 DCHECK(input->timestamp() != kNoTimestamp()); |
| 539 output_timestamp_helper_->SetBaseTimestamp(input->GetTimestamp()); | 536 output_timestamp_helper_->SetBaseTimestamp(input->timestamp()); |
| 540 } | 537 } |
| 541 | 538 |
| 542 if (decoded_audio_size > 0 && output_bytes_to_drop_ > 0) { | 539 if (decoded_audio_size > 0 && output_bytes_to_drop_ > 0) { |
| 543 int dropped_size = std::min(decoded_audio_size, output_bytes_to_drop_); | 540 int dropped_size = std::min(decoded_audio_size, output_bytes_to_drop_); |
| 544 DCHECK_EQ(dropped_size % kBytesPerChannel, 0); | 541 DCHECK_EQ(dropped_size % kBytesPerChannel, 0); |
| 545 decoded_audio_data += dropped_size; | 542 decoded_audio_data += dropped_size; |
| 546 decoded_audio_size -= dropped_size; | 543 decoded_audio_size -= dropped_size; |
| 547 output_bytes_to_drop_ -= dropped_size; | 544 output_bytes_to_drop_ -= dropped_size; |
| 548 } | 545 } |
| 549 | 546 |
| 550 if (decoded_audio_size > 0) { | 547 if (decoded_audio_size > 0) { |
| 551 // Copy the audio samples into an output buffer. | 548 // Copy the audio samples into an output buffer. |
| 552 *output_buffer = DataBuffer::CopyFrom( | 549 *output_buffer = |
| 553 decoded_audio_data, decoded_audio_size); | 550 DataBuffer::CopyFrom(decoded_audio_data, decoded_audio_size); |
| 554 (*output_buffer)->set_timestamp(output_timestamp_helper_->GetTimestamp()); | 551 (*output_buffer)->set_timestamp(output_timestamp_helper_->GetTimestamp()); |
| 555 (*output_buffer)->set_duration( | 552 (*output_buffer)->set_duration( |
| 556 output_timestamp_helper_->GetDuration(decoded_audio_size)); | 553 output_timestamp_helper_->GetDuration(decoded_audio_size)); |
| 557 output_timestamp_helper_->AddBytes(decoded_audio_size); | 554 output_timestamp_helper_->AddBytes(decoded_audio_size); |
| 558 } | 555 } |
| 559 | 556 |
| 560 // Decoding finished successfully, update statistics. | 557 // Decoding finished successfully, update statistics. |
| 561 PipelineStatistics statistics; | 558 PipelineStatistics statistics; |
| 562 statistics.audio_bytes_decoded = decoded_audio_size; | 559 statistics.audio_bytes_decoded = decoded_audio_size; |
| 563 statistics_cb_.Run(statistics); | 560 statistics_cb_.Run(statistics); |
| 564 | 561 |
| 565 return true; | 562 return true; |
| 566 } | 563 } |
| 567 | 564 |
| 568 } // namespace media | 565 } // namespace media |
| OLD | NEW |