Split FilterGraph into that and VideoFilterGraph.
authorCarl Hetherington <cth@carlh.net>
Mon, 9 Nov 2015 23:11:54 +0000 (23:11 +0000)
committerCarl Hetherington <cth@carlh.net>
Wed, 18 Nov 2015 20:51:16 +0000 (20:51 +0000)
src/lib/ffmpeg_decoder.cc
src/lib/ffmpeg_decoder.h
src/lib/filter_graph.cc
src/lib/filter_graph.h
src/lib/video_filter_graph.cc [new file with mode: 0644]
src/lib/video_filter_graph.h [new file with mode: 0644]
src/lib/wscript

index c3a42545a6ed695a97a06257971e9bd71fae6059..c393067ce376fbe11fcd8266e8195dedb7f88b83 100644 (file)
@@ -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<FilterGraph> graph;
+       shared_ptr<VideoFilterGraph> graph;
 
-       list<shared_ptr<FilterGraph> >::iterator i = _filter_graphs.begin();
+       list<shared_ptr<VideoFilterGraph> >::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 {
index dc0270cd0d4ba4433077e361b6b8d208d841b09e..1429c306b7429acb379a63c94b861321a5d59b73 100644 (file)
@@ -34,7 +34,7 @@ extern "C" {
 #include <stdint.h>
 
 class Log;
-class FilterGraph;
+class VideoFilterGraph;
 class FFmpegAudioStream;
 struct ffmpeg_pts_offset_test;
 
@@ -70,7 +70,7 @@ private:
 
        boost::shared_ptr<Log> _log;
 
-       std::list<boost::shared_ptr<FilterGraph> > _filter_graphs;
+       std::list<boost::shared_ptr<VideoFilterGraph> > _filter_graphs;
        boost::mutex _filter_graphs_mutex;
 
        ContentTime _pts_offset;
index 7af247f669f64f7fb022843f9af994a3a6d5887f..3efb6970cbf75d893428cc5f76f963cfa2d186fe 100644 (file)
@@ -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<const FFmpegContent> 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<Filter const *> filters)
+{
+       string const filters_string = Filter::ffmpeg_string (filters);
        if (filters.empty ()) {
                _copy = true;
                return;
@@ -84,21 +88,11 @@ FilterGraph::FilterGraph (shared_ptr<const FFmpegContent> 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<const FFmpegContent> 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<pair<shared_ptr<Image>, int64_t> >
-FilterGraph::process (AVFrame* frame)
-{
-       list<pair<shared_ptr<Image>, int64_t> > images;
-
-       if (_copy) {
-               images.push_back (make_pair (shared_ptr<Image> (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<Image> (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);
-}
index 8a8dd9a30e4da857fc46ccff6f649ad53aa8669f..07334063780b31fff1dcfb054bf35dbe2f86a383 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
+    Copyright (C) 2012-2015 Carl Hetherington <cth@carlh.net>
 
     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
 #define DCPOMATIC_FILTER_GRAPH_H
 
 #include "util.h"
+extern "C" {
+#include <libavfilter/buffersink.h>
+}
 
 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<const FFmpegContent> content, dcp::Size s, AVPixelFormat p);
-       ~FilterGraph ();
+       FilterGraph ();
+       virtual ~FilterGraph ();
 
-       bool can_process (dcp::Size s, AVPixelFormat p) const;
-       std::list<std::pair<boost::shared_ptr<Image>, int64_t> > process (AVFrame * frame);
+       void setup (std::vector<Filter const *>);
+
+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 (file)
index 0000000..306a17a
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+    Copyright (C) 2012-2015 Carl Hetherington <cth@carlh.net>
+
+    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 <libavfilter/buffersrc.h>
+#include <libavfilter/buffersink.h>
+}
+
+#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<pair<shared_ptr<Image>, int64_t> >
+VideoFilterGraph::process (AVFrame* frame)
+{
+       list<pair<shared_ptr<Image>, int64_t> > images;
+
+       if (_copy) {
+               images.push_back (make_pair (shared_ptr<Image> (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<Image> (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 (file)
index 0000000..08de557
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+    Copyright (C) 2012-2015 Carl Hetherington <cth@carlh.net>
+
+    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<std::pair<boost::shared_ptr<Image>, 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
+};
index 263d222c2f71813ae72e844b0a6dd0cb942a044d..315190307baecb6429703d402e64b955097f1564 100644 (file)
@@ -134,6 +134,7 @@ sources = """
           video_content.cc
           video_content_scale.cc
           video_decoder.cc
+          video_filter_graph.cc
           writer.cc
           """