convert/convert_bits.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 | #include "convert_bits.h" | ||
| 36 | #ifdef INTEL_INTRINSICS | ||
| 37 | #include "intel/convert_bits_sse.h" | ||
| 38 | #include "intel/convert_bits_avx2.h" | ||
| 39 | #endif | ||
| 40 | #include "convert_helper.h" | ||
| 41 | |||
| 42 | #include <avs/alignment.h> | ||
| 43 | #include <avs/minmax.h> | ||
| 44 | #include <avs/config.h> | ||
| 45 | #include <tuple> | ||
| 46 | #include <map> | ||
| 47 | #include <algorithm> | ||
| 48 | #include <vector> | ||
| 49 | |||
| 50 | #ifdef AVS_WINDOWS | ||
| 51 | #include <avs/win.h> | ||
| 52 | #else | ||
| 53 | #include <avs/posix.h> | ||
| 54 | #endif | ||
| 55 | |||
| 56 | // for odd dither bit differences, we still take even size but | ||
| 57 | // correction values are halved (shifted by 1) | ||
| 58 | |||
| 59 | // repeated 8x for sse size 16 | ||
| 60 | const BYTE dither2x2a_data[4] = { | ||
| 61 | 0, 1, | ||
| 62 | 1, 0, | ||
| 63 | }; | ||
| 64 | // cycle: 2 | ||
| 65 | alignas(16) const BYTE dither2x2a_data_sse2[2 * 16] = { | ||
| 66 | 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, | ||
| 67 | 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0 | ||
| 68 | }; | ||
| 69 | |||
| 70 | // e.g. 10->8 bits | ||
| 71 | // repeated 8x for sse size 16 | ||
| 72 | const BYTE dither2x2_data[4] = { | ||
| 73 | 0, 2, | ||
| 74 | 3, 1, | ||
| 75 | }; | ||
| 76 | // cycle: 2 | ||
| 77 | alignas(16) const BYTE dither2x2_data_sse2[2 * 16] = { | ||
| 78 | 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, | ||
| 79 | 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1 | ||
| 80 | }; | ||
| 81 | |||
| 82 | // e.g. 8->5 bits | ||
| 83 | const BYTE dither4x4a_data[16] = { | ||
| 84 | 0, 4, 1, 5, | ||
| 85 | 6, 2, 7, 3, | ||
| 86 | 1, 5, 0, 4, | ||
| 87 | 7, 3, 6, 2 | ||
| 88 | }; | ||
| 89 | // cycle: 4 | ||
| 90 | alignas(16) const BYTE dither4x4a_data_sse2[4 * 16] = { | ||
| 91 | 0, 4, 1, 5, 0, 4, 1, 5, 0, 4, 1, 5, 0, 4, 1, 5, | ||
| 92 | 6, 2, 7, 3, 6, 2, 7, 3, 6, 2, 7, 3, 6, 2, 7, 3, | ||
| 93 | 1, 5, 0, 4, 1, 5, 0, 4, 1, 5, 0, 4, 1, 5, 0, 4, | ||
| 94 | 7, 3, 6, 2, 7, 3, 6, 2, 7, 3, 6, 2, 7, 3, 6, 2, | ||
| 95 | }; | ||
| 96 | |||
| 97 | // e.g. 12->8 bits | ||
| 98 | const BYTE dither4x4_data[16] = { | ||
| 99 | 0, 8, 2, 10, | ||
| 100 | 12, 4, 14, 6, | ||
| 101 | 3, 11, 1, 9, | ||
| 102 | 15, 7, 13, 5 | ||
| 103 | }; | ||
| 104 | // cycle: 4 | ||
| 105 | alignas(16) const BYTE dither4x4_data_sse2[4 * 16] = { | ||
| 106 | 0, 8, 2, 10, 0, 8, 2, 10, 0, 8, 2, 10, 0, 8, 2, 10, | ||
| 107 | 12, 4, 14, 6, 12, 4, 14, 6, 12, 4, 14, 6, 12, 4, 14, 6, | ||
| 108 | 3, 11, 1, 9, 3, 11, 1, 9, 3, 11, 1, 9, 3, 11, 1, 9, | ||
| 109 | 15, 7, 13, 5, 15, 7, 13, 5, 15, 7, 13, 5, 15, 7, 13, 5 | ||
| 110 | }; | ||
| 111 | |||
| 112 | // e.g. 14->9 bits | ||
| 113 | extern const BYTE dither8x8a_data[8][8] = { | ||
| 114 | { 0, 16, 4, 20, 1, 17, 5, 21}, /* 8x8 Bayer ordered dithering pattern */ | ||
| 115 | {24, 8, 28, 12, 25, 9, 29, 13}, | ||
| 116 | { 6, 22, 2, 18, 7, 23, 3, 19}, | ||
| 117 | {30, 14, 26, 10, 31, 15, 27, 11}, | ||
| 118 | { 1, 17, 5, 21, 0, 16, 4, 20}, | ||
| 119 | {25, 9, 29, 13, 24, 8, 28, 12}, | ||
| 120 | { 7, 23, 3, 19, 6, 22, 2, 18}, | ||
| 121 | {31, 15, 27, 11, 30, 14, 26, 10} | ||
| 122 | }; | ||
| 123 | // cycle: 8 | ||
| 124 | alignas(16) const BYTE dither8x8a_data_sse2[8][16] = { | ||
| 125 | { 0, 16, 4, 20, 1, 17, 5, 21, 0, 16, 4, 20, 1, 17, 5, 21 }, | ||
| 126 | { 24, 8, 28, 12, 25, 9, 29, 13, 24, 8, 28, 12, 25, 9, 29, 13 }, | ||
| 127 | { 6, 22, 2, 18, 7, 23, 3, 19, 6, 22, 2, 18, 7, 23, 3, 19 }, | ||
| 128 | { 30, 14, 26, 10, 31, 15, 27, 11, 30, 14, 26, 10, 31, 15, 27, 11 }, | ||
| 129 | { 1, 17, 5, 21, 0, 16, 4, 20, 1, 17, 5, 21, 0, 16, 4, 20 }, | ||
| 130 | { 25, 9, 29, 13, 24, 8, 28, 12, 25, 9, 29, 13, 24, 8, 28, 12 }, | ||
| 131 | { 7, 23, 3, 19, 6, 22, 2, 18, 7, 23, 3, 19, 6, 22, 2, 18 }, | ||
| 132 | { 31, 15, 27, 11, 30, 14, 26, 10, 31, 15, 27, 11, 30, 14, 26, 10 } | ||
| 133 | }; | ||
| 134 | |||
| 135 | // e.g. 14->8 bits | ||
| 136 | extern const BYTE dither8x8_data[8][8] = { | ||
| 137 | { 0, 32, 8, 40, 2, 34, 10, 42}, | ||
| 138 | {48, 16, 56, 24, 50, 18, 58, 26}, | ||
| 139 | {12, 44, 4, 36, 14, 46, 6, 38}, | ||
| 140 | {60, 28, 52, 20, 62, 30, 54, 22}, | ||
| 141 | { 3, 35, 11, 43, 1, 33, 9, 41}, | ||
| 142 | {51, 19, 59, 27, 49, 17, 57, 25}, | ||
| 143 | {15, 47, 7, 39, 13, 45, 5, 37}, | ||
| 144 | {63, 31, 55, 23, 61, 29, 53, 21} | ||
| 145 | }; | ||
| 146 | // cycle: 8 | ||
| 147 | alignas(16) const BYTE dither8x8_data_sse2[8][16] = { | ||
| 148 | { 0, 32, 8, 40, 2, 34, 10, 42, 0, 32, 8, 40, 2, 34, 10, 42 }, | ||
| 149 | { 48, 16, 56, 24, 50, 18, 58, 26, 48, 16, 56, 24, 50, 18, 58, 26 }, | ||
| 150 | { 12, 44, 4, 36, 14, 46, 6, 38, 12, 44, 4, 36, 14, 46, 6, 38 }, | ||
| 151 | { 60, 28, 52, 20, 62, 30, 54, 22, 60, 28, 52, 20, 62, 30, 54, 22 }, | ||
| 152 | { 3, 35, 11, 43, 1, 33, 9, 41, 3, 35, 11, 43, 1, 33, 9, 41 }, | ||
| 153 | { 51, 19, 59, 27, 49, 17, 57, 25, 51, 19, 59, 27, 49, 17, 57, 25 }, | ||
| 154 | { 15, 47, 7, 39, 13, 45, 5, 37, 15, 47, 7, 39, 13, 45, 5, 37 }, | ||
| 155 | { 63, 31, 55, 23, 61, 29, 53, 21, 63, 31, 55, 23, 61, 29, 53, 21 } | ||
| 156 | }; | ||
| 157 | |||
| 158 | // e.g. 16->9 or 8->1 bits | ||
| 159 | // cycle: 16x. No special 16 byte sse2 | ||
| 160 | alignas(16) const BYTE dither16x16a_data[16][16] = { | ||
| 161 | { 0, 96, 24,120, 6,102, 30,126, 1, 97, 25,121, 7,103, 31,127 }, | ||
| 162 | { 64, 32, 88, 56, 70, 38, 94, 62, 65, 33, 89, 57, 71, 39, 95, 63 }, | ||
| 163 | { 16,112, 8,104, 22,118, 14,110, 17,113, 9,105, 23,119, 15,111 }, | ||
| 164 | { 80, 48, 72, 40, 86, 54, 78, 46, 81, 49, 73, 41, 87, 55, 79, 47 }, | ||
| 165 | { 4,100, 28,124, 2, 98, 26,122, 5,101, 29,125, 3, 99, 27,123 }, | ||
| 166 | { 68, 36, 92, 60, 66, 34, 90, 58, 69, 37, 93, 61, 67, 35, 91, 59 }, | ||
| 167 | { 20,116, 12,108, 18,114, 10,106, 21,117, 13,109, 19,115, 11,107 }, | ||
| 168 | { 84, 52, 76, 44, 82, 50, 74, 42, 85, 53, 77, 45, 83, 51, 75, 43 }, | ||
| 169 | { 1, 97, 25,121, 7,103, 31,127, 0, 96, 24,120, 6,102, 30,126 }, | ||
| 170 | { 75, 33, 89, 57, 71, 39, 95, 63, 64, 32, 88, 56, 70, 38, 94, 62 }, | ||
| 171 | { 17,113, 9,105, 23,119, 15,111, 16,112, 8,104, 22,118, 14,110 }, | ||
| 172 | { 81, 49, 73, 41, 87, 55, 79, 47, 80, 48, 72, 40, 86, 54, 78, 46 }, | ||
| 173 | { 5,101, 29,125, 3, 99, 27,123, 4,100, 28,124, 2, 98, 26,122 }, | ||
| 174 | { 69, 37, 93, 61, 67, 35, 91, 59, 68, 36, 92, 60, 66, 34, 90, 58 }, | ||
| 175 | { 21,117, 13,109, 19,115, 11,107, 20,116, 12,108, 18,114, 10,106 }, | ||
| 176 | { 85, 53, 77, 45, 83, 51, 75, 43, 84, 52, 76, 44, 82, 50, 74, 42 } | ||
| 177 | }; | ||
| 178 | |||
| 179 | // 16->8 | ||
| 180 | // cycle: 16x. No special 16 byte sse2 | ||
| 181 | alignas(16) const BYTE dither16x16_data[16][16] = { | ||
| 182 | { 0,192, 48,240, 12,204, 60,252, 3,195, 51,243, 15,207, 63,255 }, | ||
| 183 | { 128, 64,176,112,140, 76,188,124,131, 67,179,115,143, 79,191,127 }, | ||
| 184 | { 32,224, 16,208, 44,236, 28,220, 35,227, 19,211, 47,239, 31,223 }, | ||
| 185 | { 160, 96,144, 80,172,108,156, 92,163, 99,147, 83,175,111,159, 95 }, | ||
| 186 | { 8,200, 56,248, 4,196, 52,244, 11,203, 59,251, 7,199, 55,247 }, | ||
| 187 | { 136, 72,184,120,132, 68,180,116,139, 75,187,123,135, 71,183,119 }, | ||
| 188 | { 40,232, 24,216, 36,228, 20,212, 43,235, 27,219, 39,231, 23,215 }, | ||
| 189 | { 168,104,152, 88,164,100,148, 84,171,107,155, 91,167,103,151, 87 }, | ||
| 190 | { 2,194, 50,242, 14,206, 62,254, 1,193, 49,241, 13,205, 61,253 }, | ||
| 191 | { 130, 66,178,114,142, 78,190,126,129, 65,177,113,141, 77,189,125 }, | ||
| 192 | { 34,226, 18,210, 46,238, 30,222, 33,225, 17,209, 45,237, 29,221 }, | ||
| 193 | { 162, 98,146, 82,174,110,158, 94,161, 97,145, 81,173,109,157, 93 }, | ||
| 194 | { 10,202, 58,250, 6,198, 54,246, 9,201, 57,249, 5,197, 53,245 }, | ||
| 195 | { 138, 74,186,122,134, 70,182,118,137, 73,185,121,133, 69,181,117 }, | ||
| 196 | { 42,234, 26,218, 38,230, 22,214, 41,233, 25,217, 37,229, 21,213 }, | ||
| 197 | { 170,106,154, 90,166,102,150, 86,169,105,153, 89,165,101,149, 85 } | ||
| 198 | }; | ||
| 199 | |||
| 200 | |||
| 201 | template<typename pixel_t_s, typename pixel_t_d, bool chroma, bool fulls, bool fulld, bool TEMPLATE_NEED_BACKSCALE, bool TEMPLATE_LOW_DITHER_BITDEPTH> | ||
| 202 | ✗ | static void do_convert_ordered_dither_uint_c(const BYTE* srcp8, BYTE* dstp8, int src_rowsize, int src_height, int src_pitch, int dst_pitch, int source_bitdepth, int target_bitdepth, int dither_target_bitdepth) | |
| 203 | { | ||
| 204 | ✗ | const pixel_t_s* srcp = reinterpret_cast<const pixel_t_s*>(srcp8); | |
| 205 | ✗ | pixel_t_d* dstp = reinterpret_cast<pixel_t_d*>(dstp8); | |
| 206 | ✗ | dst_pitch = dst_pitch / sizeof(pixel_t_d); | |
| 207 | |||
| 208 | ✗ | src_pitch = src_pitch / sizeof(pixel_t_s); | |
| 209 | ✗ | const int src_width = src_rowsize / sizeof(pixel_t_s); | |
| 210 | |||
| 211 | // helps compiler optimization | ||
| 212 | if constexpr (sizeof(pixel_t_s) == 1) | ||
| 213 | ✗ | source_bitdepth = 8; | |
| 214 | if constexpr (sizeof(pixel_t_d) == 1) { | ||
| 215 | ✗ | target_bitdepth = 8; | |
| 216 | if (!TEMPLATE_NEED_BACKSCALE) { | ||
| 217 | ✗ | dither_target_bitdepth = 8; | |
| 218 | } | ||
| 219 | } | ||
| 220 | |||
| 221 | ✗ | const int max_pixel_value_target = (1 << target_bitdepth) - 1; | |
| 222 | ✗ | const int max_pixel_value_dithered = (1 << dither_target_bitdepth) - 1; | |
| 223 | // precheck ensures: | ||
| 224 | // target_bitdepth >= dither_target_bitdepth | ||
| 225 | // source_bitdepth - dither_target_bitdepth <= 8 (max precalculated table is 16x16) | ||
| 226 | ✗ | const bool odd_diff = (source_bitdepth - dither_target_bitdepth) & 1; | |
| 227 | ✗ | const int dither_bit_diff = (source_bitdepth - dither_target_bitdepth); | |
| 228 | ✗ | const int dither_order = (dither_bit_diff + 1) / 2; | |
| 229 | ✗ | const int dither_mask = (1 << dither_order) - 1; // 9,10=2 11,12=4 13,14=8 15,16=16 | |
| 230 | // 10->8: 0x01 (2x2) | ||
| 231 | // 11->8: 0x03 (4x4) | ||
| 232 | // 12->8: 0x03 (4x4) | ||
| 233 | // 14->8: 0x07 (8x8) | ||
| 234 | // 16->8: 0x0F (16x16) | ||
| 235 | const BYTE* matrix; | ||
| 236 | ✗ | switch (dither_order) { | |
| 237 | ✗ | case 1: matrix = reinterpret_cast<const BYTE*>(odd_diff ? dither2x2a_data : dither2x2_data); break; | |
| 238 | ✗ | case 2: matrix = reinterpret_cast<const BYTE*>(odd_diff ? dither4x4a_data : dither4x4_data); break; | |
| 239 | ✗ | case 3: matrix = reinterpret_cast<const BYTE*>(odd_diff ? dither8x8a_data : dither8x8_data); break; | |
| 240 | ✗ | case 4: matrix = reinterpret_cast<const BYTE*>(odd_diff ? dither16x16a_data : dither16x16_data); break; | |
| 241 | ✗ | default: return; // n/a | |
| 242 | } | ||
| 243 | |||
| 244 | ✗ | const int bitdiff_between_dither_and_target = target_bitdepth - dither_target_bitdepth; | |
| 245 | ✗ | assert(TEMPLATE_NEED_BACKSCALE == (target_bitdepth != dither_target_bitdepth)); // dither to x, target to y | |
| 246 | |||
| 247 | ✗ | assert(TEMPLATE_LOW_DITHER_BITDEPTH == (dither_target_bitdepth < 8)); | |
| 248 | // e.g. instead of 0,1 => -0.5,+0.5; 0,1,2,3 => -1.5,-0.5,0.5,1.5 | ||
| 249 | ✗ | const float half_maxcorr_value = ((1 << dither_bit_diff) - 1) / 2.0f; | |
| 250 | |||
| 251 | ✗ | const int source_max = (1 << source_bitdepth) - 1; | |
| 252 | //----------------------- | ||
| 253 | // When calculating src_pixel, src and dst are of the same bit depth | ||
| 254 | ✗ | bits_conv_constants d; | |
| 255 | get_bits_conv_constants(d, chroma, fulls, fulld, source_bitdepth, source_bitdepth); | ||
| 256 | |||
| 257 | ✗ | auto dst_offset_plus_round = d.dst_offset + 0.5f; | |
| 258 | ✗ | constexpr auto src_pixel_min = 0; | |
| 259 | ✗ | const auto src_pixel_max = source_max; | |
| 260 | ✗ | const float mul_factor_backfromlowdither = (float)max_pixel_value_target / max_pixel_value_dithered; | |
| 261 | //----------------------- | ||
| 262 | |||
| 263 | ✗ | for (int y = 0; y < src_height; y++) | |
| 264 | { | ||
| 265 | ✗ | int _y = (y & dither_mask) << dither_order; // ordered dither | |
| 266 | ✗ | for (int x = 0; x < src_width; x++) | |
| 267 | { | ||
| 268 | ✗ | const int corr = matrix[_y | (x & dither_mask)]; | |
| 269 | |||
| 270 | ✗ | int src_pixel = srcp[x]; | |
| 271 | |||
| 272 | if constexpr(fulls != fulld) { | ||
| 273 | ✗ | const float val = (srcp[x] - d.src_offset_i) * d.mul_factor + dst_offset_plus_round; | |
| 274 | ✗ | src_pixel = clamp((int)val, src_pixel_min, src_pixel_max); | |
| 275 | } | ||
| 276 | |||
| 277 | int new_pixel; | ||
| 278 | if (TEMPLATE_LOW_DITHER_BITDEPTH) { | ||
| 279 | // accurate dither: +/- | ||
| 280 | // accurately positioned to the center | ||
| 281 | ✗ | const float corr_f = corr - half_maxcorr_value; | |
| 282 | ✗ | new_pixel = (int)(src_pixel + corr_f) >> dither_bit_diff; | |
| 283 | } | ||
| 284 | else | ||
| 285 | ✗ | new_pixel = ((src_pixel + corr) >> dither_bit_diff); | |
| 286 | |||
| 287 | // scale back to the required bit depth | ||
| 288 | if constexpr (TEMPLATE_NEED_BACKSCALE) { // dither to x, target to y | ||
| 289 | ✗ | new_pixel = min(new_pixel, max_pixel_value_dithered); | |
| 290 | // Interesting problem of dither_bits==1 (or in general at small dither_bits) | ||
| 291 | // After simple slli 0,1 becomes 0,128, we'd expect 0,255 instead. So we make cosmetics. | ||
| 292 | if (TEMPLATE_LOW_DITHER_BITDEPTH) { | ||
| 293 | ✗ | new_pixel = (int)(new_pixel * mul_factor_backfromlowdither + 0.5f); | |
| 294 | } | ||
| 295 | else { | ||
| 296 | ✗ | new_pixel = new_pixel << bitdiff_between_dither_and_target; | |
| 297 | } | ||
| 298 | // dither_bits | ||
| 299 | // 1 0,1 => 0,128 => 0,255 | ||
| 300 | // 2 0,1,2,3 => 0,64,128,192 => 0,?,?,255 | ||
| 301 | // 3 0,...,7 => 0,32,...,224 => 0,?,?,255 | ||
| 302 | // 4 0,..,15 => 0,16,...,240 => 0,?,?,255 | ||
| 303 | // 5 0,..,31 => 0,8,....,248 => 0,?,?,255 | ||
| 304 | // 6 0,..,63 => 0,4,....,252 => 0,?,?,255 | ||
| 305 | // 7 0,.,127 => 0,2. ..,254 => 0,?,?,255 | ||
| 306 | } | ||
| 307 | ✗ | dstp[x] = (pixel_t_d)(max(min((int)new_pixel, max_pixel_value_target),0)); | |
| 308 | } | ||
| 309 | ✗ | dstp += dst_pitch; | |
| 310 | ✗ | srcp += src_pitch; | |
| 311 | } | ||
| 312 | } | ||
| 313 | |||
| 314 | template<typename pixel_t_s, typename pixel_t_d, bool chroma, bool fulls, bool fulld> | ||
| 315 | ✗ | static void convert_ordered_dither_uint_c(const BYTE* srcp8, BYTE* dstp8, int src_rowsize, int src_height, int src_pitch, int dst_pitch, int source_bitdepth, int target_bitdepth, int dither_target_bitdepth) | |
| 316 | { | ||
| 317 | ✗ | const bool need_backscale = target_bitdepth != dither_target_bitdepth; // dither to x, target to y | |
| 318 | ✗ | const bool low_dither_bitdepth = dither_target_bitdepth < 8; // 1-7 bits dither targets, need_backscale is always true, since 8 bit format is the minimum | |
| 319 | ✗ | if (need_backscale) { | |
| 320 | ✗ | if (low_dither_bitdepth) | |
| 321 | ✗ | do_convert_ordered_dither_uint_c<pixel_t_s, pixel_t_d, chroma, fulls, fulld, true, true>(srcp8, dstp8, src_rowsize, src_height, src_pitch, dst_pitch, source_bitdepth, target_bitdepth, dither_target_bitdepth); | |
| 322 | else | ||
| 323 | ✗ | do_convert_ordered_dither_uint_c<pixel_t_s, pixel_t_d, chroma, fulls, fulld, true, false>(srcp8, dstp8, src_rowsize, src_height, src_pitch, dst_pitch, source_bitdepth, target_bitdepth, dither_target_bitdepth); | |
| 324 | } | ||
| 325 | else { | ||
| 326 | ✗ | do_convert_ordered_dither_uint_c<pixel_t_s, pixel_t_d, chroma, fulls, fulld, false, false>(srcp8, dstp8, src_rowsize, src_height, src_pitch, dst_pitch, source_bitdepth, target_bitdepth, dither_target_bitdepth); | |
| 327 | } | ||
| 328 | ✗ | } | |
| 329 | |||
| 330 | // idea borrowed from fmtConv | ||
| 331 | #define FS_OPTIMIZED_SERPENTINE_COEF | ||
| 332 | |||
| 333 | template<int direction> | ||
| 334 | static AVS_FORCEINLINE void diffuse_floyd(int err, int &nextError, int *error_ptr) | ||
| 335 | { | ||
| 336 | #if defined (FS_OPTIMIZED_SERPENTINE_COEF) | ||
| 337 | ✗ | const int e1 = 0; | |
| 338 | ✗ | const int e3 = (err * 4 + 8) >> 4; | |
| 339 | #else | ||
| 340 | const int e1 = (err + 8) >> 4; | ||
| 341 | const int e3 = (err * 3 + 8) >> 4; | ||
| 342 | #endif | ||
| 343 | ✗ | const int e5 = (err * 5 + 8) >> 4; | |
| 344 | ✗ | const int e7 = err - e1 - e3 - e5; | |
| 345 | |||
| 346 | ✗ | nextError = error_ptr[direction]; | |
| 347 | ✗ | error_ptr[-direction] += e3; | |
| 348 | ✗ | error_ptr[0] += e5; | |
| 349 | ✗ | error_ptr[direction] = e1; | |
| 350 | ✗ | nextError += e7; | |
| 351 | ✗ | } | |
| 352 | |||
| 353 | #if 0 | ||
| 354 | template<int direction> | ||
| 355 | static AVS_FORCEINLINE void diffuse_floyd_f(float err, float& nextError, float* error_ptr) | ||
| 356 | { | ||
| 357 | #if defined (FS_OPTIMIZED_SERPENTINE_COEF) | ||
| 358 | const float e1 = 0; | ||
| 359 | const float e3 = err * (4.0f / 16); | ||
| 360 | #else | ||
| 361 | const float e1 = err * (1.0f / 16); | ||
| 362 | const float e3 = err * (3.0f / 16); | ||
| 363 | #endif | ||
| 364 | const float e5 = err * (5.0f / 16); | ||
| 365 | const float e7 = err * (7.0f / 16); | ||
| 366 | |||
| 367 | nextError = error_ptr[direction]; | ||
| 368 | error_ptr[-direction] += e3; | ||
| 369 | error_ptr[0] += e5; | ||
| 370 | error_ptr[direction] = e1; | ||
| 371 | nextError += e7; | ||
| 372 | } | ||
| 373 | #endif | ||
| 374 | |||
| 375 | // optimization helper: TEMPLATE_DITHER_BIT_DIFF if not <0 then hold value for frequently used differences from 16->8 | ||
| 376 | // 2nd helper: TEMPLATE_LOW_DITHER_BITDEPTH | ||
| 377 | // 3rd helper: source_bitdepth_special | ||
| 378 | template<typename pixel_t_s, typename pixel_t_d, bool chroma, bool fulls, bool fulld, int TEMPLATE_DITHER_BIT_DIFF, bool TEMPLATE_LOW_DITHER_BITDEPTH, int SOURCE_BITDEPTH_SPECIAL> | ||
| 379 | ✗ | static void do_convert_uint_floyd_c(const BYTE* srcp8, BYTE* dstp8, int src_rowsize, int src_height, int src_pitch, int dst_pitch, int source_bitdepth, int target_bitdepth, int dither_target_bitdepth) | |
| 380 | { | ||
| 381 | if constexpr (SOURCE_BITDEPTH_SPECIAL > 0) { | ||
| 382 | // called with >0 values only for special cases like 16 to 8, 16 to 10 and 10 to 8 | ||
| 383 | // Hugely helps the optimizers | ||
| 384 | ✗ | source_bitdepth = SOURCE_BITDEPTH_SPECIAL; | |
| 385 | } | ||
| 386 | if constexpr (TEMPLATE_DITHER_BIT_DIFF > 0) { | ||
| 387 | ✗ | assert(TEMPLATE_DITHER_BIT_DIFF == (source_bitdepth - dither_target_bitdepth)); | |
| 388 | ✗ | assert(target_bitdepth == dither_target_bitdepth); | |
| 389 | ✗ | dither_target_bitdepth = source_bitdepth - TEMPLATE_DITHER_BIT_DIFF; | |
| 390 | ✗ | target_bitdepth = dither_target_bitdepth; | |
| 391 | // seems that direct shift with known constant bits is really quicker than shift by 'cl'. | ||
| 392 | // Dithering from 16 to 10 bit: 109 vs 101 fps | ||
| 393 | // PF note: experienced the same with SIMD _mm_srl and _mm_srli in the other bit converter | ||
| 394 | } | ||
| 395 | ✗ | const int DITHER_BIT_DIFF = TEMPLATE_DITHER_BIT_DIFF > 0 ? TEMPLATE_DITHER_BIT_DIFF : (source_bitdepth - dither_target_bitdepth); | |
| 396 | ✗ | assert(TEMPLATE_LOW_DITHER_BITDEPTH == (dither_target_bitdepth < 8)); // must match with dispatcher | |
| 397 | |||
| 398 | ✗ | const pixel_t_s* srcp = reinterpret_cast<const pixel_t_s*>(srcp8); | |
| 399 | ✗ | src_pitch = src_pitch / sizeof(pixel_t_s); | |
| 400 | ✗ | const int src_width = src_rowsize / sizeof(pixel_t_s); | |
| 401 | |||
| 402 | ✗ | pixel_t_d* dstp = reinterpret_cast<pixel_t_d*>(dstp8); | |
| 403 | ✗ | dst_pitch = dst_pitch / sizeof(pixel_t_d); | |
| 404 | |||
| 405 | // perhaps helps compiler to optimize | ||
| 406 | if constexpr (sizeof(pixel_t_s) == 1) | ||
| 407 | ✗ | source_bitdepth = 8; | |
| 408 | if constexpr (sizeof(pixel_t_d) == 1) | ||
| 409 | ✗ | target_bitdepth = 8; | |
| 410 | |||
| 411 | ✗ | const int max_pixel_value_target = (1 << target_bitdepth) - 1; | |
| 412 | ✗ | const int BITDIFF_BETWEEN_DITHER_AND_TARGET = DITHER_BIT_DIFF - (source_bitdepth - target_bitdepth); | |
| 413 | ✗ | const int max_pixel_value_dithered = (1 << dither_target_bitdepth) - 1; | |
| 414 | |||
| 415 | ✗ | std::vector<int> error_ptr_safe(1 + src_width + 1); // accumulated errors | |
| 416 | ✗ | int *error_ptr = &error_ptr_safe[1]; | |
| 417 | |||
| 418 | ✗ | const int ROUNDER = 1 << (DITHER_BIT_DIFF - 1); // rounding | |
| 419 | ✗ | const int source_max = (1 << source_bitdepth) - 1; | |
| 420 | //----------------------- | ||
| 421 | ✗ | bits_conv_constants d; | |
| 422 | get_bits_conv_constants(d, chroma, fulls, fulld, source_bitdepth, source_bitdepth); | ||
| 423 | |||
| 424 | ✗ | auto dst_offset_plus_round = d.dst_offset + 0.5f; | |
| 425 | ✗ | constexpr auto src_pixel_min = 0; | |
| 426 | ✗ | const auto src_pixel_max = source_max; | |
| 427 | ✗ | const float mul_factor_backfromlowdither = (float)max_pixel_value_target / max_pixel_value_dithered; | |
| 428 | |||
| 429 | ✗ | int nextError = 0; // zero | |
| 430 | |||
| 431 | ✗ | for (int y = 0; y < src_height; y++) | |
| 432 | { | ||
| 433 | // serpentine forward | ||
| 434 | ✗ | if ((y & 1) == 0) | |
| 435 | { | ||
| 436 | ✗ | for (int x = 0; x < src_width; x++) | |
| 437 | { | ||
| 438 | ✗ | int err = nextError; | |
| 439 | ✗ | int src_pixel = srcp[x]; | |
| 440 | |||
| 441 | if constexpr (fulls != fulld) { | ||
| 442 | ✗ | const float val = (src_pixel - d.src_offset_i) * d.mul_factor + dst_offset_plus_round; | |
| 443 | ✗ | src_pixel = clamp((int)val, src_pixel_min, src_pixel_max); | |
| 444 | } | ||
| 445 | |||
| 446 | if (TEMPLATE_LOW_DITHER_BITDEPTH) { | ||
| 447 | // accurate dither: +/- | ||
| 448 | // accurately positioned to the center | ||
| 449 | ✗ | err = err - (1 << (DITHER_BIT_DIFF - 1)); // signed | |
| 450 | } | ||
| 451 | ✗ | int sum = src_pixel + err; | |
| 452 | |||
| 453 | ✗ | int quantized = (sum + ROUNDER) >> (DITHER_BIT_DIFF); | |
| 454 | ✗ | err = sum - (quantized << DITHER_BIT_DIFF); | |
| 455 | // Interesting problem of dither_bits==1 (or in general at small dither_bits) | ||
| 456 | // After simple slli 0,1 becomes 0,128, we'd expect 0,255 instead. So we make cosmetics. | ||
| 457 | if (TEMPLATE_LOW_DITHER_BITDEPTH) { | ||
| 458 | ✗ | quantized = min(quantized, max_pixel_value_dithered); | |
| 459 | ✗ | quantized = (int)(quantized * mul_factor_backfromlowdither + 0.5f); | |
| 460 | } | ||
| 461 | else { | ||
| 462 | ✗ | quantized <<= BITDIFF_BETWEEN_DITHER_AND_TARGET; | |
| 463 | } | ||
| 464 | ✗ | int pix = max(min(max_pixel_value_target, quantized), 0); // clamp to target bit | |
| 465 | ✗ | dstp[x] = (pixel_t_d)pix; | |
| 466 | ✗ | diffuse_floyd<1>(err, nextError, &error_ptr[x]); | |
| 467 | } | ||
| 468 | } | ||
| 469 | else { | ||
| 470 | // serpentine backward | ||
| 471 | ✗ | for (int x = src_width - 1; x >= 0; --x) | |
| 472 | { | ||
| 473 | ✗ | int err = nextError; | |
| 474 | ✗ | int src_pixel = srcp[x]; | |
| 475 | |||
| 476 | if constexpr (fulls != fulld) { | ||
| 477 | ✗ | const float val = (src_pixel - d.src_offset_i) * d.mul_factor + dst_offset_plus_round; | |
| 478 | ✗ | src_pixel = clamp((int)val, src_pixel_min, src_pixel_max); | |
| 479 | } | ||
| 480 | |||
| 481 | if (TEMPLATE_LOW_DITHER_BITDEPTH) { | ||
| 482 | // accurate dither: +/- | ||
| 483 | // accurately positioned to the center | ||
| 484 | ✗ | err = err - (1 << (DITHER_BIT_DIFF - 1)); // signed | |
| 485 | } | ||
| 486 | ✗ | int sum = src_pixel + err; | |
| 487 | |||
| 488 | ✗ | int quantized = (sum + ROUNDER) >> (DITHER_BIT_DIFF); | |
| 489 | ✗ | err = sum - (quantized << DITHER_BIT_DIFF); | |
| 490 | // Interesting problem of dither_bits==1 (or in general at small dither_bits) | ||
| 491 | // After simple slli 0,1 becomes 0,128, we'd expect 0,255 instead. So we make cosmetics. | ||
| 492 | if (TEMPLATE_LOW_DITHER_BITDEPTH) { | ||
| 493 | ✗ | quantized = min(quantized, max_pixel_value_dithered); | |
| 494 | ✗ | quantized = (int)(quantized * mul_factor_backfromlowdither + 0.5f); | |
| 495 | } | ||
| 496 | else { | ||
| 497 | ✗ | quantized <<= BITDIFF_BETWEEN_DITHER_AND_TARGET; | |
| 498 | } | ||
| 499 | ✗ | int pix = max(min(max_pixel_value_target, quantized), 0); // clamp to target bit | |
| 500 | ✗ | dstp[x] = (pixel_t_d)pix; | |
| 501 | ✗ | diffuse_floyd<-1>(err, nextError, &error_ptr[x]); | |
| 502 | } | ||
| 503 | } | ||
| 504 | ✗ | dstp += dst_pitch; | |
| 505 | ✗ | srcp += src_pitch; | |
| 506 | } | ||
| 507 | ✗ | } | |
| 508 | |||
| 509 | |||
| 510 | template<typename pixel_t_s, typename pixel_t_d, bool chroma, bool fulls, bool fulld> | ||
| 511 | ✗ | static void convert_uint_floyd_c(const BYTE* srcp8, BYTE* dstp8, int src_rowsize, int src_height, int src_pitch, int dst_pitch, int source_bitdepth, int target_bitdepth, int dither_target_bitdepth) | |
| 512 | { | ||
| 513 | ✗ | const int dither_bit_diff = source_bitdepth - dither_target_bitdepth; | |
| 514 | ✗ | const bool low_dither_bitdepth = dither_target_bitdepth < 8; | |
| 515 | // extra internal template makes it quicker for ordinary non-artistic cases | ||
| 516 | // do not make templates for all 1-16 target bit combinations | ||
| 517 | ✗ | if (low_dither_bitdepth) { | |
| 518 | ✗ | do_convert_uint_floyd_c<pixel_t_s, pixel_t_d, chroma, fulls, fulld, -1, true, -1>(srcp8, dstp8, src_rowsize, src_height, src_pitch, dst_pitch, source_bitdepth, target_bitdepth, dither_target_bitdepth); | |
| 519 | } | ||
| 520 | else { | ||
| 521 | ✗ | if (target_bitdepth == dither_target_bitdepth) { | |
| 522 | // Specifically when source_bitdepth is known as well, it hugely helps optimization | ||
| 523 | // We treat special use cases 10->8, 16->10 and 16->8 | ||
| 524 | ✗ | switch (dither_bit_diff) { | |
| 525 | ✗ | case 2: // e.g. 10->8 | |
| 526 | ✗ | if (source_bitdepth == 10) | |
| 527 | ✗ | do_convert_uint_floyd_c<pixel_t_s, pixel_t_d, chroma, fulls, fulld, 2, false, 10>(srcp8, dstp8, src_rowsize, src_height, src_pitch, dst_pitch, source_bitdepth, target_bitdepth, dither_target_bitdepth); | |
| 528 | else | ||
| 529 | ✗ | do_convert_uint_floyd_c<pixel_t_s, pixel_t_d, chroma, fulls, fulld, 2, false, -1>(srcp8, dstp8, src_rowsize, src_height, src_pitch, dst_pitch, source_bitdepth, target_bitdepth, dither_target_bitdepth); | |
| 530 | ✗ | break; | |
| 531 | ✗ | case 4: // e.g. 12->8 | |
| 532 | ✗ | do_convert_uint_floyd_c<pixel_t_s, pixel_t_d, chroma, fulls, fulld, 4, false, -1>(srcp8, dstp8, src_rowsize, src_height, src_pitch, dst_pitch, source_bitdepth, target_bitdepth, dither_target_bitdepth); | |
| 533 | ✗ | break; | |
| 534 | ✗ | case 6: // e.g. 16->10, 14->8 | |
| 535 | // prevent invalid templates to generate | ||
| 536 | // like do_convert_uint_floyd_c<unsigned short,unsigned char,0,0,1,6,0,16> which would do 16->8 but dither to 10 bit. | ||
| 537 | if constexpr (sizeof(pixel_t_s) == 2 && sizeof(pixel_t_d) == 2) { | ||
| 538 | ✗ | if (source_bitdepth == 16) | |
| 539 | ✗ | do_convert_uint_floyd_c<pixel_t_s, pixel_t_d, chroma, fulls, fulld, 6, false, 16>(srcp8, dstp8, src_rowsize, src_height, src_pitch, dst_pitch, source_bitdepth, target_bitdepth, dither_target_bitdepth); | |
| 540 | else | ||
| 541 | ✗ | do_convert_uint_floyd_c<pixel_t_s, pixel_t_d, chroma, fulls, fulld, 6, false, -1>(srcp8, dstp8, src_rowsize, src_height, src_pitch, dst_pitch, source_bitdepth, target_bitdepth, dither_target_bitdepth); | |
| 542 | } else | ||
| 543 | ✗ | do_convert_uint_floyd_c<pixel_t_s, pixel_t_d, chroma, fulls, fulld, 6, false, -1>(srcp8, dstp8, src_rowsize, src_height, src_pitch, dst_pitch, source_bitdepth, target_bitdepth, dither_target_bitdepth); | |
| 544 | ✗ | break; | |
| 545 | ✗ | case 8: // e.g. 16->8 | |
| 546 | ✗ | if (sizeof(pixel_t_s) == 2 && source_bitdepth == 16) | |
| 547 | ✗ | do_convert_uint_floyd_c<pixel_t_s, pixel_t_d, chroma, fulls, fulld, 8, false, 16>(srcp8, dstp8, src_rowsize, src_height, src_pitch, dst_pitch, source_bitdepth, target_bitdepth, dither_target_bitdepth); | |
| 548 | else | ||
| 549 | ✗ | do_convert_uint_floyd_c<pixel_t_s, pixel_t_d, chroma, fulls, fulld, 8, false, -1>(srcp8, dstp8, src_rowsize, src_height, src_pitch, dst_pitch, source_bitdepth, target_bitdepth, dither_target_bitdepth); | |
| 550 | ✗ | break; | |
| 551 | ✗ | default: // difference is more than 8 or exotic dither to less than 8 bits, we accept 10-15% speed minus | |
| 552 | ✗ | do_convert_uint_floyd_c<pixel_t_s, pixel_t_d, chroma, fulls, fulld, -1, false, -1>(srcp8, dstp8, src_rowsize, src_height, src_pitch, dst_pitch, source_bitdepth, target_bitdepth, dither_target_bitdepth); | |
| 553 | } | ||
| 554 | } | ||
| 555 | else { | ||
| 556 | ✗ | do_convert_uint_floyd_c<pixel_t_s, pixel_t_d, chroma, fulls, fulld, -1, false, -1>(srcp8, dstp8, src_rowsize, src_height, src_pitch, dst_pitch, source_bitdepth, target_bitdepth, dither_target_bitdepth); | |
| 557 | } | ||
| 558 | } | ||
| 559 | ✗ | } | |
| 560 | |||
| 561 | // float to 8-16 bits | ||
| 562 | template<typename pixel_t, bool chroma, bool fulls, bool fulld> | ||
| 563 | ✗ | static void convert_32_to_uintN_c(const BYTE *srcp, BYTE *dstp, int src_rowsize, int src_height, int src_pitch, int dst_pitch, int source_bitdepth, int target_bitdepth, int dither_target_bitdepth) | |
| 564 | { | ||
| 565 | ✗ | const float *srcp0 = reinterpret_cast<const float *>(srcp); | |
| 566 | ✗ | pixel_t *dstp0 = reinterpret_cast<pixel_t *>(dstp); | |
| 567 | |||
| 568 | ✗ | src_pitch = src_pitch / sizeof(float); | |
| 569 | ✗ | dst_pitch = dst_pitch / sizeof(pixel_t); | |
| 570 | |||
| 571 | ✗ | const int src_width = src_rowsize / sizeof(float); | |
| 572 | |||
| 573 | //----------------------- | ||
| 574 | |||
| 575 | ✗ | bits_conv_constants d; | |
| 576 | get_bits_conv_constants(d, chroma, fulls, fulld, source_bitdepth, target_bitdepth); | ||
| 577 | |||
| 578 | ✗ | auto dst_offset_plus_round = d.dst_offset + 0.5f; | |
| 579 | ✗ | constexpr auto dst_pixel_min = 0; | |
| 580 | ✗ | const auto dst_pixel_max = (1 << target_bitdepth) - 1; | |
| 581 | |||
| 582 | ✗ | for(int y=0; y<src_height; y++) | |
| 583 | { | ||
| 584 | ✗ | for (int x = 0; x < src_width; x++) | |
| 585 | { | ||
| 586 | ✗ | const int pixel = (int)((srcp0[x] - d.src_offset) * d.mul_factor + dst_offset_plus_round); | |
| 587 | ✗ | dstp0[x] = pixel_t(clamp(pixel, dst_pixel_min, dst_pixel_max)); | |
| 588 | } | ||
| 589 | ✗ | dstp0 += dst_pitch; | |
| 590 | ✗ | srcp0 += src_pitch; | |
| 591 | } | ||
| 592 | ✗ | } | |
| 593 | |||
| 594 | // YUV: bit shift 8-16 <=> 8-16 bits | ||
| 595 | // shift right or left, depending on expandrange | ||
| 596 | template<typename pixel_t_s, typename pixel_t_d> | ||
| 597 | ✗ | static void convert_uint_limited_c(const BYTE* srcp, BYTE* dstp, int src_rowsize, int src_height, int src_pitch, int dst_pitch, int source_bitdepth, int target_bitdepth, int dither_target_bitdepth) | |
| 598 | { | ||
| 599 | ✗ | const pixel_t_s* srcp0 = reinterpret_cast<const pixel_t_s*>(srcp); | |
| 600 | ✗ | pixel_t_d* dstp0 = reinterpret_cast<pixel_t_d*>(dstp); | |
| 601 | |||
| 602 | ✗ | src_pitch = src_pitch / sizeof(pixel_t_s); | |
| 603 | ✗ | dst_pitch = dst_pitch / sizeof(pixel_t_d); | |
| 604 | |||
| 605 | ✗ | const int src_width = src_rowsize / sizeof(pixel_t_s); | |
| 606 | |||
| 607 | ✗ | if (target_bitdepth > source_bitdepth) // expandrange | |
| 608 | { | ||
| 609 | ✗ | const int shift_bits = target_bitdepth - source_bitdepth; | |
| 610 | ✗ | for (int y = 0; y < src_height; y++) | |
| 611 | { | ||
| 612 | ✗ | for (int x = 0; x < src_width; x++) { | |
| 613 | ✗ | dstp0[x] = (pixel_t_d)(srcp0[x]) << shift_bits; // expand range. No clamp before, source is assumed to have valid range | |
| 614 | } | ||
| 615 | ✗ | dstp0 += dst_pitch; | |
| 616 | ✗ | srcp0 += src_pitch; | |
| 617 | } | ||
| 618 | } | ||
| 619 | else | ||
| 620 | { | ||
| 621 | // reduce range | ||
| 622 | ✗ | const int shift_bits = source_bitdepth - target_bitdepth; | |
| 623 | ✗ | const int round = 1 << (shift_bits - 1); | |
| 624 | |||
| 625 | ✗ | const pixel_t_s source_max = (1 << source_bitdepth) - 1; | |
| 626 | |||
| 627 | ✗ | for (int y = 0; y < src_height; y++) | |
| 628 | { | ||
| 629 | ✗ | const pixel_t_s* AVS_RESTRICT s = srcp0; | |
| 630 | ✗ | pixel_t_d* AVS_RESTRICT d = dstp0; | |
| 631 | |||
| 632 | ✗ | for (int x = 0; x < src_width; x++) { | |
| 633 | ✗ | int val = static_cast<int>(s[x]) + round; | |
| 634 | ✗ | if (val > source_max) val = source_max; // no saturated add in C | |
| 635 | ✗ | d[x] = static_cast<pixel_t_d>(val >> shift_bits); | |
| 636 | } | ||
| 637 | ✗ | dstp0 += dst_pitch; | |
| 638 | ✗ | srcp0 += src_pitch; | |
| 639 | } | ||
| 640 | } | ||
| 641 | ✗ | } | |
| 642 | |||
| 643 | // chroma is special in full range | ||
| 644 | template<typename pixel_t_s, typename pixel_t_d, bool chroma, bool fulls, bool fulld> | ||
| 645 | ✗ | static void convert_uint_c(const BYTE* srcp, BYTE* dstp, int src_rowsize, int src_height, int src_pitch, int dst_pitch, int source_bitdepth, int target_bitdepth, int dither_target_bitdepth) | |
| 646 | { | ||
| 647 | // limited to limited is bitshift, see in other function | ||
| 648 | if constexpr (!fulls && !fulld) { | ||
| 649 | ✗ | convert_uint_limited_c< pixel_t_s, pixel_t_d>(srcp, dstp, src_rowsize, src_height, src_pitch, dst_pitch, source_bitdepth, target_bitdepth, dither_target_bitdepth); | |
| 650 | ✗ | return; | |
| 651 | } | ||
| 652 | |||
| 653 | ✗ | const pixel_t_s* srcp0 = reinterpret_cast<const pixel_t_s*>(srcp); | |
| 654 | ✗ | pixel_t_d* dstp0 = reinterpret_cast<pixel_t_d*>(dstp); | |
| 655 | |||
| 656 | ✗ | src_pitch = src_pitch / sizeof(pixel_t_s); | |
| 657 | ✗ | dst_pitch = dst_pitch / sizeof(pixel_t_d); | |
| 658 | |||
| 659 | ✗ | const int src_width = src_rowsize / sizeof(pixel_t_s); | |
| 660 | |||
| 661 | if constexpr (sizeof(pixel_t_s) == 1 && sizeof(pixel_t_d) == 2) { | ||
| 662 | ✗ | if (fulls && fulld && !chroma && source_bitdepth == 8 && target_bitdepth == 16) { | |
| 663 | // special case * 65535 / 255 = *257 exactly | ||
| 664 | ✗ | for (int y = 0; y < src_height; y++) | |
| 665 | { | ||
| 666 | ✗ | for (int x = 0; x < src_width; x++) | |
| 667 | { | ||
| 668 | ✗ | dstp0[x] = (pixel_t_d)(srcp0[x] * 257); | |
| 669 | } | ||
| 670 | ✗ | dstp0 += dst_pitch; | |
| 671 | ✗ | srcp0 += src_pitch; | |
| 672 | } | ||
| 673 | ✗ | return; | |
| 674 | } | ||
| 675 | } | ||
| 676 | |||
| 677 | ✗ | const int target_max = (1 << target_bitdepth) - 1; | |
| 678 | |||
| 679 | ✗ | bits_conv_constants d; | |
| 680 | get_bits_conv_constants(d, chroma, fulls, fulld, source_bitdepth, target_bitdepth); | ||
| 681 | |||
| 682 | ✗ | auto dst_offset_plus_round = d.dst_offset + 0.5f; | |
| 683 | ✗ | constexpr auto target_min = 0; | |
| 684 | |||
| 685 | ✗ | for (int y = 0; y < src_height; y++) { | |
| 686 | ✗ | for (int x = 0; x < src_width; x++) | |
| 687 | { | ||
| 688 | ✗ | const float val = (srcp0[x] - d.src_offset_i) * d.mul_factor + dst_offset_plus_round; | |
| 689 | ✗ | dstp0[x] = clamp((int)val, target_min, target_max); | |
| 690 | } | ||
| 691 | |||
| 692 | ✗ | dstp0 += dst_pitch; | |
| 693 | ✗ | srcp0 += src_pitch; | |
| 694 | } | ||
| 695 | ✗ | } | |
| 696 | |||
| 697 | |||
| 698 | |||
| 699 | // 8 bit to float, 16/14/12/10 bits to float | ||
| 700 | template<typename pixel_t, bool chroma, bool fulls, bool fulld> | ||
| 701 | ✗ | static void convert_uintN_to_float_c(const BYTE *srcp, BYTE *dstp, int src_rowsize, int src_height, int src_pitch, int dst_pitch, int source_bitdepth, int target_bitdepth, int dither_target_bitdepth) | |
| 702 | { | ||
| 703 | ✗ | const pixel_t *srcp0 = reinterpret_cast<const pixel_t *>(srcp); | |
| 704 | ✗ | float *dstp0 = reinterpret_cast<float *>(dstp); | |
| 705 | |||
| 706 | ✗ | src_pitch = src_pitch / sizeof(pixel_t); | |
| 707 | ✗ | dst_pitch = dst_pitch / sizeof(float); | |
| 708 | |||
| 709 | ✗ | const int src_width = src_rowsize / sizeof(pixel_t); | |
| 710 | |||
| 711 | //----------------------- | ||
| 712 | ✗ | bits_conv_constants d; | |
| 713 | get_bits_conv_constants(d, chroma, fulls, fulld, source_bitdepth, target_bitdepth); | ||
| 714 | |||
| 715 | ✗ | for (int y = 0; y < src_height; y++) | |
| 716 | { | ||
| 717 | ✗ | for (int x = 0; x < src_width; x++) | |
| 718 | { | ||
| 719 | ✗ | const float pixel = (srcp0[x] - d.src_offset_i) * d.mul_factor + d.dst_offset; | |
| 720 | ✗ | dstp0[x] = pixel; // no clamp | |
| 721 | } | ||
| 722 | ✗ | dstp0 += dst_pitch; | |
| 723 | ✗ | srcp0 += src_pitch; | |
| 724 | } | ||
| 725 | ✗ | } | |
| 726 | |||
| 727 | // float to float | ||
| 728 | template<bool chroma, bool fulls, bool fulld> | ||
| 729 | ✗ | static void convert_float_to_float_c(const BYTE* srcp, BYTE* dstp, int src_rowsize, int src_height, int src_pitch, int dst_pitch, int source_bitdepth, int target_bitdepth, int dither_target_bitdepth) | |
| 730 | { | ||
| 731 | // float is good if always full range. For historical reasons Avisynth has "limited" range float, | ||
| 732 | // which is simply a /255.0 reduction of original byte pixels | ||
| 733 | ✗ | const float* srcp0 = reinterpret_cast<const float*>(srcp); | |
| 734 | ✗ | float* dstp0 = reinterpret_cast<float*>(dstp); | |
| 735 | |||
| 736 | ✗ | src_pitch = src_pitch / sizeof(float); | |
| 737 | ✗ | dst_pitch = dst_pitch / sizeof(float); | |
| 738 | |||
| 739 | ✗ | const int src_width = src_rowsize / sizeof(float); | |
| 740 | |||
| 741 | //----------------------- | ||
| 742 | ✗ | bits_conv_constants d; | |
| 743 | get_bits_conv_constants(d, chroma, fulls, fulld, source_bitdepth, target_bitdepth); | ||
| 744 | |||
| 745 | ✗ | for (int y = 0; y < src_height; y++) | |
| 746 | { | ||
| 747 | ✗ | for (int x = 0; x < src_width; x++) | |
| 748 | { | ||
| 749 | ✗ | const float pixel = (srcp0[x] - d.src_offset) * d.mul_factor + d.dst_offset; | |
| 750 | ✗ | dstp0[x] = pixel; // no clamp | |
| 751 | } | ||
| 752 | ✗ | dstp0 += dst_pitch; | |
| 753 | ✗ | srcp0 += src_pitch; | |
| 754 | } | ||
| 755 | ✗ | } | |
| 756 | |||
| 757 | ✗ | static void get_convert_32_to_uintN_functions(int target_bitdepth, bool fulls, bool fulld, | |
| 758 | #ifdef INTEL_INTRINSICS | ||
| 759 | bool sse2, bool sse4, bool avx2, | ||
| 760 | #endif | ||
| 761 | BitDepthConvFuncPtr& conv_function, BitDepthConvFuncPtr& conv_function_chroma, BitDepthConvFuncPtr& conv_function_a) | ||
| 762 | { | ||
| 763 | // 32bit->8-16bits support fulls fulld | ||
| 764 | // pure C | ||
| 765 | #define convert_32_to_uintN_functions(uint_X_t) \ | ||
| 766 | conv_function_a = convert_32_to_uintN_c<uint_X_t, false, true, true>; /* full-full */ \ | ||
| 767 | if (fulls && fulld) { \ | ||
| 768 | conv_function = convert_32_to_uintN_c<uint_X_t, false, true, true>; \ | ||
| 769 | conv_function_chroma = convert_32_to_uintN_c<uint_X_t, true, true, true>; \ | ||
| 770 | } \ | ||
| 771 | else if (fulls && !fulld) { \ | ||
| 772 | conv_function = convert_32_to_uintN_c<uint_X_t, false, true, false>; \ | ||
| 773 | conv_function_chroma = convert_32_to_uintN_c<uint_X_t, true, true, false>; \ | ||
| 774 | } \ | ||
| 775 | else if (!fulls && fulld) { \ | ||
| 776 | conv_function = convert_32_to_uintN_c<uint_X_t, false, false, true>; \ | ||
| 777 | conv_function_chroma = convert_32_to_uintN_c<uint_X_t, true, false, true>; \ | ||
| 778 | } \ | ||
| 779 | else if (!fulls && !fulld) { \ | ||
| 780 | conv_function = convert_32_to_uintN_c<uint_X_t, false, false, false>; \ | ||
| 781 | conv_function_chroma = convert_32_to_uintN_c<uint_X_t, true, false, false>; \ | ||
| 782 | } | ||
| 783 | |||
| 784 | #ifdef INTEL_INTRINSICS | ||
| 785 | #undef convert_32_to_uintN_functions | ||
| 786 | |||
| 787 | #define convert_32_to_uintN_functions(uint_X_t) \ | ||
| 788 | conv_function_a = avx2 ? convert_32_to_uintN_avx2<uint_X_t, false, true, true> : sse4 ? convert_32_to_uintN_sse41<uint_X_t, false, true, true> : convert_32_to_uintN_c<uint_X_t, false, true, true>; /* full-full */ \ | ||
| 789 | if (fulls && fulld) { \ | ||
| 790 | conv_function = avx2 ? convert_32_to_uintN_avx2<uint_X_t, false, true, true> : sse4 ? convert_32_to_uintN_sse41<uint_X_t, false, true, true> : convert_32_to_uintN_c<uint_X_t, false, true, true>; \ | ||
| 791 | conv_function_chroma = avx2 ? convert_32_to_uintN_avx2<uint_X_t, true, true, true> : sse4 ? convert_32_to_uintN_sse41<uint_X_t, true, true, true> : convert_32_to_uintN_c<uint_X_t, true, true, true>; \ | ||
| 792 | } \ | ||
| 793 | else if (fulls && !fulld) { \ | ||
| 794 | conv_function = avx2 ? convert_32_to_uintN_avx2<uint_X_t, false, true, false> : sse4 ? convert_32_to_uintN_sse41<uint_X_t, false, true, false> : convert_32_to_uintN_c<uint_X_t, false, true, false>; \ | ||
| 795 | conv_function_chroma = avx2 ? convert_32_to_uintN_avx2<uint_X_t, true, true, false> : sse4 ? convert_32_to_uintN_sse41<uint_X_t, true, true, false> : convert_32_to_uintN_c<uint_X_t, true, true, false>; \ | ||
| 796 | } \ | ||
| 797 | else if (!fulls && fulld) { \ | ||
| 798 | conv_function = avx2 ? convert_32_to_uintN_avx2<uint_X_t, false, false, true> : sse4 ? convert_32_to_uintN_sse41<uint_X_t, false, false, true> : convert_32_to_uintN_c<uint_X_t, false, false, true>; \ | ||
| 799 | conv_function_chroma = avx2 ? convert_32_to_uintN_avx2<uint_X_t, true, false, true> : sse4 ? convert_32_to_uintN_sse41<uint_X_t, true, false, true> : convert_32_to_uintN_c<uint_X_t, true, false, true>; \ | ||
| 800 | } \ | ||
| 801 | else if (!fulls && !fulld) { \ | ||
| 802 | conv_function = avx2 ? convert_32_to_uintN_avx2<uint_X_t, false, false, false> : sse4 ? convert_32_to_uintN_sse41<uint_X_t, false, false, false> : convert_32_to_uintN_c<uint_X_t, false, false, false>; \ | ||
| 803 | conv_function_chroma = avx2 ? convert_32_to_uintN_avx2<uint_X_t, true, false, false> : sse4 ? convert_32_to_uintN_sse41<uint_X_t, true, false, false> : convert_32_to_uintN_c<uint_X_t, true, false, false>; \ | ||
| 804 | } | ||
| 805 | #endif | ||
| 806 | |||
| 807 | ✗ | switch (target_bitdepth) | |
| 808 | { | ||
| 809 | ✗ | case 8: | |
| 810 | ✗ | convert_32_to_uintN_functions(uint8_t); // all variations of fulls fulld | |
| 811 | ✗ | break; | |
| 812 | ✗ | default: | |
| 813 | // 10-16 bits | ||
| 814 | ✗ | convert_32_to_uintN_functions(uint16_t); // all variations of fulls fulld | |
| 815 | ✗ | break; | |
| 816 | } | ||
| 817 | |||
| 818 | #undef convert_32_to_uintN_functions | ||
| 819 | ✗ | } | |
| 820 | |||
| 821 | ✗ | static void get_convert_float_to_float_functions(bool fulls, bool fulld, | |
| 822 | BitDepthConvFuncPtr& conv_function, BitDepthConvFuncPtr& conv_function_chroma, BitDepthConvFuncPtr& conv_function_a) | ||
| 823 | { | ||
| 824 | // 32bit->32bits support fulls fulld, alpha is always full-full | ||
| 825 | ✗ | conv_function_a = convert_float_to_float_c<false, true, true>; /* full-full */ | |
| 826 | ✗ | if (fulls && fulld) { | |
| 827 | ✗ | conv_function = convert_float_to_float_c<false, true, true>; | |
| 828 | ✗ | conv_function_chroma = convert_float_to_float_c<true, true, true>; | |
| 829 | } | ||
| 830 | ✗ | else if (fulls && !fulld) { | |
| 831 | ✗ | conv_function = convert_float_to_float_c<false, true, false>; | |
| 832 | ✗ | conv_function_chroma = convert_float_to_float_c<true, true, false>; | |
| 833 | } | ||
| 834 | ✗ | else if (!fulls && fulld) { \ | |
| 835 | ✗ | conv_function = convert_float_to_float_c<false, false, true>; | |
| 836 | ✗ | conv_function_chroma = convert_float_to_float_c<true, false, true>; | |
| 837 | } | ||
| 838 | ✗ | else if (!fulls && !fulld) { | |
| 839 | ✗ | conv_function = convert_float_to_float_c<false, false, false>; | |
| 840 | ✗ | conv_function_chroma = convert_float_to_float_c<true, false, false>; | |
| 841 | } | ||
| 842 | ✗ | } | |
| 843 | |||
| 844 | ✗ | static void get_convert_uintN_to_float_functions(int bits_per_pixel, bool fulls, bool fulld, | |
| 845 | #ifdef INTEL_INTRINSICS | ||
| 846 | bool sse2, bool sse4, bool avx2, | ||
| 847 | #endif | ||
| 848 | BitDepthConvFuncPtr& conv_function, BitDepthConvFuncPtr& conv_function_chroma, BitDepthConvFuncPtr& conv_function_a) | ||
| 849 | { | ||
| 850 | // 8-16bit->32bits support fulls fulld, alpha is always full-full | ||
| 851 | #define convert_uintN_to_float_functions(uint_X_t) \ | ||
| 852 | conv_function_a = convert_uintN_to_float_c<uint_X_t, false, true, true>; /* full-full */ \ | ||
| 853 | if (fulls && fulld) { \ | ||
| 854 | conv_function = convert_uintN_to_float_c<uint_X_t, false, true, true>; \ | ||
| 855 | conv_function_chroma = convert_uintN_to_float_c<uint_X_t, true, true, true>; \ | ||
| 856 | } \ | ||
| 857 | else if (fulls && !fulld) { \ | ||
| 858 | conv_function = convert_uintN_to_float_c<uint_X_t, false, true, false>; \ | ||
| 859 | conv_function_chroma = convert_uintN_to_float_c<uint_X_t, true, true, false>; \ | ||
| 860 | } \ | ||
| 861 | else if (!fulls && fulld) { \ | ||
| 862 | conv_function = convert_uintN_to_float_c<uint_X_t, false, false, true>; \ | ||
| 863 | conv_function_chroma = convert_uintN_to_float_c<uint_X_t, true, false, true>; \ | ||
| 864 | } \ | ||
| 865 | else if (!fulls && !fulld) { \ | ||
| 866 | conv_function = convert_uintN_to_float_c<uint_X_t, false, false, false>; \ | ||
| 867 | conv_function_chroma = convert_uintN_to_float_c<uint_X_t, true, false, false>; \ | ||
| 868 | } | ||
| 869 | |||
| 870 | #define convert_uintN_to_float_functions_avx2(uint_X_t) \ | ||
| 871 | conv_function_a = convert_uintN_to_float_avx2<uint_X_t, false, true, true>; /* full-full */ \ | ||
| 872 | if (fulls && fulld) { \ | ||
| 873 | conv_function = convert_uintN_to_float_avx2<uint_X_t, false, true, true>; \ | ||
| 874 | conv_function_chroma = convert_uintN_to_float_avx2<uint_X_t, true, true, true>; \ | ||
| 875 | } \ | ||
| 876 | else if (fulls && !fulld) { \ | ||
| 877 | conv_function = convert_uintN_to_float_avx2<uint_X_t, false, true, false>; \ | ||
| 878 | conv_function_chroma = convert_uintN_to_float_avx2<uint_X_t, true, true, false>; \ | ||
| 879 | } \ | ||
| 880 | else if (!fulls && fulld) { \ | ||
| 881 | conv_function = convert_uintN_to_float_avx2<uint_X_t, false, false, true>; \ | ||
| 882 | conv_function_chroma = convert_uintN_to_float_avx2<uint_X_t, true, false, true>; \ | ||
| 883 | } \ | ||
| 884 | else if (!fulls && !fulld) { \ | ||
| 885 | conv_function = convert_uintN_to_float_avx2<uint_X_t, false, false, false>; \ | ||
| 886 | conv_function_chroma = convert_uintN_to_float_avx2<uint_X_t, true, false, false>; \ | ||
| 887 | } | ||
| 888 | |||
| 889 | ✗ | switch (bits_per_pixel) { | |
| 890 | ✗ | case 8: | |
| 891 | ✗ | convert_uintN_to_float_functions(uint8_t); | |
| 892 | ✗ | break; | |
| 893 | ✗ | default: // 10-16 bits | |
| 894 | ✗ | convert_uintN_to_float_functions(uint16_t); | |
| 895 | ✗ | break; | |
| 896 | } | ||
| 897 | |||
| 898 | #ifdef INTEL_INTRINSICS | ||
| 899 | ✗ | if (avx2) { | |
| 900 | ✗ | switch (bits_per_pixel) { | |
| 901 | ✗ | case 8: | |
| 902 | ✗ | convert_uintN_to_float_functions_avx2(uint8_t); | |
| 903 | ✗ | break; | |
| 904 | ✗ | default: // 10-16 bits | |
| 905 | ✗ | convert_uintN_to_float_functions_avx2(uint16_t); | |
| 906 | ✗ | break; | |
| 907 | } | ||
| 908 | } | ||
| 909 | #endif | ||
| 910 | |||
| 911 | |||
| 912 | #undef convert_uintN_to_float_functions | ||
| 913 | ✗ | } | |
| 914 | |||
| 915 | ✗ | static void get_convert_uintN_to_uintN_ordered_dither_functions(int source_bitdepth, int target_bitdepth, bool fulls, bool fulld, | |
| 916 | #ifdef INTEL_INTRINSICS | ||
| 917 | bool sse2, bool sse4, bool avx2, | ||
| 918 | #endif | ||
| 919 | BitDepthConvFuncPtr& conv_function, BitDepthConvFuncPtr& conv_function_chroma) | ||
| 920 | { | ||
| 921 | // 8-16->8-16 bits support any fulls fulld combination | ||
| 922 | // dither has no "conv_function_a" | ||
| 923 | // pure C | ||
| 924 | #define convert_uintN_to_uintN_ordered_dither_functions(uint_X_t, uint_X_dest_t) \ | ||
| 925 | if (fulls && fulld) { \ | ||
| 926 | conv_function = convert_ordered_dither_uint_c<uint_X_t, uint_X_dest_t, false, true, true>; \ | ||
| 927 | conv_function_chroma = convert_ordered_dither_uint_c<uint_X_t, uint_X_dest_t, true, true, true>; \ | ||
| 928 | } \ | ||
| 929 | else if (fulls && !fulld) { \ | ||
| 930 | conv_function = convert_ordered_dither_uint_c<uint_X_t, uint_X_dest_t, false, true, false>; \ | ||
| 931 | conv_function_chroma = convert_ordered_dither_uint_c<uint_X_t, uint_X_dest_t, true, true, false>; \ | ||
| 932 | } \ | ||
| 933 | else if (!fulls && fulld) { \ | ||
| 934 | conv_function = convert_ordered_dither_uint_c<uint_X_t, uint_X_dest_t, false, false, true>; \ | ||
| 935 | conv_function_chroma = convert_ordered_dither_uint_c<uint_X_t, uint_X_dest_t, true, false, true>; \ | ||
| 936 | } \ | ||
| 937 | else if (!fulls && !fulld) { \ | ||
| 938 | conv_function = convert_ordered_dither_uint_c<uint_X_t, uint_X_dest_t, false, false, false>; \ | ||
| 939 | conv_function_chroma = convert_ordered_dither_uint_c<uint_X_t, uint_X_dest_t, true, false, false>; \ | ||
| 940 | } | ||
| 941 | |||
| 942 | #ifdef INTEL_INTRINSICS | ||
| 943 | #undef convert_uintN_to_uintN_ordered_dither_functions | ||
| 944 | // dither has no "conv_function_a" | ||
| 945 | #define convert_uintN_to_uintN_ordered_dither_functions(uint_X_t, uint_X_dest_t) \ | ||
| 946 | if (fulls && fulld) { \ | ||
| 947 | conv_function = avx2 ? convert_ordered_dither_uint_avx2<uint_X_t, uint_X_dest_t, false, true, true> : sse4 ? convert_ordered_dither_uint_sse41<uint_X_t, uint_X_dest_t, false, true, true> : convert_ordered_dither_uint_c<uint_X_t, uint_X_dest_t, false, true, true>; \ | ||
| 948 | conv_function_chroma = avx2 ? convert_ordered_dither_uint_avx2<uint_X_t, uint_X_dest_t, true, true, true> : sse4 ? convert_ordered_dither_uint_sse41<uint_X_t, uint_X_dest_t, true, true, true> : convert_ordered_dither_uint_c<uint_X_t, uint_X_dest_t, true, true, true>; \ | ||
| 949 | } \ | ||
| 950 | else if (fulls && !fulld) { \ | ||
| 951 | conv_function = avx2 ? convert_ordered_dither_uint_avx2<uint_X_t, uint_X_dest_t, false, true, false> : sse4 ? convert_ordered_dither_uint_sse41<uint_X_t, uint_X_dest_t, false, true, false> : convert_ordered_dither_uint_c<uint_X_t, uint_X_dest_t, false, true, false>; \ | ||
| 952 | conv_function_chroma = avx2 ? convert_ordered_dither_uint_avx2<uint_X_t, uint_X_dest_t, true, true, false> : sse4 ? convert_ordered_dither_uint_sse41<uint_X_t, uint_X_dest_t, true, true, false> : convert_ordered_dither_uint_c<uint_X_t, uint_X_dest_t, true, true, false>; \ | ||
| 953 | } \ | ||
| 954 | else if (!fulls && fulld) { \ | ||
| 955 | conv_function = avx2 ? convert_ordered_dither_uint_avx2<uint_X_t, uint_X_dest_t, false, false, true> : sse4 ? convert_ordered_dither_uint_sse41<uint_X_t, uint_X_dest_t, false, false, true> : convert_ordered_dither_uint_c<uint_X_t, uint_X_dest_t, false, false, true>; \ | ||
| 956 | conv_function_chroma = avx2 ? convert_ordered_dither_uint_avx2<uint_X_t, uint_X_dest_t, true, false, true> : sse4 ? convert_ordered_dither_uint_sse41<uint_X_t, uint_X_dest_t, true, false, true> : convert_ordered_dither_uint_c<uint_X_t, uint_X_dest_t, true, false, true>; \ | ||
| 957 | } \ | ||
| 958 | else if (!fulls && !fulld) { \ | ||
| 959 | conv_function = avx2 ? convert_ordered_dither_uint_avx2<uint_X_t, uint_X_dest_t, false, false, false> : sse4 ? convert_ordered_dither_uint_sse41<uint_X_t, uint_X_dest_t, false, false, false> : convert_ordered_dither_uint_c<uint_X_t, uint_X_dest_t, false, false, false>; \ | ||
| 960 | conv_function_chroma = avx2 ? convert_ordered_dither_uint_avx2<uint_X_t, uint_X_dest_t, true, false, false> : sse4 ? convert_ordered_dither_uint_sse41<uint_X_t, uint_X_dest_t, true, false, false> : convert_ordered_dither_uint_c<uint_X_t, uint_X_dest_t, true, false, false>; \ | ||
| 961 | } | ||
| 962 | #endif | ||
| 963 | // all variations of fulls fulld byte/word source/target | ||
| 964 | ✗ | switch (target_bitdepth) | |
| 965 | { | ||
| 966 | ✗ | case 8: | |
| 967 | ✗ | if (source_bitdepth == 8) { | |
| 968 | ✗ | convert_uintN_to_uintN_ordered_dither_functions(uint8_t, uint8_t); | |
| 969 | } | ||
| 970 | else { | ||
| 971 | ✗ | convert_uintN_to_uintN_ordered_dither_functions(uint16_t, uint8_t); | |
| 972 | } | ||
| 973 | ✗ | break; | |
| 974 | ✗ | default: | |
| 975 | // uint16_t target is always uint16_t source | ||
| 976 | ✗ | convert_uintN_to_uintN_ordered_dither_functions(uint16_t, uint16_t); | |
| 977 | ✗ | break; | |
| 978 | } | ||
| 979 | |||
| 980 | #undef convert_uintN_to_uintN_ordered_dither_functions | ||
| 981 | ✗ | } | |
| 982 | |||
| 983 | ✗ | static void get_convert_uintN_to_uintN_floyd_dither_functions(int source_bitdepth, int target_bitdepth, bool fulls, bool fulld, | |
| 984 | BitDepthConvFuncPtr& conv_function, BitDepthConvFuncPtr& conv_function_chroma) | ||
| 985 | { | ||
| 986 | // 8-16->8-16 bits support any fulls fulld combination | ||
| 987 | // dither has no "conv_function_a" | ||
| 988 | // pure C | ||
| 989 | #define convert_uintN_to_uintN_floyd_dither_functions(uint_X_t, uint_X_dest_t) \ | ||
| 990 | if (fulls && fulld) { \ | ||
| 991 | conv_function = convert_uint_floyd_c<uint_X_t, uint_X_dest_t, false, true, true>; \ | ||
| 992 | conv_function_chroma = convert_uint_floyd_c<uint_X_t, uint_X_dest_t, true, true, true>; \ | ||
| 993 | } \ | ||
| 994 | else if (fulls && !fulld) { \ | ||
| 995 | conv_function = convert_uint_floyd_c<uint_X_t, uint_X_dest_t, false, true, false>; \ | ||
| 996 | conv_function_chroma = convert_uint_floyd_c<uint_X_t, uint_X_dest_t, true, true, false>; \ | ||
| 997 | } \ | ||
| 998 | else if (!fulls && fulld) { \ | ||
| 999 | conv_function = convert_uint_floyd_c<uint_X_t, uint_X_dest_t, false, false, true>; \ | ||
| 1000 | conv_function_chroma = convert_uint_floyd_c<uint_X_t, uint_X_dest_t, true, false, true>; \ | ||
| 1001 | } \ | ||
| 1002 | else if (!fulls && !fulld) { \ | ||
| 1003 | conv_function = convert_uint_floyd_c<uint_X_t, uint_X_dest_t, false, false, false>; \ | ||
| 1004 | conv_function_chroma = convert_uint_floyd_c<uint_X_t, uint_X_dest_t, true, false, false>; \ | ||
| 1005 | } | ||
| 1006 | |||
| 1007 | // all variations of fulls fulld byte/word source/target | ||
| 1008 | ✗ | switch (target_bitdepth) | |
| 1009 | { | ||
| 1010 | ✗ | case 8: | |
| 1011 | ✗ | if (source_bitdepth == 8) { | |
| 1012 | ✗ | convert_uintN_to_uintN_floyd_dither_functions(uint8_t, uint8_t); | |
| 1013 | } | ||
| 1014 | else { | ||
| 1015 | ✗ | convert_uintN_to_uintN_floyd_dither_functions(uint16_t, uint8_t); | |
| 1016 | } | ||
| 1017 | ✗ | break; | |
| 1018 | ✗ | default: | |
| 1019 | // uint16_t target is always uint16_t source | ||
| 1020 | ✗ | convert_uintN_to_uintN_floyd_dither_functions(uint16_t, uint16_t); | |
| 1021 | ✗ | break; | |
| 1022 | } | ||
| 1023 | |||
| 1024 | #undef convert_uintN_to_uintN_floyd_dither_functions | ||
| 1025 | ✗ | } | |
| 1026 | |||
| 1027 | |||
| 1028 | 8 | static void get_convert_uintN_to_uintN_functions(int source_bitdepth, int target_bitdepth, bool fulls, bool fulld, | |
| 1029 | #ifdef INTEL_INTRINSICS | ||
| 1030 | bool sse2, bool sse4, bool avx2, | ||
| 1031 | #endif | ||
| 1032 | BitDepthConvFuncPtr& conv_function, BitDepthConvFuncPtr& conv_function_chroma, BitDepthConvFuncPtr& conv_function_a) | ||
| 1033 | { | ||
| 1034 | // 8-16->8-16 bits support any fulls fulld combination | ||
| 1035 | // pure C | ||
| 1036 | #define convert_uintN_to_uintN_functions(uint_X_t, uint_X_dest_t) \ | ||
| 1037 | conv_function_a = convert_uint_c<uint_X_t, uint_X_dest_t, false, true, true>; /* full-full */ \ | ||
| 1038 | if (fulls && fulld) { \ | ||
| 1039 | conv_function = convert_uint_c<uint_X_t, uint_X_dest_t, false, true, true>; \ | ||
| 1040 | conv_function_chroma = convert_uint_c<uint_X_t, uint_X_dest_t, true, true, true>; \ | ||
| 1041 | } \ | ||
| 1042 | else if (fulls && !fulld) { \ | ||
| 1043 | conv_function = convert_uint_c<uint_X_t, uint_X_dest_t, false, true, false>; \ | ||
| 1044 | conv_function_chroma = convert_uint_c<uint_X_t, uint_X_dest_t, true, true, false>; \ | ||
| 1045 | } \ | ||
| 1046 | else if (!fulls && fulld) { \ | ||
| 1047 | conv_function = convert_uint_c<uint_X_t, uint_X_dest_t, false, false, true>; \ | ||
| 1048 | conv_function_chroma = convert_uint_c<uint_X_t, uint_X_dest_t, true, false, true>; \ | ||
| 1049 | } \ | ||
| 1050 | else if (!fulls && !fulld) { \ | ||
| 1051 | conv_function = convert_uint_c<uint_X_t, uint_X_dest_t, false, false, false>; \ | ||
| 1052 | conv_function_chroma = convert_uint_c<uint_X_t, uint_X_dest_t, true, false, false>; \ | ||
| 1053 | } | ||
| 1054 | |||
| 1055 | #ifdef INTEL_INTRINSICS | ||
| 1056 | #undef convert_uintN_to_uintN_functions | ||
| 1057 | |||
| 1058 | #define convert_uintN_to_uintN_functions(uint_X_t, uint_X_dest_t) \ | ||
| 1059 | conv_function_a = avx2 ? convert_uint_avx2<uint_X_t, uint_X_dest_t, false, true, true> : sse4 ? convert_uint_sse41<uint_X_t, uint_X_dest_t, false, true, true> : convert_uint_c<uint_X_t, uint_X_dest_t, false, true, true>; /* full-full */ \ | ||
| 1060 | if (fulls && fulld) { \ | ||
| 1061 | conv_function = avx2 ? convert_uint_avx2<uint_X_t, uint_X_dest_t, false, true, true> : sse4 ? convert_uint_sse41<uint_X_t, uint_X_dest_t, false, true, true> : convert_uint_c<uint_X_t, uint_X_dest_t, false, true, true>; \ | ||
| 1062 | conv_function_chroma = avx2 ? convert_uint_avx2<uint_X_t, uint_X_dest_t, true, true, true> : sse4 ? convert_uint_sse41<uint_X_t, uint_X_dest_t, true, true, true> : convert_uint_c<uint_X_t, uint_X_dest_t, true, true, true>; \ | ||
| 1063 | } \ | ||
| 1064 | else if (fulls && !fulld) { \ | ||
| 1065 | conv_function = avx2 ? convert_uint_avx2<uint_X_t, uint_X_dest_t, false, true, false> : sse4 ? convert_uint_sse41<uint_X_t, uint_X_dest_t, false, true, false> : convert_uint_c<uint_X_t, uint_X_dest_t, false, true, false>; \ | ||
| 1066 | conv_function_chroma = avx2 ? convert_uint_avx2<uint_X_t, uint_X_dest_t, true, true, false> : sse4 ? convert_uint_sse41<uint_X_t, uint_X_dest_t, true, true, false> : convert_uint_c<uint_X_t, uint_X_dest_t, true, true, false>; \ | ||
| 1067 | } \ | ||
| 1068 | else if (!fulls && fulld) { \ | ||
| 1069 | conv_function = avx2 ? convert_uint_avx2<uint_X_t, uint_X_dest_t, false, false, true> : sse4 ? convert_uint_sse41<uint_X_t, uint_X_dest_t, false, false, true> : convert_uint_c<uint_X_t, uint_X_dest_t, false, false, true>; \ | ||
| 1070 | conv_function_chroma = avx2 ? convert_uint_avx2<uint_X_t, uint_X_dest_t, true, false, true> : sse4 ? convert_uint_sse41<uint_X_t, uint_X_dest_t, true, false, true> : convert_uint_c<uint_X_t, uint_X_dest_t, true, false, true>; \ | ||
| 1071 | } \ | ||
| 1072 | else if (!fulls && !fulld) { \ | ||
| 1073 | conv_function = avx2 ? convert_uint_avx2<uint_X_t, uint_X_dest_t, false, false, false> : sse4 ? convert_uint_sse41<uint_X_t, uint_X_dest_t, false, false, false> : convert_uint_c<uint_X_t, uint_X_dest_t, false, false, false>; \ | ||
| 1074 | conv_function_chroma = avx2 ? convert_uint_avx2<uint_X_t, uint_X_dest_t, true, false, false> : sse4 ? convert_uint_sse41<uint_X_t, uint_X_dest_t, true, false, false> : convert_uint_c<uint_X_t, uint_X_dest_t, true, false, false>; \ | ||
| 1075 | } | ||
| 1076 | #endif | ||
| 1077 | |||
| 1078 | // all variations of fulls fulld byte/word source/target | ||
| 1079 |
2/2✓ Branch 2 → 3 taken 1 time.
✓ Branch 2 → 120 taken 7 times.
|
8 | switch (target_bitdepth) |
| 1080 | { | ||
| 1081 | 1 | case 8: | |
| 1082 |
1/2✗ Branch 3 → 4 not taken.
✓ Branch 3 → 62 taken 1 time.
|
1 | if (source_bitdepth == 8) { |
| 1083 | ✗ | convert_uintN_to_uintN_functions(uint8_t, uint8_t); | |
| 1084 | } | ||
| 1085 | else { | ||
| 1086 |
5/52✓ Branch 62 → 63 taken 1 time.
✗ Branch 62 → 64 not taken.
✗ Branch 64 → 65 not taken.
✗ Branch 64 → 66 not taken.
✓ Branch 67 → 68 taken 1 time.
✗ Branch 67 → 80 not taken.
✓ Branch 68 → 69 taken 1 time.
✗ Branch 68 → 80 not taken.
✓ Branch 69 → 70 taken 1 time.
✗ Branch 69 → 71 not taken.
✗ Branch 71 → 72 not taken.
✗ Branch 71 → 73 not taken.
✓ Branch 74 → 75 taken 1 time.
✗ Branch 74 → 76 not taken.
✗ Branch 76 → 77 not taken.
✗ Branch 76 → 78 not taken.
✗ Branch 80 → 81 not taken.
✗ Branch 80 → 93 not taken.
✗ Branch 81 → 82 not taken.
✗ Branch 81 → 93 not taken.
✗ Branch 82 → 83 not taken.
✗ Branch 82 → 84 not taken.
✗ Branch 84 → 85 not taken.
✗ Branch 84 → 86 not taken.
✗ Branch 87 → 88 not taken.
✗ Branch 87 → 89 not taken.
✗ Branch 89 → 90 not taken.
✗ Branch 89 → 91 not taken.
✗ Branch 93 → 94 not taken.
✗ Branch 93 → 106 not taken.
✗ Branch 94 → 95 not taken.
✗ Branch 94 → 106 not taken.
✗ Branch 95 → 96 not taken.
✗ Branch 95 → 97 not taken.
✗ Branch 97 → 98 not taken.
✗ Branch 97 → 99 not taken.
✗ Branch 100 → 101 not taken.
✗ Branch 100 → 102 not taken.
✗ Branch 102 → 103 not taken.
✗ Branch 102 → 104 not taken.
✗ Branch 106 → 107 not taken.
✗ Branch 106 → 119 not taken.
✗ Branch 107 → 108 not taken.
✗ Branch 107 → 119 not taken.
✗ Branch 108 → 109 not taken.
✗ Branch 108 → 110 not taken.
✗ Branch 110 → 111 not taken.
✗ Branch 110 → 112 not taken.
✗ Branch 113 → 114 not taken.
✗ Branch 113 → 115 not taken.
✗ Branch 115 → 116 not taken.
✗ Branch 115 → 117 not taken.
|
1 | convert_uintN_to_uintN_functions(uint16_t, uint8_t); |
| 1087 | } | ||
| 1088 | 1 | break; | |
| 1089 | 7 | default: | |
| 1090 | // 10-16 bits | ||
| 1091 |
2/2✓ Branch 120 → 121 taken 6 times.
✓ Branch 120 → 179 taken 1 time.
|
7 | if (source_bitdepth == 8) |
| 1092 | { | ||
| 1093 |
18/52✓ Branch 121 → 122 taken 6 times.
✗ Branch 121 → 123 not taken.
✗ Branch 123 → 124 not taken.
✗ Branch 123 → 125 not taken.
✓ Branch 126 → 127 taken 5 times.
✓ Branch 126 → 139 taken 1 time.
✓ Branch 127 → 128 taken 4 times.
✓ Branch 127 → 139 taken 1 time.
✓ Branch 128 → 129 taken 4 times.
✗ Branch 128 → 130 not taken.
✗ Branch 130 → 131 not taken.
✗ Branch 130 → 132 not taken.
✓ Branch 133 → 134 taken 4 times.
✗ Branch 133 → 135 not taken.
✗ Branch 135 → 136 not taken.
✗ Branch 135 → 137 not taken.
✓ Branch 139 → 140 taken 1 time.
✓ Branch 139 → 152 taken 1 time.
✓ Branch 140 → 141 taken 1 time.
✗ Branch 140 → 152 not taken.
✓ Branch 141 → 142 taken 1 time.
✗ Branch 141 → 143 not taken.
✗ Branch 143 → 144 not taken.
✗ Branch 143 → 145 not taken.
✓ Branch 146 → 147 taken 1 time.
✗ Branch 146 → 148 not taken.
✗ Branch 148 → 149 not taken.
✗ Branch 148 → 150 not taken.
✓ Branch 152 → 153 taken 1 time.
✗ Branch 152 → 165 not taken.
✗ Branch 153 → 154 not taken.
✓ Branch 153 → 165 taken 1 time.
✗ Branch 154 → 155 not taken.
✗ Branch 154 → 156 not taken.
✗ Branch 156 → 157 not taken.
✗ Branch 156 → 158 not taken.
✗ Branch 159 → 160 not taken.
✗ Branch 159 → 161 not taken.
✗ Branch 161 → 162 not taken.
✗ Branch 161 → 163 not taken.
✓ Branch 165 → 166 taken 1 time.
✗ Branch 165 → 178 not taken.
✓ Branch 166 → 167 taken 1 time.
✗ Branch 166 → 178 not taken.
✓ Branch 167 → 168 taken 1 time.
✗ Branch 167 → 169 not taken.
✗ Branch 169 → 170 not taken.
✗ Branch 169 → 171 not taken.
✓ Branch 172 → 173 taken 1 time.
✗ Branch 172 → 174 not taken.
✗ Branch 174 → 175 not taken.
✗ Branch 174 → 176 not taken.
|
6 | convert_uintN_to_uintN_functions(uint8_t, uint16_t); |
| 1094 | } | ||
| 1095 | else { | ||
| 1096 |
5/52✓ Branch 179 → 180 taken 1 time.
✗ Branch 179 → 181 not taken.
✗ Branch 181 → 182 not taken.
✗ Branch 181 → 183 not taken.
✓ Branch 184 → 185 taken 1 time.
✗ Branch 184 → 197 not taken.
✓ Branch 185 → 186 taken 1 time.
✗ Branch 185 → 197 not taken.
✓ Branch 186 → 187 taken 1 time.
✗ Branch 186 → 188 not taken.
✗ Branch 188 → 189 not taken.
✗ Branch 188 → 190 not taken.
✓ Branch 191 → 192 taken 1 time.
✗ Branch 191 → 193 not taken.
✗ Branch 193 → 194 not taken.
✗ Branch 193 → 195 not taken.
✗ Branch 197 → 198 not taken.
✗ Branch 197 → 210 not taken.
✗ Branch 198 → 199 not taken.
✗ Branch 198 → 210 not taken.
✗ Branch 199 → 200 not taken.
✗ Branch 199 → 201 not taken.
✗ Branch 201 → 202 not taken.
✗ Branch 201 → 203 not taken.
✗ Branch 204 → 205 not taken.
✗ Branch 204 → 206 not taken.
✗ Branch 206 → 207 not taken.
✗ Branch 206 → 208 not taken.
✗ Branch 210 → 211 not taken.
✗ Branch 210 → 223 not taken.
✗ Branch 211 → 212 not taken.
✗ Branch 211 → 223 not taken.
✗ Branch 212 → 213 not taken.
✗ Branch 212 → 214 not taken.
✗ Branch 214 → 215 not taken.
✗ Branch 214 → 216 not taken.
✗ Branch 217 → 218 not taken.
✗ Branch 217 → 219 not taken.
✗ Branch 219 → 220 not taken.
✗ Branch 219 → 221 not taken.
✗ Branch 223 → 224 not taken.
✗ Branch 223 → 236 not taken.
✗ Branch 224 → 225 not taken.
✗ Branch 224 → 236 not taken.
✗ Branch 225 → 226 not taken.
✗ Branch 225 → 227 not taken.
✗ Branch 227 → 228 not taken.
✗ Branch 227 → 229 not taken.
✗ Branch 230 → 231 not taken.
✗ Branch 230 → 232 not taken.
✗ Branch 232 → 233 not taken.
✗ Branch 232 → 234 not taken.
|
1 | convert_uintN_to_uintN_functions(uint16_t, uint16_t); |
| 1097 | } | ||
| 1098 | 7 | break; | |
| 1099 | } | ||
| 1100 | |||
| 1101 | #undef convert_uintN_to_uintN_functions | ||
| 1102 | 8 | } | |
| 1103 | |||
| 1104 | 8 | void get_convert_any_bits_functions(int dither_mode, int source_bitdepth, int target_bitdepth, bool fulls, bool fulld, | |
| 1105 | #ifdef INTEL_INTRINSICS | ||
| 1106 | bool sse2, bool sse4, bool avx2, | ||
| 1107 | #endif | ||
| 1108 | BitDepthConvFuncPtr& conv_function, BitDepthConvFuncPtr& conv_function_chroma, BitDepthConvFuncPtr& conv_function_a) | ||
| 1109 | { | ||
| 1110 | |||
| 1111 |
2/4✓ Branch 2 → 3 taken 8 times.
✗ Branch 2 → 10 not taken.
✓ Branch 3 → 4 taken 8 times.
✗ Branch 3 → 10 not taken.
|
8 | if (source_bitdepth <= 16 && target_bitdepth <= 16) |
| 1112 | { | ||
| 1113 | // get basic non-dithered versions | ||
| 1114 | #ifdef INTEL_INTRINSICS | ||
| 1115 | 8 | get_convert_uintN_to_uintN_functions(source_bitdepth, target_bitdepth, fulls, fulld, sse2, sse4, avx2, conv_function, conv_function_chroma, conv_function_a); | |
| 1116 | #else | ||
| 1117 | get_convert_uintN_to_uintN_functions(source_bitdepth, target_bitdepth, fulls, fulld, conv_function, conv_function_chroma, conv_function_a); | ||
| 1118 | #endif | ||
| 1119 |
2/2✓ Branch 5 → 6 taken 2 times.
✓ Branch 5 → 10 taken 6 times.
|
8 | if (target_bitdepth <= source_bitdepth) { |
| 1120 | // dither is only down | ||
| 1121 |
1/2✗ Branch 6 → 7 not taken.
✓ Branch 6 → 8 taken 2 times.
|
2 | if (dither_mode == 0) { |
| 1122 | // ordered dither | ||
| 1123 | #ifdef INTEL_INTRINSICS | ||
| 1124 | ✗ | get_convert_uintN_to_uintN_ordered_dither_functions(source_bitdepth, target_bitdepth, fulls, fulld, sse2, sse4, avx2, conv_function, conv_function_chroma); | |
| 1125 | #else | ||
| 1126 | get_convert_uintN_to_uintN_ordered_dither_functions(source_bitdepth, target_bitdepth, fulls, fulld, conv_function, conv_function_chroma); | ||
| 1127 | #endif | ||
| 1128 | } | ||
| 1129 |
1/2✗ Branch 8 → 9 not taken.
✓ Branch 8 → 10 taken 2 times.
|
2 | else if (dither_mode == 1) { |
| 1130 | // Floyd, no SIMD there | ||
| 1131 | ✗ | get_convert_uintN_to_uintN_floyd_dither_functions(source_bitdepth, target_bitdepth, fulls, fulld, conv_function, conv_function_chroma); | |
| 1132 | } | ||
| 1133 | } | ||
| 1134 | } | ||
| 1135 | |||
| 1136 | // 32->8-16 bit | ||
| 1137 |
1/4✗ Branch 10 → 11 not taken.
✓ Branch 10 → 13 taken 8 times.
✗ Branch 11 → 12 not taken.
✗ Branch 11 → 13 not taken.
|
8 | if (source_bitdepth == 32 && target_bitdepth <= 16) { |
| 1138 | #ifdef INTEL_INTRINSICS | ||
| 1139 | ✗ | get_convert_32_to_uintN_functions(target_bitdepth, fulls, fulld, sse2, sse4, avx2, conv_function, conv_function_chroma, conv_function_a); | |
| 1140 | #else | ||
| 1141 | get_convert_32_to_uintN_functions(target_bitdepth, fulls, fulld, conv_function, conv_function_chroma, conv_function_a); | ||
| 1142 | #endif | ||
| 1143 | } | ||
| 1144 | |||
| 1145 | // 8-32->32 | ||
| 1146 |
1/2✗ Branch 13 → 14 not taken.
✓ Branch 13 → 17 taken 8 times.
|
8 | if (target_bitdepth == 32) { |
| 1147 | ✗ | if (source_bitdepth <= 16) // 8-16->32 bit | |
| 1148 | #ifdef INTEL_INTRINSICS | ||
| 1149 | ✗ | get_convert_uintN_to_float_functions(source_bitdepth, fulls, fulld, sse2, sse4, avx2, conv_function, conv_function_chroma, conv_function_a); | |
| 1150 | #else | ||
| 1151 | get_convert_uintN_to_float_functions(source_bitdepth, fulls, fulld, conv_function, conv_function_chroma, conv_function_a); | ||
| 1152 | #endif | ||
| 1153 | else | ||
| 1154 | ✗ | get_convert_float_to_float_functions(fulls, fulld, conv_function, conv_function_chroma, conv_function_a); | |
| 1155 | } | ||
| 1156 | 8 | } | |
| 1157 | |||
| 1158 | |||
| 1159 | 4 | ConvertBits::ConvertBits(PClip _child, const int _dither_mode, const int _target_bitdepth, bool _truerange, | |
| 1160 | int _ColorRange_src, int _ColorRange_dest, | ||
| 1161 | 4 | int _dither_bitdepth, IScriptEnvironment* env) : | |
| 1162 | GenericVideoFilter(_child), | ||
| 1163 | 4 | conv_function(nullptr), conv_function_chroma(nullptr), conv_function_a(nullptr), | |
| 1164 | 4 | target_bitdepth(_target_bitdepth), dither_mode(_dither_mode), dither_bitdepth(_dither_bitdepth), | |
| 1165 |
2/4✓ Branch 2 → 3 taken 4 times.
✗ Branch 2 → 153 not taken.
✓ Branch 3 → 4 taken 4 times.
✗ Branch 3 → 151 not taken.
|
4 | fulls(false), fulld(false), truerange(_truerange) |
| 1166 | { | ||
| 1167 | |||
| 1168 |
1/2✓ Branch 5 → 6 taken 4 times.
✗ Branch 5 → 154 not taken.
|
4 | pixelsize = vi.ComponentSize(); |
| 1169 |
1/2✓ Branch 6 → 7 taken 4 times.
✗ Branch 6 → 154 not taken.
|
4 | bits_per_pixel = vi.BitsPerComponent(); |
| 1170 | 4 | format_change_only = false; | |
| 1171 | |||
| 1172 | #ifdef INTEL_INTRINSICS | ||
| 1173 |
1/2✓ Branch 7 → 8 taken 4 times.
✗ Branch 7 → 154 not taken.
|
4 | const bool sse2 = !!(env->GetCPUFlags() & CPUF_SSE2); |
| 1174 |
1/2✓ Branch 8 → 9 taken 4 times.
✗ Branch 8 → 154 not taken.
|
4 | const bool sse4 = !!(env->GetCPUFlags() & CPUF_SSE4_1); |
| 1175 |
1/2✓ Branch 9 → 10 taken 4 times.
✗ Branch 9 → 154 not taken.
|
4 | const bool avx2 = !!(env->GetCPUFlags() & CPUF_AVX2); |
| 1176 | #endif | ||
| 1177 | |||
| 1178 | // full or limited decision | ||
| 1179 | // dest: if undefined, use src | ||
| 1180 |
3/4✓ Branch 10 → 11 taken 2 times.
✓ Branch 10 → 13 taken 2 times.
✗ Branch 11 → 12 not taken.
✓ Branch 11 → 13 taken 2 times.
|
4 | if (_ColorRange_dest != ColorRange_Compat_e::AVS_COLORRANGE_LIMITED && _ColorRange_dest != ColorRange_Compat_e::AVS_COLORRANGE_FULL) { |
| 1181 | ✗ | _ColorRange_dest = _ColorRange_src; | |
| 1182 | } | ||
| 1183 | // | ||
| 1184 | 4 | fulls = _ColorRange_src == ColorRange_Compat_e::AVS_COLORRANGE_FULL; | |
| 1185 | 4 | fulld = _ColorRange_dest == ColorRange_Compat_e::AVS_COLORRANGE_FULL; | |
| 1186 | |||
| 1187 |
1/2✗ Branch 13 → 14 not taken.
✓ Branch 13 → 28 taken 4 times.
|
4 | if (!truerange) { |
| 1188 | ✗ | if ((target_bitdepth == 8 || target_bitdepth == 32) && pixelsize == 2) | |
| 1189 | ✗ | bits_per_pixel = 16; | |
| 1190 | ✗ | if (target_bitdepth > 8 && target_bitdepth <= 16 && (bits_per_pixel == 8 || bits_per_pixel == 32)) | |
| 1191 | ✗ | target_bitdepth = 16; | |
| 1192 | ✗ | if (target_bitdepth > 8 && target_bitdepth <= 16 && bits_per_pixel > 8 && bits_per_pixel <= 16) | |
| 1193 | ✗ | format_change_only = true; | |
| 1194 | } | ||
| 1195 | |||
| 1196 | #ifdef INTEL_INTRINSICS | ||
| 1197 | 4 | get_convert_any_bits_functions(dither_mode, bits_per_pixel, target_bitdepth, fulls, fulld, sse2, sse4, avx2, conv_function, conv_function_chroma, conv_function_a); | |
| 1198 | #else | ||
| 1199 | get_convert_any_bits_functions(dither_mode, bits_per_pixel, target_bitdepth, fulls, fulld, conv_function, conv_function_chroma, conv_function_a); | ||
| 1200 | #endif | ||
| 1201 | |||
| 1202 | // Set VideoInfo | ||
| 1203 |
2/2✓ Branch 29 → 30 taken 1 time.
✓ Branch 29 → 86 taken 3 times.
|
4 | if (target_bitdepth == 8) { |
| 1204 |
2/4✓ Branch 30 → 31 taken 1 time.
✗ Branch 30 → 154 not taken.
✓ Branch 31 → 32 taken 1 time.
✗ Branch 31 → 33 not taken.
|
1 | if (vi.NumComponents() == 1) |
| 1205 | 1 | vi.pixel_type = VideoInfo::CS_Y8; | |
| 1206 | ✗ | else if (vi.IsYV411()) | |
| 1207 | ✗ | vi.pixel_type = VideoInfo::CS_YV411; | |
| 1208 | ✗ | else if (vi.Is420() || vi.IsYV12()) | |
| 1209 | ✗ | vi.pixel_type = vi.IsYUVA() ? VideoInfo::CS_YUVA420 : VideoInfo::CS_YV12; | |
| 1210 | ✗ | else if (vi.Is422()) | |
| 1211 | ✗ | vi.pixel_type = vi.IsYUVA() ? VideoInfo::CS_YUVA422 : VideoInfo::CS_YV16; | |
| 1212 | ✗ | else if (vi.Is444()) | |
| 1213 | ✗ | vi.pixel_type = vi.IsYUVA() ? VideoInfo::CS_YUVA444 : VideoInfo::CS_YV24; | |
| 1214 | ✗ | else if (vi.IsRGB48() || vi.IsRGB24()) | |
| 1215 | ✗ | vi.pixel_type = VideoInfo::CS_BGR24; | |
| 1216 | ✗ | else if (vi.IsRGB64() || vi.IsRGB32()) | |
| 1217 | ✗ | vi.pixel_type = VideoInfo::CS_BGR32; | |
| 1218 | ✗ | else if (vi.IsPlanarRGB()) | |
| 1219 | ✗ | vi.pixel_type = VideoInfo::CS_RGBP; | |
| 1220 | ✗ | else if (vi.IsPlanarRGBA()) | |
| 1221 | ✗ | vi.pixel_type = VideoInfo::CS_RGBAP; | |
| 1222 | else | ||
| 1223 | ✗ | env->ThrowError("ConvertTo8bit: unsupported color space"); | |
| 1224 | |||
| 1225 | 1 | return; | |
| 1226 | } | ||
| 1227 |
2/4✓ Branch 86 → 87 taken 3 times.
✗ Branch 86 → 116 not taken.
✓ Branch 87 → 88 taken 3 times.
✗ Branch 87 → 116 not taken.
|
3 | else if (target_bitdepth > 8 && target_bitdepth <= 16) { |
| 1228 | // set output vi format | ||
| 1229 |
5/10✓ Branch 88 → 89 taken 3 times.
✗ Branch 88 → 154 not taken.
✓ Branch 89 → 90 taken 3 times.
✗ Branch 89 → 92 not taken.
✓ Branch 90 → 91 taken 3 times.
✗ Branch 90 → 154 not taken.
✗ Branch 91 → 92 not taken.
✓ Branch 91 → 93 taken 3 times.
✗ Branch 94 → 95 not taken.
✓ Branch 94 → 96 taken 3 times.
|
3 | if (vi.IsRGB24() || vi.IsRGB48()) { |
| 1230 | ✗ | vi.pixel_type = VideoInfo::CS_BGR48; | |
| 1231 | } | ||
| 1232 |
5/10✓ Branch 96 → 97 taken 3 times.
✗ Branch 96 → 154 not taken.
✓ Branch 97 → 98 taken 3 times.
✗ Branch 97 → 100 not taken.
✓ Branch 98 → 99 taken 3 times.
✗ Branch 98 → 154 not taken.
✗ Branch 99 → 100 not taken.
✓ Branch 99 → 101 taken 3 times.
✗ Branch 102 → 103 not taken.
✓ Branch 102 → 104 taken 3 times.
|
3 | else if (vi.IsRGB32() || vi.IsRGB64()) { |
| 1233 | ✗ | vi.pixel_type = VideoInfo::CS_BGR64; | |
| 1234 | } | ||
| 1235 | else { | ||
| 1236 | // Y or YUV(A) or PlanarRGB(A) | ||
| 1237 |
2/4✓ Branch 104 → 105 taken 3 times.
✗ Branch 104 → 154 not taken.
✗ Branch 105 → 106 not taken.
✓ Branch 105 → 107 taken 3 times.
|
3 | if (vi.IsYV12()) // YV12 can have an exotic compatibility constant |
| 1238 | ✗ | vi.pixel_type = VideoInfo::CS_YV12; // override for known | |
| 1239 | int new_bitdepth_bits; | ||
| 1240 |
2/7✗ Branch 107 → 108 not taken.
✓ Branch 107 → 109 taken 2 times.
✗ Branch 107 → 110 not taken.
✗ Branch 107 → 111 not taken.
✓ Branch 107 → 112 taken 1 time.
✗ Branch 107 → 113 not taken.
✗ Branch 107 → 114 not taken.
|
3 | switch (target_bitdepth) { |
| 1241 | ✗ | case 8: new_bitdepth_bits = VideoInfo::CS_Sample_Bits_8; break; | |
| 1242 | 2 | case 10: new_bitdepth_bits = VideoInfo::CS_Sample_Bits_10; break; | |
| 1243 | ✗ | case 12: new_bitdepth_bits = VideoInfo::CS_Sample_Bits_12; break; | |
| 1244 | ✗ | case 14: new_bitdepth_bits = VideoInfo::CS_Sample_Bits_14; break; | |
| 1245 | 1 | case 16: new_bitdepth_bits = VideoInfo::CS_Sample_Bits_16; break; | |
| 1246 | ✗ | case 32: new_bitdepth_bits = VideoInfo::CS_Sample_Bits_32; break; | |
| 1247 | } | ||
| 1248 | 3 | vi.pixel_type = (vi.pixel_type & ~VideoInfo::CS_Sample_Bits_Mask) | new_bitdepth_bits; | |
| 1249 | } | ||
| 1250 | 3 | return; | |
| 1251 | } | ||
| 1252 | ✗ | else if (target_bitdepth == 32) { | |
| 1253 | ✗ | if (vi.NumComponents() == 1) | |
| 1254 | ✗ | vi.pixel_type = VideoInfo::CS_Y32; | |
| 1255 | ✗ | else if (vi.Is420()) | |
| 1256 | ✗ | vi.pixel_type = vi.IsYUVA() ? VideoInfo::CS_YUVA420PS : VideoInfo::CS_YUV420PS; | |
| 1257 | ✗ | else if (vi.Is422()) | |
| 1258 | ✗ | vi.pixel_type = vi.IsYUVA() ? VideoInfo::CS_YUVA422PS : VideoInfo::CS_YUV422PS; | |
| 1259 | ✗ | else if (vi.Is444()) | |
| 1260 | ✗ | vi.pixel_type = vi.IsYUVA() ? VideoInfo::CS_YUVA444PS : VideoInfo::CS_YUV444PS; | |
| 1261 | ✗ | else if (vi.IsPlanarRGB()) | |
| 1262 | ✗ | vi.pixel_type = VideoInfo::CS_RGBPS; | |
| 1263 | ✗ | else if (vi.IsPlanarRGBA()) | |
| 1264 | ✗ | vi.pixel_type = VideoInfo::CS_RGBAPS; | |
| 1265 | else | ||
| 1266 | ✗ | env->ThrowError("ConvertToFloat: unsupported color space"); | |
| 1267 | |||
| 1268 | ✗ | return; | |
| 1269 | } | ||
| 1270 | |||
| 1271 | ✗ | env->ThrowError("ConvertBits: unsupported target bit-depth (%d)", target_bitdepth); | |
| 1272 | |||
| 1273 | ✗ | } | |
| 1274 | |||
| 1275 | 4 | AVSValue __cdecl ConvertBits::Create(AVSValue args, void* user_data, IScriptEnvironment* env) { | |
| 1276 |
2/4✓ Branch 2 → 3 taken 4 times.
✗ Branch 2 → 599 not taken.
✓ Branch 3 → 4 taken 4 times.
✗ Branch 3 → 599 not taken.
|
4 | PClip clip = args[0].AsClip(); |
| 1277 | //0 1 2 3 4 5 6 | ||
| 1278 | //c[bits]i[truerange]b[dither]i[dither_bits]i[fulls]b[fulld]b | ||
| 1279 | |||
| 1280 |
1/2✓ Branch 5 → 6 taken 4 times.
✗ Branch 5 → 597 not taken.
|
4 | const VideoInfo &vi = clip->GetVideoInfo(); |
| 1281 | |||
| 1282 | 4 | int create_param = (int)reinterpret_cast<intptr_t>(user_data); | |
| 1283 | |||
| 1284 | // when converting from/true 10-16 bit formats, truerange=false indicates bitdepth of 16 bits regardless of the 10-12-14 bit format | ||
| 1285 | // FIXME: stop supporting this parameter (a workaround in the dawn of hbd?) | ||
| 1286 |
2/4✓ Branch 6 → 7 taken 4 times.
✗ Branch 6 → 597 not taken.
✓ Branch 7 → 8 taken 4 times.
✗ Branch 7 → 597 not taken.
|
4 | bool assume_truerange = args[2].AsBool(true); // n/a for non planar formats |
| 1287 | |||
| 1288 |
1/2✓ Branch 8 → 9 taken 4 times.
✗ Branch 8 → 597 not taken.
|
4 | int source_bitdepth = vi.BitsPerComponent(); |
| 1289 | // default comes from old legacy To8,To16,ToFloat functions | ||
| 1290 | // or the clip's actual bit depth | ||
| 1291 |
1/2✓ Branch 9 → 10 taken 4 times.
✗ Branch 9 → 11 not taken.
|
4 | const int default_target_bitdepth = create_param == 0 ? source_bitdepth : create_param; |
| 1292 |
2/4✓ Branch 12 → 13 taken 4 times.
✗ Branch 12 → 597 not taken.
✓ Branch 13 → 14 taken 4 times.
✗ Branch 13 → 597 not taken.
|
4 | int target_bitdepth = args[1].AsInt(default_target_bitdepth); // "bits" parameter |
| 1293 |
2/4✓ Branch 14 → 15 taken 4 times.
✗ Branch 14 → 597 not taken.
✓ Branch 15 → 16 taken 4 times.
✗ Branch 15 → 597 not taken.
|
4 | int dither_bitdepth = args[4].AsInt(target_bitdepth); // "dither_bits" parameter |
| 1294 | |||
| 1295 |
7/12✓ Branch 16 → 17 taken 3 times.
✓ Branch 16 → 23 taken 1 time.
✓ Branch 17 → 18 taken 1 time.
✓ Branch 17 → 23 taken 2 times.
✓ Branch 18 → 19 taken 1 time.
✗ Branch 18 → 23 not taken.
✓ Branch 19 → 20 taken 1 time.
✗ Branch 19 → 23 not taken.
✗ Branch 20 → 21 not taken.
✓ Branch 20 → 23 taken 1 time.
✗ Branch 21 → 22 not taken.
✗ Branch 21 → 23 not taken.
|
4 | if(target_bitdepth!=8 && target_bitdepth!=10 && target_bitdepth!=12 && target_bitdepth!=14 && target_bitdepth!=16 && target_bitdepth!=32) |
| 1296 | ✗ | env->ThrowError("ConvertBits: invalid bit depth: %d", target_bitdepth); | |
| 1297 | |||
| 1298 |
1/4✗ Branch 23 → 24 not taken.
✓ Branch 23 → 26 taken 4 times.
✗ Branch 24 → 25 not taken.
✗ Branch 24 → 26 not taken.
|
4 | if(create_param == 8 && target_bitdepth !=8) |
| 1299 | ✗ | env->ThrowError("ConvertTo8Bit: invalid bit depth: %d", target_bitdepth); | |
| 1300 |
1/4✗ Branch 26 → 27 not taken.
✓ Branch 26 → 29 taken 4 times.
✗ Branch 27 → 28 not taken.
✗ Branch 27 → 29 not taken.
|
4 | if(create_param == 32 && target_bitdepth !=32) |
| 1301 | ✗ | env->ThrowError("ConvertToFloat: invalid bit depth: %d", target_bitdepth); | |
| 1302 |
1/6✗ Branch 29 → 30 not taken.
✓ Branch 29 → 33 taken 4 times.
✗ Branch 30 → 31 not taken.
✗ Branch 30 → 32 not taken.
✗ Branch 31 → 32 not taken.
✗ Branch 31 → 33 not taken.
|
4 | if(create_param == 16 && (target_bitdepth == 8 || target_bitdepth ==32)) |
| 1303 | ✗ | env->ThrowError("ConvertTo16bit: invalid bit depth: %d", target_bitdepth); | |
| 1304 | |||
| 1305 |
3/6✓ Branch 33 → 34 taken 4 times.
✗ Branch 33 → 597 not taken.
✓ Branch 34 → 35 taken 4 times.
✗ Branch 34 → 597 not taken.
✓ Branch 35 → 36 taken 4 times.
✗ Branch 35 → 39 not taken.
|
4 | if (args[2].Defined()) { |
| 1306 |
2/4✓ Branch 36 → 37 taken 4 times.
✗ Branch 36 → 597 not taken.
✗ Branch 37 → 38 not taken.
✓ Branch 37 → 39 taken 4 times.
|
4 | if (!vi.IsPlanar()) |
| 1307 | ✗ | env->ThrowError("ConvertBits: truerange specified for non-planar source"); | |
| 1308 | } | ||
| 1309 | |||
| 1310 | // retrieve full/limited | ||
| 1311 | int ColorRange_src; | ||
| 1312 | int ColorRange_dest; | ||
| 1313 |
4/6✓ Branch 39 → 40 taken 4 times.
✗ Branch 39 → 597 not taken.
✓ Branch 40 → 41 taken 4 times.
✗ Branch 40 → 597 not taken.
✓ Branch 41 → 42 taken 2 times.
✓ Branch 41 → 47 taken 2 times.
|
4 | if (args[5].Defined()) |
| 1314 |
3/6✓ Branch 42 → 43 taken 2 times.
✗ Branch 42 → 597 not taken.
✓ Branch 43 → 44 taken 2 times.
✗ Branch 43 → 597 not taken.
✓ Branch 44 → 45 taken 2 times.
✗ Branch 44 → 46 not taken.
|
2 | ColorRange_src = args[5].AsBool() ? ColorRange_Compat_e::AVS_COLORRANGE_FULL : ColorRange_Compat_e::AVS_COLORRANGE_LIMITED; |
| 1315 | else | ||
| 1316 | 2 | ColorRange_src = -1; // undefined. A frame property may override | |
| 1317 |
3/6✓ Branch 48 → 49 taken 4 times.
✗ Branch 48 → 597 not taken.
✓ Branch 49 → 50 taken 4 times.
✗ Branch 49 → 597 not taken.
✓ Branch 50 → 51 taken 4 times.
✗ Branch 50 → 56 not taken.
|
4 | if (args[6].Defined()) |
| 1318 |
4/6✓ Branch 51 → 52 taken 4 times.
✗ Branch 51 → 597 not taken.
✓ Branch 52 → 53 taken 4 times.
✗ Branch 52 → 597 not taken.
✓ Branch 53 → 54 taken 2 times.
✓ Branch 53 → 55 taken 2 times.
|
4 | ColorRange_dest = args[6].AsBool() ? ColorRange_Compat_e::AVS_COLORRANGE_FULL : ColorRange_Compat_e::AVS_COLORRANGE_LIMITED; |
| 1319 | else | ||
| 1320 | ✗ | ColorRange_dest = -1; // undefined. A frame property or ColorRange_src may override | |
| 1321 |
3/4✓ Branch 57 → 58 taken 4 times.
✗ Branch 57 → 72 not taken.
✓ Branch 58 → 59 taken 2 times.
✓ Branch 58 → 72 taken 2 times.
|
4 | if (ColorRange_src != ColorRange_Compat_e::AVS_COLORRANGE_LIMITED && ColorRange_src != ColorRange_Compat_e::AVS_COLORRANGE_FULL) { |
| 1322 | // try getting frame props if parameter is not specified | ||
| 1323 |
1/2✓ Branch 60 → 61 taken 2 times.
✗ Branch 60 → 361 not taken.
|
2 | auto frame0 = clip->GetFrame(0, env); |
| 1324 |
1/2✓ Branch 61 → 62 taken 2 times.
✗ Branch 61 → 359 not taken.
|
2 | const AVSMap* props = env->getFramePropsRO(frame0); |
| 1325 |
2/4✓ Branch 62 → 63 taken 2 times.
✗ Branch 62 → 359 not taken.
✓ Branch 63 → 64 taken 2 times.
✗ Branch 63 → 66 not taken.
|
2 | if (env->propNumElements(props, "_ColorRange") > 0) { |
| 1326 |
1/2✓ Branch 64 → 65 taken 2 times.
✗ Branch 64 → 359 not taken.
|
2 | ColorRange_src = (int)env->propGetIntSaturated(props, "_ColorRange", 0, nullptr); |
| 1327 | } | ||
| 1328 | else { | ||
| 1329 | // no param, no frame property -> rgb is full others are limited | ||
| 1330 | ✗ | ColorRange_src = vi.IsRGB() ? ColorRange_Compat_e::AVS_COLORRANGE_FULL : ColorRange_Compat_e::AVS_COLORRANGE_LIMITED; | |
| 1331 | } | ||
| 1332 | 2 | } | |
| 1333 | // cr_dest = cr_source if not specified | ||
| 1334 |
3/4✓ Branch 72 → 73 taken 2 times.
✓ Branch 72 → 75 taken 2 times.
✗ Branch 73 → 74 not taken.
✓ Branch 73 → 75 taken 2 times.
|
4 | if (ColorRange_dest != ColorRange_Compat_e::AVS_COLORRANGE_LIMITED && ColorRange_dest != ColorRange_Compat_e::AVS_COLORRANGE_FULL) { |
| 1335 | ✗ | ColorRange_dest = ColorRange_src; | |
| 1336 | } | ||
| 1337 | 4 | bool fulls = ColorRange_src == ColorRange_Compat_e::AVS_COLORRANGE_FULL; | |
| 1338 | 4 | bool fulld = ColorRange_dest == ColorRange_Compat_e::AVS_COLORRANGE_FULL; | |
| 1339 | |||
| 1340 | |||
| 1341 |
2/4✓ Branch 75 → 76 taken 4 times.
✗ Branch 75 → 597 not taken.
✓ Branch 76 → 77 taken 4 times.
✗ Branch 76 → 597 not taken.
|
4 | int dither_type = args[3].AsInt(-1); |
| 1342 |
2/4✓ Branch 77 → 78 taken 4 times.
✗ Branch 77 → 597 not taken.
✓ Branch 78 → 79 taken 4 times.
✗ Branch 78 → 597 not taken.
|
4 | bool dither_defined = args[3].Defined(); |
| 1343 |
5/8✓ Branch 79 → 80 taken 4 times.
✗ Branch 79 → 84 not taken.
✓ Branch 80 → 81 taken 4 times.
✗ Branch 80 → 84 not taken.
✓ Branch 81 → 82 taken 3 times.
✓ Branch 81 → 84 taken 1 time.
✗ Branch 82 → 83 not taken.
✓ Branch 82 → 84 taken 3 times.
|
4 | if(dither_defined && dither_type != 1 && dither_type != 0 && dither_type != -1) |
| 1344 | ✗ | env->ThrowError("ConvertBits: invalid dither type parameter. Only -1 (disabled), 0 (ordered dither) or 1 (Floyd-S) is allowed"); | |
| 1345 | |||
| 1346 |
2/2✓ Branch 84 → 85 taken 1 time.
✓ Branch 84 → 91 taken 3 times.
|
4 | if (dither_type >= 0) { |
| 1347 |
1/2✗ Branch 85 → 86 not taken.
✓ Branch 85 → 87 taken 1 time.
|
1 | if (source_bitdepth < target_bitdepth) |
| 1348 | ✗ | env->ThrowError("ConvertBits: dithering is allowed only for scale down"); | |
| 1349 |
1/2✗ Branch 87 → 88 not taken.
✓ Branch 87 → 89 taken 1 time.
|
1 | if (dither_bitdepth > target_bitdepth) |
| 1350 | ✗ | env->ThrowError("ConvertBits: dither_bits must be <= target bitdepth"); | |
| 1351 |
1/2✗ Branch 89 → 90 not taken.
✓ Branch 89 → 91 taken 1 time.
|
1 | if (target_bitdepth == 32) |
| 1352 | ✗ | env->ThrowError("ConvertBits: dithering is not allowed into 32 bit float target"); | |
| 1353 | } | ||
| 1354 | |||
| 1355 | // 3.7.1 t25 | ||
| 1356 | // Unfortunately 32 bit float dithering is not implemented, thus we convert to 16 bit | ||
| 1357 | // intermediate clip | ||
| 1358 |
1/6✗ Branch 91 → 92 not taken.
✓ Branch 91 → 126 taken 4 times.
✗ Branch 92 → 93 not taken.
✗ Branch 92 → 94 not taken.
✗ Branch 93 → 94 not taken.
✗ Branch 93 → 126 not taken.
|
4 | if (source_bitdepth == 32 && (dither_type == 0 || dither_type == 1)) { |
| 1359 | // c[bits]i[truerange]b[dither]i[dither_bits]i[fulls]b[fulld]b | ||
| 1360 | |||
| 1361 | ✗ | source_bitdepth = 16; | |
| 1362 | // solving ordered dither maximum bit depth difference of 8 problem | ||
| 1363 | // by automatic preconversion | ||
| 1364 | ✗ | if (dither_type == 0 && source_bitdepth - dither_bitdepth > 8) { | |
| 1365 | ✗ | source_bitdepth = dither_bitdepth + 8; | |
| 1366 | ✗ | if (source_bitdepth % 2) | |
| 1367 | ✗ | source_bitdepth--; // must be even | |
| 1368 | } | ||
| 1369 | |||
| 1370 | ✗ | AVSValue new_args[7] = { clip, source_bitdepth, true, -1 /* no dither */, AVSValue() /*dither_bits*/, fulls, fulld }; | |
| 1371 | ✗ | clip = env->Invoke("ConvertBits", AVSValue(new_args, 7)).AsClip(); | |
| 1372 | |||
| 1373 | ✗ | clip = env->Invoke("Cache", AVSValue(clip)).AsClip(); | |
| 1374 | // and now the source range becomes the previous target | ||
| 1375 | ✗ | fulls = fulld; | |
| 1376 | ✗ | ColorRange_src = ColorRange_dest; | |
| 1377 | ✗ | } | |
| 1378 | |||
| 1379 | // solving ordered dither maximum bit depth difference of 8 problem | ||
| 1380 | // by automatic preconversion | ||
| 1381 |
4/6✓ Branch 126 → 127 taken 4 times.
✗ Branch 126 → 159 not taken.
✓ Branch 127 → 128 taken 1 time.
✓ Branch 127 → 159 taken 3 times.
✓ Branch 128 → 129 taken 1 time.
✗ Branch 128 → 159 not taken.
|
4 | if (source_bitdepth <= 16 && dither_type == 0 && source_bitdepth - dither_bitdepth > 8) { |
| 1382 | // c[bits]i[truerange]b[dither]i[dither_bits]i[fulls]b[fulld]b | ||
| 1383 | 1 | source_bitdepth = dither_bitdepth + 8; | |
| 1384 |
1/2✓ Branch 129 → 130 taken 1 time.
✗ Branch 129 → 131 not taken.
|
1 | if (source_bitdepth % 2) |
| 1385 | 1 | source_bitdepth--; // must be even | |
| 1386 | |||
| 1387 |
7/18✓ Branch 131 → 132 taken 1 time.
✗ Branch 131 → 393 not taken.
✓ Branch 132 → 133 taken 1 time.
✗ Branch 132 → 393 not taken.
✓ Branch 133 → 134 taken 1 time.
✗ Branch 133 → 393 not taken.
✓ Branch 134 → 135 taken 1 time.
✗ Branch 134 → 393 not taken.
✓ Branch 135 → 136 taken 1 time.
✗ Branch 135 → 393 not taken.
✓ Branch 136 → 137 taken 1 time.
✗ Branch 136 → 393 not taken.
✓ Branch 137 → 138 taken 1 time.
✗ Branch 137 → 393 not taken.
✗ Branch 393 → 394 not taken.
✗ Branch 393 → 397 not taken.
✗ Branch 395 → 396 not taken.
✗ Branch 395 → 397 not taken.
|
8 | AVSValue new_args[7] = { clip, source_bitdepth, true, -1 /* no dither */, AVSValue() /*dither_bits*/, fulls, fulld }; |
| 1388 |
4/8✓ Branch 138 → 139 taken 1 time.
✗ Branch 138 → 404 not taken.
✓ Branch 139 → 140 taken 1 time.
✗ Branch 139 → 402 not taken.
✓ Branch 140 → 141 taken 1 time.
✗ Branch 140 → 400 not taken.
✓ Branch 141 → 142 taken 1 time.
✗ Branch 141 → 398 not taken.
|
1 | clip = env->Invoke("ConvertBits", AVSValue(new_args, 7)).AsClip(); |
| 1389 | |||
| 1390 |
4/8✓ Branch 145 → 146 taken 1 time.
✗ Branch 145 → 413 not taken.
✓ Branch 146 → 147 taken 1 time.
✗ Branch 146 → 411 not taken.
✓ Branch 147 → 148 taken 1 time.
✗ Branch 147 → 409 not taken.
✓ Branch 148 → 149 taken 1 time.
✗ Branch 148 → 407 not taken.
|
1 | clip = env->Invoke("Cache", AVSValue(clip)).AsClip(); |
| 1391 | // and now the source range becomes the previous target | ||
| 1392 | 1 | fulls = fulld; | |
| 1393 | 1 | ColorRange_src = ColorRange_dest; | |
| 1394 |
2/4✓ Branch 153 → 154 taken 7 times.
✓ Branch 153 → 157 taken 1 time.
✗ Branch 417 → 418 not taken.
✗ Branch 417 → 421 not taken.
|
8 | } |
| 1395 | |||
| 1396 |
1/2✗ Branch 159 → 160 not taken.
✓ Branch 159 → 161 taken 4 times.
|
4 | if (source_bitdepth == dither_bitdepth) |
| 1397 | ✗ | dither_type = -1; // ignore dithering | |
| 1398 | |||
| 1399 |
2/2✓ Branch 161 → 162 taken 1 time.
✓ Branch 161 → 167 taken 3 times.
|
4 | if(dither_type == 0) { |
| 1400 |
2/4✓ Branch 162 → 163 taken 1 time.
✗ Branch 162 → 164 not taken.
✗ Branch 163 → 164 not taken.
✓ Branch 163 → 165 taken 1 time.
|
1 | if (dither_bitdepth < 1 || dither_bitdepth > 16) |
| 1401 | ✗ | env->ThrowError("ConvertBits: ordered dither: invalid dither_bits specified (1-16 allowed)"); | |
| 1402 | |||
| 1403 | // this error message cannot appear if the automatic bit depth reducing conversions above are done | ||
| 1404 |
1/2✗ Branch 165 → 166 not taken.
✓ Branch 165 → 167 taken 1 time.
|
1 | if(source_bitdepth - dither_bitdepth > 8) |
| 1405 | ✗ | env->ThrowError("ConvertBits: dither_bits cannot differ with more than 8 bits from source"); | |
| 1406 | } | ||
| 1407 | |||
| 1408 | // floyd | ||
| 1409 |
1/2✗ Branch 167 → 168 not taken.
✓ Branch 167 → 171 taken 4 times.
|
4 | if (dither_type == 1) { |
| 1410 | ✗ | if (dither_bitdepth < 1 || dither_bitdepth > 16) | |
| 1411 | ✗ | env->ThrowError("ConvertBits: Floyd-S: invalid dither_bits specified (1-16 allowed)"); | |
| 1412 | } | ||
| 1413 | |||
| 1414 | // no change -> return unmodified if no transform required | ||
| 1415 |
1/2✗ Branch 171 → 172 not taken.
✓ Branch 171 → 177 taken 4 times.
|
4 | if (source_bitdepth == target_bitdepth) { // 10->10 .. 16->16 |
| 1416 | ✗ | if((dither_type < 0 || dither_bitdepth == target_bitdepth) && fulls == fulld) | |
| 1417 | ✗ | return clip; | |
| 1418 | } | ||
| 1419 | |||
| 1420 | // YUY2 conversion is limited | ||
| 1421 |
2/4✓ Branch 177 → 178 taken 4 times.
✗ Branch 177 → 597 not taken.
✗ Branch 178 → 179 not taken.
✓ Branch 178 → 181 taken 4 times.
|
4 | if (vi.IsYUY2()) { |
| 1422 | ✗ | if (target_bitdepth != 8) | |
| 1423 | ✗ | env->ThrowError("ConvertBits: YUY2 input must stay in 8 bits"); | |
| 1424 | } | ||
| 1425 | |||
| 1426 |
2/4✓ Branch 181 → 182 taken 4 times.
✗ Branch 181 → 597 not taken.
✗ Branch 182 → 183 not taken.
✓ Branch 182 → 185 taken 4 times.
|
4 | if (vi.IsYV411()) { |
| 1427 | ✗ | if (target_bitdepth != 8) | |
| 1428 | ✗ | env->ThrowError("ConvertBits: YV411 input must stay in 8 bits"); | |
| 1429 | } | ||
| 1430 | |||
| 1431 | // packed RGB conversion is limited | ||
| 1432 |
3/10✓ Branch 185 → 186 taken 4 times.
✗ Branch 185 → 597 not taken.
✗ Branch 186 → 187 not taken.
✓ Branch 186 → 190 taken 4 times.
✗ Branch 187 → 188 not taken.
✗ Branch 187 → 597 not taken.
✗ Branch 188 → 189 not taken.
✗ Branch 188 → 190 not taken.
✗ Branch 191 → 192 not taken.
✓ Branch 191 → 195 taken 4 times.
|
4 | if (vi.IsRGB() && !vi.IsPlanar()) { |
| 1433 | ✗ | if (target_bitdepth != 8 && target_bitdepth != 16) | |
| 1434 | ✗ | env->ThrowError("ConvertBits: invalid bit-depth for packed RGB formats, only 8 or 16 possible"); | |
| 1435 | } | ||
| 1436 | |||
| 1437 | // remark | ||
| 1438 | // source_10_bit.ConvertTo16bit(truerange=true) : upscale range | ||
| 1439 | // source_10_bit.ConvertTo16bit(truerange=false) : leaves data, only format conversion | ||
| 1440 | // source_10_bit.ConvertTo16bit(bits=12,truerange=true) : upscale range from 10 to 12 | ||
| 1441 | // source_10_bit.ConvertTo16bit(bits=12,truerange=false) : leaves data, only format conversion | ||
| 1442 | // source_16_bit.ConvertTo16bit(bits=10, truerange=true) : downscale range | ||
| 1443 | // source_16_bit.ConvertTo16bit(bits=10, truerange=false) : leaves data, only format conversion | ||
| 1444 | |||
| 1445 | // yuy2 is autoconverted to/from YV16. fulls-fulld and dither to lower bit depths are supported | ||
| 1446 |
1/2✓ Branch 195 → 196 taken 4 times.
✗ Branch 195 → 597 not taken.
|
4 | bool need_convert_yuy2 = vi.IsYUY2(); |
| 1447 | // for dither, planar rgb conversion happens | ||
| 1448 |
2/6✓ Branch 196 → 197 taken 4 times.
✗ Branch 196 → 597 not taken.
✗ Branch 197 → 198 not taken.
✓ Branch 197 → 200 taken 4 times.
✗ Branch 198 → 199 not taken.
✗ Branch 198 → 200 not taken.
|
4 | bool need_convert_24 = vi.IsRGB24() && dither_type >= 0; |
| 1449 |
2/6✓ Branch 201 → 202 taken 4 times.
✗ Branch 201 → 597 not taken.
✗ Branch 202 → 203 not taken.
✓ Branch 202 → 205 taken 4 times.
✗ Branch 203 → 204 not taken.
✗ Branch 203 → 205 not taken.
|
4 | bool need_convert_32 = vi.IsRGB32() && dither_type >= 0; |
| 1450 |
2/6✓ Branch 206 → 207 taken 4 times.
✗ Branch 206 → 597 not taken.
✗ Branch 207 → 208 not taken.
✓ Branch 207 → 210 taken 4 times.
✗ Branch 208 → 209 not taken.
✗ Branch 208 → 210 not taken.
|
4 | bool need_convert_48 = vi.IsRGB48() && dither_type >= 0; |
| 1451 |
2/6✓ Branch 211 → 212 taken 4 times.
✗ Branch 211 → 597 not taken.
✗ Branch 212 → 213 not taken.
✓ Branch 212 → 215 taken 4 times.
✗ Branch 213 → 214 not taken.
✗ Branch 213 → 215 not taken.
|
4 | bool need_convert_64 = vi.IsRGB64() && dither_type >= 0; |
| 1452 | |||
| 1453 | // convert to planar on the fly if dither was asked | ||
| 1454 |
2/4✓ Branch 216 → 217 taken 4 times.
✗ Branch 216 → 218 not taken.
✗ Branch 217 → 218 not taken.
✓ Branch 217 → 233 taken 4 times.
|
4 | if (need_convert_24 || need_convert_48) { |
| 1455 | ✗ | AVSValue new_args[1] = { clip }; | |
| 1456 | ✗ | clip = env->Invoke("ConvertToPlanarRGB", AVSValue(new_args, 1)).AsClip(); | |
| 1457 | ✗ | } | |
| 1458 |
2/4✓ Branch 233 → 234 taken 4 times.
✗ Branch 233 → 235 not taken.
✗ Branch 234 → 235 not taken.
✓ Branch 234 → 250 taken 4 times.
|
4 | else if (need_convert_32 || need_convert_64) { |
| 1459 | ✗ | AVSValue new_args[1] = { clip }; | |
| 1460 | ✗ | clip = env->Invoke("ConvertToPlanarRGBA", AVSValue(new_args, 1)).AsClip(); | |
| 1461 | ✗ | } | |
| 1462 |
1/2✗ Branch 250 → 251 not taken.
✓ Branch 250 → 266 taken 4 times.
|
4 | else if (need_convert_yuy2) { |
| 1463 | ✗ | AVSValue new_args[1] = { clip }; | |
| 1464 | ✗ | clip = env->Invoke("ConvertToYV16", AVSValue(new_args, 1)).AsClip(); | |
| 1465 | ✗ | } | |
| 1466 | |||
| 1467 |
5/12✓ Branch 266 → 267 taken 4 times.
✗ Branch 266 → 597 not taken.
✓ Branch 267 → 268 taken 4 times.
✗ Branch 267 → 492 not taken.
✓ Branch 268 → 269 taken 4 times.
✗ Branch 268 → 490 not taken.
✓ Branch 269 → 270 taken 4 times.
✗ Branch 269 → 490 not taken.
✗ Branch 271 → 272 not taken.
✓ Branch 271 → 273 taken 4 times.
✗ Branch 493 → 494 not taken.
✗ Branch 493 → 495 not taken.
|
4 | AVSValue result = new ConvertBits(clip, dither_type, target_bitdepth, assume_truerange, ColorRange_src, ColorRange_dest, dither_bitdepth, env); |
| 1468 | |||
| 1469 | // convert back to packed rgb from planar on the fly | ||
| 1470 |
2/4✓ Branch 273 → 274 taken 4 times.
✗ Branch 273 → 275 not taken.
✗ Branch 274 → 275 not taken.
✓ Branch 274 → 304 taken 4 times.
|
4 | if (need_convert_24 || need_convert_48) { |
| 1471 | ✗ | AVSValue new_args[1] = { result }; | |
| 1472 | ✗ | if(target_bitdepth == 8) | |
| 1473 | ✗ | result = env->Invoke("ConvertToRGB24", AVSValue(new_args, 1)).AsClip(); | |
| 1474 | else | ||
| 1475 | ✗ | result = env->Invoke("ConvertToRGB48", AVSValue(new_args, 1)).AsClip(); | |
| 1476 |
2/8✗ Branch 298 → 299 not taken.
✗ Branch 298 → 302 not taken.
✓ Branch 304 → 305 taken 4 times.
✗ Branch 304 → 306 not taken.
✗ Branch 305 → 306 not taken.
✓ Branch 305 → 335 taken 4 times.
✗ Branch 526 → 527 not taken.
✗ Branch 526 → 530 not taken.
|
4 | } else if (need_convert_32 || need_convert_64) { |
| 1477 | ✗ | AVSValue new_args[1] = { result }; | |
| 1478 | ✗ | if (target_bitdepth == 8) | |
| 1479 | ✗ | result = env->Invoke("ConvertToRGB32", AVSValue(new_args, 1)).AsClip(); | |
| 1480 | else | ||
| 1481 | ✗ | result = env->Invoke("ConvertToRGB64", AVSValue(new_args, 1)).AsClip(); | |
| 1482 | ✗ | } | |
| 1483 |
1/2✗ Branch 335 → 336 not taken.
✓ Branch 335 → 353 taken 4 times.
|
4 | else if (need_convert_yuy2) { |
| 1484 | ✗ | AVSValue new_args[1] = { result }; | |
| 1485 | ✗ | result = env->Invoke("ConvertToYUY2", AVSValue(new_args, 1)).AsClip(); | |
| 1486 | ✗ | } | |
| 1487 | |||
| 1488 |
1/2✓ Branch 353 → 354 taken 4 times.
✗ Branch 353 → 595 not taken.
|
4 | return result; |
| 1489 | 4 | } | |
| 1490 | |||
| 1491 | |||
| 1492 | 4 | PVideoFrame __stdcall ConvertBits::GetFrame(int n, IScriptEnvironment* env) { | |
| 1493 |
1/2✓ Branch 3 → 4 taken 4 times.
✗ Branch 3 → 128 not taken.
|
4 | PVideoFrame src = child->GetFrame(n, env); |
| 1494 | |||
| 1495 |
1/2✗ Branch 4 → 5 not taken.
✓ Branch 4 → 10 taken 4 times.
|
4 | if (format_change_only) |
| 1496 | { | ||
| 1497 | // for 10-16 bit: simple format override in constructor | ||
| 1498 | ✗ | env->MakeWritable(&src); | |
| 1499 | ✗ | src->AmendPixelType(vi.pixel_type); | |
| 1500 | ✗ | return src; | |
| 1501 | } | ||
| 1502 | |||
| 1503 |
1/2✓ Branch 10 → 11 taken 4 times.
✗ Branch 10 → 126 not taken.
|
4 | PVideoFrame dst = env->NewVideoFrameP(vi, &src); |
| 1504 | |||
| 1505 |
1/2✓ Branch 11 → 12 taken 4 times.
✗ Branch 11 → 124 not taken.
|
4 | auto props = env->getFramePropsRW(dst); |
| 1506 |
3/4✓ Branch 12 → 13 taken 2 times.
✓ Branch 12 → 14 taken 2 times.
✓ Branch 15 → 16 taken 4 times.
✗ Branch 15 → 124 not taken.
|
4 | update_ColorRange(props, fulld ? ColorRange_Compat_e::AVS_COLORRANGE_FULL : ColorRange_Compat_e::AVS_COLORRANGE_LIMITED, env); |
| 1507 | |||
| 1508 |
2/4✓ Branch 16 → 17 taken 4 times.
✗ Branch 16 → 124 not taken.
✓ Branch 17 → 18 taken 4 times.
✗ Branch 17 → 104 not taken.
|
4 | if(vi.IsPlanar()) |
| 1509 | { | ||
| 1510 | 4 | int planes_y[4] = { PLANAR_Y, PLANAR_U, PLANAR_V, PLANAR_A }; | |
| 1511 | 4 | int planes_r[4] = { PLANAR_G, PLANAR_B, PLANAR_R, PLANAR_A }; | |
| 1512 |
2/8✓ Branch 18 → 19 taken 4 times.
✗ Branch 18 → 123 not taken.
✗ Branch 19 → 20 not taken.
✓ Branch 19 → 22 taken 4 times.
✗ Branch 20 → 21 not taken.
✗ Branch 20 → 123 not taken.
✗ Branch 21 → 22 not taken.
✗ Branch 21 → 23 not taken.
|
4 | int *planes = (vi.IsYUV() || vi.IsYUVA()) ? planes_y : planes_r; |
| 1513 |
3/4✓ Branch 101 → 102 taken 8 times.
✗ Branch 101 → 123 not taken.
✓ Branch 102 → 25 taken 4 times.
✓ Branch 102 → 103 taken 4 times.
|
8 | for (int p = 0; p < vi.NumComponents(); ++p) { |
| 1514 | 4 | const int plane = planes[p]; | |
| 1515 |
1/2✗ Branch 25 → 26 not taken.
✓ Branch 25 → 53 taken 4 times.
|
4 | if (plane == PLANAR_A) { |
| 1516 | ✗ | if (conv_function_a == nullptr) | |
| 1517 | ✗ | env->BitBlt(dst->GetWritePtr(plane), dst->GetPitch(plane), src->GetReadPtr(plane), src->GetPitch(plane), src->GetRowSize(plane), src->GetHeight(plane)); | |
| 1518 | else | ||
| 1519 | ✗ | conv_function_a(src->GetReadPtr(plane), dst->GetWritePtr(plane), | |
| 1520 | src->GetRowSize(plane), src->GetHeight(plane), | ||
| 1521 | src->GetPitch(plane), dst->GetPitch(plane), | ||
| 1522 | bits_per_pixel, target_bitdepth, dither_bitdepth | ||
| 1523 | ); | ||
| 1524 | } | ||
| 1525 |
1/2✗ Branch 53 → 54 not taken.
✓ Branch 53 → 67 taken 4 times.
|
4 | else if (conv_function == nullptr) |
| 1526 | ✗ | env->BitBlt(dst->GetWritePtr(plane), dst->GetPitch(plane), src->GetReadPtr(plane), src->GetPitch(plane), src->GetRowSize(plane), src->GetHeight(plane)); | |
| 1527 | else { | ||
| 1528 |
2/4✓ Branch 67 → 68 taken 4 times.
✗ Branch 67 → 69 not taken.
✗ Branch 68 → 69 not taken.
✓ Branch 68 → 70 taken 4 times.
|
4 | const bool chroma = (plane == PLANAR_U || plane == PLANAR_V); |
| 1529 |
1/4✗ Branch 71 → 72 not taken.
✓ Branch 71 → 87 taken 4 times.
✗ Branch 72 → 73 not taken.
✗ Branch 72 → 87 not taken.
|
4 | if (chroma && conv_function_chroma != nullptr) |
| 1530 | // 32bit float and 8-16 when full-range involved needs separate signed-aware conversion | ||
| 1531 | ✗ | conv_function_chroma(src->GetReadPtr(plane), dst->GetWritePtr(plane), | |
| 1532 | src->GetRowSize(plane), src->GetHeight(plane), | ||
| 1533 | src->GetPitch(plane), dst->GetPitch(plane), | ||
| 1534 | bits_per_pixel, target_bitdepth, dither_bitdepth); | ||
| 1535 | else | ||
| 1536 |
7/14✓ Branch 88 → 89 taken 4 times.
✗ Branch 88 → 123 not taken.
✓ Branch 90 → 91 taken 4 times.
✗ Branch 90 → 123 not taken.
✓ Branch 92 → 93 taken 4 times.
✗ Branch 92 → 123 not taken.
✓ Branch 94 → 95 taken 4 times.
✗ Branch 94 → 123 not taken.
✓ Branch 96 → 97 taken 4 times.
✗ Branch 96 → 123 not taken.
✓ Branch 98 → 99 taken 4 times.
✗ Branch 98 → 123 not taken.
✓ Branch 99 → 100 taken 4 times.
✗ Branch 99 → 123 not taken.
|
4 | conv_function(src->GetReadPtr(plane), dst->GetWritePtr(plane), |
| 1537 | src->GetRowSize(plane), src->GetHeight(plane), | ||
| 1538 | src->GetPitch(plane), dst->GetPitch(plane), | ||
| 1539 | bits_per_pixel, target_bitdepth, dither_bitdepth); | ||
| 1540 | } | ||
| 1541 | } | ||
| 1542 | } | ||
| 1543 | else { | ||
| 1544 | // packed RGBs | ||
| 1545 | ✗ | conv_function(src->GetReadPtr(), dst->GetWritePtr(), | |
| 1546 | src->GetRowSize(), src->GetHeight(), | ||
| 1547 | src->GetPitch(), dst->GetPitch(), | ||
| 1548 | bits_per_pixel, target_bitdepth, dither_bitdepth); | ||
| 1549 | } | ||
| 1550 |
1/2✓ Branch 117 → 118 taken 4 times.
✗ Branch 117 → 124 not taken.
|
4 | return dst; |
| 1551 | 4 | } | |
| 1552 |