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 |