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

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

Issue 23172019: FFmpeg roll for M31. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 3 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 | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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/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
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
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
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_);
scherkus (not reviewing) 2013/08/27 00:23:44 when are refs taken? worth writing a ScopedAVFram
DaleCurtis 2013/08/27 00:30:13 API contract says we have to call this to destroy
DaleCurtis 2013/08/27 00:30:51 (contract when refcounted_frames=1 that is).
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_);
jrummell 2013/08/27 01:05:24 Should this be done outside the if block just in c
DaleCurtis 2013/08/27 01:16:59 I used ffmpeg and ffplay as reference here and the
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
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
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698