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 238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
249 | 249 |
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 demuxer_stream_(NULL), | |
260 opus_decoder_(NULL), | 259 opus_decoder_(NULL), |
261 channel_layout_(CHANNEL_LAYOUT_NONE), | 260 channel_layout_(CHANNEL_LAYOUT_NONE), |
262 samples_per_second_(0), | 261 samples_per_second_(0), |
263 sample_format_(kSampleFormatF32), | 262 sample_format_(kSampleFormatF32), |
264 bits_per_channel_(SampleFormatToBytesPerChannel(sample_format_) * 8), | 263 bits_per_channel_(SampleFormatToBytesPerChannel(sample_format_) * 8), |
265 last_input_timestamp_(kNoTimestamp()), | 264 last_input_timestamp_(kNoTimestamp()), |
266 frames_to_discard_(0), | 265 frames_to_discard_(0), |
267 frame_delay_at_start_(0), | 266 frame_delay_at_start_(0), |
268 start_input_timestamp_(kNoTimestamp()) { | 267 start_input_timestamp_(kNoTimestamp()) { |
269 } | 268 } |
270 | 269 |
271 void OpusAudioDecoder::Initialize( | 270 void OpusAudioDecoder::Initialize(const AudioDecoderConfig& config, |
272 DemuxerStream* stream, | 271 const PipelineStatusCB& status_cb) { |
273 const PipelineStatusCB& status_cb, | |
274 const StatisticsCB& statistics_cb) { | |
275 DCHECK(task_runner_->BelongsToCurrentThread()); | 272 DCHECK(task_runner_->BelongsToCurrentThread()); |
276 PipelineStatusCB initialize_cb = BindToCurrentLoop(status_cb); | 273 PipelineStatusCB initialize_cb = BindToCurrentLoop(status_cb); |
277 | 274 |
278 if (demuxer_stream_) { | 275 // TODO reinitialization |
279 // TODO(scherkus): initialization currently happens more than once in | |
280 // PipelineIntegrationTest.BasicPlayback. | |
281 DLOG(ERROR) << "Initialize has already been called."; | |
282 CHECK(false); | |
283 } | |
284 | 276 |
285 weak_this_ = weak_factory_.GetWeakPtr(); | 277 weak_this_ = weak_factory_.GetWeakPtr(); |
286 demuxer_stream_ = stream; | 278 config_ = config; |
287 | 279 |
288 if (!ConfigureDecoder()) { | 280 if (!ConfigureDecoder()) { |
289 initialize_cb.Run(DECODER_ERROR_NOT_SUPPORTED); | 281 initialize_cb.Run(DECODER_ERROR_NOT_SUPPORTED); |
290 return; | 282 return; |
291 } | 283 } |
292 | 284 |
293 statistics_cb_ = statistics_cb; | |
294 initialize_cb.Run(PIPELINE_OK); | 285 initialize_cb.Run(PIPELINE_OK); |
295 } | 286 } |
296 | 287 |
297 void OpusAudioDecoder::Read(const ReadCB& read_cb) { | 288 void OpusAudioDecoder::Decode(const scoped_refptr<DecoderBuffer>& buffer, |
| 289 const DecodeCB& decode_cb) { |
298 DCHECK(task_runner_->BelongsToCurrentThread()); | 290 DCHECK(task_runner_->BelongsToCurrentThread()); |
299 DCHECK(!read_cb.is_null()); | 291 DCHECK(!decode_cb.is_null()); |
300 CHECK(read_cb_.is_null()) << "Overlapping decodes are not supported."; | 292 CHECK(decode_cb_.is_null()) << "Overlapping decodes are not supported."; |
301 DCHECK(stop_cb_.is_null()); | 293 DCHECK(stop_cb_.is_null()); |
302 read_cb_ = BindToCurrentLoop(read_cb); | 294 decode_cb_ = BindToCurrentLoop(decode_cb); |
303 | 295 |
304 ReadFromDemuxerStream(); | 296 DecodeBuffer(buffer); |
305 } | 297 } |
306 | 298 |
307 int OpusAudioDecoder::bits_per_channel() { | 299 int OpusAudioDecoder::bits_per_channel() { |
308 DCHECK(task_runner_->BelongsToCurrentThread()); | 300 DCHECK(task_runner_->BelongsToCurrentThread()); |
309 return bits_per_channel_; | 301 return bits_per_channel_; |
310 } | 302 } |
311 | 303 |
312 ChannelLayout OpusAudioDecoder::channel_layout() { | 304 ChannelLayout OpusAudioDecoder::channel_layout() { |
313 DCHECK(task_runner_->BelongsToCurrentThread()); | 305 DCHECK(task_runner_->BelongsToCurrentThread()); |
314 return channel_layout_; | 306 return channel_layout_; |
315 } | 307 } |
316 | 308 |
317 int OpusAudioDecoder::samples_per_second() { | 309 int OpusAudioDecoder::samples_per_second() { |
318 DCHECK(task_runner_->BelongsToCurrentThread()); | 310 DCHECK(task_runner_->BelongsToCurrentThread()); |
319 return samples_per_second_; | 311 return samples_per_second_; |
320 } | 312 } |
321 | 313 |
322 void OpusAudioDecoder::Reset(const base::Closure& closure) { | 314 void OpusAudioDecoder::Reset(const base::Closure& closure) { |
323 DCHECK(task_runner_->BelongsToCurrentThread()); | 315 DCHECK(task_runner_->BelongsToCurrentThread()); |
324 reset_cb_ = BindToCurrentLoop(closure); | 316 reset_cb_ = BindToCurrentLoop(closure); |
325 | 317 |
326 // A demuxer read is pending, we'll wait until it finishes. | 318 // A decode is pending, we'll wait until it finishes. |
327 if (!read_cb_.is_null()) | 319 if (!decode_cb_.is_null()) |
328 return; | 320 return; |
329 | 321 |
330 DoReset(); | 322 DoReset(); |
331 } | 323 } |
332 | 324 |
333 void OpusAudioDecoder::Stop(const base::Closure& closure) { | 325 void OpusAudioDecoder::Stop(const base::Closure& closure) { |
334 DCHECK(task_runner_->BelongsToCurrentThread()); | 326 DCHECK(task_runner_->BelongsToCurrentThread()); |
335 stop_cb_ = BindToCurrentLoop(closure); | 327 stop_cb_ = BindToCurrentLoop(closure); |
336 | 328 |
337 // A demuxer read is pending, we'll wait until it finishes. | 329 // A demuxer read is pending, we'll wait until it finishes. |
338 if (!read_cb_.is_null()) | 330 if (!decode_cb_.is_null()) |
339 return; | 331 return; |
340 | 332 |
341 if (!reset_cb_.is_null()) { | 333 if (!reset_cb_.is_null()) { |
342 DoReset(); | 334 DoReset(); |
343 return; | 335 return; |
344 } | 336 } |
345 | 337 |
346 DoStop(); | 338 DoStop(); |
347 } | 339 } |
348 | 340 |
(...skipping 12 matching lines...) Expand all Loading... |
361 | 353 |
362 void OpusAudioDecoder::DoStop() { | 354 void OpusAudioDecoder::DoStop() { |
363 DCHECK(!stop_cb_.is_null()); | 355 DCHECK(!stop_cb_.is_null()); |
364 | 356 |
365 opus_multistream_decoder_ctl(opus_decoder_, OPUS_RESET_STATE); | 357 opus_multistream_decoder_ctl(opus_decoder_, OPUS_RESET_STATE); |
366 ResetTimestampState(); | 358 ResetTimestampState(); |
367 CloseDecoder(); | 359 CloseDecoder(); |
368 base::ResetAndReturn(&stop_cb_).Run(); | 360 base::ResetAndReturn(&stop_cb_).Run(); |
369 } | 361 } |
370 | 362 |
371 void OpusAudioDecoder::ReadFromDemuxerStream() { | 363 void OpusAudioDecoder::DecodeBuffer( |
372 DCHECK(!read_cb_.is_null()); | |
373 demuxer_stream_->Read(base::Bind(&OpusAudioDecoder::BufferReady, weak_this_)); | |
374 } | |
375 | |
376 void OpusAudioDecoder::BufferReady( | |
377 DemuxerStream::Status status, | |
378 const scoped_refptr<DecoderBuffer>& input) { | 364 const scoped_refptr<DecoderBuffer>& input) { |
379 DCHECK(task_runner_->BelongsToCurrentThread()); | 365 DCHECK(task_runner_->BelongsToCurrentThread()); |
380 DCHECK(!read_cb_.is_null()); | 366 DCHECK(!decode_cb_.is_null()); |
381 DCHECK_EQ(status != DemuxerStream::kOk, !input.get()) << status; | |
382 | 367 |
383 // Drop the buffer, fire |read_cb_| and complete the pending Reset(). | 368 // Drop the buffer, fire |read_cb_| and complete the pending Reset(). |
384 // If there happens to also be a pending Stop(), that will be handled at | 369 // If there happens to also be a pending Stop(), that will be handled at |
385 // the end of DoReset(). | 370 // the end of DoReset(). |
386 if (!reset_cb_.is_null()) { | 371 if (!reset_cb_.is_null()) { |
387 base::ResetAndReturn(&read_cb_).Run(kAborted, NULL); | 372 base::ResetAndReturn(&decode_cb_).Run(kAborted, NULL); |
388 DoReset(); | 373 DoReset(); |
389 return; | 374 return; |
390 } | 375 } |
391 | 376 |
392 // Drop the buffer, fire |read_cb_| and complete the pending Stop(). | 377 // Drop the buffer, fire |read_cb_| and complete the pending Stop(). |
393 if (!stop_cb_.is_null()) { | 378 if (!stop_cb_.is_null()) { |
394 base::ResetAndReturn(&read_cb_).Run(kAborted, NULL); | 379 base::ResetAndReturn(&decode_cb_).Run(kAborted, NULL); |
395 DoStop(); | 380 DoStop(); |
396 return; | 381 return; |
397 } | 382 } |
398 | 383 |
399 if (status == DemuxerStream::kAborted) { | |
400 DCHECK(!input.get()); | |
401 base::ResetAndReturn(&read_cb_).Run(kAborted, NULL); | |
402 return; | |
403 } | |
404 | |
405 if (status == DemuxerStream::kConfigChanged) { | |
406 DCHECK(!input.get()); | |
407 DVLOG(1) << "Config changed."; | |
408 | |
409 if (!ConfigureDecoder()) { | |
410 base::ResetAndReturn(&read_cb_).Run(kDecodeError, NULL); | |
411 return; | |
412 } | |
413 | |
414 ResetTimestampState(); | |
415 ReadFromDemuxerStream(); | |
416 return; | |
417 } | |
418 | |
419 DCHECK_EQ(status, DemuxerStream::kOk); | |
420 DCHECK(input.get()); | 384 DCHECK(input.get()); |
421 | 385 |
422 // Libopus does not buffer output. Decoding is complete when an end of stream | 386 // Libopus does not buffer output. Decoding is complete when an end of stream |
423 // input buffer is received. | 387 // input buffer is received. |
424 if (input->end_of_stream()) { | 388 if (input->end_of_stream()) { |
425 base::ResetAndReturn(&read_cb_).Run(kOk, AudioBuffer::CreateEOSBuffer()); | 389 base::ResetAndReturn(&decode_cb_).Run(kOk, AudioBuffer::CreateEOSBuffer()); |
426 return; | 390 return; |
427 } | 391 } |
428 | 392 |
429 // Make sure we are notified if http://crbug.com/49709 returns. Issue also | 393 // Make sure we are notified if http://crbug.com/49709 returns. Issue also |
430 // occurs with some damaged files. | 394 // occurs with some damaged files. |
431 if (input->timestamp() == kNoTimestamp() && | 395 if (input->timestamp() == kNoTimestamp() && |
432 output_timestamp_helper_->base_timestamp() == kNoTimestamp()) { | 396 output_timestamp_helper_->base_timestamp() == kNoTimestamp()) { |
433 DLOG(ERROR) << "Received a buffer without timestamps!"; | 397 DLOG(ERROR) << "Received a buffer without timestamps!"; |
434 base::ResetAndReturn(&read_cb_).Run(kDecodeError, NULL); | 398 base::ResetAndReturn(&decode_cb_).Run(kDecodeError, NULL); |
435 return; | 399 return; |
436 } | 400 } |
437 | 401 |
438 if (last_input_timestamp_ != kNoTimestamp() && | 402 if (last_input_timestamp_ != kNoTimestamp() && |
439 input->timestamp() != kNoTimestamp() && | 403 input->timestamp() != kNoTimestamp() && |
440 input->timestamp() < last_input_timestamp_) { | 404 input->timestamp() < last_input_timestamp_) { |
441 base::TimeDelta diff = input->timestamp() - last_input_timestamp_; | 405 base::TimeDelta diff = input->timestamp() - last_input_timestamp_; |
442 DLOG(ERROR) << "Input timestamps are not monotonically increasing! " | 406 DLOG(ERROR) << "Input timestamps are not monotonically increasing! " |
443 << " ts " << input->timestamp().InMicroseconds() << " us" | 407 << " ts " << input->timestamp().InMicroseconds() << " us" |
444 << " diff " << diff.InMicroseconds() << " us"; | 408 << " diff " << diff.InMicroseconds() << " us"; |
445 base::ResetAndReturn(&read_cb_).Run(kDecodeError, NULL); | 409 base::ResetAndReturn(&decode_cb_).Run(kDecodeError, NULL); |
446 return; | 410 return; |
447 } | 411 } |
448 | 412 |
449 // Apply the necessary codec delay. | 413 // Apply the necessary codec delay. |
450 if (start_input_timestamp_ == kNoTimestamp()) | 414 if (start_input_timestamp_ == kNoTimestamp()) |
451 start_input_timestamp_ = input->timestamp(); | 415 start_input_timestamp_ = input->timestamp(); |
452 if (last_input_timestamp_ == kNoTimestamp() && | 416 if (last_input_timestamp_ == kNoTimestamp() && |
453 input->timestamp() == start_input_timestamp_) { | 417 input->timestamp() == start_input_timestamp_) { |
454 frames_to_discard_ = frame_delay_at_start_; | 418 frames_to_discard_ = frame_delay_at_start_; |
455 } | 419 } |
456 | 420 |
457 last_input_timestamp_ = input->timestamp(); | 421 last_input_timestamp_ = input->timestamp(); |
458 | 422 |
459 scoped_refptr<AudioBuffer> output_buffer; | 423 scoped_refptr<AudioBuffer> output_buffer; |
460 | 424 |
461 if (!Decode(input, &output_buffer)) { | 425 if (!Decode(input, &output_buffer)) { |
462 base::ResetAndReturn(&read_cb_).Run(kDecodeError, NULL); | 426 base::ResetAndReturn(&decode_cb_).Run(kDecodeError, NULL); |
463 return; | 427 return; |
464 } | 428 } |
465 | 429 |
466 if (output_buffer.get()) { | 430 if (output_buffer.get()) { |
467 // Execute callback to return the decoded audio. | 431 // Execute callback to return the decoded audio. |
468 base::ResetAndReturn(&read_cb_).Run(kOk, output_buffer); | 432 base::ResetAndReturn(&decode_cb_).Run(kOk, output_buffer); |
469 } else { | 433 } else { |
470 // We exhausted the input data, but it wasn't enough for a frame. Ask for | 434 // We exhausted the input data, but it wasn't enough for a frame. |
471 // more data in order to fulfill this read. | 435 base::ResetAndReturn(&decode_cb_).Run(kNotEnoughData, NULL); |
472 ReadFromDemuxerStream(); | |
473 } | 436 } |
474 } | 437 } |
475 | 438 |
476 bool OpusAudioDecoder::ConfigureDecoder() { | 439 bool OpusAudioDecoder::ConfigureDecoder() { |
477 const AudioDecoderConfig& config = demuxer_stream_->audio_decoder_config(); | 440 if (config_.codec() != kCodecOpus) { |
478 | |
479 if (config.codec() != kCodecOpus) { | |
480 DVLOG(1) << "Codec must be kCodecOpus."; | 441 DVLOG(1) << "Codec must be kCodecOpus."; |
481 return false; | 442 return false; |
482 } | 443 } |
483 | 444 |
484 const int channel_count = | 445 const int channel_count = |
485 ChannelLayoutToChannelCount(config.channel_layout()); | 446 ChannelLayoutToChannelCount(config_.channel_layout()); |
486 if (!config.IsValidConfig() || channel_count > kMaxVorbisChannels) { | 447 if (!config_.IsValidConfig() || channel_count > kMaxVorbisChannels) { |
487 DLOG(ERROR) << "Invalid or unsupported audio stream -" | 448 DLOG(ERROR) << "Invalid or unsupported audio stream -" |
488 << " codec: " << config.codec() | 449 << " codec: " << config_.codec() |
489 << " channel count: " << channel_count | 450 << " channel count: " << channel_count |
490 << " channel layout: " << config.channel_layout() | 451 << " channel layout: " << config_.channel_layout() |
491 << " bits per channel: " << config.bits_per_channel() | 452 << " bits per channel: " << config_.bits_per_channel() |
492 << " samples per second: " << config.samples_per_second(); | 453 << " samples per second: " << config_.samples_per_second(); |
493 return false; | 454 return false; |
494 } | 455 } |
495 | 456 |
496 if (config.is_encrypted()) { | 457 if (config_.is_encrypted()) { |
497 DLOG(ERROR) << "Encrypted audio stream not supported."; | 458 DLOG(ERROR) << "Encrypted audio stream not supported."; |
498 return false; | 459 return false; |
499 } | 460 } |
500 | 461 |
| 462 // TODO(rileya) Remove this check once we properly support midstream audio |
| 463 // config changes. |
501 if (opus_decoder_ && | 464 if (opus_decoder_ && |
502 (channel_layout_ != config.channel_layout() || | 465 (channel_layout_ != config_.channel_layout() || |
503 samples_per_second_ != config.samples_per_second())) { | 466 samples_per_second_ != config_.samples_per_second())) { |
504 DLOG(ERROR) << "Unsupported config change -" | 467 DLOG(ERROR) << "Unsupported config change -" |
505 << ", channel_layout: " << channel_layout_ | 468 << ", channel_layout: " << channel_layout_ |
506 << " -> " << config.channel_layout() | 469 << " -> " << config_.channel_layout() |
507 << ", sample_rate: " << samples_per_second_ | 470 << ", sample_rate: " << samples_per_second_ |
508 << " -> " << config.samples_per_second(); | 471 << " -> " << config_.samples_per_second(); |
509 return false; | 472 return false; |
510 } | 473 } |
511 | 474 |
512 // Clean up existing decoder if necessary. | 475 // Clean up existing decoder if necessary. |
513 CloseDecoder(); | 476 CloseDecoder(); |
514 | 477 |
515 // Parse the Opus Extra Data. | 478 // Parse the Opus Extra Data. |
516 OpusExtraData opus_extra_data; | 479 OpusExtraData opus_extra_data; |
517 if (!ParseOpusExtraData(config.extra_data(), config.extra_data_size(), | 480 if (!ParseOpusExtraData(config_.extra_data(), config_.extra_data_size(), |
518 config, | 481 config_, |
519 &opus_extra_data)) | 482 &opus_extra_data)) |
520 return false; | 483 return false; |
521 | 484 |
522 // Convert from seconds to samples. | 485 // Convert from seconds to samples. |
523 timestamp_offset_ = config.codec_delay(); | 486 timestamp_offset_ = config_.codec_delay(); |
524 frame_delay_at_start_ = TimeDeltaToAudioFrames(config.codec_delay(), | 487 frame_delay_at_start_ = TimeDeltaToAudioFrames(config_.codec_delay(), |
525 config.samples_per_second()); | 488 config_.samples_per_second()); |
526 if (timestamp_offset_ <= base::TimeDelta() || frame_delay_at_start_ < 0) { | 489 if (timestamp_offset_ <= base::TimeDelta() || frame_delay_at_start_ < 0) { |
527 DLOG(ERROR) << "Invalid file. Incorrect value for codec delay: " | 490 DLOG(ERROR) << "Invalid file. Incorrect value for codec delay: " |
528 << config.codec_delay().InMicroseconds(); | 491 << config_.codec_delay().InMicroseconds(); |
529 return false; | 492 return false; |
530 } | 493 } |
531 | 494 |
532 if (frame_delay_at_start_ != opus_extra_data.skip_samples) { | 495 if (frame_delay_at_start_ != opus_extra_data.skip_samples) { |
533 DLOG(ERROR) << "Invalid file. Codec Delay in container does not match the " | 496 DLOG(ERROR) << "Invalid file. Codec Delay in container does not match the " |
534 << "value in Opus Extra Data."; | 497 << "value in Opus Extra Data."; |
535 return false; | 498 return false; |
536 } | 499 } |
537 | 500 |
538 uint8 channel_mapping[kMaxVorbisChannels] = {0}; | 501 uint8 channel_mapping[kMaxVorbisChannels] = {0}; |
539 memcpy(&channel_mapping, | 502 memcpy(&channel_mapping, |
540 kDefaultOpusChannelLayout, | 503 kDefaultOpusChannelLayout, |
541 kMaxChannelsWithDefaultLayout); | 504 kMaxChannelsWithDefaultLayout); |
542 | 505 |
543 if (channel_count > kMaxChannelsWithDefaultLayout) { | 506 if (channel_count > kMaxChannelsWithDefaultLayout) { |
544 RemapOpusChannelLayout(opus_extra_data.stream_map, | 507 RemapOpusChannelLayout(opus_extra_data.stream_map, |
545 channel_count, | 508 channel_count, |
546 channel_mapping); | 509 channel_mapping); |
547 } | 510 } |
548 | 511 |
549 // Init Opus. | 512 // Init Opus. |
550 int status = OPUS_INVALID_STATE; | 513 int status = OPUS_INVALID_STATE; |
551 opus_decoder_ = opus_multistream_decoder_create(config.samples_per_second(), | 514 opus_decoder_ = opus_multistream_decoder_create(config_.samples_per_second(), |
552 channel_count, | 515 channel_count, |
553 opus_extra_data.num_streams, | 516 opus_extra_data.num_streams, |
554 opus_extra_data.num_coupled, | 517 opus_extra_data.num_coupled, |
555 channel_mapping, | 518 channel_mapping, |
556 &status); | 519 &status); |
557 if (!opus_decoder_ || status != OPUS_OK) { | 520 if (!opus_decoder_ || status != OPUS_OK) { |
558 DLOG(ERROR) << "opus_multistream_decoder_create failed status=" | 521 DLOG(ERROR) << "opus_multistream_decoder_create failed status=" |
559 << opus_strerror(status); | 522 << opus_strerror(status); |
560 return false; | 523 return false; |
561 } | 524 } |
562 | 525 |
563 status = opus_multistream_decoder_ctl( | 526 status = opus_multistream_decoder_ctl( |
564 opus_decoder_, OPUS_SET_GAIN(opus_extra_data.gain_db)); | 527 opus_decoder_, OPUS_SET_GAIN(opus_extra_data.gain_db)); |
565 if (status != OPUS_OK) { | 528 if (status != OPUS_OK) { |
566 DLOG(ERROR) << "Failed to set OPUS header gain; status=" | 529 DLOG(ERROR) << "Failed to set OPUS header gain; status=" |
567 << opus_strerror(status); | 530 << opus_strerror(status); |
568 return false; | 531 return false; |
569 } | 532 } |
570 | 533 |
571 channel_layout_ = config.channel_layout(); | 534 channel_layout_ = config_.channel_layout(); |
572 samples_per_second_ = config.samples_per_second(); | 535 samples_per_second_ = config_.samples_per_second(); |
573 output_timestamp_helper_.reset( | 536 output_timestamp_helper_.reset( |
574 new AudioTimestampHelper(config.samples_per_second())); | 537 new AudioTimestampHelper(config_.samples_per_second())); |
575 start_input_timestamp_ = kNoTimestamp(); | 538 start_input_timestamp_ = kNoTimestamp(); |
576 return true; | 539 return true; |
577 } | 540 } |
578 | 541 |
579 void OpusAudioDecoder::CloseDecoder() { | 542 void OpusAudioDecoder::CloseDecoder() { |
580 if (opus_decoder_) { | 543 if (opus_decoder_) { |
581 opus_multistream_decoder_destroy(opus_decoder_); | 544 opus_multistream_decoder_destroy(opus_decoder_); |
582 opus_decoder_ = NULL; | 545 opus_decoder_ = NULL; |
583 } | 546 } |
584 } | 547 } |
585 | 548 |
586 void OpusAudioDecoder::ResetTimestampState() { | 549 void OpusAudioDecoder::ResetTimestampState() { |
587 output_timestamp_helper_->SetBaseTimestamp(kNoTimestamp()); | 550 output_timestamp_helper_->SetBaseTimestamp(kNoTimestamp()); |
588 last_input_timestamp_ = kNoTimestamp(); | 551 last_input_timestamp_ = kNoTimestamp(); |
589 frames_to_discard_ = TimeDeltaToAudioFrames( | 552 frames_to_discard_ = |
590 demuxer_stream_->audio_decoder_config().seek_preroll(), | 553 TimeDeltaToAudioFrames(config_.seek_preroll(), samples_per_second_); |
591 samples_per_second_); | |
592 } | 554 } |
593 | 555 |
594 bool OpusAudioDecoder::Decode(const scoped_refptr<DecoderBuffer>& input, | 556 bool OpusAudioDecoder::Decode(const scoped_refptr<DecoderBuffer>& input, |
595 scoped_refptr<AudioBuffer>* output_buffer) { | 557 scoped_refptr<AudioBuffer>* output_buffer) { |
596 // Allocate a buffer for the output samples. | 558 // Allocate a buffer for the output samples. |
597 *output_buffer = AudioBuffer::CreateBuffer( | 559 *output_buffer = AudioBuffer::CreateBuffer( |
598 sample_format_, | 560 sample_format_, |
599 ChannelLayoutToChannelCount(channel_layout_), | 561 ChannelLayoutToChannelCount(channel_layout_), |
600 kMaxOpusOutputPacketSizeSamples); | 562 kMaxOpusOutputPacketSizeSamples); |
601 const int buffer_size = | 563 const int buffer_size = |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
651 } | 613 } |
652 output_buffer->get()->TrimEnd(discard_padding); | 614 output_buffer->get()->TrimEnd(discard_padding); |
653 frames_to_output -= discard_padding; | 615 frames_to_output -= discard_padding; |
654 } | 616 } |
655 } else { | 617 } else { |
656 frames_to_discard_ -= frames_to_output; | 618 frames_to_discard_ -= frames_to_output; |
657 frames_to_output = 0; | 619 frames_to_output = 0; |
658 } | 620 } |
659 | 621 |
660 // Decoding finished successfully, update statistics. | 622 // Decoding finished successfully, update statistics. |
661 PipelineStatistics statistics; | 623 // TODO |
662 statistics.audio_bytes_decoded = input->data_size(); | 624 //PipelineStatistics statistics; |
663 statistics_cb_.Run(statistics); | 625 //statistics.audio_bytes_decoded = input->data_size(); |
| 626 //statistics_cb_.Run(statistics); |
664 | 627 |
665 // Assign timestamp and duration to the buffer. | 628 // Assign timestamp and duration to the buffer. |
666 output_buffer->get()->set_timestamp( | 629 output_buffer->get()->set_timestamp( |
667 output_timestamp_helper_->GetTimestamp() - timestamp_offset_); | 630 output_timestamp_helper_->GetTimestamp() - timestamp_offset_); |
668 output_buffer->get()->set_duration( | 631 output_buffer->get()->set_duration( |
669 output_timestamp_helper_->GetFrameDuration(frames_to_output)); | 632 output_timestamp_helper_->GetFrameDuration(frames_to_output)); |
670 output_timestamp_helper_->AddFrames(frames_decoded); | 633 output_timestamp_helper_->AddFrames(frames_decoded); |
671 | 634 |
672 // Discard the buffer to indicate we need more data. | 635 // Discard the buffer to indicate we need more data. |
673 if (!frames_to_output) | 636 if (!frames_to_output) |
674 *output_buffer = NULL; | 637 *output_buffer = NULL; |
675 | 638 |
676 return true; | 639 return true; |
677 } | 640 } |
678 | 641 |
679 } // namespace media | 642 } // namespace media |
OLD | NEW |