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 |