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