Cleanup: clarify some namespace use.
[dcpomatic.git] / src / lib / filter.cc
1 /*
2     Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net>
3
4     This file is part of DCP-o-matic.
5
6     DCP-o-matic is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10
11     DCP-o-matic is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15
16     You should have received a copy of the GNU General Public License
17     along with DCP-o-matic.  If not, see <http://www.gnu.org/licenses/>.
18
19 */
20
21
22 /** @file src/filter.cc
23  *  @brief A class to describe one of FFmpeg's video or audio filters.
24  */
25
26
27 #include "dcpomatic_assert.h"
28 #include "filter.h"
29 #include <dcp/warnings.h>
30 LIBDCP_DISABLE_WARNINGS
31 extern "C" {
32 #include <libavfilter/avfilter.h>
33 }
34 LIBDCP_ENABLE_WARNINGS
35 #include <algorithm>
36
37 #include "i18n.h"
38
39
40 using std::string;
41 using std::vector;
42 using boost::optional;
43
44
45 vector<Filter> Filter::_filters;
46
47
48 /** @param id Our id.
49  *  @param name User-visible name.
50  *  @param category User-visible category.
51  *  @param ffmpeg_string String for a FFmpeg filter descriptor.
52  */
53 Filter::Filter(string id, string name, string category, string ffmpeg_string)
54         : _id(id)
55         , _name(name)
56         , _category(category)
57         , _ffmpeg(ffmpeg_string)
58 {
59
60 }
61
62
63 /** @return All available filters */
64 vector<Filter>
65 Filter::all ()
66 {
67         return _filters;
68 }
69
70
71 /** Set up the static _filters vector; must be called before from_*
72  *  methods are used.
73  */
74 void
75 Filter::setup_filters ()
76 {
77         /* Note: "none" is a magic id name, so don't use it here */
78
79         auto maybe_add = [](string id, string name, string category, string ffmpeg)
80         {
81                 string check_name = ffmpeg;
82                 size_t end = check_name.find("=");
83                 if (end != string::npos) {
84                         check_name = check_name.substr(0, end);
85                 }
86
87                 if (avfilter_get_by_name(check_name.c_str())) {
88                         _filters.push_back(Filter(id, name, category, ffmpeg));
89                 }
90         };
91
92         maybe_add (N_("vflip"),       _("Vertical flip"),                    _("Orientation"),     N_("vflip"));
93         maybe_add (N_("hflip"),       _("Horizontal flip"),                  _("Orientation"),     N_("hflip"));
94         maybe_add (N_("90clock"),     _("Rotate 90 degrees clockwise"),      _("Orientation"),     N_("transpose=dir=clock"));
95         maybe_add (N_("90anticlock"), _("Rotate 90 degrees anti-clockwise"), _("Orientation"),     N_("transpose=dir=cclock"));
96         maybe_add (N_("mcdeint"),     _("Motion compensating deinterlacer"), _("De-interlacing"),  N_("mcdeint"));
97         maybe_add (N_("kerndeint"),   _("Kernel deinterlacer"),              _("De-interlacing"),  N_("kerndeint"));
98         maybe_add (N_("yadif"),       _("Yet Another Deinterlacing Filter"), _("De-interlacing"),  N_("yadif"));
99         maybe_add (N_("bwdif"),       _("Bob Weaver Deinterlacing Filter"),  _("De-interlacing"),  N_("bwdif"));
100         maybe_add (N_("weave"),       _("Weave filter"),                     _("De-interlacing"),  N_("weave"));
101         maybe_add (N_("gradfun"),     _("Gradient debander"),                _("Misc"),            N_("gradfun"));
102         maybe_add (N_("unsharp"),     _("Unsharp mask and Gaussian blur"),   _("Misc"),            N_("unsharp"));
103         maybe_add (N_("denoise3d"),   _("3D denoiser"),                      _("Noise reduction"), N_("denoise3d"));
104         maybe_add (N_("hqdn3d"),      _("High quality 3D denoiser"),         _("Noise reduction"), N_("hqdn3d"));
105         maybe_add (N_("telecine"),    _("Telecine filter"),                  _("Misc"),            N_("telecine"));
106         maybe_add (N_("ow"),          _("Overcomplete wavelet denoiser"),    _("Noise reduction"), N_("mp=ow"));
107         maybe_add (N_("premultiply"), _("Premultiply alpha channel"),        _("Misc"),            N_("premultiply=inplace=1"));
108 }
109
110
111 /** @param filters Set of filters.
112  *  @return String to pass to FFmpeg for the video filters.
113  */
114 string
115 Filter::ffmpeg_string(vector<Filter> const& filters)
116 {
117         string ff;
118
119         for (auto const& i: filters) {
120                 if (!ff.empty ()) {
121                         ff += N_(",");
122                 }
123                 ff += i.ffmpeg();
124         }
125
126         return ff;
127 }
128
129
130 /** @param d Our id.
131  *  @return Corresponding Filter, if found.
132  */
133 optional<Filter>
134 Filter::from_id(string id)
135 {
136         auto iter = std::find_if(_filters.begin(), _filters.end(), [id](Filter const& filter) { return filter.id() == id; });
137         if (iter == _filters.end()) {
138                 return {};
139         }
140         return *iter;
141 }
142
143
144 bool
145 operator==(Filter const& a, Filter const& b)
146 {
147         return a.id() == b.id() && a.name() == b.name() && a.category() == b.category() && a.ffmpeg() == b.ffmpeg();
148 }
149
150
151 bool
152 operator!=(Filter const& a, Filter const& b)
153 {
154         return a.id() != b.id() || a.name() != b.name() || a.category() != b.category() || a.ffmpeg() != b.ffmpeg();
155 }
156
157
158 bool
159 operator<(Filter const& a, Filter const& b)
160 {
161         if (a.id() != b.id()) {
162                 return a.id() < b.id();
163         }
164
165         if (a.name() != b.name()) {
166                 return a.name() < b.name();
167         }
168
169         if (a.category() != b.category()) {
170                 return a.category() < b.category();
171         }
172
173         return a.ffmpeg() < b.ffmpeg();
174 }