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

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: add Reset() tests. Only enable ABC in MSE case. 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/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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698