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/10auto 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/10auto 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/10auto 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/10auto 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 ¶m) { | |
| 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 |