X-Git-Url: https://git.carlh.net/gitweb/?a=blobdiff_plain;f=src%2Flib%2Fvideo_filter_graph.cc;h=26f858437173294e80cb1691b708ab6ae000254e;hb=323b8cbb0b95297fbd027ffdc4ea5003b59ef25f;hp=201150560bb1ffaae82a7c72e8c97c3682a2eab1;hpb=a8a0dfd1b21de6c0facf965ab119833ff6f790bf;p=dcpomatic.git diff --git a/src/lib/video_filter_graph.cc b/src/lib/video_filter_graph.cc index 201150560..26f858437 100644 --- a/src/lib/video_filter_graph.cc +++ b/src/lib/video_filter_graph.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2015 Carl Hetherington + Copyright (C) 2012-2021 Carl Hetherington This file is part of DCP-o-matic. @@ -18,44 +18,94 @@ */ -#include "video_filter_graph.h" -#include "image.h" + #include "compose.hpp" +#include "image.h" +#include "scope_guard.h" +#include "video_filter_graph.h" 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) + +VideoFilterGraph::VideoFilterGraph (dcp::Size s, AVPixelFormat p, dcp::Fraction r) : _size (s) , _pixel_format (p) + , _frame_rate (r) { } + +list> +VideoFilterGraph::process(shared_ptr image) +{ + if (_copy) { + return { image }; + } + + auto frame = av_frame_alloc(); + if (!frame) { + throw std::bad_alloc(); + } + + 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) { @@ -63,7 +113,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); } } @@ -71,6 +121,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. @@ -81,40 +132,40 @@ VideoFilterGraph::can_process (dcp::Size s, AVPixelFormat p) const return (_size == s && _pixel_format == p); } + string VideoFilterGraph::src_parameters () const { - SafeStringStream a; - - a << "video_size=" << _size.width << "x" << _size.height << ":" - << "pix_fmt=" << _pixel_format << ":" - << "time_base=1/1:" - << "pixel_aspect=1/1"; - - return a.str (); + char buffer[256]; + snprintf ( + buffer, sizeof(buffer), + "video_size=%dx%d:pix_fmt=%d:frame_rate=%d/%d:time_base=1/1:pixel_aspect=1/1", + _size.width, _size.height, + _pixel_format, + _frame_rate.numerator, _frame_rate.denominator + ); + 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 = 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 { return "buffersink"; } -