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