GCC Code Coverage Report


Directory: avs_core/
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 84.0% 178 / 0 / 212
Functions: 83.3% 25 / 0 / 30
Branches: 71.3% 164 / 0 / 230

convert/convert_helper.cpp
Line Branch Exec Source
1 // Avisynth v2.5. Copyright 2002-2009 Ben Rudiak-Gould et al.
2 // http://avisynth.nl
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, or visit
17 // http://www.gnu.org/copyleft/gpl.html .
18 //
19 // Linking Avisynth statically or dynamically with other modules is making a
20 // combined work based on Avisynth. Thus, the terms and conditions of the GNU
21 // General Public License cover the whole combination.
22 //
23 // As a special exception, the copyright holders of Avisynth give you
24 // permission to link Avisynth with independent modules that communicate with
25 // Avisynth solely through the interfaces defined in avisynth.h, regardless of the license
26 // terms of these independent modules, and to copy and distribute the
27 // resulting combined work under terms of your choice, provided that
28 // every copy of the combined work is accompanied by a complete copy of
29 // the source code of Avisynth (the version of Avisynth used to produce the
30 // combined work), being distributed under the terms of the GNU General
31 // Public License plus this exception. An independent module is a module
32 // which is not derived from or based on Avisynth, such as 3rd-party filters,
33 // import and export plugins, or graphical user interfaces.
34
35
36 #include <avisynth.h>
37 #ifdef AVS_WINDOWS
38 #include <avs/win.h>
39 #else
40 #include <avs/posix.h>
41 #endif
42
43 #include "convert_matrix.h"
44 #include "convert_helper.h"
45
46 #include <unordered_map>
47 #include <iostream>
48 #include <vector>
49 #include <sstream>
50
51 const std::vector<std::pair<const char*, ColorRange_Compat_e>> g_range_table{
52 { "limited", AVS_COLORRANGE_LIMITED },
53 { "full", AVS_COLORRANGE_FULL },
54 { "l", AVS_COLORRANGE_LIMITED },
55 { "f", AVS_COLORRANGE_FULL },
56 };
57
58 const std::vector<std::pair<const char*, ChromaLocation_e>> g_chromaloc_table{
59 { "left", AVS_CHROMA_LEFT },
60 { "center", AVS_CHROMA_CENTER },
61 { "top_left", AVS_CHROMA_TOP_LEFT },
62 { "top", AVS_CHROMA_TOP }, // not used in Avisynth
63 { "bottom_left", AVS_CHROMA_BOTTOM_LEFT }, // not used in Avisynth
64 { "bottom", AVS_CHROMA_BOTTOM }, // not used in Avisynth
65 { "dv", AVS_CHROMA_DV }, // Special to Avisynth
66 // compatibility
67 { "mpeg1", AVS_CHROMA_CENTER },
68 { "mpeg2", AVS_CHROMA_LEFT },
69 { "jpeg", AVS_CHROMA_CENTER },
70 };
71
72 // unlike Avisynth conventions, the strings do not contain hints on full or limited range
73 // e.g. PC.709 or Rec709
74 const std::vector<std::pair<const char*, Matrix_e>> g_matrix_table{
75 { "rgb", AVS_MATRIX_RGB },
76 { "709", AVS_MATRIX_BT709 },
77 { "unspec", AVS_MATRIX_UNSPECIFIED },
78 { "170m", AVS_MATRIX_ST170_M },
79 { "240m", AVS_MATRIX_ST240_M },
80 { "470bg", AVS_MATRIX_BT470_BG },
81 { "fcc", AVS_MATRIX_BT470_M },
82 { "470m", AVS_MATRIX_BT470_M }, // as of 20211111 name is an add-on in Avisynth+
83 { "ycgco", AVS_MATRIX_YCGCO },
84 { "2020ncl", AVS_MATRIX_BT2020_NCL },
85 { "2020cl", AVS_MATRIX_BT2020_CL },
86 { "chromacl", AVS_MATRIX_CHROMATICITY_DERIVED_CL },
87 { "chromancl", AVS_MATRIX_CHROMATICITY_DERIVED_NCL },
88 { "ictcp", AVS_MATRIX_ICTCP },
89 // compatibility
90 { "601", AVS_MATRIX_BT470_BG },
91 { "2020", AVS_MATRIX_BT2020_NCL },
92 };
93
94 // old Avisynth "matrix" parameter strings
95 const std::vector<std::pair<const char*, Old_Avs_Matrix_e>> g_old_avs_matrix_table{
96 { "rec601", AVS_OLD_MATRIX_Rec601 },
97 { "rec709", AVS_OLD_MATRIX_Rec709 },
98 { "pc.601", AVS_OLD_MATRIX_PC_601 },
99 { "pc.709", AVS_OLD_MATRIX_PC_709 },
100 { "pc601", AVS_OLD_MATRIX_PC_601 },
101 { "pc709", AVS_OLD_MATRIX_PC_709 },
102 { "average", AVS_OLD_MATRIX_AVERAGE },
103 { "rec2020", AVS_OLD_MATRIX_Rec2020 },
104 { "pc.2020", AVS_OLD_MATRIX_PC_2020 },
105 { "pc2020", AVS_OLD_MATRIX_PC_2020 }
106 };
107
108 // not used in Avisynth (yet)
109 const std::vector<std::pair<const char*, Transfer_e>> g_transfer_table{
110 { "709", AVS_TRANSFER_BT709 },
111 { "unspec", AVS_TRANSFER_UNSPECIFIED },
112 { "601", AVS_TRANSFER_BT601 },
113 { "linear", AVS_TRANSFER_LINEAR },
114 { "2020_10", AVS_TRANSFER_BT2020_10 },
115 { "2020_12", AVS_TRANSFER_BT2020_12 },
116 { "240m", AVS_TRANSFER_ST240_M },
117 { "470m", AVS_TRANSFER_BT470_M },
118 { "470bg", AVS_TRANSFER_BT470_BG },
119 { "log100", AVS_TRANSFER_LOG_100 },
120 { "log316", AVS_TRANSFER_LOG_316 },
121 { "st2084", AVS_TRANSFER_ST2084 },
122 { "std-b67", AVS_TRANSFER_ARIB_B67 },
123 { "srgb", AVS_TRANSFER_IEC_61966_2_1 },
124 { "xvycc", AVS_TRANSFER_IEC_61966_2_4 },
125 };
126
127 // not used in Avisynth (yet)
128 const std::vector<std::pair<const char*, Primaries_e>> g_primaries_table{
129 { "709", AVS_PRIMARIES_BT709 },
130 { "unspec", AVS_PRIMARIES_UNSPECIFIED },
131 { "170m", AVS_PRIMARIES_ST170_M },
132 { "240m", AVS_PRIMARIES_ST240_M },
133 { "470m", AVS_PRIMARIES_BT470_M },
134 { "470bg", AVS_PRIMARIES_BT470_BG },
135 { "film", AVS_PRIMARIES_FILM },
136 { "2020", AVS_PRIMARIES_BT2020 },
137 { "st428", AVS_PRIMARIES_ST428 },
138 { "xyz", AVS_PRIMARIES_ST428 },
139 { "st431-2", AVS_PRIMARIES_ST431_2 },
140 { "st432-1", AVS_PRIMARIES_ST432_1 },
141 { "ebu3213-e", AVS_PRIMARIES_EBU3213_E },
142 };
143
144 // -1: null input or empty string
145 // -2: not found
146 // table index otherwise
147 template<class T>
148 112 auto lookup_table(const std::vector<std::pair<const char *, T>>& table, const char* key) {
149
4/10
auto lookup_table<Primaries_e>(std::vector<std::pair<char const*, Primaries_e>, std::allocator<std::pair<char const*, Primaries_e> > > const&, char const*):
✗ Branch 2 → 3 not taken.
✗ Branch 2 → 4 not taken.
auto lookup_table<ChromaLocation_e>(std::vector<std::pair<char const*, ChromaLocation_e>, std::allocator<std::pair<char const*, ChromaLocation_e> > > const&, char const*):
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 4 taken 5 times.
auto lookup_table<Old_Avs_Matrix_e>(std::vector<std::pair<char const*, Old_Avs_Matrix_e>, std::allocator<std::pair<char const*, Old_Avs_Matrix_e> > > const&, char const*):
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 4 taken 55 times.
auto lookup_table<ColorRange_Compat_e>(std::vector<std::pair<char const*, ColorRange_Compat_e>, std::allocator<std::pair<char const*, ColorRange_Compat_e> > > const&, char const*):
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 4 taken 24 times.
auto lookup_table<Matrix_e>(std::vector<std::pair<char const*, Matrix_e>, std::allocator<std::pair<char const*, Matrix_e> > > const&, char const*):
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 4 taken 28 times.
112 if (key == nullptr) return -1;
150
6/10
auto lookup_table<Primaries_e>(std::vector<std::pair<char const*, Primaries_e>, std::allocator<std::pair<char const*, Primaries_e> > > const&, char const*):
✗ Branch 4 → 5 not taken.
✗ Branch 4 → 6 not taken.
auto lookup_table<ChromaLocation_e>(std::vector<std::pair<char const*, ChromaLocation_e>, std::allocator<std::pair<char const*, ChromaLocation_e> > > const&, char const*):
✓ Branch 4 → 5 taken 1 time.
✓ Branch 4 → 6 taken 4 times.
auto lookup_table<Old_Avs_Matrix_e>(std::vector<std::pair<char const*, Old_Avs_Matrix_e>, std::allocator<std::pair<char const*, Old_Avs_Matrix_e> > > const&, char const*):
✓ Branch 4 → 5 taken 17 times.
✓ Branch 4 → 6 taken 38 times.
auto lookup_table<ColorRange_Compat_e>(std::vector<std::pair<char const*, ColorRange_Compat_e>, std::allocator<std::pair<char const*, ColorRange_Compat_e> > > const&, char const*):
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 24 times.
auto lookup_table<Matrix_e>(std::vector<std::pair<char const*, Matrix_e>, std::allocator<std::pair<char const*, Matrix_e> > > const&, char const*):
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 28 times.
112 if (*key == 0) return -1;
151
4/10
auto lookup_table<Primaries_e>(std::vector<std::pair<char const*, Primaries_e>, std::allocator<std::pair<char const*, Primaries_e> > > const&, char const*):
✗ Branch 8 → 9 not taken.
✗ Branch 8 → 26 not taken.
auto lookup_table<ChromaLocation_e>(std::vector<std::pair<char const*, ChromaLocation_e>, std::allocator<std::pair<char const*, ChromaLocation_e> > > const&, char const*):
✓ Branch 8 → 9 taken 4 times.
✗ Branch 8 → 26 not taken.
auto lookup_table<Old_Avs_Matrix_e>(std::vector<std::pair<char const*, Old_Avs_Matrix_e>, std::allocator<std::pair<char const*, Old_Avs_Matrix_e> > > const&, char const*):
✓ Branch 8 → 9 taken 38 times.
✗ Branch 8 → 26 not taken.
auto lookup_table<ColorRange_Compat_e>(std::vector<std::pair<char const*, ColorRange_Compat_e>, std::allocator<std::pair<char const*, ColorRange_Compat_e> > > const&, char const*):
✓ Branch 8 → 9 taken 24 times.
✗ Branch 8 → 26 not taken.
auto lookup_table<Matrix_e>(std::vector<std::pair<char const*, Matrix_e>, std::allocator<std::pair<char const*, Matrix_e> > > const&, char const*):
✓ Branch 8 → 9 taken 28 times.
✗ Branch 8 → 26 not taken.
94 auto it = std::find_if(table.begin(), table.end(),
152 598 [&key](const auto& element) { return !lstrcmpi(element.first, key); });
153
8/10
auto lookup_table<Primaries_e>(std::vector<std::pair<char const*, Primaries_e>, std::allocator<std::pair<char const*, Primaries_e> > > const&, char const*):
✗ Branch 17 → 18 not taken.
✗ Branch 17 → 21 not taken.
auto lookup_table<ChromaLocation_e>(std::vector<std::pair<char const*, ChromaLocation_e>, std::allocator<std::pair<char const*, ChromaLocation_e> > > const&, char const*):
✓ Branch 17 → 18 taken 3 times.
✓ Branch 17 → 21 taken 1 time.
auto lookup_table<Old_Avs_Matrix_e>(std::vector<std::pair<char const*, Old_Avs_Matrix_e>, std::allocator<std::pair<char const*, Old_Avs_Matrix_e> > > const&, char const*):
✓ Branch 17 → 18 taken 7 times.
✓ Branch 17 → 21 taken 31 times.
auto lookup_table<ColorRange_Compat_e>(std::vector<std::pair<char const*, ColorRange_Compat_e>, std::allocator<std::pair<char const*, ColorRange_Compat_e> > > const&, char const*):
✓ Branch 17 → 18 taken 23 times.
✓ Branch 17 → 21 taken 1 time.
auto lookup_table<Matrix_e>(std::vector<std::pair<char const*, Matrix_e>, std::allocator<std::pair<char const*, Matrix_e> > > const&, char const*):
✓ Branch 17 → 18 taken 27 times.
✓ Branch 17 → 21 taken 1 time.
248 return it != std::end(table) ? it->second : -2;
154 }
155
156 bool getPrimaries(const char* primaries_name, IScriptEnvironment* env, int& _Primaries) {
157 auto index = lookup_table<Primaries_e>(g_primaries_table, primaries_name);
158 if (index >= 0) {
159 _Primaries = index;
160 return true;
161 }
162
163 if (index == -2) // not found
164 env->ThrowError("Convert: Unknown Primaries");
165
166 // empty
167 return false;
168 }
169
170 28 static bool getMatrix(const char* matrix_name, IScriptEnvironment* env, int& _Matrix) {
171 28 auto index = lookup_table<Matrix_e>(g_matrix_table, matrix_name);
172
2/2
✓ Branch 3 → 4 taken 27 times.
✓ Branch 3 → 5 taken 1 time.
28 if (index >= 0) {
173 27 _Matrix = index;
174 27 return true;
175 }
176
177
1/2
✓ Branch 5 → 6 taken 1 time.
✗ Branch 5 → 7 not taken.
1 if (index == -2) // not found
178 1 env->ThrowError("Convert: Unknown matrix");
179
180 // empty
181 return false;
182 }
183
184 5 static bool getChromaLocation(const char* chromaloc_name, IScriptEnvironment* env, int& _ChromaLocation) {
185 5 auto index = lookup_table<ChromaLocation_e>(g_chromaloc_table, chromaloc_name);
186
2/2
✓ Branch 3 → 4 taken 3 times.
✓ Branch 3 → 5 taken 2 times.
5 if (index >= 0) {
187 3 _ChromaLocation = index;
188 3 return true;
189 }
190
191
2/2
✓ Branch 5 → 6 taken 1 time.
✓ Branch 5 → 7 taken 1 time.
2 if (index == -2) // not found
192 1 env->ThrowError("Unknown chroma placement");
193
194 // empty
195 1 return false;
196 }
197
198 24 bool getColorRange(const char* color_range_name, IScriptEnvironment* env, int& _ColorRange) {
199 24 auto color_range_enum = lookup_table<ColorRange_Compat_e>(g_range_table, color_range_name);
200
2/2
✓ Branch 3 → 4 taken 23 times.
✓ Branch 3 → 5 taken 1 time.
24 if (color_range_enum >= 0) {
201 23 _ColorRange = color_range_enum;
202 23 return true;
203 }
204
205
1/2
✓ Branch 5 → 6 taken 1 time.
✗ Branch 5 → 7 not taken.
1 if (color_range_enum == -2) // not found
206 1 env->ThrowError("Convert: Unknown color range, must be 'auto', 'full', 'f', 'limited' or 'l'");
207
208 // empty
209 return false;
210
211 }
212
213 // Converts old-style Avisynth matrix to separated _Matrix and _ColorRange values
214 // if not found or empty, returns false, does not throw exception.
215 // _ColorRange for matrix generation
216 // _ColorRange_Out for desired output range, can be set even to nothing for PC.xxx matrices
217 55 static bool getOldMatrix(const char* matrix_name, int &_Matrix, int &_ColorRange) {
218 55 auto old_matrix_enum = lookup_table<Old_Avs_Matrix_e>(g_old_avs_matrix_table, matrix_name);
219
2/2
✓ Branch 3 → 4 taken 48 times.
✓ Branch 3 → 5 taken 7 times.
55 if (old_matrix_enum < 0)
220 48 return false; // not found or empty
221
222
6/8
✓ Branch 5 → 6 taken 1 time.
✓ Branch 5 → 7 taken 1 time.
✓ Branch 5 → 8 taken 2 times.
✓ Branch 5 → 9 taken 1 time.
✓ Branch 5 → 10 taken 1 time.
✓ Branch 5 → 11 taken 1 time.
✗ Branch 5 → 12 not taken.
✗ Branch 5 → 13 not taken.
7 switch (old_matrix_enum) {
223 1 case Old_Avs_Matrix_e::AVS_OLD_MATRIX_Rec601:
224 1 _Matrix = Matrix_e::AVS_MATRIX_ST170_M;
225 1 _ColorRange = ColorRange_Compat_e::AVS_COLORRANGE_LIMITED;
226 1 break;
227 1 case Old_Avs_Matrix_e::AVS_OLD_MATRIX_PC_601:
228 1 _Matrix = Matrix_e::AVS_MATRIX_ST170_M;
229 1 _ColorRange = -1; // better no change the range ColorRange_Compat_e::AVS_COLORRANGE_FULL;
230 1 break;
231 2 case Old_Avs_Matrix_e::AVS_OLD_MATRIX_Rec709:
232 2 _Matrix = Matrix_e::AVS_MATRIX_BT709;
233 2 _ColorRange = ColorRange_Compat_e::AVS_COLORRANGE_LIMITED;
234 2 break;
235 1 case Old_Avs_Matrix_e::AVS_OLD_MATRIX_PC_709:
236 1 _Matrix = Matrix_e::AVS_MATRIX_BT709;
237 1 _ColorRange = -1; // better no change the range ColorRange_Compat_e::AVS_COLORRANGE_FULL;
238 1 break;
239 1 case Old_Avs_Matrix_e::AVS_OLD_MATRIX_Rec2020:
240 1 _Matrix = Matrix_e::AVS_MATRIX_BT2020_NCL;
241 1 _ColorRange = ColorRange_Compat_e::AVS_COLORRANGE_LIMITED;
242 1 break;
243 1 case Old_Avs_Matrix_e::AVS_OLD_MATRIX_PC_2020:
244 1 _Matrix = Matrix_e::AVS_MATRIX_BT2020_NCL;
245 1 _ColorRange = -1; // better no change the range ColorRange_Compat_e::AVS_COLORRANGE_FULL;
246 1 break;
247 case Old_Avs_Matrix_e::AVS_OLD_MATRIX_AVERAGE:
248 _Matrix = Matrix_e::AVS_MATRIX_AVERAGE; // non-standard!
249 _ColorRange = -1;
250 break;
251 }
252 7 return true;
253 }
254
255
256 1 static bool is_paramstring_auto(const std::string &param) {
257 1 return !lstrcmpi(param.c_str(), "auto"); // true is match
258 }
259
260 47 static bool is_paramstring_same(const std::string& param) {
261 47 return !lstrcmpi(param.c_str(), "same"); // true is match
262 }
263
264 94 static bool is_paramstring_empty_or_auto(const std::string& param) {
265
4/4
✓ Branch 3 → 4 taken 55 times.
✓ Branch 3 → 6 taken 39 times.
✓ Branch 5 → 6 taken 3 times.
✓ Branch 5 → 7 taken 52 times.
94 return param.empty() || !lstrcmpi(param.c_str(), "auto"); // true is match
266 }
267
268 10 static bool is_paramstring_empty_or_auto(const char* param) {
269
2/2
✓ Branch 2 → 3 taken 2 times.
✓ Branch 2 → 4 taken 8 times.
10 if (!param)
270 2 return true;
271 8 return !lstrcmpi(param, "auto"); // true is match
272 }
273
274 // called from yuv <-> rgb and to_greyscale converters
275 56 void matrix_parse_merge_with_props_def(bool rgb_in, bool rgb_out, const char* matrix_name, const AVSMap* props, int& _Matrix, int& _ColorRange, int& _ColorRange_Out, int _Matrix_Default, int _ColorRange_Default, IScriptEnvironment* env) {
276 // if once we'd like to use input colorrange when input is rgb (e.g. studio rgb of ColorBars is limited)
277
2/2
✓ Branch 2 → 3 taken 22 times.
✓ Branch 2 → 4 taken 34 times.
56 int _ColorRange_In = rgb_in ? ColorRange_Compat_e::AVS_COLORRANGE_FULL : ColorRange_Compat_e::AVS_COLORRANGE_LIMITED;
278
2/2
✓ Branch 5 → 6 taken 24 times.
✓ Branch 5 → 7 taken 32 times.
56 int _Default_ColorRange_Out = rgb_out ? ColorRange_Compat_e::AVS_COLORRANGE_FULL : ColorRange_Compat_e::AVS_COLORRANGE_LIMITED; // RGB -> YUV or YUV -> RGB
279
280
2/2
✓ Branch 8 → 9 taken 37 times.
✓ Branch 8 → 21 taken 19 times.
56 if (props) {
281 // _ColorRange exists for RGB as well
282
3/4
✓ Branch 9 → 10 taken 37 times.
✗ Branch 9 → 149 not taken.
✓ Branch 10 → 11 taken 10 times.
✓ Branch 10 → 15 taken 27 times.
37 if (env->propNumElements(props, "_ColorRange") > 0) {
283
1/2
✓ Branch 11 → 12 taken 10 times.
✗ Branch 11 → 149 not taken.
10 _ColorRange_In = (int)env->propGetIntSaturated(props, "_ColorRange", 0, nullptr);
284 10 _ColorRange_Default = _ColorRange_In;
285
3/4
✓ Branch 12 → 13 taken 5 times.
✓ Branch 12 → 15 taken 5 times.
✗ Branch 13 → 14 not taken.
✓ Branch 13 → 15 taken 5 times.
10 if (rgb_in && rgb_out) // rgb in and out: keep input
286 _Default_ColorRange_Out = _ColorRange_In;
287 }
288
2/2
✓ Branch 15 → 16 taken 23 times.
✓ Branch 15 → 21 taken 14 times.
37 if (!rgb_in) {
289
3/4
✓ Branch 16 → 17 taken 23 times.
✗ Branch 16 → 149 not taken.
✓ Branch 17 → 18 taken 4 times.
✓ Branch 17 → 21 taken 19 times.
23 if (env->propNumElements(props, "_Matrix") > 0) {
290
1/2
✓ Branch 18 → 19 taken 4 times.
✗ Branch 18 → 149 not taken.
4 int tmp_matrix = (int)env->propGetIntSaturated(props, "_Matrix", 0, nullptr);
291
2/2
✓ Branch 19 → 20 taken 3 times.
✓ Branch 19 → 21 taken 1 time.
4 if (tmp_matrix != Matrix_e::AVS_MATRIX_UNSPECIFIED)
292 3 _Matrix_Default = tmp_matrix;
293 }
294 }
295 }
296
297 // valid values:
298 // old matrix name, optionally followed by 'auto' e.g. Rec709
299 // matrix name, optionally followed by color range e.g. 709:limited 2020:f 601:full
300 56 std::vector<std::string> splits;
301 56 std::string split;
302
303
2/2
✓ Branch 23 → 24 taken 42 times.
✓ Branch 23 → 40 taken 14 times.
56 if (matrix_name) {
304
2/4
✓ Branch 26 → 27 taken 42 times.
✗ Branch 26 → 124 not taken.
✓ Branch 27 → 28 taken 42 times.
✗ Branch 27 → 122 not taken.
42 std::istringstream ss(matrix_name);
305
4/6
✓ Branch 32 → 33 taken 109 times.
✗ Branch 32 → 128 not taken.
✓ Branch 33 → 34 taken 109 times.
✗ Branch 33 → 128 not taken.
✓ Branch 34 → 31 taken 67 times.
✓ Branch 34 → 35 taken 42 times.
109 while (std::getline(ss, split, ':'))
306
1/2
✓ Branch 31 → 32 taken 67 times.
✗ Branch 31 → 128 not taken.
67 splits.push_back(split);
307
308
2/2
✓ Branch 36 → 37 taken 1 time.
✓ Branch 36 → 38 taken 41 times.
42 if (splits.size() > 2)
309
1/2
✗ Branch 37 → 38 not taken.
✓ Branch 37 → 128 taken 1 time.
1 env->ThrowError("Invalid matrix specifier, too many parts");
310 42 }
311
312
6/10
✓ Branch 41 → 42 taken 38 times.
✓ Branch 41 → 44 taken 17 times.
✓ Branch 43 → 47 taken 38 times.
✗ Branch 43 → 131 not taken.
✓ Branch 46 → 47 taken 17 times.
✗ Branch 46 → 131 not taken.
✓ Branch 47 → 48 taken 17 times.
✓ Branch 47 → 50 taken 38 times.
✗ Branch 131 → 132 not taken.
✗ Branch 131 → 134 not taken.
72 std::string s_matrix_name = splits.size() > 0 ? splits[0] : "";
313
6/10
✓ Branch 51 → 52 taken 26 times.
✓ Branch 51 → 54 taken 29 times.
✓ Branch 53 → 57 taken 26 times.
✗ Branch 53 → 136 not taken.
✓ Branch 56 → 57 taken 29 times.
✗ Branch 56 → 136 not taken.
✓ Branch 57 → 58 taken 29 times.
✓ Branch 57 → 60 taken 26 times.
✗ Branch 136 → 137 not taken.
✗ Branch 136 → 139 not taken.
84 std::string s_color_range_name = splits.size() > 1 ? splits[1] : "";
314
315 // PC.xxx is like xxx:same (same is not supported though)
316 // recxxx is like xxx:l (limited)
317
3/4
✓ Branch 61 → 62 taken 55 times.
✗ Branch 61 → 141 not taken.
✓ Branch 62 → 63 taken 7 times.
✓ Branch 62 → 77 taken 48 times.
55 if (getOldMatrix(s_matrix_name.c_str(), _Matrix, _ColorRange)) {
318 // old avs syntax: single matrix names
319
2/2
✓ Branch 63 → 64 taken 3 times.
✓ Branch 63 → 65 taken 4 times.
7 if (_ColorRange < 0) {
320 // PC.xx does not suggest neither limited, not full
321 // keep input range
322 3 _ColorRange = _ColorRange_In; // a default range is set for getting the matrix
323 3 _ColorRange_Out = _ColorRange_In;
324 } else {
325 // _ColorRange was explicitely set by matrix
326
2/2
✓ Branch 65 → 66 taken 1 time.
✓ Branch 65 → 67 taken 3 times.
4 if (rgb_in) {
327 // RGB -> YUV
328 1 _ColorRange_Out = _ColorRange;
329 1 _ColorRange = _ColorRange_In; // a frame prop may override default RGB full input range
330 }
331 else {
332 // YUV -> RGB
333 // _ColorRange; // input range is defined by the matrix
334 3 _ColorRange_Out = _Default_ColorRange_Out;
335 }
336 }
337
5/6
✓ Branch 69 → 70 taken 1 time.
✓ Branch 69 → 73 taken 6 times.
✓ Branch 71 → 72 taken 1 time.
✗ Branch 71 → 73 not taken.
✓ Branch 74 → 75 taken 1 time.
✓ Branch 74 → 76 taken 6 times.
7 if (!s_color_range_name.empty() && !is_paramstring_auto(s_color_range_name))
338
1/2
✗ Branch 75 → 76 not taken.
✓ Branch 75 → 141 taken 1 time.
1 env->ThrowError("Error: this 'old-style' matrix string can only be followed by 'auto' color range");
339 6 return;
340 }
341
342
7/8
✓ Branch 78 → 79 taken 28 times.
✓ Branch 78 → 82 taken 20 times.
✓ Branch 80 → 81 taken 27 times.
✓ Branch 80 → 141 taken 1 time.
✗ Branch 81 → 82 not taken.
✓ Branch 81 → 83 taken 27 times.
✓ Branch 84 → 85 taken 20 times.
✓ Branch 84 → 86 taken 27 times.
48 if (is_paramstring_empty_or_auto(s_matrix_name) || !getMatrix(s_matrix_name.c_str(), env, _Matrix)) {
343 20 _Matrix = _Matrix_Default;
344 }
345
2/2
✓ Branch 86 → 87 taken 3 times.
✓ Branch 86 → 88 taken 44 times.
47 if (_Matrix == Matrix_e::AVS_MATRIX_UNSPECIFIED) {
346 3 _Matrix = _Matrix_Default;
347 }
348
349 // new in 3.7.3: same range as input's, e.g. "709:same" is like "PC.709"
350
2/2
✓ Branch 89 → 90 taken 1 time.
✓ Branch 89 → 91 taken 46 times.
47 if (is_paramstring_same(s_color_range_name)) {
351 1 _ColorRange = _ColorRange_In;
352 1 _ColorRange_Out = _ColorRange;
353 }
354
7/8
✓ Branch 92 → 93 taken 24 times.
✓ Branch 92 → 96 taken 22 times.
✓ Branch 94 → 95 taken 23 times.
✓ Branch 94 → 141 taken 1 time.
✗ Branch 95 → 96 not taken.
✓ Branch 95 → 97 taken 23 times.
✓ Branch 98 → 99 taken 22 times.
✓ Branch 98 → 100 taken 23 times.
46 else if (is_paramstring_empty_or_auto(s_color_range_name) || !getColorRange(s_color_range_name.c_str(), env, _ColorRange)) {
355 // not specified or auto
356 // RGB -> YUV
357 // YUV -> RGB
358 22 _ColorRange = _ColorRange_In;
359 22 _ColorRange_Out = _Default_ColorRange_Out;
360 }
361 else {
362
2/2
✓ Branch 100 → 101 taken 13 times.
✓ Branch 100 → 102 taken 10 times.
23 if (rgb_in) {
363 // RGB -> YUV
364 13 _ColorRange_Out = _ColorRange;
365 13 _ColorRange = _ColorRange_In; // a frame prop may override default RGB full input range
366 }
367 else {
368 // YUV -> RGB
369 // _ColorRange; // input range is defined by the matrix
370 10 _ColorRange_Out = _Default_ColorRange_Out; // unlike RGB->YUV, we have no way to tell output rgb's range, it's always full
371 }
372 }
373
8/8
✓ Branch 105 → 106 taken 46 times.
✓ Branch 105 → 107 taken 6 times.
✓ Branch 109 → 110 taken 46 times.
✓ Branch 109 → 111 taken 6 times.
✓ Branch 113 → 114 taken 46 times.
✓ Branch 113 → 115 taken 6 times.
✓ Branch 117 → 118 taken 46 times.
✓ Branch 117 → 120 taken 6 times.
84 }
374
375 52 void matrix_parse_merge_with_props(bool rgb_in, bool rgb_out, const char* matrix_name, const AVSMap* props, int& _Matrix, int& _ColorRange, int& ColorRange_Out, IScriptEnvironment * env) {
376 52 int _Matrix_Default = Matrix_e::AVS_MATRIX_ST170_M; // Rec601 AVS_MATRIX_ST170_M (6-NTSC) and not AVS_MATRIX_BT470_BG (5-PAL)
377 52 int _ColorRange_Default = ColorRange_Compat_e::AVS_COLORRANGE_LIMITED;
378 52 matrix_parse_merge_with_props_def(rgb_in, rgb_out, matrix_name, props, _Matrix, _ColorRange, ColorRange_Out, _Matrix_Default, _ColorRange_Default, env);
379 48 }
380
381 10 void chromaloc_parse_merge_with_props(VideoInfo& vi, const char* chromaloc_name, const AVSMap* props, int& _ChromaLocation, int _ChromaLocation_Default, IScriptEnvironment* env) {
382
2/2
✓ Branch 2 → 3 taken 6 times.
✓ Branch 2 → 18 taken 4 times.
10 if (props) {
383
8/8
✓ Branch 4 → 5 taken 4 times.
✓ Branch 4 → 9 taken 2 times.
✓ Branch 6 → 7 taken 3 times.
✓ Branch 6 → 9 taken 1 time.
✓ Branch 8 → 9 taken 1 time.
✓ Branch 8 → 10 taken 2 times.
✓ Branch 11 → 12 taken 4 times.
✓ Branch 11 → 16 taken 2 times.
6 if (vi.Is420() || vi.Is422() || vi.IsYV411()) { // yes, YV411 can also have valid _ChromaLocation, if 'left'-ish one is given
384
1/2
✓ Branch 13 → 14 taken 4 times.
✗ Branch 13 → 18 not taken.
4 if (env->propNumElements(props, "_ChromaLocation") > 0) {
385 4 _ChromaLocation_Default = (int)env->propGetIntSaturated(props, "_ChromaLocation", 0, nullptr);
386 }
387 }
388 else {
389 // Theoretically RGB and not subsampled formats must not have chroma location
390 2 if (env->propNumElements(props, "_ChromaLocation") > 0) {
391 // Uncommented for a while, just ignore when there is any
392 // env->ThrowError("Error: _ChromaLocation property found at a non-subsampled source.");
393 }
394 }
395 }
396
397
6/6
✓ Branch 19 → 20 taken 5 times.
✓ Branch 19 → 22 taken 5 times.
✓ Branch 21 → 22 taken 1 time.
✓ Branch 21 → 23 taken 3 times.
✓ Branch 24 → 25 taken 6 times.
✓ Branch 24 → 26 taken 3 times.
10 if (is_paramstring_empty_or_auto(chromaloc_name) || !getChromaLocation(chromaloc_name, env, _ChromaLocation)) {
398 6 _ChromaLocation = _ChromaLocation_Default;
399 }
400 9 }
401
402 4 void export_frame_props(VideoInfo& vi, AVSMap* props, int _Matrix, int _ColorRange, IScriptEnvironment* env) {
403 // fixme: what to do with the special "AVERAGE" non standard matrix? Solution 1: delete entry
404
2/2
✓ Branch 2 → 3 taken 1 time.
✓ Branch 2 → 4 taken 3 times.
4 if (_Matrix == Matrix_e::AVS_MATRIX_AVERAGE)
405 1 env->propDeleteKey(props, "_Matrix");
406
2/2
✓ Branch 4 → 5 taken 1 time.
✓ Branch 4 → 6 taken 2 times.
3 else if (_Matrix < 0)
407 1 env->propDeleteKey(props, "_Matrix");
408 else
409 2 env->propSetInt(props, "_Matrix", _Matrix, AVSPropAppendMode::PROPAPPENDMODE_REPLACE);
410
411 4 env->propSetInt(props, "_ColorRange", _ColorRange, AVSPropAppendMode::PROPAPPENDMODE_REPLACE);
412 4 }
413
414 /* avsresize:
415 The name of the frame properties that are read and set are: _ChromaLocation, _ColorRange, _Matrix, _Transfer, _Primaries
416 The frame properties read and set the corresponding numerical index of the parameters. For example: matrix "709" has numerical index `1` and the frame property have value of `1`.
417 If colorspace_op is not defined and there are frame properties, they are used for default source values.
418 If colorspace_op is not defined and there are no frame properties or they are not supported, default values are used as before (there are default values for matrix, range and chromaloc).
419 If colorspace_op is defined and you want to use the frame property for a source value, use "auto".
420 If colorspace_op is defined and you use "auto" without frame property, the default value for that argument will be used if exist.
421 If you use "auto" for argument with frame property that has value of 2 (unspec) and use anything different than "same" for destination, error will be raised.
422 If you use "auto=>same" for matrix/transfer/primaries with frame property 2 (unspec) and you want to make colorspace conversion, error will be raised. For example:
423 */
424
425 20 void update_Matrix_and_ColorRange(AVSMap* props, int theMatrix, int theColorRange, IScriptEnvironment* env)
426 {
427 20 auto set_int_if_positive = [&](const char* key, int x)
428 {
429
1/2
✓ Branch 2 → 3 taken 20 times.
✗ Branch 2 → 4 not taken.
20 if (x >= 0)
430 20 env->propSetInt(props, key, x, AVSPropAppendMode::PROPAPPENDMODE_REPLACE);
431 else
432 env->propDeleteKey(props, key);
433 40 };
434
435
3/4
✓ Branch 2 → 3 taken 6 times.
✓ Branch 2 → 4 taken 14 times.
✓ Branch 3 → 4 taken 6 times.
✗ Branch 3 → 6 not taken.
20 if (theColorRange == ColorRange_Compat_e::AVS_COLORRANGE_FULL || theColorRange == ColorRange_Compat_e::AVS_COLORRANGE_LIMITED)
436
1/2
✓ Branch 4 → 5 taken 20 times.
✗ Branch 4 → 9 not taken.
20 env->propSetInt(props, "_ColorRange", theColorRange, AVSPropAppendMode::PROPAPPENDMODE_REPLACE);
437 else
438 env->propDeleteKey(props, "_ColorRange");
439
440
1/2
✓ Branch 7 → 8 taken 20 times.
✗ Branch 7 → 9 not taken.
20 set_int_if_positive("_Matrix", theMatrix);
441 //set_int_if_positive("_Transfer", theTransferCharacteristics);
442 //set_int_if_positive("_Primaries", theColorPrimaries);
443 20 }
444
445 void update_Transfer_and_Primaries(AVSMap* props, int theTransfer, int thePrimaries, IScriptEnvironment* env)
446 {
447 auto set_int_if_positive = [&](const char* key, int x)
448 {
449 if (x >= 0)
450 env->propSetInt(props, key, x, AVSPropAppendMode::PROPAPPENDMODE_REPLACE);
451 else
452 env->propDeleteKey(props, key);
453 };
454 set_int_if_positive("_Transfer", theTransfer);
455 set_int_if_positive("_Primaries", thePrimaries);
456 }
457
458 11 void update_ChromaLocation(AVSMap* props, int theChromaLocation, IScriptEnvironment* env)
459 {
460 11 auto set_int_if_positive = [&](const char* key, int x)
461 {
462
1/2
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 4 taken 11 times.
11 if (x >= 0)
463 env->propSetInt(props, key, x, AVSPropAppendMode::PROPAPPENDMODE_REPLACE);
464 else
465 11 env->propDeleteKey(props, key);
466 22 };
467
468
1/2
✓ Branch 2 → 3 taken 11 times.
✗ Branch 2 → 4 not taken.
11 set_int_if_positive("_ChromaLocation", theChromaLocation);
469 11 }
470
471 7 void update_ColorRange(AVSMap* props, int theColorRange, IScriptEnvironment* env)
472 {
473
3/4
✓ Branch 2 → 3 taken 4 times.
✓ Branch 2 → 4 taken 3 times.
✓ Branch 3 → 4 taken 4 times.
✗ Branch 3 → 5 not taken.
7 if (theColorRange == ColorRange_Compat_e::AVS_COLORRANGE_FULL || theColorRange == ColorRange_Compat_e::AVS_COLORRANGE_LIMITED)
474 7 env->propSetInt(props, "_ColorRange", theColorRange, AVSPropAppendMode::PROPAPPENDMODE_REPLACE);
475 else
476 env->propDeleteKey(props, "_ColorRange");
477 7 }
478