X-Git-Url: https://git.carlh.net/gitweb/?a=blobdiff_plain;f=src%2Flib%2Fffmpeg_decoder.cc;h=8da607e7eb62861812d035d88461f39fc83c1bcd;hb=11325f810e214935e4115248223c186a6e4cc184;hp=d8319723a3538f03cdb6bb94fe3ec41cb1082287;hpb=d9362bdd24f01e4c833e89d63ac3816f36eae36e;p=dcpomatic.git diff --git a/src/lib/ffmpeg_decoder.cc b/src/lib/ffmpeg_decoder.cc index d8319723a..8da607e7e 100644 --- a/src/lib/ffmpeg_decoder.cc +++ b/src/lib/ffmpeg_decoder.cc @@ -42,6 +42,7 @@ extern "C" { #include "ffmpeg_decoder.h" #include "filter_graph.h" #include "audio_buffers.h" +#include "ffmpeg_content.h" #include "i18n.h" @@ -60,7 +61,7 @@ using libdcp::Size; FFmpegDecoder::FFmpegDecoder (shared_ptr f, shared_ptr c, bool video, bool audio) : Decoder (f) , VideoDecoder (f, c) - , AudioDecoder (f, c) + , AudioDecoder (f) , SubtitleDecoder (f) , FFmpeg (c) , _subtitle_codec_context (0) @@ -96,6 +97,8 @@ FFmpegDecoder::FFmpegDecoder (shared_ptr f, shared_ptrfirst_video().get(), c->audio_stream()->first_audio.get()); } else if (have_video) { _video_pts_offset = - c->first_video().get(); + } else if (have_audio) { + _audio_pts_offset = - c->audio_stream()->first_audio.get(); } /* Now adjust both so that the video pts starts on a frame */ @@ -120,7 +123,30 @@ FFmpegDecoder::~FFmpegDecoder () if (_subtitle_codec_context) { avcodec_close (_subtitle_codec_context); } -} +} + +void +FFmpegDecoder::flush () +{ + /* Get any remaining frames */ + + _packet.data = 0; + _packet.size = 0; + + /* XXX: should we reset _packet.data and size after each *_decode_* call? */ + + if (_decode_video) { + while (decode_video_packet ()) {} + } + + if (_ffmpeg_content->audio_stream() && _decode_audio) { + decode_audio_packet (); + } + + /* Stop us being asked for any more data */ + _video_position = _ffmpeg_content->video_length (); + _audio_position = _ffmpeg_content->audio_length (); +} void FFmpegDecoder::pass () @@ -137,34 +163,20 @@ FFmpegDecoder::pass () film->log()->log (String::compose (N_("error on av_read_frame (%1) (%2)"), buf, r)); } - /* Get any remaining frames */ - - _packet.data = 0; - _packet.size = 0; - - /* XXX: should we reset _packet.data and size after each *_decode_* call? */ - - if (_decode_video) { - while (decode_video_packet ()) {} - } - - if (_ffmpeg_content->audio_stream() && _decode_audio) { - decode_audio_packet (); - } - - /* Stop us being asked for any more data */ - _video_position = _ffmpeg_content->video_length (); - _audio_position = _ffmpeg_content->audio_length (); + flush (); return; } avcodec_get_frame_defaults (_frame); + shared_ptr film = _film.lock (); + assert (film); + if (_packet.stream_index == _video_stream && _decode_video) { decode_video_packet (); } else if (_ffmpeg_content->audio_stream() && _packet.stream_index == _ffmpeg_content->audio_stream()->id && _decode_audio) { decode_audio_packet (); - } else if (_ffmpeg_content->subtitle_stream() && _packet.stream_index == _ffmpeg_content->subtitle_stream()->id) { + } else if (_ffmpeg_content->subtitle_stream() && _packet.stream_index == _ffmpeg_content->subtitle_stream()->id && film->with_subtitles ()) { decode_subtitle_packet (); } @@ -357,43 +369,48 @@ FFmpegDecoder::decode_audio_packet () */ AVPacket copy_packet = _packet; - + while (copy_packet.size > 0) { int frame_finished; int const decode_result = avcodec_decode_audio4 (audio_codec_context(), _frame, &frame_finished, ©_packet); - if (decode_result >= 0) { - if (frame_finished) { - - if (_audio_position == 0) { - /* Where we are in the source, in seconds */ - double const pts = av_q2d (_format_context->streams[copy_packet.stream_index]->time_base) - * av_frame_get_best_effort_timestamp(_frame) + _audio_pts_offset; - - if (pts > 0) { - /* Emit some silence */ - shared_ptr silence ( - new AudioBuffers ( - _ffmpeg_content->audio_channels(), - pts * _ffmpeg_content->content_audio_frame_rate() - ) - ); - - silence->make_silent (); - audio (silence, _audio_position); - } - } - - int const data_size = av_samples_get_buffer_size ( - 0, audio_codec_context()->channels, _frame->nb_samples, audio_sample_format (), 1 - ); + if (decode_result < 0) { + shared_ptr film = _film.lock (); + assert (film); + film->log()->log (String::compose ("avcodec_decode_audio4 failed (%1)", decode_result)); + return; + } - audio (deinterleave_audio (_frame->data, data_size), _audio_position); - - copy_packet.data += decode_result; - copy_packet.size -= decode_result; + if (frame_finished) { + + if (_audio_position == 0) { + /* Where we are in the source, in seconds */ + double const pts = av_q2d (_format_context->streams[copy_packet.stream_index]->time_base) + * av_frame_get_best_effort_timestamp(_frame) + _audio_pts_offset; + + if (pts > 0) { + /* Emit some silence */ + shared_ptr silence ( + new AudioBuffers ( + _ffmpeg_content->audio_channels(), + pts * _ffmpeg_content->content_audio_frame_rate() + ) + ); + + silence->make_silent (); + audio (silence, _audio_position); + } } + + int const data_size = av_samples_get_buffer_size ( + 0, audio_codec_context()->channels, _frame->nb_samples, audio_sample_format (), 1 + ); + + audio (deinterleave_audio (_frame->data, data_size), _audio_position); } + + copy_packet.data += decode_result; + copy_packet.size -= decode_result; } }