Tidy up filters dialog; don't show non-existant ones, and categorise them.
[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 c User-visible category.
37  *  @param v String for a FFmpeg video filter descriptor, or "".
38  *  @param p String for a FFmpeg post-processing descriptor, or "".
39  */
40 Filter::Filter (string i, string n, string c, string v, string p)
41         : _id (i)
42         , _name (n)
43         , _category (c)
44         , _vf (v)
45         , _pp (p)
46 {
47
48 }
49
50 /** @return All available filters */
51 vector<Filter const *>
52 Filter::all ()
53 {
54         return _filters;
55 }
56
57
58 /** Set up the static _filters vector; must be called before from_*
59  *  methods are used.
60  */
61 void
62 Filter::setup_filters ()
63 {
64         /* Note: "none" is a magic id name, so don't use it here */
65            
66         maybe_add ("pphb",      "Horizontal deblocking filter",                "De-blocking",     "",          "hb");
67         maybe_add ("ppvb",      "Vertical deblocking filter",                  "De-blocking",     "",          "vb");
68         maybe_add ("ppha",      "Horizontal deblocking filter A",              "De-blocking",     "",          "ha");
69         maybe_add ("ppva",      "Vertical deblocking filter A",                "De-blocking",     "",          "va");
70         maybe_add ("pph1",      "Experimental horizontal deblocking filter 1", "De-blocking",     "",          "h1");
71         maybe_add ("pphv",      "Experimental vertical deblocking filter 1",   "De-blocking",     "",          "v1");
72         maybe_add ("ppdr",      "Deringing filter",                            "Misc",            "",          "dr");
73         maybe_add ("pplb",      "Linear blend deinterlacer",                   "De-interlacing",  "",          "lb");
74         maybe_add ("ppli",      "Linear interpolating deinterlacer",           "De-interlacing",  "",          "li");
75         maybe_add ("ppci",      "Cubic interpolating deinterlacer",            "De-interlacing",  "",          "ci");
76         maybe_add ("ppmd",      "Median deinterlacer",                         "De-interlacing",  "",          "md");
77         maybe_add ("ppfd",      "FFMPEG deinterlacer",                         "De-interlacing",  "",          "fd");
78         maybe_add ("ppl5",      "FIR low-pass deinterlacer",                   "De-interlacing",  "",          "l5");
79         maybe_add ("mcdeint",   "Motion compensating deinterlacer",            "De-interlacing",  "mcdeint",   "");
80         maybe_add ("kerndeint", "Kernel deinterlacer",                         "De-interlacing",  "kerndeint", "");
81         maybe_add ("yadif",     "Yet Another Deinterlacing Filter",            "De-interlacing",  "yadif",     "");
82         maybe_add ("pptn",      "Temporal noise reducer",                      "Noise reduction", "",          "tn");
83         maybe_add ("ppfq",      "Force quantizer",                             "Misc",            "",          "fq");
84         maybe_add ("gradfun",   "Gradient debander",                           "Misc",            "gradfun",   "");
85         maybe_add ("unsharp",   "Unsharp mask and Gaussian blur",              "Misc",            "unsharp",   "");
86         maybe_add ("denoise3d", "3D denoiser",                                 "Noise reduction", "denoise3d", "");
87         maybe_add ("hqdn3d",    "High quality 3D denoiser",                    "Noise reduction", "hqdn3d",    "");
88         maybe_add ("telecine",  "Telecine filter",                             "Misc",            "telecine",  "");
89         maybe_add ("ow",        "Overcomplete wavelet denoiser",               "Noise reduction", "mp=ow",     "");
90 }
91
92 void
93 Filter::maybe_add (string i, string n, string c, string v, string p)
94 {
95         if (!v.empty ()) {
96                 if (avfilter_get_by_name (i.c_str())) {
97                         _filters.push_back (new Filter (i, n, c, v, p));
98                 }
99         } else if (!p.empty ()) {
100                 pp_mode* m = pp_get_mode_by_name_and_quality (p.c_str(), PP_QUALITY_MAX);
101                 if (m) {
102                         _filters.push_back (new Filter (i, n, c, v, p));
103                         pp_free_mode (m);
104                 }
105         }
106 }
107
108 /** @param filters Set of filters.
109  *  @return A pair; .first is a string to pass to FFmpeg for the video filters,
110  *  .second is a string to pass for the post-processors.
111  */
112 pair<string, string>
113 Filter::ffmpeg_strings (vector<Filter const *> const & filters)
114 {
115         string vf;
116         string pp;
117
118         for (vector<Filter const *>::const_iterator i = filters.begin(); i != filters.end(); ++i) {
119                 if (!(*i)->vf().empty ()) {
120                         if (!vf.empty ()) {
121                                 vf += ",";
122                         }
123                         vf += (*i)->vf ();
124                 }
125                 
126                 if (!(*i)->pp().empty ()) {
127                         if (!pp.empty()) {
128                                 pp += ",";
129                         }
130                         pp += (*i)->pp ();
131                 }
132         }
133
134         return make_pair (vf, pp);
135 }
136
137 /** @param d Our id.
138  *  @return Corresponding Filter, or 0.
139  */
140 Filter const *
141 Filter::from_id (string d)
142 {
143         vector<Filter const *>::iterator i = _filters.begin ();
144         while (i != _filters.end() && (*i)->id() != d) {
145                 ++i;
146         }
147
148         if (i == _filters.end ()) {
149                 return 0;
150         }
151
152         return *i;
153 }
154