X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;ds=sidebyside;f=src%2Flib%2Fvideo_filter_graph.cc;h=1cc1425202d190f6c5937a16fb4fd29d209bd7a1;hb=HEAD;hp=6075500e9d9148f5af103e9f56f6034dbdc3ab58;hpb=255562e13056c967ca969d6762024166500d8038;p=dcpomatic.git diff --git a/src/lib/video_filter_graph.cc b/src/lib/video_filter_graph.cc index 6075500e9..d5840c6d3 100644 --- a/src/lib/video_filter_graph.cc +++ b/src/lib/video_filter_graph.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2018 Carl Hetherington + Copyright (C) 2012-2021 Carl Hetherington This file is part of DCP-o-matic. @@ -18,22 +18,29 @@ */ -#include "video_filter_graph.h" -#include "image.h" + #include "compose.hpp" +#include "dcpomatic_assert.h" +#include "exceptions.h" +#include "image.h" +#include "video_filter_graph.h" +#include extern "C" { #include #include +#include } #include "i18n.h" + using std::list; +using std::make_pair; +using std::make_shared; using std::pair; -using std::vector; +using std::shared_ptr; using std::string; -using std::make_pair; -using boost::shared_ptr; + VideoFilterGraph::VideoFilterGraph (dcp::Size s, AVPixelFormat p, dcp::Fraction r) : _size (s) @@ -43,20 +50,64 @@ VideoFilterGraph::VideoFilterGraph (dcp::Size s, AVPixelFormat p, dcp::Fraction } + +list> +VideoFilterGraph::process(shared_ptr image) +{ + if (_copy) { + return { image }; + } + + auto frame = av_frame_alloc(); + if (!frame) { + throw std::bad_alloc(); + } + + dcp::ScopeGuard sg = [&frame]() { av_frame_free(&frame); }; + + for (int i = 0; i < image->planes(); ++i) { + frame->data[i] = image->data()[i]; + frame->linesize[i] = image->stride()[i]; + } + + frame->width = image->size().width; + frame->height = image->size().height; + frame->format = image->pixel_format(); + + int r = av_buffersrc_write_frame(_buffer_src_context, frame); + if (r < 0) { + throw DecodeError(String::compose(N_("could not push buffer into filter chain (%1)."), r)); + } + + list> images; + + while (true) { + if (av_buffersink_get_frame(_buffer_sink_context, _frame) < 0) { + break; + } + + images.push_back(make_shared(_frame, Image::Alignment::PADDED)); + av_frame_unref (_frame); + } + + return images; +} + + /** Take an AVFrame and process it using our configured filters, returning a * set of Images. Caller handles memory management of the input frame. */ -list, int64_t> > +list, int64_t>> VideoFilterGraph::process (AVFrame* frame) { - list, int64_t> > images; + list, int64_t>> images; if (_copy) { - images.push_back (make_pair (shared_ptr (new Image (frame)), av_frame_get_best_effort_timestamp (frame))); + images.push_back (make_pair(make_shared(frame, Image::Alignment::PADDED), frame->best_effort_timestamp)); } else { int r = av_buffersrc_write_frame (_buffer_src_context, frame); if (r < 0) { - throw DecodeError (String::compose (N_("could not push buffer into filter chain (%1)."), r)); + throw DecodeError (String::compose(N_("could not push buffer into filter chain (%1)."), r)); } while (true) { @@ -64,7 +115,7 @@ VideoFilterGraph::process (AVFrame* frame) break; } - images.push_back (make_pair (shared_ptr (new Image (_frame)), av_frame_get_best_effort_timestamp (_frame))); + images.push_back (make_pair(make_shared(_frame, Image::Alignment::PADDED), frame->best_effort_timestamp)); av_frame_unref (_frame); } } @@ -72,6 +123,7 @@ VideoFilterGraph::process (AVFrame* frame) return images; } + /** @param s Image size. * @param p Pixel format. * @return true if this chain can process images with `s' and `p', otherwise false. @@ -82,6 +134,7 @@ VideoFilterGraph::can_process (dcp::Size s, AVPixelFormat p) const return (_size == s && _pixel_format == p); } + string VideoFilterGraph::src_parameters () const { @@ -96,23 +149,23 @@ VideoFilterGraph::src_parameters () const return buffer; } -void * -VideoFilterGraph::sink_parameters () const + +void +VideoFilterGraph::set_parameters (AVFilterContext* context) const { - AVBufferSinkParams* sink_params = av_buffersink_params_alloc (); - AVPixelFormat* pixel_fmts = new AVPixelFormat[2]; - pixel_fmts[0] = _pixel_format; - pixel_fmts[1] = AV_PIX_FMT_NONE; - sink_params->pixel_fmts = pixel_fmts; - return sink_params; + AVPixelFormat pix_fmts[] = { _pixel_format, AV_PIX_FMT_NONE }; + int r = av_opt_set_int_list (context, "pix_fmts", pix_fmts, AV_PIX_FMT_NONE, AV_OPT_SEARCH_CHILDREN); + DCPOMATIC_ASSERT (r >= 0); } + string VideoFilterGraph::src_name () const { return "buffer"; } + string VideoFilterGraph::sink_name () const {