From b147c77c6d44399ad522298ac52a481fe5988287 Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Mon, 9 Nov 2015 23:11:54 +0000 Subject: [PATCH] Split FilterGraph into that and VideoFilterGraph. --- src/lib/ffmpeg_decoder.cc | 9 +-- src/lib/ffmpeg_decoder.h | 4 +- src/lib/filter_graph.cc | 69 ++++------------------ src/lib/filter_graph.h | 21 ++++--- src/lib/video_filter_graph.cc | 105 ++++++++++++++++++++++++++++++++++ src/lib/video_filter_graph.h | 37 ++++++++++++ src/lib/wscript | 1 + 7 files changed, 174 insertions(+), 72 deletions(-) create mode 100644 src/lib/video_filter_graph.cc create mode 100644 src/lib/video_filter_graph.h diff --git a/src/lib/ffmpeg_decoder.cc b/src/lib/ffmpeg_decoder.cc index c3a42545a..c393067ce 100644 --- a/src/lib/ffmpeg_decoder.cc +++ b/src/lib/ffmpeg_decoder.cc @@ -29,7 +29,7 @@ #include "ffmpeg_decoder.h" #include "ffmpeg_audio_stream.h" #include "ffmpeg_subtitle_stream.h" -#include "filter_graph.h" +#include "video_filter_graph.h" #include "audio_buffers.h" #include "ffmpeg_content.h" #include "raw_image_proxy.h" @@ -363,15 +363,16 @@ FFmpegDecoder::decode_video_packet () boost::mutex::scoped_lock lm (_filter_graphs_mutex); - shared_ptr graph; + shared_ptr graph; - list >::iterator i = _filter_graphs.begin(); + list >::iterator i = _filter_graphs.begin(); while (i != _filter_graphs.end() && !(*i)->can_process (dcp::Size (_frame->width, _frame->height), (AVPixelFormat) _frame->format)) { ++i; } if (i == _filter_graphs.end ()) { - graph.reset (new FilterGraph (_ffmpeg_content, dcp::Size (_frame->width, _frame->height), (AVPixelFormat) _frame->format)); + graph.reset (new VideoFilterGraph (dcp::Size (_frame->width, _frame->height), (AVPixelFormat) _frame->format)); + graph->setup (_ffmpeg_content->filters ()); _filter_graphs.push_back (graph); LOG_GENERAL (N_("New graph for %1x%2, pixel format %3"), _frame->width, _frame->height, _frame->format); } else { diff --git a/src/lib/ffmpeg_decoder.h b/src/lib/ffmpeg_decoder.h index dc0270cd0..1429c306b 100644 --- a/src/lib/ffmpeg_decoder.h +++ b/src/lib/ffmpeg_decoder.h @@ -34,7 +34,7 @@ extern "C" { #include class Log; -class FilterGraph; +class VideoFilterGraph; class FFmpegAudioStream; struct ffmpeg_pts_offset_test; @@ -70,7 +70,7 @@ private: boost::shared_ptr _log; - std::list > _filter_graphs; + std::list > _filter_graphs; boost::mutex _filter_graphs_mutex; ContentTime _pts_offset; diff --git a/src/lib/filter_graph.cc b/src/lib/filter_graph.cc index 7af247f66..3efb6970c 100644 --- a/src/lib/filter_graph.cc +++ b/src/lib/filter_graph.cc @@ -25,7 +25,6 @@ #include "filter.h" #include "exceptions.h" #include "image.h" -#include "ffmpeg_content.h" #include "safe_stringstream.h" #include "compose.hpp" extern "C" { @@ -44,6 +43,7 @@ using std::list; using std::pair; using std::make_pair; using std::cout; +using std::vector; using boost::shared_ptr; using boost::weak_ptr; using dcp::Size; @@ -53,15 +53,19 @@ using dcp::Size; * @param s Size of the images to process. * @param p Pixel format of the images to process. */ -FilterGraph::FilterGraph (shared_ptr content, dcp::Size s, AVPixelFormat p) +FilterGraph::FilterGraph () : _copy (false) , _buffer_src_context (0) , _buffer_sink_context (0) - , _size (s) - , _pixel_format (p) , _frame (0) { - string const filters = Filter::ffmpeg_string (content->filters()); + +} + +void +FilterGraph::setup (vector filters) +{ + string const filters_string = Filter::ffmpeg_string (filters); if (filters.empty ()) { _copy = true; return; @@ -84,21 +88,11 @@ FilterGraph::FilterGraph (shared_ptr content, dcp::Size s, throw DecodeError (N_("Could not create buffer sink filter")); } - SafeStringStream a; - a << "video_size=" << _size.width << "x" << _size.height << ":" - << "pix_fmt=" << _pixel_format << ":" - << "time_base=1/1:" - << "pixel_aspect=1/1"; - - if (avfilter_graph_create_filter (&_buffer_src_context, buffer_src, "in", a.str().c_str(), 0, graph) < 0) { + if (avfilter_graph_create_filter (&_buffer_src_context, buffer_src, "in", src_parameters().c_str(), 0, graph) < 0) { throw DecodeError (N_("could not create buffer source")); } - 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; + AVBufferSinkParams* sink_params = sink_parameters (); if (avfilter_graph_create_filter (&_buffer_sink_context, buffer_sink, N_("out"), 0, sink_params, graph) < 0) { throw DecodeError (N_("could not create buffer sink.")); @@ -118,7 +112,7 @@ FilterGraph::FilterGraph (shared_ptr content, dcp::Size s, inputs->pad_idx = 0; inputs->next = 0; - if (avfilter_graph_parse (graph, filters.c_str(), inputs, outputs, 0) < 0) { + if (avfilter_graph_parse (graph, filters_string.c_str(), inputs, outputs, 0) < 0) { throw DecodeError (N_("could not set up filter graph.")); } @@ -133,42 +127,3 @@ FilterGraph::~FilterGraph () av_frame_free (&_frame); } } - -/** 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> > -FilterGraph::process (AVFrame* frame) -{ - list, int64_t> > images; - - if (_copy) { - images.push_back (make_pair (shared_ptr (new Image (frame)), av_frame_get_best_effort_timestamp (frame))); - } 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)); - } - - while (true) { - if (av_buffersink_get_frame (_buffer_sink_context, _frame) < 0) { - break; - } - - images.push_back (make_pair (shared_ptr (new Image (_frame)), av_frame_get_best_effort_timestamp (_frame))); - av_frame_unref (_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. - */ -bool -FilterGraph::can_process (dcp::Size s, AVPixelFormat p) const -{ - return (_size == s && _pixel_format == p); -} diff --git a/src/lib/filter_graph.h b/src/lib/filter_graph.h index 8a8dd9a30..073340637 100644 --- a/src/lib/filter_graph.h +++ b/src/lib/filter_graph.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2012 Carl Hetherington + Copyright (C) 2012-2015 Carl Hetherington This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -25,11 +25,14 @@ #define DCPOMATIC_FILTER_GRAPH_H #include "util.h" +extern "C" { +#include +} struct AVFilterContext; struct AVFrame; class Image; -class FFmpegContent; +class Filter; /** @class FilterGraph * @brief A graph of FFmpeg filters. @@ -37,19 +40,19 @@ class FFmpegContent; class FilterGraph : public boost::noncopyable { public: - FilterGraph (boost::shared_ptr content, dcp::Size s, AVPixelFormat p); - ~FilterGraph (); + FilterGraph (); + virtual ~FilterGraph (); - bool can_process (dcp::Size s, AVPixelFormat p) const; - std::list, int64_t> > process (AVFrame * frame); + void setup (std::vector); + +protected: + virtual std::string src_parameters () const = 0; + virtual AVBufferSinkParams* sink_parameters () const = 0; -private: /** true if this graph has no filters in, so it just copies stuff straight through */ bool _copy; AVFilterContext* _buffer_src_context; AVFilterContext* _buffer_sink_context; - dcp::Size _size; ///< size of the images that this chain can process - AVPixelFormat _pixel_format; ///< pixel format of the images that this chain can process AVFrame* _frame; }; diff --git a/src/lib/video_filter_graph.cc b/src/lib/video_filter_graph.cc new file mode 100644 index 000000000..306a17a5d --- /dev/null +++ b/src/lib/video_filter_graph.cc @@ -0,0 +1,105 @@ +/* + Copyright (C) 2012-2015 Carl Hetherington + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include "video_filter_graph.h" +#include "image.h" +#include "compose.hpp" +extern "C" { +#include +#include +} + +#include "i18n.h" + +using std::list; +using std::pair; +using std::vector; +using std::string; +using std::make_pair; +using boost::shared_ptr; + +VideoFilterGraph::VideoFilterGraph (dcp::Size s, AVPixelFormat p) + : _size (s) + , _pixel_format (p) +{ + +} + +/** 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> > +VideoFilterGraph::process (AVFrame* frame) +{ + list, int64_t> > images; + + if (_copy) { + images.push_back (make_pair (shared_ptr (new Image (frame)), av_frame_get_best_effort_timestamp (frame))); + } 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)); + } + + while (true) { + if (av_buffersink_get_frame (_buffer_sink_context, _frame) < 0) { + break; + } + + images.push_back (make_pair (shared_ptr (new Image (_frame)), av_frame_get_best_effort_timestamp (_frame))); + av_frame_unref (_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. + */ +bool +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 (); +} + +AVBufferSinkParams * +VideoFilterGraph::sink_parameters () 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; +} diff --git a/src/lib/video_filter_graph.h b/src/lib/video_filter_graph.h new file mode 100644 index 000000000..08de557ca --- /dev/null +++ b/src/lib/video_filter_graph.h @@ -0,0 +1,37 @@ +/* + Copyright (C) 2012-2015 Carl Hetherington + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include "filter_graph.h" + +class VideoFilterGraph : public FilterGraph +{ +public: + VideoFilterGraph (dcp::Size s, AVPixelFormat p); + + bool can_process (dcp::Size s, AVPixelFormat p) const; + std::list, int64_t> > process (AVFrame * frame); + +protected: + std::string src_parameters () const; + AVBufferSinkParams* sink_parameters () const; + +private: + dcp::Size _size; ///< size of the images that this chain can process + AVPixelFormat _pixel_format; ///< pixel format of the images that this chain can process +}; diff --git a/src/lib/wscript b/src/lib/wscript index 263d222c2..315190307 100644 --- a/src/lib/wscript +++ b/src/lib/wscript @@ -134,6 +134,7 @@ sources = """ video_content.cc video_content_scale.cc video_decoder.cc + video_filter_graph.cc writer.cc """ -- 2.30.2