X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;ds=sidebyside;f=src%2Flib%2Fffmpeg_decoder.cc;h=ea961a894d5446b5a81731ea86909a14cc918635;hb=ac34066d5e448d1984d11a180be74e31b6e13b5c;hp=3202dcd3e7b11750213ef0284fa584e198b382d5;hpb=df811a0dd2772417496991b72fde0ef3304241d9;p=dcpomatic.git diff --git a/src/lib/ffmpeg_decoder.cc b/src/lib/ffmpeg_decoder.cc index 3202dcd3e..ea961a894 100644 --- a/src/lib/ffmpeg_decoder.cc +++ b/src/lib/ffmpeg_decoder.cc @@ -18,31 +18,33 @@ */ + /** @file src/ffmpeg_decoder.cc * @brief A decoder using FFmpeg to decode content. */ -#include "filter.h" -#include "exceptions.h" -#include "image.h" -#include "util.h" -#include "log.h" + +#include "audio_buffers.h" +#include "audio_content.h" +#include "audio_decoder.h" +#include "compose.hpp" #include "dcpomatic_log.h" -#include "ffmpeg_decoder.h" -#include "text_decoder.h" +#include "exceptions.h" #include "ffmpeg_audio_stream.h" -#include "ffmpeg_subtitle_stream.h" -#include "video_filter_graph.h" -#include "audio_buffers.h" #include "ffmpeg_content.h" -#include "raw_image_proxy.h" -#include "video_decoder.h" +#include "ffmpeg_decoder.h" +#include "ffmpeg_subtitle_stream.h" #include "film.h" -#include "audio_decoder.h" -#include "compose.hpp" -#include "text_content.h" -#include "audio_content.h" +#include "filter.h" #include "frame_interval_checker.h" +#include "image.h" +#include "log.h" +#include "raw_image_proxy.h" +#include "text_content.h" +#include "text_decoder.h" +#include "util.h" +#include "video_decoder.h" +#include "video_filter_graph.h" #include #include #include @@ -52,28 +54,22 @@ extern "C" { #include } #include -#include #include #include +#include #include #include "i18n.h" + using std::cout; -using std::string; -using std::vector; -using std::list; +using std::dynamic_pointer_cast; +using std::make_shared; using std::min; -using std::pair; -using std::max; -using std::map; using std::shared_ptr; -using std::make_shared; -using std::make_pair; -using boost::is_any_of; -using boost::split; +using std::string; +using std::vector; using boost::optional; -using std::dynamic_pointer_cast; using dcp::Size; using namespace dcpomatic; @@ -86,7 +82,7 @@ FFmpegDecoder::FFmpegDecoder (shared_ptr film, shared_ptr(this, c); _pts_offset = pts_offset (c->ffmpeg_audio_streams(), c->first_video(), c->active_video_frame_rate(film)); /* It doesn't matter what size or pixel format this is, it just needs to be black */ - _black_image.reset (new Image (AV_PIX_FMT_RGB24, dcp::Size (128, 128), true)); + _black_image = make_shared(AV_PIX_FMT_RGB24, dcp::Size (128, 128), Image::Alignment::PADDED); _black_image->make_black (); } else { _pts_offset = {}; @@ -427,12 +423,6 @@ FFmpegDecoder::seek (ContentTime time, bool accurate) for (auto& i: _next_time) { i.second = boost::optional(); } - - /* We find that we get some errors from av_send_packet after a seek. Perhaps we should ignore - * all of them (which seems risky), or perhaps we should have some proper fix. But instead - * let's ignore the next 2 errors. - */ - _errors_to_ignore = 2; } @@ -516,18 +506,8 @@ FFmpegDecoder::decode_and_process_audio_packet (AVPacket* packet) int r = avcodec_send_packet (context, packet); if (r < 0) { - /* We could cope with AVERROR(EAGAIN) and re-send the packet but I think it should never happen. - * Likewise I think AVERROR_EOF should not happen. - */ - if (_errors_to_ignore > 0) { - /* We see errors here after a seek, which is hopefully to be nothing to worry about */ - --_errors_to_ignore; - LOG_GENERAL("Ignoring error %1 avcodec_send_packet after seek; will ignore %2 more", r, _errors_to_ignore); - return; - } - throw DecodeError (N_("avcodec_send_packet"), N_("FFmpegDecoder::decode_and_process_audio_packet"), r); + LOG_WARNING("avcodec_send_packet returned %1 for an audio packet", r); } - while (r >= 0) { r = avcodec_receive_frame (context, _frame); if (r == AVERROR(EAGAIN)) { @@ -552,11 +532,8 @@ FFmpegDecoder::decode_and_process_video_packet (AVPacket* packet) auto context = video_codec_context(); int r = avcodec_send_packet (context, packet); - if (r < 0 && !(r == AVERROR_EOF && !packet)) { - /* We could cope with AVERROR(EAGAIN) and re-send the packet but I think it should never happen. - * AVERROR_EOF can happen during flush if we've already sent a flush packet. - */ - throw DecodeError (N_("avcodec_send_packet"), N_("FFmpegDecoder::decode_and_process_video_packet"), r); + if (r < 0) { + LOG_WARNING("avcodec_send_packet returned %1 for a video packet", r); } r = avcodec_receive_frame (context, _frame); @@ -622,12 +599,14 @@ FFmpegDecoder::decode_and_process_subtitle_packet (AVPacket* packet) return; } + auto sub_period = subtitle_period (packet, ffmpeg_content()->subtitle_stream()->stream(_format_context), sub); + /* Stop any current subtitle, either at the time it was supposed to stop, or now if now is sooner */ if (_have_current_subtitle) { if (_current_subtitle_to) { - only_text()->emit_stop (min(*_current_subtitle_to, subtitle_period(sub).from + _pts_offset)); + only_text()->emit_stop (min(*_current_subtitle_to, sub_period.from + _pts_offset)); } else { - only_text()->emit_stop (subtitle_period(sub).from + _pts_offset); + only_text()->emit_stop (sub_period.from + _pts_offset); } _have_current_subtitle = false; } @@ -641,7 +620,6 @@ FFmpegDecoder::decode_and_process_subtitle_packet (AVPacket* packet) /* Subtitle PTS (within the source, not taking into account any of the source that we may have chopped off for the DCP). */ - auto sub_period = subtitle_period (sub); ContentTime from; from = sub_period.from + _pts_offset; if (sub_period.to) { @@ -683,7 +661,7 @@ FFmpegDecoder::process_bitmap_subtitle (AVSubtitleRect const * rect, ContentTime /* Note BGRA is expressed little-endian, so the first byte in the word is B, second G, third R, fourth A. */ - auto image = make_shared(AV_PIX_FMT_BGRA, dcp::Size (rect->w, rect->h), true); + auto image = make_shared(AV_PIX_FMT_BGRA, dcp::Size (rect->w, rect->h), Image::Alignment::PADDED); #ifdef DCPOMATIC_HAVE_AVSUBTITLERECT_PICT /* Start of the first line in the subtitle */