| 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 238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 249 | 249 |
| 250 for (int i = 0; i < extra_data->channels; ++i) | 250 for (int i = 0; i < extra_data->channels; ++i) |
| 251 extra_data->stream_map[i] = *(data + kOpusExtraDataStreamMapOffset + i); | 251 extra_data->stream_map[i] = *(data + kOpusExtraDataStreamMapOffset + i); |
| 252 return true; | 252 return true; |
| 253 } | 253 } |
| 254 | 254 |
| 255 OpusAudioDecoder::OpusAudioDecoder( | 255 OpusAudioDecoder::OpusAudioDecoder( |
| 256 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) | 256 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) |
| 257 : task_runner_(task_runner), | 257 : task_runner_(task_runner), |
| 258 weak_factory_(this), | 258 weak_factory_(this), |
| 259 demuxer_stream_(NULL), | |
| 260 opus_decoder_(NULL), | 259 opus_decoder_(NULL), |
| 261 channel_layout_(CHANNEL_LAYOUT_NONE), | 260 channel_layout_(CHANNEL_LAYOUT_NONE), |
| 262 samples_per_second_(0), | 261 samples_per_second_(0), |
| 263 sample_format_(kSampleFormatF32), | 262 sample_format_(kSampleFormatF32), |
| 264 bits_per_channel_(SampleFormatToBytesPerChannel(sample_format_) * 8), | 263 bits_per_channel_(SampleFormatToBytesPerChannel(sample_format_) * 8), |
| 265 last_input_timestamp_(kNoTimestamp()), | 264 last_input_timestamp_(kNoTimestamp()), |
| 266 frames_to_discard_(0), | 265 frames_to_discard_(0), |
| 267 frame_delay_at_start_(0), | 266 frame_delay_at_start_(0), |
| 268 start_input_timestamp_(kNoTimestamp()) { | 267 start_input_timestamp_(kNoTimestamp()) { |
| 269 } | 268 } |
| 270 | 269 |
| 271 void OpusAudioDecoder::Initialize( | 270 void OpusAudioDecoder::Initialize(const AudioDecoderConfig& config, |
| 272 DemuxerStream* stream, | 271 const PipelineStatusCB& status_cb) { |
| 273 const PipelineStatusCB& status_cb, | |
| 274 const StatisticsCB& statistics_cb) { | |
| 275 DCHECK(task_runner_->BelongsToCurrentThread()); | 272 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 276 PipelineStatusCB initialize_cb = BindToCurrentLoop(status_cb); | 273 PipelineStatusCB initialize_cb = BindToCurrentLoop(status_cb); |
| 277 | 274 |
| 278 if (demuxer_stream_) { | |
| 279 // TODO(scherkus): initialization currently happens more than once in | |
| 280 // PipelineIntegrationTest.BasicPlayback. | |
| 281 DLOG(ERROR) << "Initialize has already been called."; | |
| 282 CHECK(false); | |
| 283 } | |
| 284 | |
| 285 weak_this_ = weak_factory_.GetWeakPtr(); | 275 weak_this_ = weak_factory_.GetWeakPtr(); |
| 286 demuxer_stream_ = stream; | 276 config_ = config; |
| 287 | 277 |
| 288 if (!ConfigureDecoder()) { | 278 if (!ConfigureDecoder()) { |
| 289 initialize_cb.Run(DECODER_ERROR_NOT_SUPPORTED); | 279 initialize_cb.Run(DECODER_ERROR_NOT_SUPPORTED); |
| 290 return; | 280 return; |
| 291 } | 281 } |
| 292 | 282 |
| 293 statistics_cb_ = statistics_cb; | |
| 294 initialize_cb.Run(PIPELINE_OK); | 283 initialize_cb.Run(PIPELINE_OK); |
| 295 } | 284 } |
| 296 | 285 |
| 297 void OpusAudioDecoder::Read(const ReadCB& read_cb) { | 286 void OpusAudioDecoder::Decode(const scoped_refptr<DecoderBuffer>& buffer, |
| 287 const DecodeCB& decode_cb) { |
| 298 DCHECK(task_runner_->BelongsToCurrentThread()); | 288 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 299 DCHECK(!read_cb.is_null()); | 289 DCHECK(!decode_cb.is_null()); |
| 300 CHECK(read_cb_.is_null()) << "Overlapping decodes are not supported."; | |
| 301 DCHECK(stop_cb_.is_null()); | |
| 302 read_cb_ = BindToCurrentLoop(read_cb); | |
| 303 | 290 |
| 304 ReadFromDemuxerStream(); | 291 DecodeBuffer(buffer, BindToCurrentLoop(decode_cb)); |
| 305 } | 292 } |
| 306 | 293 |
| 307 int OpusAudioDecoder::bits_per_channel() { | 294 int OpusAudioDecoder::bits_per_channel() { |
| 308 DCHECK(task_runner_->BelongsToCurrentThread()); | 295 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 309 return bits_per_channel_; | 296 return bits_per_channel_; |
| 310 } | 297 } |
| 311 | 298 |
| 312 ChannelLayout OpusAudioDecoder::channel_layout() { | 299 ChannelLayout OpusAudioDecoder::channel_layout() { |
| 313 DCHECK(task_runner_->BelongsToCurrentThread()); | 300 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 314 return channel_layout_; | 301 return channel_layout_; |
| 315 } | 302 } |
| 316 | 303 |
| 317 int OpusAudioDecoder::samples_per_second() { | 304 int OpusAudioDecoder::samples_per_second() { |
| 318 DCHECK(task_runner_->BelongsToCurrentThread()); | 305 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 319 return samples_per_second_; | 306 return samples_per_second_; |
| 320 } | 307 } |
| 321 | 308 |
| 322 void OpusAudioDecoder::Reset(const base::Closure& closure) { | 309 void OpusAudioDecoder::Reset(const base::Closure& closure) { |
| 323 DCHECK(task_runner_->BelongsToCurrentThread()); | 310 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 324 reset_cb_ = BindToCurrentLoop(closure); | |
| 325 | 311 |
| 326 // A demuxer read is pending, we'll wait until it finishes. | 312 opus_multistream_decoder_ctl(opus_decoder_, OPUS_RESET_STATE); |
| 327 if (!read_cb_.is_null()) | 313 ResetTimestampState(); |
| 328 return; | 314 task_runner_->PostTask(FROM_HERE, closure); |
| 329 | |
| 330 DoReset(); | |
| 331 } | 315 } |
| 332 | 316 |
| 333 void OpusAudioDecoder::Stop(const base::Closure& closure) { | 317 void OpusAudioDecoder::Stop(const base::Closure& closure) { |
| 334 DCHECK(task_runner_->BelongsToCurrentThread()); | 318 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 335 stop_cb_ = BindToCurrentLoop(closure); | |
| 336 | 319 |
| 337 // A demuxer read is pending, we'll wait until it finishes. | 320 opus_multistream_decoder_ctl(opus_decoder_, OPUS_RESET_STATE); |
| 338 if (!read_cb_.is_null()) | 321 ResetTimestampState(); |
| 339 return; | 322 CloseDecoder(); |
| 340 | 323 task_runner_->PostTask(FROM_HERE, closure); |
| 341 if (!reset_cb_.is_null()) { | |
| 342 DoReset(); | |
| 343 return; | |
| 344 } | |
| 345 | |
| 346 DoStop(); | |
| 347 } | 324 } |
| 348 | 325 |
| 349 OpusAudioDecoder::~OpusAudioDecoder() {} | 326 OpusAudioDecoder::~OpusAudioDecoder() {} |
| 350 | 327 |
| 351 void OpusAudioDecoder::DoReset() { | 328 void OpusAudioDecoder::DecodeBuffer( |
| 352 DCHECK(!reset_cb_.is_null()); | 329 const scoped_refptr<DecoderBuffer>& input, |
| 330 const DecodeCB& decode_cb) { |
| 331 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 332 DCHECK(!decode_cb.is_null()); |
| 353 | 333 |
| 354 opus_multistream_decoder_ctl(opus_decoder_, OPUS_RESET_STATE); | |
| 355 ResetTimestampState(); | |
| 356 base::ResetAndReturn(&reset_cb_).Run(); | |
| 357 | |
| 358 if (!stop_cb_.is_null()) | |
| 359 DoStop(); | |
| 360 } | |
| 361 | |
| 362 void OpusAudioDecoder::DoStop() { | |
| 363 DCHECK(!stop_cb_.is_null()); | |
| 364 | |
| 365 opus_multistream_decoder_ctl(opus_decoder_, OPUS_RESET_STATE); | |
| 366 ResetTimestampState(); | |
| 367 CloseDecoder(); | |
| 368 base::ResetAndReturn(&stop_cb_).Run(); | |
| 369 } | |
| 370 | |
| 371 void OpusAudioDecoder::ReadFromDemuxerStream() { | |
| 372 DCHECK(!read_cb_.is_null()); | |
| 373 demuxer_stream_->Read(base::Bind(&OpusAudioDecoder::BufferReady, weak_this_)); | |
| 374 } | |
| 375 | |
| 376 void OpusAudioDecoder::BufferReady( | |
| 377 DemuxerStream::Status status, | |
| 378 const scoped_refptr<DecoderBuffer>& input) { | |
| 379 DCHECK(task_runner_->BelongsToCurrentThread()); | |
| 380 DCHECK(!read_cb_.is_null()); | |
| 381 DCHECK_EQ(status != DemuxerStream::kOk, !input.get()) << status; | |
| 382 | |
| 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) { | |
| 400 DCHECK(!input.get()); | |
| 401 base::ResetAndReturn(&read_cb_).Run(kAborted, NULL); | |
| 402 return; | |
| 403 } | |
| 404 | |
| 405 if (status == DemuxerStream::kConfigChanged) { | |
| 406 DCHECK(!input.get()); | |
| 407 DVLOG(1) << "Config changed."; | |
| 408 | |
| 409 if (!ConfigureDecoder()) { | |
| 410 base::ResetAndReturn(&read_cb_).Run(kDecodeError, NULL); | |
| 411 return; | |
| 412 } | |
| 413 | |
| 414 ResetTimestampState(); | |
| 415 ReadFromDemuxerStream(); | |
| 416 return; | |
| 417 } | |
| 418 | |
| 419 DCHECK_EQ(status, DemuxerStream::kOk); | |
| 420 DCHECK(input.get()); | 334 DCHECK(input.get()); |
| 421 | 335 |
| 422 // Libopus does not buffer output. Decoding is complete when an end of stream | 336 // Libopus does not buffer output. Decoding is complete when an end of stream |
| 423 // input buffer is received. | 337 // input buffer is received. |
| 424 if (input->end_of_stream()) { | 338 if (input->end_of_stream()) { |
| 425 base::ResetAndReturn(&read_cb_).Run(kOk, AudioBuffer::CreateEOSBuffer()); | 339 decode_cb.Run(kOk, AudioBuffer::CreateEOSBuffer()); |
| 426 return; | 340 return; |
| 427 } | 341 } |
| 428 | 342 |
| 429 // Make sure we are notified if http://crbug.com/49709 returns. Issue also | 343 // Make sure we are notified if http://crbug.com/49709 returns. Issue also |
| 430 // occurs with some damaged files. | 344 // occurs with some damaged files. |
| 431 if (input->timestamp() == kNoTimestamp() && | 345 if (input->timestamp() == kNoTimestamp() && |
| 432 output_timestamp_helper_->base_timestamp() == kNoTimestamp()) { | 346 output_timestamp_helper_->base_timestamp() == kNoTimestamp()) { |
| 433 DLOG(ERROR) << "Received a buffer without timestamps!"; | 347 DLOG(ERROR) << "Received a buffer without timestamps!"; |
| 434 base::ResetAndReturn(&read_cb_).Run(kDecodeError, NULL); | 348 decode_cb.Run(kDecodeError, NULL); |
| 435 return; | 349 return; |
| 436 } | 350 } |
| 437 | 351 |
| 438 if (last_input_timestamp_ != kNoTimestamp() && | 352 if (last_input_timestamp_ != kNoTimestamp() && |
| 439 input->timestamp() != kNoTimestamp() && | 353 input->timestamp() != kNoTimestamp() && |
| 440 input->timestamp() < last_input_timestamp_) { | 354 input->timestamp() < last_input_timestamp_) { |
| 441 base::TimeDelta diff = input->timestamp() - last_input_timestamp_; | 355 base::TimeDelta diff = input->timestamp() - last_input_timestamp_; |
| 442 DLOG(ERROR) << "Input timestamps are not monotonically increasing! " | 356 DLOG(ERROR) << "Input timestamps are not monotonically increasing! " |
| 443 << " ts " << input->timestamp().InMicroseconds() << " us" | 357 << " ts " << input->timestamp().InMicroseconds() << " us" |
| 444 << " diff " << diff.InMicroseconds() << " us"; | 358 << " diff " << diff.InMicroseconds() << " us"; |
| 445 base::ResetAndReturn(&read_cb_).Run(kDecodeError, NULL); | 359 decode_cb.Run(kDecodeError, NULL); |
| 446 return; | 360 return; |
| 447 } | 361 } |
| 448 | 362 |
| 449 // Apply the necessary codec delay. | 363 // Apply the necessary codec delay. |
| 450 if (start_input_timestamp_ == kNoTimestamp()) | 364 if (start_input_timestamp_ == kNoTimestamp()) |
| 451 start_input_timestamp_ = input->timestamp(); | 365 start_input_timestamp_ = input->timestamp(); |
| 452 if (last_input_timestamp_ == kNoTimestamp() && | 366 if (last_input_timestamp_ == kNoTimestamp() && |
| 453 input->timestamp() == start_input_timestamp_) { | 367 input->timestamp() == start_input_timestamp_) { |
| 454 frames_to_discard_ = frame_delay_at_start_; | 368 frames_to_discard_ = frame_delay_at_start_; |
| 455 } | 369 } |
| 456 | 370 |
| 457 last_input_timestamp_ = input->timestamp(); | 371 last_input_timestamp_ = input->timestamp(); |
| 458 | 372 |
| 459 scoped_refptr<AudioBuffer> output_buffer; | 373 scoped_refptr<AudioBuffer> output_buffer; |
| 460 | 374 |
| 461 if (!Decode(input, &output_buffer)) { | 375 if (!Decode(input, &output_buffer)) { |
| 462 base::ResetAndReturn(&read_cb_).Run(kDecodeError, NULL); | 376 decode_cb.Run(kDecodeError, NULL); |
| 463 return; | 377 return; |
| 464 } | 378 } |
| 465 | 379 |
| 466 if (output_buffer.get()) { | 380 if (output_buffer.get()) { |
| 467 // Execute callback to return the decoded audio. | 381 // Execute callback to return the decoded audio. |
| 468 base::ResetAndReturn(&read_cb_).Run(kOk, output_buffer); | 382 decode_cb.Run(kOk, output_buffer); |
| 469 } else { | 383 } else { |
| 470 // We exhausted the input data, but it wasn't enough for a frame. Ask for | 384 // We exhausted the input data, but it wasn't enough for a frame. |
| 471 // more data in order to fulfill this read. | 385 decode_cb.Run(kNotEnoughData, NULL); |
| 472 ReadFromDemuxerStream(); | |
| 473 } | 386 } |
| 474 } | 387 } |
| 475 | 388 |
| 476 bool OpusAudioDecoder::ConfigureDecoder() { | 389 bool OpusAudioDecoder::ConfigureDecoder() { |
| 477 const AudioDecoderConfig& config = demuxer_stream_->audio_decoder_config(); | 390 if (config_.codec() != kCodecOpus) { |
| 478 | |
| 479 if (config.codec() != kCodecOpus) { | |
| 480 DVLOG(1) << "Codec must be kCodecOpus."; | 391 DVLOG(1) << "Codec must be kCodecOpus."; |
| 481 return false; | 392 return false; |
| 482 } | 393 } |
| 483 | 394 |
| 484 const int channel_count = | 395 const int channel_count = |
| 485 ChannelLayoutToChannelCount(config.channel_layout()); | 396 ChannelLayoutToChannelCount(config_.channel_layout()); |
| 486 if (!config.IsValidConfig() || channel_count > kMaxVorbisChannels) { | 397 if (!config_.IsValidConfig() || channel_count > kMaxVorbisChannels) { |
| 487 DLOG(ERROR) << "Invalid or unsupported audio stream -" | 398 DLOG(ERROR) << "Invalid or unsupported audio stream -" |
| 488 << " codec: " << config.codec() | 399 << " codec: " << config_.codec() |
| 489 << " channel count: " << channel_count | 400 << " channel count: " << channel_count |
| 490 << " channel layout: " << config.channel_layout() | 401 << " channel layout: " << config_.channel_layout() |
| 491 << " bits per channel: " << config.bits_per_channel() | 402 << " bits per channel: " << config_.bits_per_channel() |
| 492 << " samples per second: " << config.samples_per_second(); | 403 << " samples per second: " << config_.samples_per_second(); |
| 493 return false; | 404 return false; |
| 494 } | 405 } |
| 495 | 406 |
| 496 if (config.is_encrypted()) { | 407 if (config_.is_encrypted()) { |
| 497 DLOG(ERROR) << "Encrypted audio stream not supported."; | 408 DLOG(ERROR) << "Encrypted audio stream not supported."; |
| 498 return false; | 409 return false; |
| 499 } | 410 } |
| 500 | 411 |
| 412 // TODO(rileya) Remove this check once we properly support midstream audio |
| 413 // config changes. |
| 501 if (opus_decoder_ && | 414 if (opus_decoder_ && |
| 502 (channel_layout_ != config.channel_layout() || | 415 (channel_layout_ != config_.channel_layout() || |
| 503 samples_per_second_ != config.samples_per_second())) { | 416 samples_per_second_ != config_.samples_per_second())) { |
| 504 DLOG(ERROR) << "Unsupported config change -" | 417 DLOG(ERROR) << "Unsupported config change -" |
| 505 << ", channel_layout: " << channel_layout_ | 418 << ", channel_layout: " << channel_layout_ |
| 506 << " -> " << config.channel_layout() | 419 << " -> " << config_.channel_layout() |
| 507 << ", sample_rate: " << samples_per_second_ | 420 << ", sample_rate: " << samples_per_second_ |
| 508 << " -> " << config.samples_per_second(); | 421 << " -> " << config_.samples_per_second(); |
| 509 return false; | 422 return false; |
| 510 } | 423 } |
| 511 | 424 |
| 512 // Clean up existing decoder if necessary. | 425 // Clean up existing decoder if necessary. |
| 513 CloseDecoder(); | 426 CloseDecoder(); |
| 514 | 427 |
| 515 // Parse the Opus Extra Data. | 428 // Parse the Opus Extra Data. |
| 516 OpusExtraData opus_extra_data; | 429 OpusExtraData opus_extra_data; |
| 517 if (!ParseOpusExtraData(config.extra_data(), config.extra_data_size(), | 430 if (!ParseOpusExtraData(config_.extra_data(), config_.extra_data_size(), |
| 518 config, | 431 config_, |
| 519 &opus_extra_data)) | 432 &opus_extra_data)) |
| 520 return false; | 433 return false; |
| 521 | 434 |
| 522 // Convert from seconds to samples. | 435 // Convert from seconds to samples. |
| 523 timestamp_offset_ = config.codec_delay(); | 436 timestamp_offset_ = config_.codec_delay(); |
| 524 frame_delay_at_start_ = TimeDeltaToAudioFrames(config.codec_delay(), | 437 frame_delay_at_start_ = TimeDeltaToAudioFrames(config_.codec_delay(), |
| 525 config.samples_per_second()); | 438 config_.samples_per_second()); |
| 526 if (timestamp_offset_ <= base::TimeDelta() || frame_delay_at_start_ < 0) { | 439 if (timestamp_offset_ <= base::TimeDelta() || frame_delay_at_start_ < 0) { |
| 527 DLOG(ERROR) << "Invalid file. Incorrect value for codec delay: " | 440 DLOG(ERROR) << "Invalid file. Incorrect value for codec delay: " |
| 528 << config.codec_delay().InMicroseconds(); | 441 << config_.codec_delay().InMicroseconds(); |
| 529 return false; | 442 return false; |
| 530 } | 443 } |
| 531 | 444 |
| 532 if (frame_delay_at_start_ != opus_extra_data.skip_samples) { | 445 if (frame_delay_at_start_ != opus_extra_data.skip_samples) { |
| 533 DLOG(ERROR) << "Invalid file. Codec Delay in container does not match the " | 446 DLOG(ERROR) << "Invalid file. Codec Delay in container does not match the " |
| 534 << "value in Opus Extra Data."; | 447 << "value in Opus Extra Data."; |
| 535 return false; | 448 return false; |
| 536 } | 449 } |
| 537 | 450 |
| 538 uint8 channel_mapping[kMaxVorbisChannels] = {0}; | 451 uint8 channel_mapping[kMaxVorbisChannels] = {0}; |
| 539 memcpy(&channel_mapping, | 452 memcpy(&channel_mapping, |
| 540 kDefaultOpusChannelLayout, | 453 kDefaultOpusChannelLayout, |
| 541 kMaxChannelsWithDefaultLayout); | 454 kMaxChannelsWithDefaultLayout); |
| 542 | 455 |
| 543 if (channel_count > kMaxChannelsWithDefaultLayout) { | 456 if (channel_count > kMaxChannelsWithDefaultLayout) { |
| 544 RemapOpusChannelLayout(opus_extra_data.stream_map, | 457 RemapOpusChannelLayout(opus_extra_data.stream_map, |
| 545 channel_count, | 458 channel_count, |
| 546 channel_mapping); | 459 channel_mapping); |
| 547 } | 460 } |
| 548 | 461 |
| 549 // Init Opus. | 462 // Init Opus. |
| 550 int status = OPUS_INVALID_STATE; | 463 int status = OPUS_INVALID_STATE; |
| 551 opus_decoder_ = opus_multistream_decoder_create(config.samples_per_second(), | 464 opus_decoder_ = opus_multistream_decoder_create(config_.samples_per_second(), |
| 552 channel_count, | 465 channel_count, |
| 553 opus_extra_data.num_streams, | 466 opus_extra_data.num_streams, |
| 554 opus_extra_data.num_coupled, | 467 opus_extra_data.num_coupled, |
| 555 channel_mapping, | 468 channel_mapping, |
| 556 &status); | 469 &status); |
| 557 if (!opus_decoder_ || status != OPUS_OK) { | 470 if (!opus_decoder_ || status != OPUS_OK) { |
| 558 DLOG(ERROR) << "opus_multistream_decoder_create failed status=" | 471 DLOG(ERROR) << "opus_multistream_decoder_create failed status=" |
| 559 << opus_strerror(status); | 472 << opus_strerror(status); |
| 560 return false; | 473 return false; |
| 561 } | 474 } |
| 562 | 475 |
| 563 status = opus_multistream_decoder_ctl( | 476 status = opus_multistream_decoder_ctl( |
| 564 opus_decoder_, OPUS_SET_GAIN(opus_extra_data.gain_db)); | 477 opus_decoder_, OPUS_SET_GAIN(opus_extra_data.gain_db)); |
| 565 if (status != OPUS_OK) { | 478 if (status != OPUS_OK) { |
| 566 DLOG(ERROR) << "Failed to set OPUS header gain; status=" | 479 DLOG(ERROR) << "Failed to set OPUS header gain; status=" |
| 567 << opus_strerror(status); | 480 << opus_strerror(status); |
| 568 return false; | 481 return false; |
| 569 } | 482 } |
| 570 | 483 |
| 571 channel_layout_ = config.channel_layout(); | 484 channel_layout_ = config_.channel_layout(); |
| 572 samples_per_second_ = config.samples_per_second(); | 485 samples_per_second_ = config_.samples_per_second(); |
| 573 output_timestamp_helper_.reset( | 486 output_timestamp_helper_.reset( |
| 574 new AudioTimestampHelper(config.samples_per_second())); | 487 new AudioTimestampHelper(config_.samples_per_second())); |
| 575 start_input_timestamp_ = kNoTimestamp(); | 488 start_input_timestamp_ = kNoTimestamp(); |
| 576 return true; | 489 return true; |
| 577 } | 490 } |
| 578 | 491 |
| 579 void OpusAudioDecoder::CloseDecoder() { | 492 void OpusAudioDecoder::CloseDecoder() { |
| 580 if (opus_decoder_) { | 493 if (opus_decoder_) { |
| 581 opus_multistream_decoder_destroy(opus_decoder_); | 494 opus_multistream_decoder_destroy(opus_decoder_); |
| 582 opus_decoder_ = NULL; | 495 opus_decoder_ = NULL; |
| 583 } | 496 } |
| 584 } | 497 } |
| 585 | 498 |
| 586 void OpusAudioDecoder::ResetTimestampState() { | 499 void OpusAudioDecoder::ResetTimestampState() { |
| 587 output_timestamp_helper_->SetBaseTimestamp(kNoTimestamp()); | 500 output_timestamp_helper_->SetBaseTimestamp(kNoTimestamp()); |
| 588 last_input_timestamp_ = kNoTimestamp(); | 501 last_input_timestamp_ = kNoTimestamp(); |
| 589 frames_to_discard_ = TimeDeltaToAudioFrames( | 502 frames_to_discard_ = |
| 590 demuxer_stream_->audio_decoder_config().seek_preroll(), | 503 TimeDeltaToAudioFrames(config_.seek_preroll(), samples_per_second_); |
| 591 samples_per_second_); | |
| 592 } | 504 } |
| 593 | 505 |
| 594 bool OpusAudioDecoder::Decode(const scoped_refptr<DecoderBuffer>& input, | 506 bool OpusAudioDecoder::Decode(const scoped_refptr<DecoderBuffer>& input, |
| 595 scoped_refptr<AudioBuffer>* output_buffer) { | 507 scoped_refptr<AudioBuffer>* output_buffer) { |
| 596 // Allocate a buffer for the output samples. | 508 // Allocate a buffer for the output samples. |
| 597 *output_buffer = AudioBuffer::CreateBuffer( | 509 *output_buffer = AudioBuffer::CreateBuffer( |
| 598 sample_format_, | 510 sample_format_, |
| 599 ChannelLayoutToChannelCount(channel_layout_), | 511 ChannelLayoutToChannelCount(channel_layout_), |
| 600 kMaxOpusOutputPacketSizeSamples); | 512 kMaxOpusOutputPacketSizeSamples); |
| 601 const int buffer_size = | 513 const int buffer_size = |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 650 return false; | 562 return false; |
| 651 } | 563 } |
| 652 output_buffer->get()->TrimEnd(discard_padding); | 564 output_buffer->get()->TrimEnd(discard_padding); |
| 653 frames_to_output -= discard_padding; | 565 frames_to_output -= discard_padding; |
| 654 } | 566 } |
| 655 } else { | 567 } else { |
| 656 frames_to_discard_ -= frames_to_output; | 568 frames_to_discard_ -= frames_to_output; |
| 657 frames_to_output = 0; | 569 frames_to_output = 0; |
| 658 } | 570 } |
| 659 | 571 |
| 660 // Decoding finished successfully, update statistics. | |
| 661 PipelineStatistics statistics; | |
| 662 statistics.audio_bytes_decoded = input->data_size(); | |
| 663 statistics_cb_.Run(statistics); | |
| 664 | |
| 665 // Assign timestamp and duration to the buffer. | 572 // Assign timestamp and duration to the buffer. |
| 666 output_buffer->get()->set_timestamp( | 573 output_buffer->get()->set_timestamp( |
| 667 output_timestamp_helper_->GetTimestamp() - timestamp_offset_); | 574 output_timestamp_helper_->GetTimestamp() - timestamp_offset_); |
| 668 output_buffer->get()->set_duration( | 575 output_buffer->get()->set_duration( |
| 669 output_timestamp_helper_->GetFrameDuration(frames_to_output)); | 576 output_timestamp_helper_->GetFrameDuration(frames_to_output)); |
| 670 output_timestamp_helper_->AddFrames(frames_decoded); | 577 output_timestamp_helper_->AddFrames(frames_decoded); |
| 671 | 578 |
| 672 // Discard the buffer to indicate we need more data. | 579 // Discard the buffer to indicate we need more data. |
| 673 if (!frames_to_output) | 580 if (!frames_to_output) |
| 674 *output_buffer = NULL; | 581 *output_buffer = NULL; |
| 675 | 582 |
| 676 return true; | 583 return true; |
| 677 } | 584 } |
| 678 | 585 |
| 679 } // namespace media | 586 } // namespace media |
| OLD | NEW |