Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(201)

Side by Side Diff: media/filters/opus_audio_decoder.cc

Issue 177333003: Add support for midstream audio configuration changes. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@ABS
Patch Set: Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698