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/ffmpeg_audio_decoder.h" | 5 #include "media/filters/ffmpeg_audio_decoder.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/callback_helpers.h" | 8 #include "base/callback_helpers.h" |
9 #include "base/location.h" | 9 #include "base/location.h" |
10 #include "base/message_loop/message_loop_proxy.h" | 10 #include "base/message_loop/message_loop_proxy.h" |
(...skipping 339 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
350 | 350 |
351 // Release existing decoder resources if necessary. | 351 // Release existing decoder resources if necessary. |
352 ReleaseFFmpegResources(); | 352 ReleaseFFmpegResources(); |
353 | 353 |
354 // Initialize AVCodecContext structure. | 354 // Initialize AVCodecContext structure. |
355 codec_context_ = avcodec_alloc_context3(NULL); | 355 codec_context_ = avcodec_alloc_context3(NULL); |
356 AudioDecoderConfigToAVCodecContext(config, codec_context_); | 356 AudioDecoderConfigToAVCodecContext(config, codec_context_); |
357 | 357 |
358 codec_context_->opaque = this; | 358 codec_context_->opaque = this; |
359 codec_context_->get_buffer2 = GetAudioBufferImpl; | 359 codec_context_->get_buffer2 = GetAudioBufferImpl; |
| 360 codec_context_->refcounted_frames = 1; |
360 | 361 |
361 AVCodec* codec = avcodec_find_decoder(codec_context_->codec_id); | 362 AVCodec* codec = avcodec_find_decoder(codec_context_->codec_id); |
362 if (!codec || avcodec_open2(codec_context_, codec, NULL) < 0) { | 363 if (!codec || avcodec_open2(codec_context_, codec, NULL) < 0) { |
363 DLOG(ERROR) << "Could not initialize audio decoder: " | 364 DLOG(ERROR) << "Could not initialize audio decoder: " |
364 << codec_context_->codec_id; | 365 << codec_context_->codec_id; |
365 return false; | 366 return false; |
366 } | 367 } |
367 | 368 |
368 // Success! | 369 // Success! |
369 av_frame_ = avcodec_alloc_frame(); | 370 av_frame_ = avcodec_alloc_frame(); |
(...skipping 19 matching lines...) Expand all Loading... |
389 return true; | 390 return true; |
390 } | 391 } |
391 | 392 |
392 void FFmpegAudioDecoder::ReleaseFFmpegResources() { | 393 void FFmpegAudioDecoder::ReleaseFFmpegResources() { |
393 if (codec_context_) { | 394 if (codec_context_) { |
394 av_free(codec_context_->extradata); | 395 av_free(codec_context_->extradata); |
395 avcodec_close(codec_context_); | 396 avcodec_close(codec_context_); |
396 av_free(codec_context_); | 397 av_free(codec_context_); |
397 } | 398 } |
398 | 399 |
399 if (av_frame_) { | 400 if (av_frame_) |
400 av_free(av_frame_); | 401 av_frame_free(&av_frame_); |
401 av_frame_ = NULL; | |
402 } | |
403 } | 402 } |
404 | 403 |
405 void FFmpegAudioDecoder::ResetTimestampState() { | 404 void FFmpegAudioDecoder::ResetTimestampState() { |
406 output_timestamp_helper_->SetBaseTimestamp(kNoTimestamp()); | 405 output_timestamp_helper_->SetBaseTimestamp(kNoTimestamp()); |
407 last_input_timestamp_ = kNoTimestamp(); | 406 last_input_timestamp_ = kNoTimestamp(); |
408 output_frames_to_drop_ = 0; | 407 output_frames_to_drop_ = 0; |
409 } | 408 } |
410 | 409 |
411 void FFmpegAudioDecoder::RunDecodeLoop( | 410 void FFmpegAudioDecoder::RunDecodeLoop( |
412 const scoped_refptr<DecoderBuffer>& input, | 411 const scoped_refptr<DecoderBuffer>& input, |
413 bool skip_eos_append) { | 412 bool skip_eos_append) { |
414 AVPacket packet; | 413 AVPacket packet; |
415 av_init_packet(&packet); | 414 av_init_packet(&packet); |
416 if (input->end_of_stream()) { | 415 if (input->end_of_stream()) { |
417 packet.data = NULL; | 416 packet.data = NULL; |
418 packet.size = 0; | 417 packet.size = 0; |
419 } else { | 418 } else { |
420 packet.data = const_cast<uint8*>(input->data()); | 419 packet.data = const_cast<uint8*>(input->data()); |
421 packet.size = input->data_size(); | 420 packet.size = input->data_size(); |
422 } | 421 } |
423 | 422 |
424 // Each audio packet may contain several frames, so we must call the decoder | 423 // Each audio packet may contain several frames, so we must call the decoder |
425 // until we've exhausted the packet. Regardless of the packet size we always | 424 // until we've exhausted the packet. Regardless of the packet size we always |
426 // want to hand it to the decoder at least once, otherwise we would end up | 425 // want to hand it to the decoder at least once, otherwise we would end up |
427 // skipping end of stream packets since they have a size of zero. | 426 // skipping end of stream packets since they have a size of zero. |
428 do { | 427 do { |
429 // Reset frame to default values. | |
430 avcodec_get_frame_defaults(av_frame_); | |
431 | |
432 int frame_decoded = 0; | 428 int frame_decoded = 0; |
433 int result = avcodec_decode_audio4( | 429 int result = avcodec_decode_audio4( |
434 codec_context_, av_frame_, &frame_decoded, &packet); | 430 codec_context_, av_frame_, &frame_decoded, &packet); |
435 | 431 |
436 if (result < 0) { | 432 if (result < 0) { |
437 DCHECK(!input->end_of_stream()) | 433 DCHECK(!input->end_of_stream()) |
438 << "End of stream buffer produced an error! " | 434 << "End of stream buffer produced an error! " |
439 << "This is quite possibly a bug in the audio decoder not handling " | 435 << "This is quite possibly a bug in the audio decoder not handling " |
440 << "end of stream AVPackets correctly."; | 436 << "end of stream AVPackets correctly."; |
441 | 437 |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
480 << " Sample Rate: " << av_frame_->sample_rate << " vs " | 476 << " Sample Rate: " << av_frame_->sample_rate << " vs " |
481 << samples_per_second_ | 477 << samples_per_second_ |
482 << ", Channels: " << channels << " vs " | 478 << ", Channels: " << channels << " vs " |
483 << channels_ | 479 << channels_ |
484 << ", Sample Format: " << av_frame_->format << " vs " | 480 << ", Sample Format: " << av_frame_->format << " vs " |
485 << av_sample_format_; | 481 << av_sample_format_; |
486 | 482 |
487 // This is an unrecoverable error, so bail out. | 483 // This is an unrecoverable error, so bail out. |
488 QueuedAudioBuffer queue_entry = { kDecodeError, NULL }; | 484 QueuedAudioBuffer queue_entry = { kDecodeError, NULL }; |
489 queued_audio_.push_back(queue_entry); | 485 queued_audio_.push_back(queue_entry); |
| 486 av_frame_unref(av_frame_); |
490 break; | 487 break; |
491 } | 488 } |
492 | 489 |
493 // Get the AudioBuffer that the data was decoded into. Adjust the number | 490 // Get the AudioBuffer that the data was decoded into. Adjust the number |
494 // of frames, in case fewer than requested were actually decoded. | 491 // of frames, in case fewer than requested were actually decoded. |
495 output = reinterpret_cast<AudioBuffer*>( | 492 output = reinterpret_cast<AudioBuffer*>( |
496 av_buffer_get_opaque(av_frame_->buf[0])); | 493 av_buffer_get_opaque(av_frame_->buf[0])); |
497 DCHECK_EQ(channels_, output->channel_count()); | 494 DCHECK_EQ(channels_, output->channel_count()); |
498 original_frames = av_frame_->nb_samples; | 495 original_frames = av_frame_->nb_samples; |
499 int unread_frames = output->frame_count() - original_frames; | 496 int unread_frames = output->frame_count() - original_frames; |
500 DCHECK_GE(unread_frames, 0); | 497 DCHECK_GE(unread_frames, 0); |
501 if (unread_frames > 0) | 498 if (unread_frames > 0) |
502 output->TrimEnd(unread_frames); | 499 output->TrimEnd(unread_frames); |
503 | 500 |
504 // If there are frames to drop, get rid of as many as we can. | 501 // If there are frames to drop, get rid of as many as we can. |
505 if (output_frames_to_drop_ > 0) { | 502 if (output_frames_to_drop_ > 0) { |
506 int drop = std::min(output->frame_count(), output_frames_to_drop_); | 503 int drop = std::min(output->frame_count(), output_frames_to_drop_); |
507 output->TrimStart(drop); | 504 output->TrimStart(drop); |
508 output_frames_to_drop_ -= drop; | 505 output_frames_to_drop_ -= drop; |
509 } | 506 } |
510 | 507 |
511 decoded_frames = output->frame_count(); | 508 decoded_frames = output->frame_count(); |
| 509 av_frame_unref(av_frame_); |
512 } | 510 } |
513 | 511 |
| 512 // WARNING: |av_frame_| no longer has valid data at this point. |
| 513 |
514 if (decoded_frames > 0) { | 514 if (decoded_frames > 0) { |
515 // Set the timestamp/duration once all the extra frames have been | 515 // Set the timestamp/duration once all the extra frames have been |
516 // discarded. | 516 // discarded. |
517 output->set_timestamp(output_timestamp_helper_->GetTimestamp()); | 517 output->set_timestamp(output_timestamp_helper_->GetTimestamp()); |
518 output->set_duration( | 518 output->set_duration( |
519 output_timestamp_helper_->GetFrameDuration(decoded_frames)); | 519 output_timestamp_helper_->GetFrameDuration(decoded_frames)); |
520 output_timestamp_helper_->AddFrames(decoded_frames); | 520 output_timestamp_helper_->AddFrames(decoded_frames); |
521 } else if (IsEndOfStream(result, original_frames, input) && | 521 } else if (IsEndOfStream(result, original_frames, input) && |
522 !skip_eos_append) { | 522 !skip_eos_append) { |
523 DCHECK_EQ(packet.size, 0); | 523 DCHECK_EQ(packet.size, 0); |
(...skipping 11 matching lines...) Expand all Loading... |
535 // Decoding finished successfully, update statistics. | 535 // Decoding finished successfully, update statistics. |
536 if (result > 0) { | 536 if (result > 0) { |
537 PipelineStatistics statistics; | 537 PipelineStatistics statistics; |
538 statistics.audio_bytes_decoded = result; | 538 statistics.audio_bytes_decoded = result; |
539 statistics_cb_.Run(statistics); | 539 statistics_cb_.Run(statistics); |
540 } | 540 } |
541 } while (packet.size > 0); | 541 } while (packet.size > 0); |
542 } | 542 } |
543 | 543 |
544 } // namespace media | 544 } // namespace media |
OLD | NEW |