| 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 239 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 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 opus_decoder_(NULL), | 259 opus_decoder_(NULL), |
| 260 channel_layout_(CHANNEL_LAYOUT_NONE), | |
| 261 samples_per_second_(0), | |
| 262 sample_format_(kSampleFormatF32), | |
| 263 bits_per_channel_(SampleFormatToBytesPerChannel(sample_format_) * 8), | |
| 264 last_input_timestamp_(kNoTimestamp()), | 260 last_input_timestamp_(kNoTimestamp()), |
| 265 frames_to_discard_(0), | 261 frames_to_discard_(0), |
| 266 frame_delay_at_start_(0), | 262 frame_delay_at_start_(0), |
| 267 start_input_timestamp_(kNoTimestamp()) { | 263 start_input_timestamp_(kNoTimestamp()) { |
| 268 } | 264 } |
| 269 | 265 |
| 270 void OpusAudioDecoder::Initialize(const AudioDecoderConfig& config, | 266 void OpusAudioDecoder::Initialize(const AudioDecoderConfig& config, |
| 271 const PipelineStatusCB& status_cb) { | 267 const PipelineStatusCB& status_cb) { |
| 272 DCHECK(task_runner_->BelongsToCurrentThread()); | 268 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 273 PipelineStatusCB initialize_cb = BindToCurrentLoop(status_cb); | 269 PipelineStatusCB initialize_cb = BindToCurrentLoop(status_cb); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 284 } | 280 } |
| 285 | 281 |
| 286 void OpusAudioDecoder::Decode(const scoped_refptr<DecoderBuffer>& buffer, | 282 void OpusAudioDecoder::Decode(const scoped_refptr<DecoderBuffer>& buffer, |
| 287 const DecodeCB& decode_cb) { | 283 const DecodeCB& decode_cb) { |
| 288 DCHECK(task_runner_->BelongsToCurrentThread()); | 284 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 289 DCHECK(!decode_cb.is_null()); | 285 DCHECK(!decode_cb.is_null()); |
| 290 | 286 |
| 291 DecodeBuffer(buffer, BindToCurrentLoop(decode_cb)); | 287 DecodeBuffer(buffer, BindToCurrentLoop(decode_cb)); |
| 292 } | 288 } |
| 293 | 289 |
| 294 int OpusAudioDecoder::bits_per_channel() { | |
| 295 DCHECK(task_runner_->BelongsToCurrentThread()); | |
| 296 return bits_per_channel_; | |
| 297 } | |
| 298 | |
| 299 ChannelLayout OpusAudioDecoder::channel_layout() { | |
| 300 DCHECK(task_runner_->BelongsToCurrentThread()); | |
| 301 return channel_layout_; | |
| 302 } | |
| 303 | |
| 304 int OpusAudioDecoder::samples_per_second() { | |
| 305 DCHECK(task_runner_->BelongsToCurrentThread()); | |
| 306 return samples_per_second_; | |
| 307 } | |
| 308 | |
| 309 void OpusAudioDecoder::Reset(const base::Closure& closure) { | 290 void OpusAudioDecoder::Reset(const base::Closure& closure) { |
| 310 DCHECK(task_runner_->BelongsToCurrentThread()); | 291 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 311 | 292 |
| 312 opus_multistream_decoder_ctl(opus_decoder_, OPUS_RESET_STATE); | 293 opus_multistream_decoder_ctl(opus_decoder_, OPUS_RESET_STATE); |
| 313 ResetTimestampState(); | 294 ResetTimestampState(); |
| 314 task_runner_->PostTask(FROM_HERE, closure); | 295 task_runner_->PostTask(FROM_HERE, closure); |
| 315 } | 296 } |
| 316 | 297 |
| 317 void OpusAudioDecoder::Stop(const base::Closure& closure) { | 298 void OpusAudioDecoder::Stop(const base::Closure& closure) { |
| 318 DCHECK(task_runner_->BelongsToCurrentThread()); | 299 DCHECK(task_runner_->BelongsToCurrentThread()); |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 402 << " bits per channel: " << config_.bits_per_channel() | 383 << " bits per channel: " << config_.bits_per_channel() |
| 403 << " samples per second: " << config_.samples_per_second(); | 384 << " samples per second: " << config_.samples_per_second(); |
| 404 return false; | 385 return false; |
| 405 } | 386 } |
| 406 | 387 |
| 407 if (config_.is_encrypted()) { | 388 if (config_.is_encrypted()) { |
| 408 DLOG(ERROR) << "Encrypted audio stream not supported."; | 389 DLOG(ERROR) << "Encrypted audio stream not supported."; |
| 409 return false; | 390 return false; |
| 410 } | 391 } |
| 411 | 392 |
| 412 // TODO(rileya) Remove this check once we properly support midstream audio | |
| 413 // config changes. | |
| 414 if (opus_decoder_ && | |
| 415 (channel_layout_ != config_.channel_layout() || | |
| 416 samples_per_second_ != config_.samples_per_second())) { | |
| 417 DLOG(ERROR) << "Unsupported config change -" | |
| 418 << ", channel_layout: " << channel_layout_ | |
| 419 << " -> " << config_.channel_layout() | |
| 420 << ", sample_rate: " << samples_per_second_ | |
| 421 << " -> " << config_.samples_per_second(); | |
| 422 return false; | |
| 423 } | |
| 424 | |
| 425 // Clean up existing decoder if necessary. | 393 // Clean up existing decoder if necessary. |
| 426 CloseDecoder(); | 394 CloseDecoder(); |
| 427 | 395 |
| 428 // Parse the Opus Extra Data. | 396 // Parse the Opus Extra Data. |
| 429 OpusExtraData opus_extra_data; | 397 OpusExtraData opus_extra_data; |
| 430 if (!ParseOpusExtraData(config_.extra_data(), config_.extra_data_size(), | 398 if (!ParseOpusExtraData(config_.extra_data(), config_.extra_data_size(), |
| 431 config_, | 399 config_, |
| 432 &opus_extra_data)) | 400 &opus_extra_data)) |
| 433 return false; | 401 return false; |
| 434 | 402 |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 474 } | 442 } |
| 475 | 443 |
| 476 status = opus_multistream_decoder_ctl( | 444 status = opus_multistream_decoder_ctl( |
| 477 opus_decoder_, OPUS_SET_GAIN(opus_extra_data.gain_db)); | 445 opus_decoder_, OPUS_SET_GAIN(opus_extra_data.gain_db)); |
| 478 if (status != OPUS_OK) { | 446 if (status != OPUS_OK) { |
| 479 DLOG(ERROR) << "Failed to set OPUS header gain; status=" | 447 DLOG(ERROR) << "Failed to set OPUS header gain; status=" |
| 480 << opus_strerror(status); | 448 << opus_strerror(status); |
| 481 return false; | 449 return false; |
| 482 } | 450 } |
| 483 | 451 |
| 484 channel_layout_ = config_.channel_layout(); | |
| 485 samples_per_second_ = config_.samples_per_second(); | |
| 486 output_timestamp_helper_.reset( | 452 output_timestamp_helper_.reset( |
| 487 new AudioTimestampHelper(config_.samples_per_second())); | 453 new AudioTimestampHelper(config_.samples_per_second())); |
| 488 start_input_timestamp_ = kNoTimestamp(); | 454 start_input_timestamp_ = kNoTimestamp(); |
| 489 return true; | 455 return true; |
| 490 } | 456 } |
| 491 | 457 |
| 492 void OpusAudioDecoder::CloseDecoder() { | 458 void OpusAudioDecoder::CloseDecoder() { |
| 493 if (opus_decoder_) { | 459 if (opus_decoder_) { |
| 494 opus_multistream_decoder_destroy(opus_decoder_); | 460 opus_multistream_decoder_destroy(opus_decoder_); |
| 495 opus_decoder_ = NULL; | 461 opus_decoder_ = NULL; |
| 496 } | 462 } |
| 497 } | 463 } |
| 498 | 464 |
| 499 void OpusAudioDecoder::ResetTimestampState() { | 465 void OpusAudioDecoder::ResetTimestampState() { |
| 500 output_timestamp_helper_->SetBaseTimestamp(kNoTimestamp()); | 466 output_timestamp_helper_->SetBaseTimestamp(kNoTimestamp()); |
| 501 last_input_timestamp_ = kNoTimestamp(); | 467 last_input_timestamp_ = kNoTimestamp(); |
| 502 frames_to_discard_ = | 468 frames_to_discard_ = TimeDeltaToAudioFrames(config_.seek_preroll(), |
| 503 TimeDeltaToAudioFrames(config_.seek_preroll(), samples_per_second_); | 469 config_.samples_per_second()); |
| 504 } | 470 } |
| 505 | 471 |
| 506 bool OpusAudioDecoder::Decode(const scoped_refptr<DecoderBuffer>& input, | 472 bool OpusAudioDecoder::Decode(const scoped_refptr<DecoderBuffer>& input, |
| 507 scoped_refptr<AudioBuffer>* output_buffer) { | 473 scoped_refptr<AudioBuffer>* output_buffer) { |
| 508 // Allocate a buffer for the output samples. | 474 // Allocate a buffer for the output samples. |
| 509 *output_buffer = AudioBuffer::CreateBuffer( | 475 *output_buffer = AudioBuffer::CreateBuffer( |
| 510 sample_format_, | 476 config_.sample_format(), |
| 511 channel_layout_, | 477 config_.channel_layout(), |
| 512 samples_per_second_, | 478 config_.samples_per_second(), |
| 513 kMaxOpusOutputPacketSizeSamples); | 479 kMaxOpusOutputPacketSizeSamples); |
| 514 const int buffer_size = | 480 const int buffer_size = |
| 515 output_buffer->get()->channel_count() * | 481 output_buffer->get()->channel_count() * |
| 516 output_buffer->get()->frame_count() * | 482 output_buffer->get()->frame_count() * |
| 517 SampleFormatToBytesPerChannel(sample_format_); | 483 SampleFormatToBytesPerChannel(config_.sample_format()); |
| 518 | 484 |
| 519 float* float_output_buffer = reinterpret_cast<float*>( | 485 float* float_output_buffer = reinterpret_cast<float*>( |
| 520 output_buffer->get()->channel_data()[0]); | 486 output_buffer->get()->channel_data()[0]); |
| 521 const int frames_decoded = | 487 const int frames_decoded = |
| 522 opus_multistream_decode_float(opus_decoder_, | 488 opus_multistream_decode_float(opus_decoder_, |
| 523 input->data(), | 489 input->data(), |
| 524 input->data_size(), | 490 input->data_size(), |
| 525 float_output_buffer, | 491 float_output_buffer, |
| 526 buffer_size, | 492 buffer_size, |
| 527 0); | 493 0); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 549 | 515 |
| 550 // Handle frame discard and trimming. | 516 // Handle frame discard and trimming. |
| 551 int frames_to_output = frames_decoded; | 517 int frames_to_output = frames_decoded; |
| 552 if (frames_decoded > frames_to_discard_) { | 518 if (frames_decoded > frames_to_discard_) { |
| 553 if (frames_to_discard_ > 0) { | 519 if (frames_to_discard_ > 0) { |
| 554 output_buffer->get()->TrimStart(frames_to_discard_); | 520 output_buffer->get()->TrimStart(frames_to_discard_); |
| 555 frames_to_output -= frames_to_discard_; | 521 frames_to_output -= frames_to_discard_; |
| 556 frames_to_discard_ = 0; | 522 frames_to_discard_ = 0; |
| 557 } | 523 } |
| 558 if (input->discard_padding().InMicroseconds() > 0) { | 524 if (input->discard_padding().InMicroseconds() > 0) { |
| 559 int discard_padding = TimeDeltaToAudioFrames(input->discard_padding(), | 525 int discard_padding = TimeDeltaToAudioFrames( |
| 560 samples_per_second_); | 526 input->discard_padding(), config_.samples_per_second()); |
| 561 if (discard_padding < 0 || discard_padding > frames_to_output) { | 527 if (discard_padding < 0 || discard_padding > frames_to_output) { |
| 562 DVLOG(1) << "Invalid file. Incorrect discard padding value."; | 528 DVLOG(1) << "Invalid file. Incorrect discard padding value."; |
| 563 return false; | 529 return false; |
| 564 } | 530 } |
| 565 output_buffer->get()->TrimEnd(discard_padding); | 531 output_buffer->get()->TrimEnd(discard_padding); |
| 566 frames_to_output -= discard_padding; | 532 frames_to_output -= discard_padding; |
| 567 } | 533 } |
| 568 } else { | 534 } else { |
| 569 frames_to_discard_ -= frames_to_output; | 535 frames_to_discard_ -= frames_to_output; |
| 570 frames_to_output = 0; | 536 frames_to_output = 0; |
| 571 } | 537 } |
| 572 | 538 |
| 573 // Assign timestamp and duration to the buffer. | 539 // Assign timestamp and duration to the buffer. |
| 574 output_buffer->get()->set_timestamp( | 540 output_buffer->get()->set_timestamp( |
| 575 output_timestamp_helper_->GetTimestamp() - timestamp_offset_); | 541 output_timestamp_helper_->GetTimestamp() - timestamp_offset_); |
| 576 output_buffer->get()->set_duration( | 542 output_buffer->get()->set_duration( |
| 577 output_timestamp_helper_->GetFrameDuration(frames_to_output)); | 543 output_timestamp_helper_->GetFrameDuration(frames_to_output)); |
| 578 output_timestamp_helper_->AddFrames(frames_decoded); | 544 output_timestamp_helper_->AddFrames(frames_decoded); |
| 579 | 545 |
| 580 // Discard the buffer to indicate we need more data. | 546 // Discard the buffer to indicate we need more data. |
| 581 if (!frames_to_output) | 547 if (!frames_to_output) |
| 582 *output_buffer = NULL; | 548 *output_buffer = NULL; |
| 583 | 549 |
| 584 return true; | 550 return true; |
| 585 } | 551 } |
| 586 | 552 |
| 587 } // namespace media | 553 } // namespace media |
| OLD | NEW |