Only offer filters and postproc that exist.
[dcpomatic.git] / src / lib / filter.cc
1 /*
2     Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 */
19
20 /** @file src/filter.cc
21  *  @brief A class to describe one of FFmpeg's video or post-processing filters.
22  */
23
24 #include "filter.h"
25 extern "C" {
26 #include <libavfilter/avfilter.h>
27 #include <libpostproc/postprocess.h>
28 }
29
30 using namespace std;
31
32 vector<Filter const *> Filter::_filters;
33
34 /** @param i Our id.
35  *  @param n User-visible name.
36  *  @param v String for a FFmpeg video filter descriptor, or "".
37  *  @param p String for a FFmpeg post-processing descriptor, or "".
38  */
39 Filter::Filter (string i, string n, string v, string p)
40         : _id (i)
41         , _name (n)
42         , _vf (v)
43         , _pp (p)
44 {
45
46 }
47
48 /** @return All available filters */
49 vector<Filter const *>
50 Filter::all ()
51 {
52         return _filters;
53 }
54
55
56 /** Set up the static _filters vector; must be called before from_*
57  *  methods are used.
58  */
59 void
60 Filter::setup_filters ()
61 {
62         /* Note: "none" is a magic id name, so don't use it here */
63            
64         maybe_add ("pphb", "Horizontal deblocking filter", "", "hb");
65         maybe_add ("ppvb", "Vertical deblocking filter", "", "vb");
66         maybe_add ("ppha", "Horizontal deblocking filter A", "", "ha");
67         maybe_add ("ppva", "Vertical deblocking filter A", "", "va");
68         maybe_add ("pph1", "Experimental horizontal deblocking filter 1", "", "h1");
69         maybe_add ("pphv", "Experimental vertical deblocking filter 1", "", "v1");
70         maybe_add ("ppdr", "Deringing filter", "", "dr");
71         maybe_add ("pplb", "Linear blend deinterlacer", "", "lb");
72         maybe_add ("ppli", "Linear interpolating deinterlacer", "", "li");
73         maybe_add ("ppci", "Cubic interpolating deinterlacer", "", "ci");
74         maybe_add ("ppmd", "Median deinterlacer", "", "md");
75         maybe_add ("ppfd", "FFMPEG deinterlacer", "", "fd");
76         maybe_add ("ppl5", "FIR low-pass deinterlacer", "", "l5");
77         maybe_add ("mcdeint", "Motion compensating deinterlacer", "mcdeint", "");
78         maybe_add ("kerndeint", "Kernel deinterlacer", "kerndeint", "");
79         maybe_add ("yadif", "Yet Another Deinterlacing Filter", "yadif", "");
80         maybe_add ("pptn", "Temporal noise reducer", "", "tn");
81         maybe_add ("ppfq", "Force quantizer", "", "fq");
82         maybe_add ("gradfun", "Gradient debander", "gradfun", "");
83         maybe_add ("unsharp", "Unsharp mask and Gaussian blur", "unsharp", "");
84         maybe_add ("denoise3d", "3D denoiser", "denoise3d", "");
85         maybe_add ("hqdn3d", "High quality 3D denoiser", "hqdn3d", "");
86         maybe_add ("telecine", "Telecine filter", "telecine", "");
87         maybe_add ("ow", "Overcomplete wavelet denoiser", "mp=ow", "");
88 }
89
90 void
91 Filter::maybe_add (string i, string n, string v, string p)
92 {
93         if (!v.empty ()) {
94                 if (avfilter_get_by_name (i.c_str())) {
95                         _filters.push_back (new Filter (i, n, v, p));
96                 }
97         } else if (!p.empty ()) {
98                 pp_mode* m = pp_get_mode_by_name_and_quality (p.c_str(), PP_QUALITY_MAX);
99                 if (m) {
100                         _filters.push_back (new Filter (i, n, v, p));
101                         pp_free_mode (m);
102                 }
103         }
104 }
105
106 /** @param filters Set of filters.
107  *  @return A pair; .first is a string to pass to FFmpeg for the video filters,
108  *  .second is a string to pass for the post-processors.
109  */
110 pair<string, string>
111 Filter::ffmpeg_strings (vector<Filter const *> const & filters)
112 {
113         string vf;
114         string pp;
115
116         for (vector<Filter const *>::const_iterator i = filters.begin(); i != filters.end(); ++i) {
117                 if (!(*i)->vf().empty ()) {
118                         if (!vf.empty ()) {
119                                 vf += ",";
120                         }
121                         vf += (*i)->vf ();
122                 }
123                 
124                 if (!(*i)->pp().empty ()) {
125                         if (!pp.empty()) {
126                                 pp += ",";
127                         }
128                         pp += (*i)->pp ();
129                 }
130         }
131
132         return make_pair (vf, pp);
133 }
134
135 /** @param d Our id.
136  *  @return Corresponding Filter, or 0.
137  */
138 Filter const *
139 Filter::from_id (string d)
140 {
141         vector<Filter const *>::iterator i = _filters.begin ();
142         while (i != _filters.end() && (*i)->id() != d) {
143                 ++i;
144         }
145
146         if (i == _filters.end ()) {
147                 return 0;
148         }
149
150         return *i;
151 }
152