| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | /** | ||
| 2 | * Copyright (C) 2026 Niklas Haas | ||
| 3 | * | ||
| 4 | * This file is part of FFmpeg. | ||
| 5 | * | ||
| 6 | * FFmpeg is free software; you can redistribute it and/or | ||
| 7 | * modify it under the terms of the GNU Lesser General Public | ||
| 8 | * License as published by the Free Software Foundation; either | ||
| 9 | * version 2.1 of the License, or (at your option) any later version. | ||
| 10 | * | ||
| 11 | * FFmpeg is distributed in the hope that it will be useful, | ||
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 14 | * Lesser General Public License for more details. | ||
| 15 | * | ||
| 16 | * You should have received a copy of the GNU Lesser General Public | ||
| 17 | * License along with FFmpeg; if not, write to the Free Software | ||
| 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
| 19 | */ | ||
| 20 | |||
| 21 | #include <stdbool.h> | ||
| 22 | |||
| 23 | #include "libavutil/avassert.h" | ||
| 24 | #include "libavutil/mem.h" | ||
| 25 | #include "libavutil/refstruct.h" | ||
| 26 | |||
| 27 | #include "ops.h" | ||
| 28 | #include "uops.h" | ||
| 29 | #include "uops_list.h" | ||
| 30 | |||
| 31 | 239160066 | int ff_sws_uop_cmp(const SwsUOp *a, const SwsUOp *b) | |
| 32 | { | ||
| 33 |
2/2✓ Branch 0 taken 150875282 times.
✓ Branch 1 taken 88284784 times.
|
239160066 | if (a->type != b->type) |
| 34 | 150875282 | return (int) a->type - b->type; | |
| 35 |
2/2✓ Branch 0 taken 66050005 times.
✓ Branch 1 taken 22234779 times.
|
88284784 | if (a->uop != b->uop) |
| 36 | 66050005 | return (int) a->uop - b->uop; | |
| 37 |
2/2✓ Branch 0 taken 9923682 times.
✓ Branch 1 taken 12311097 times.
|
22234779 | if (a->mask != b->mask) |
| 38 | 9923682 | return (int) a->mask - b->mask; | |
| 39 | 12311097 | return memcmp(&a->par, &b->par, sizeof(a->par)); | |
| 40 | } | ||
| 41 | |||
| 42 | static const struct { | ||
| 43 | char abbr[32]; | ||
| 44 | } uop_names[SWS_UOP_TYPE_NB] = { | ||
| 45 | #define UOP_NAME(OP, ABBR) [OP] = { ABBR }, | ||
| 46 | UOPS_LIST(UOP_NAME) | ||
| 47 | #undef UOP_NAME | ||
| 48 | }; | ||
| 49 | |||
| 50 | #define Q2PIXEL(val) ff_sws_pixel_from_q64(op->type, val) | ||
| 51 | |||
| 52 | 1517146 | void ff_sws_uop_name(const SwsUOp *op, char buf[SWS_UOP_NAME_MAX]) | |
| 53 | { | ||
| 54 | AVBPrint bp; | ||
| 55 | 1517146 | av_bprint_init_for_buffer(&bp, buf, SWS_UOP_NAME_MAX); | |
| 56 | |||
| 57 |
1/2✓ Branch 0 taken 1517146 times.
✗ Branch 1 not taken.
|
1517146 | if (op->type != SWS_PIXEL_NONE) |
| 58 | 1517146 | av_bprintf(&bp, "%s_", ff_sws_pixel_type_name(op->type)); | |
| 59 | 1517146 | av_bprintf(&bp, "%s", uop_names[op->uop].abbr); | |
| 60 | |||
| 61 |
1/2✓ Branch 0 taken 1517146 times.
✗ Branch 1 not taken.
|
1517146 | if (op->mask) |
| 62 | 1517146 | av_bprintf(&bp, "_%s", ff_sws_comp_mask_str(op->mask)); | |
| 63 | |||
| 64 | 1517146 | const SwsUOpParams *par = &op->par; | |
| 65 |
10/10✓ Branch 0 taken 145772 times.
✓ Branch 1 taken 2691 times.
✓ Branch 2 taken 24814 times.
✓ Branch 3 taken 86527 times.
✓ Branch 4 taken 58702 times.
✓ Branch 5 taken 52189 times.
✓ Branch 6 taken 99777 times.
✓ Branch 7 taken 86214 times.
✓ Branch 8 taken 92 times.
✓ Branch 9 taken 960368 times.
|
1517146 | switch (op->uop) { |
| 66 | 145772 | case SWS_UOP_READ_PLANAR_FH: | |
| 67 | case SWS_UOP_READ_PLANAR_FV: | ||
| 68 | case SWS_UOP_READ_PLANAR_FV_FMA: | ||
| 69 | 145772 | av_bprintf(&bp, "_%s", ff_sws_pixel_type_name(par->filter.type)); | |
| 70 | 145772 | break; | |
| 71 | 2691 | case SWS_UOP_RW_SHUFFLE: | |
| 72 | 2691 | av_bprintf(&bp, "_%x_%u_%u", par->shuffle.clear_value, | |
| 73 | 2691 | par->shuffle.read_size, par->shuffle.write_size); | |
| 74 | 2691 | break; | |
| 75 | 24814 | case SWS_UOP_LSHIFT: | |
| 76 | case SWS_UOP_RSHIFT: | ||
| 77 | 24814 | av_bprintf(&bp, "_%u", par->shift.amount); | |
| 78 | 24814 | break; | |
| 79 | 86527 | case SWS_UOP_PERMUTE: | |
| 80 | case SWS_UOP_COPY: | ||
| 81 | 86527 | av_bprint_chars(&bp, '_', 1); | |
| 82 |
2/2✓ Branch 0 taken 231804 times.
✓ Branch 1 taken 86527 times.
|
318331 | for (int i = 0; i < par->move.num_moves; i++) |
| 83 | 231804 | av_bprint_chars(&bp, "txyzw"[par->move.dst[i] + 1], 1); | |
| 84 | 86527 | av_bprint_chars(&bp, '_', 1); | |
| 85 |
2/2✓ Branch 0 taken 231804 times.
✓ Branch 1 taken 86527 times.
|
318331 | for (int i = 0; i < par->move.num_moves; i++) |
| 86 | 231804 | av_bprint_chars(&bp, "txyzw"[par->move.src[i] + 1], 1); | |
| 87 | 86527 | break; | |
| 88 | 58702 | case SWS_UOP_PACK: | |
| 89 | case SWS_UOP_UNPACK: | ||
| 90 | 58702 | av_bprint_chars(&bp, '_', 1); | |
| 91 |
4/4✓ Branch 0 taken 234808 times.
✓ Branch 1 taken 16339 times.
✓ Branch 2 taken 192445 times.
✓ Branch 3 taken 42363 times.
|
251147 | for (int i = 0; i < 4 && par->pack.pattern[i]; i++) |
| 92 | 192445 | av_bprintf(&bp, "%x", par->pack.pattern[i]); | |
| 93 | 58702 | break; | |
| 94 | 52189 | case SWS_UOP_CLEAR: | |
| 95 | 52189 | av_bprint_chars(&bp, '_', 1); | |
| 96 |
2/2✓ Branch 0 taken 208756 times.
✓ Branch 1 taken 52189 times.
|
260945 | for (int i = 0; i < 4; i++) { |
| 97 |
2/2✓ Branch 0 taken 145889 times.
✓ Branch 1 taken 62867 times.
|
208756 | if (!SWS_COMP_TEST(op->mask, i)) |
| 98 | 145889 | continue; | |
| 99 |
2/2✓ Branch 0 taken 17888 times.
✓ Branch 1 taken 44979 times.
|
62867 | else if (SWS_COMP_TEST(par->clear.one, i)) |
| 100 | 17888 | av_bprint_chars(&bp, '1', 1); | |
| 101 |
2/2✓ Branch 0 taken 10549 times.
✓ Branch 1 taken 34430 times.
|
44979 | else if (SWS_COMP_TEST(par->clear.zero, i)) |
| 102 | 10549 | av_bprint_chars(&bp, '0', 1); | |
| 103 | else | ||
| 104 | 34430 | av_bprint_chars(&bp, 'x', 1); | |
| 105 | } | ||
| 106 | 52189 | break; | |
| 107 | 99777 | case SWS_UOP_LINEAR: | |
| 108 | case SWS_UOP_LINEAR_FMA: | ||
| 109 |
2/2✓ Branch 0 taken 399108 times.
✓ Branch 1 taken 99777 times.
|
498885 | for (int i = 0; i < 4; i++) { |
| 110 |
2/2✓ Branch 0 taken 146731 times.
✓ Branch 1 taken 252377 times.
|
399108 | if (!SWS_COMP_TEST(op->mask, i)) |
| 111 | 146731 | continue; | |
| 112 | 252377 | av_bprint_chars(&bp, '_', 1); | |
| 113 |
2/2✓ Branch 0 taken 1261885 times.
✓ Branch 1 taken 252377 times.
|
1514262 | for (int j = 0; j < 5; j++) { |
| 114 |
2/2✓ Branch 0 taken 405 times.
✓ Branch 1 taken 1261480 times.
|
1261885 | if (par->lin.one & SWS_MASK(i, j)) |
| 115 | 405 | av_bprint_chars(&bp, '1', 1); | |
| 116 |
2/2✓ Branch 0 taken 521658 times.
✓ Branch 1 taken 739822 times.
|
1261480 | else if (par->lin.zero & SWS_MASK(i, j)) |
| 117 | 521658 | av_bprint_chars(&bp, '0', 1); | |
| 118 |
2/2✓ Branch 0 taken 111215 times.
✓ Branch 1 taken 628607 times.
|
739822 | else if (par->lin.exact & SWS_MASK(i, j)) |
| 119 | 111215 | av_bprint_chars(&bp, 'X', 1); | |
| 120 | else | ||
| 121 | 628607 | av_bprint_chars(&bp, 'x', 1); | |
| 122 | } | ||
| 123 | } | ||
| 124 | 99777 | break; | |
| 125 | 86214 | case SWS_UOP_DITHER: | |
| 126 |
2/2✓ Branch 0 taken 344856 times.
✓ Branch 1 taken 86214 times.
|
431070 | for (int i = 0; i < 4; i++) { |
| 127 |
2/2✓ Branch 0 taken 230756 times.
✓ Branch 1 taken 114100 times.
|
344856 | if (SWS_COMP_TEST(op->mask, i)) |
| 128 | 230756 | av_bprintf(&bp, "_%d", par->dither.y_offset[i]); | |
| 129 | } | ||
| 130 | 86214 | const unsigned size = 1u << par->dither.size_log2; | |
| 131 | 86214 | av_bprintf(&bp, "_%ux%u", size, size); | |
| 132 | 86214 | break; | |
| 133 | 92 | case SWS_UOP_LUT_3D: | |
| 134 |
2/2✓ Branch 0 taken 46 times.
✓ Branch 1 taken 46 times.
|
92 | av_bprintf(&bp, "_%s", par->lut3d.dynamic ? "dynamic" : "static"); |
| 135 | 92 | break; | |
| 136 | } | ||
| 137 | |||
| 138 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1517146 times.
|
1517146 | av_assert0(av_bprint_is_complete(&bp)); |
| 139 | 1517146 | } | |
| 140 | |||
| 141 | 11333999 | static void uop_uninit(SwsUOp *uop) | |
| 142 | { | ||
| 143 |
4/4✓ Branch 0 taken 549677 times.
✓ Branch 1 taken 1134073 times.
✓ Branch 2 taken 280960 times.
✓ Branch 3 taken 9369289 times.
|
11333999 | switch (uop->uop) { |
| 144 | 549677 | case SWS_UOP_DITHER: | |
| 145 | 549677 | av_refstruct_unref(&uop->data.ptr); | |
| 146 | 549677 | break; | |
| 147 | 1134073 | case SWS_UOP_READ_PLANAR_FH: | |
| 148 | case SWS_UOP_READ_PLANAR_FV: | ||
| 149 | case SWS_UOP_READ_PLANAR_FV_FMA: | ||
| 150 | 1134073 | av_refstruct_unref(&uop->data.kernel); | |
| 151 | 1134073 | break; | |
| 152 | 280960 | case SWS_UOP_LUT_3D: | |
| 153 | 280960 | av_refstruct_unref(&uop->data.lut3d); | |
| 154 | 280960 | break; | |
| 155 | } | ||
| 156 | |||
| 157 | 11333999 | *uop = (SwsUOp) {0}; | |
| 158 | 11333999 | } | |
| 159 | |||
| 160 | 2388903 | void ff_sws_uop_list_free(SwsUOpList **p_ops) | |
| 161 | { | ||
| 162 | 2388903 | SwsUOpList *ops = *p_ops; | |
| 163 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2388903 times.
|
2388903 | if (!ops) |
| 164 | ✗ | return; | |
| 165 | |||
| 166 |
2/2✓ Branch 0 taken 11244890 times.
✓ Branch 1 taken 2388903 times.
|
13633793 | for (int i = 0; i < ops->num_ops; i++) |
| 167 | 11244890 | uop_uninit(&ops->ops[i]); | |
| 168 | |||
| 169 | 2388903 | av_freep(&ops->ops); | |
| 170 | 2388903 | av_free(ops); | |
| 171 | 2388903 | *p_ops = NULL; | |
| 172 | } | ||
| 173 | |||
| 174 | 2388903 | SwsUOpList *ff_sws_uop_list_alloc(void) | |
| 175 | { | ||
| 176 | 2388903 | return av_mallocz(sizeof(SwsUOpList)); | |
| 177 | } | ||
| 178 | |||
| 179 | 11333999 | int ff_sws_uop_list_append(SwsUOpList *uops, SwsUOp *uop) | |
| 180 | { | ||
| 181 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 11333999 times.
|
11333999 | if (!av_dynarray2_add((void **) &uops->ops, &uops->num_ops, |
| 182 | sizeof(*uop), (uint8_t *) uop)) | ||
| 183 | { | ||
| 184 | ✗ | uop_uninit(uop); | |
| 185 | ✗ | return AVERROR(ENOMEM); | |
| 186 | } | ||
| 187 | |||
| 188 | 11333999 | *uop = (SwsUOp) {0}; | |
| 189 | 11333999 | return 0; | |
| 190 | } | ||
| 191 | |||
| 192 | 32245 | void ff_sws_uop_list_remove_at(SwsUOpList *uops, int index, int count) | |
| 193 | { | ||
| 194 | 32245 | const int end = uops->num_ops - count; | |
| 195 | av_assert2(index >= 0 && count >= 0 && index + count <= uops->num_ops); | ||
| 196 |
2/2✓ Branch 0 taken 89109 times.
✓ Branch 1 taken 32245 times.
|
121354 | for (int i = 0; i < count; i++) |
| 197 | 89109 | uop_uninit(&uops->ops[index + i]); | |
| 198 |
2/2✓ Branch 0 taken 5230 times.
✓ Branch 1 taken 32245 times.
|
37475 | for (int i = index; i < end; i++) |
| 199 | 5230 | uops->ops[i] = uops->ops[i + count]; | |
| 200 | 32245 | uops->num_ops = end; | |
| 201 | 32245 | } | |
| 202 | |||
| 203 | 573022 | int ff_sws_dither_height(const SwsDitherUOp *dither) | |
| 204 | { | ||
| 205 | 573022 | int max_offset = 0; | |
| 206 |
2/2✓ Branch 0 taken 2292088 times.
✓ Branch 1 taken 573022 times.
|
2865110 | for (int i = 0; i < 4; i++) |
| 207 | 2292088 | max_offset = FFMAX(max_offset, dither->y_offset[i]); | |
| 208 | 573022 | return (1 << dither->size_log2) + max_offset; | |
| 209 | } | ||
| 210 | |||
| 211 | 4999010 | static SwsPixelType pixel_type_to_int(const SwsPixelType type) | |
| 212 | { | ||
| 213 |
3/4✓ Branch 0 taken 964186 times.
✓ Branch 1 taken 2779787 times.
✓ Branch 2 taken 1255037 times.
✗ Branch 3 not taken.
|
4999010 | switch (ff_sws_pixel_type_size(type)) { |
| 214 | 964186 | case 1: return SWS_PIXEL_U8; | |
| 215 | 2779787 | case 2: return SWS_PIXEL_U16; | |
| 216 | 1255037 | case 4: return SWS_PIXEL_U32; | |
| 217 | ✗ | default: break; | |
| 218 | } | ||
| 219 | |||
| 220 | ✗ | av_unreachable("Invalid pixel type!"); | |
| 221 | return SWS_PIXEL_NONE; | ||
| 222 | } | ||
| 223 | |||
| 224 | 1604169 | static bool exact_product_f32(float a, float b) | |
| 225 | { | ||
| 226 | 1604169 | volatile float prod = a * b; | |
| 227 |
2/2✓ Branch 0 taken 815479 times.
✓ Branch 1 taken 788690 times.
|
1604169 | volatile float result = b ? prod / b : 0.0f; |
| 228 |
4/4✓ Branch 0 taken 815479 times.
✓ Branch 1 taken 788690 times.
✓ Branch 2 taken 809878 times.
✓ Branch 3 taken 5601 times.
|
1604169 | return !b || result == a; |
| 229 | } | ||
| 230 | |||
| 231 | 897709 | static bool exact_prod(SwsPixelType type, SwsPixel coef, | |
| 232 | const SwsComps *comps, int idx) | ||
| 233 | { | ||
| 234 | 897709 | const AVRational64 minq = comps->min[idx]; | |
| 235 | 897709 | const AVRational64 maxq = comps->max[idx]; | |
| 236 |
2/2✓ Branch 0 taken 1158 times.
✓ Branch 1 taken 896551 times.
|
897709 | if (ff_sws_pixel_type_is_int(type)) |
| 237 | 1158 | return true; | |
| 238 |
3/4✓ Branch 0 taken 802346 times.
✓ Branch 1 taken 94205 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 802346 times.
|
896551 | else if (!minq.den || !maxq.den) |
| 239 | 94205 | return false; /* unknown bounds */ | |
| 240 | |||
| 241 | 802346 | const SwsPixel min = ff_sws_pixel_from_q64(type, minq); | |
| 242 | 802346 | const SwsPixel max = ff_sws_pixel_from_q64(type, maxq); | |
| 243 |
1/2✓ Branch 0 taken 802346 times.
✗ Branch 1 not taken.
|
802346 | switch (type) { |
| 244 | 802346 | case SWS_PIXEL_F32: | |
| 245 |
4/4✓ Branch 1 taken 801823 times.
✓ Branch 2 taken 523 times.
✓ Branch 3 taken 796745 times.
✓ Branch 4 taken 5078 times.
|
1604169 | return exact_product_f32(coef.f32, min.f32) && |
| 246 | 801823 | exact_product_f32(coef.f32, max.f32); | |
| 247 | } | ||
| 248 | |||
| 249 | ✗ | av_unreachable("Invalid pixel type!"); | |
| 250 | return false; | ||
| 251 | } | ||
| 252 | |||
| 253 | 492393 | static bool check_filter_fma(SwsContext *ctx, SwsUOpFlags flags, const SwsOp *op) | |
| 254 | { | ||
| 255 |
2/2✓ Branch 0 taken 262673 times.
✓ Branch 1 taken 229720 times.
|
492393 | if (!(flags & SWS_UOP_FLAG_FMA)) |
| 256 | 262673 | return false; | |
| 257 |
2/2✓ Branch 0 taken 154248 times.
✓ Branch 1 taken 75472 times.
|
229720 | if (!(ctx->flags & SWS_BITEXACT)) |
| 258 | 154248 | return true; | |
| 259 |
2/2✓ Branch 0 taken 42672 times.
✓ Branch 1 taken 32800 times.
|
75472 | if (!ff_sws_pixel_type_is_int(op->type)) |
| 260 | 42672 | return false; | |
| 261 | |||
| 262 | 32800 | const int bits = ff_sws_pixel_type_size(op->type) * 8; | |
| 263 | 32800 | const uint64_t max_val = UINT64_MAX >> (64 - bits); | |
| 264 | |||
| 265 | /* Maximum value representable losslessly as float. Note that this is | ||
| 266 | * currently true only for U8, but that may change if we ever update the | ||
| 267 | * value of SWS_FILTER_SCALE. */ | ||
| 268 | 32800 | return max_val * SWS_FILTER_SCALE <= (1 << 22); | |
| 269 | } | ||
| 270 | |||
| 271 | 4218692 | static int translate_rw_op(SwsContext *ctx, SwsUOpList *ops, SwsUOpFlags flags, | |
| 272 | const SwsOp *op) | ||
| 273 | { | ||
| 274 | 8437384 | SwsUOp uop = { | |
| 275 | 4218692 | .type = op->type, | |
| 276 |
6/6✓ Branch 0 taken 3105548 times.
✓ Branch 1 taken 1113144 times.
✓ Branch 2 taken 2956537 times.
✓ Branch 3 taken 1262155 times.
✓ Branch 4 taken 759177 times.
✓ Branch 5 taken 3459515 times.
|
4218692 | .mask = SWS_COMP_MASK(op->rw.elems > 0, op->rw.elems > 1, |
| 277 | op->rw.elems > 2, op->rw.elems > 3), | ||
| 278 | }; | ||
| 279 | |||
| 280 | /* Non-filtered reads don't care about the exact pixel contents */ | ||
| 281 |
2/2✓ Branch 0 taken 3084619 times.
✓ Branch 1 taken 1134073 times.
|
4218692 | if (!op->rw.filter.op) |
| 282 | 3084619 | uop.type = pixel_type_to_int(op->type); | |
| 283 | |||
| 284 | 4218692 | const bool is_read = op->op == SWS_OP_READ; | |
| 285 |
2/2✓ Branch 0 taken 1134073 times.
✓ Branch 1 taken 3084619 times.
|
4218692 | if (op->rw.filter.op) { |
| 286 |
3/6✓ Branch 0 taken 1134073 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1134073 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1134073 times.
|
1134073 | if (op->op == SWS_OP_WRITE || op->rw.frac || op->rw.mode != SWS_RW_PLANAR) |
| 287 | ✗ | return AVERROR(ENOTSUP); | |
| 288 | 1134073 | uop.par.filter.type = op->rw.filter.type; | |
| 289 | 1134073 | uop.data.kernel = av_refstruct_ref(op->rw.filter.kernel); | |
| 290 |
2/2✓ Branch 0 taken 641680 times.
✓ Branch 1 taken 492393 times.
|
1134073 | if (op->rw.filter.op == SWS_OP_FILTER_H) { |
| 291 | 641680 | uop.uop = SWS_UOP_READ_PLANAR_FH; | |
| 292 |
2/2✓ Branch 1 taken 165926 times.
✓ Branch 2 taken 326467 times.
|
492393 | } else if (check_filter_fma(ctx, flags, op)) { |
| 293 | 165926 | uop.uop = SWS_UOP_READ_PLANAR_FV_FMA; | |
| 294 | } else { | ||
| 295 | 326467 | uop.uop = SWS_UOP_READ_PLANAR_FV; | |
| 296 | } | ||
| 297 |
4/4✓ Branch 0 taken 1189012 times.
✓ Branch 1 taken 1895607 times.
✓ Branch 2 taken 705830 times.
✓ Branch 3 taken 483182 times.
|
3084619 | } else if (op->rw.mode == SWS_RW_PACKED && op->rw.elems > 1) { |
| 298 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 705830 times.
|
705830 | if (op->rw.frac) |
| 299 | ✗ | return AVERROR(ENOTSUP); | |
| 300 |
2/2✓ Branch 0 taken 413790 times.
✓ Branch 1 taken 292040 times.
|
705830 | uop.uop = is_read ? SWS_UOP_READ_PACKED : SWS_UOP_WRITE_PACKED; |
| 301 |
2/2✓ Branch 0 taken 9768 times.
✓ Branch 1 taken 2369021 times.
|
2378789 | } else if (op->rw.mode == SWS_RW_PALETTE) { |
| 302 |
4/6✓ Branch 0 taken 9636 times.
✓ Branch 1 taken 132 times.
✓ Branch 2 taken 9636 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 9636 times.
|
9768 | if (!(flags & SWS_UOP_FLAG_READ_PALETTE) || op->rw.frac || !is_read) |
| 303 | 132 | return AVERROR(ENOTSUP); | |
| 304 | 9636 | uop.uop = SWS_UOP_READ_PALETTE; | |
| 305 |
2/2✓ Branch 0 taken 36699 times.
✓ Branch 1 taken 2332322 times.
|
2369021 | } else if (op->rw.frac == 3) { |
| 306 |
2/2✓ Branch 0 taken 21345 times.
✓ Branch 1 taken 15354 times.
|
36699 | uop.uop = is_read ? SWS_UOP_READ_BIT : SWS_UOP_WRITE_BIT; |
| 307 |
2/2✓ Branch 0 taken 39212 times.
✓ Branch 1 taken 2293110 times.
|
2332322 | } else if (op->rw.frac == 1) { |
| 308 |
2/2✓ Branch 0 taken 23852 times.
✓ Branch 1 taken 15360 times.
|
39212 | uop.uop = is_read ? SWS_UOP_READ_NIBBLE : SWS_UOP_WRITE_NIBBLE; |
| 309 | } else { | ||
| 310 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2293110 times.
|
2293110 | av_assert0(!op->rw.frac); |
| 311 |
2/2✓ Branch 0 taken 696590 times.
✓ Branch 1 taken 1596520 times.
|
2293110 | uop.uop = is_read ? SWS_UOP_READ_PLANAR : SWS_UOP_WRITE_PLANAR; |
| 312 | } | ||
| 313 | |||
| 314 | 4218560 | const int planes = ff_sws_rw_op_planes(op); | |
| 315 |
2/2✓ Branch 0 taken 2299286 times.
✓ Branch 1 taken 1919274 times.
|
4218560 | if (op->op == SWS_OP_READ) { |
| 316 | 2299286 | ops->planes_in |= SWS_COMP_ELEMS(planes); | |
| 317 | } else { | ||
| 318 | 1919274 | ops->planes_out |= SWS_COMP_ELEMS(planes); | |
| 319 | } | ||
| 320 | |||
| 321 | 4218560 | return ff_sws_uop_list_append(ops, &uop); | |
| 322 | } | ||
| 323 | |||
| 324 | 2593854 | static int count_idx(const int *arr, size_t size, int val) | |
| 325 | { | ||
| 326 | 2593854 | int num = 0; | |
| 327 |
2/2✓ Branch 0 taken 12969270 times.
✓ Branch 1 taken 2593854 times.
|
15563124 | for (size_t i = 0; i < size; i++) { |
| 328 |
2/2✓ Branch 0 taken 3577561 times.
✓ Branch 1 taken 9391709 times.
|
12969270 | if (arr[i] == val) |
| 329 | 3577561 | num++; | |
| 330 | } | ||
| 331 | |||
| 332 | 2593854 | return num; | |
| 333 | } | ||
| 334 | |||
| 335 | 626817 | static int translate_swizzle(SwsUOpList *ops, const SwsOp *op) | |
| 336 | { | ||
| 337 | 1880451 | SwsUOp uop = { | |
| 338 | .uop = SWS_UOP_PERMUTE, | ||
| 339 | 626817 | .type = pixel_type_to_int(op->type), | |
| 340 | 626817 | .mask = ff_sws_comp_mask_needed(op), | |
| 341 | }; | ||
| 342 | 626817 | SwsMoveUOp *par = &uop.par.move; | |
| 343 | |||
| 344 | /* Mask of components that are not yet satisfied */ | ||
| 345 | 626817 | SwsCompMask todo = uop.mask; | |
| 346 |
2/2✓ Branch 0 taken 2507268 times.
✓ Branch 1 taken 626817 times.
|
3134085 | for (int i = 0; i < 4; i++) { |
| 347 |
2/2✓ Branch 0 taken 967344 times.
✓ Branch 1 taken 1539924 times.
|
2507268 | if (op->swizzle.in[i] == i) |
| 348 | 967344 | todo &= ~SWS_COMP(i); | |
| 349 | } | ||
| 350 | |||
| 351 | /* Mask of components whose value is required for the final output */ | ||
| 352 | 626817 | SwsCompMask needed = 0; | |
| 353 |
2/2✓ Branch 0 taken 2507268 times.
✓ Branch 1 taken 626817 times.
|
3134085 | for (int i = 0; i < 4; i++) { |
| 354 |
2/2✓ Branch 0 taken 1891249 times.
✓ Branch 1 taken 616019 times.
|
2507268 | if (SWS_OP_NEEDED(op, i)) |
| 355 | 1891249 | needed |= SWS_COMP(op->swizzle.in[i]); | |
| 356 | } | ||
| 357 | |||
| 358 | /* Current mapping of registers to components */ | ||
| 359 | 626817 | int idx[4 + 1] = { 0, 1, 2, 3, -1 }; /* +1 for tmp */ | |
| 360 | |||
| 361 | /* Decompose the swizzle mask into a series of register-register moves */ | ||
| 362 |
2/2✓ Branch 0 taken 1752044 times.
✓ Branch 1 taken 626817 times.
|
2378861 | while (todo) { |
| 363 | 1752044 | int dst = -1, src = -1; | |
| 364 | |||
| 365 | /* Find next unsatisfied dst <- src move that doesn't clobber a value */ | ||
| 366 |
2/2✓ Branch 0 taken 4516019 times.
✓ Branch 1 taken 374634 times.
|
4890653 | for (dst = 0; dst < 4; dst++) { |
| 367 |
2/2✓ Branch 0 taken 1922165 times.
✓ Branch 1 taken 2593854 times.
|
4516019 | if (!SWS_COMP_TEST(todo, dst)) |
| 368 | 1922165 | continue; /* already satisfied */ | |
| 369 | 2593854 | const int cur = idx[dst]; | |
| 370 |
4/4✓ Branch 1 taken 1610147 times.
✓ Branch 2 taken 983707 times.
✓ Branch 3 taken 1216444 times.
✓ Branch 4 taken 393703 times.
|
2593854 | if (count_idx(idx, FF_ARRAY_ELEMS(idx), cur) == 1 && SWS_COMP_TEST(needed, cur)) |
| 371 | 1216444 | continue; /* clobbers last remaining, still-needed value */ | |
| 372 |
1/2✓ Branch 0 taken 4272371 times.
✗ Branch 1 not taken.
|
4272371 | for (src = 0; src < FF_ARRAY_ELEMS(idx); src++) { |
| 373 |
2/2✓ Branch 0 taken 1377410 times.
✓ Branch 1 taken 2894961 times.
|
4272371 | if (idx[src] == op->swizzle.in[dst]) { |
| 374 | /* Prevent read-after-write dependency. */ | ||
| 375 |
4/4✓ Branch 0 taken 1091284 times.
✓ Branch 1 taken 286126 times.
✓ Branch 2 taken 422 times.
✓ Branch 3 taken 1090862 times.
|
1377410 | if (par->num_moves > 0 && src == par->dst[par->num_moves - 1]) |
| 376 | 422 | src = par->src[par->num_moves - 1]; | |
| 377 | 1377410 | break; | |
| 378 | } | ||
| 379 | } | ||
| 380 | av_assert1(src < FF_ARRAY_ELEMS(idx)); | ||
| 381 | 1377410 | todo &= ~SWS_COMP(dst); | |
| 382 | 1377410 | break; | |
| 383 | } | ||
| 384 | |||
| 385 |
2/2✓ Branch 0 taken 374634 times.
✓ Branch 1 taken 1377410 times.
|
1752044 | if (dst == 4) { |
| 386 | /* Stuck in a cycle, break it by saving to the scratch register */ | ||
| 387 | 374634 | dst = 4; | |
| 388 |
1/2✓ Branch 0 taken 409573 times.
✗ Branch 1 not taken.
|
409573 | for (src = 0; src < 4; src++) { |
| 389 |
2/2✓ Branch 0 taken 374634 times.
✓ Branch 1 taken 34939 times.
|
409573 | if (SWS_COMP_TEST(todo, src)) { |
| 390 | 374634 | needed &= ~SWS_COMP(idx[src]); | |
| 391 | 374634 | break; | |
| 392 | } | ||
| 393 | } | ||
| 394 | av_assert1(src < 4); | ||
| 395 | } | ||
| 396 | |||
| 397 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1752044 times.
|
1752044 | av_assert0(par->num_moves < SWS_UOP_MOVE_MAX); |
| 398 |
2/2✓ Branch 0 taken 1377410 times.
✓ Branch 1 taken 374634 times.
|
1752044 | par->dst[par->num_moves] = dst > 3 ? -1 : dst; |
| 399 |
2/2✓ Branch 0 taken 1377410 times.
✓ Branch 1 taken 374634 times.
|
1752044 | par->src[par->num_moves] = src > 3 ? -1 : src; |
| 400 | 1752044 | par->num_moves++; | |
| 401 | 1752044 | idx[dst] = idx[src]; | |
| 402 | } | ||
| 403 | |||
| 404 | /* Check for duplicates in the final register map */ | ||
| 405 | 626817 | SwsCompMask seen = 0; | |
| 406 |
2/2✓ Branch 0 taken 2308120 times.
✓ Branch 1 taken 524485 times.
|
2832605 | for (int i = 0; i < 4; i++) { |
| 407 |
2/2✓ Branch 0 taken 527826 times.
✓ Branch 1 taken 1780294 times.
|
2308120 | if (!SWS_COMP_TEST(uop.mask, i)) |
| 408 | 527826 | continue; | |
| 409 | av_assert2(idx[i] >= 0); /* should be no tmp register */ | ||
| 410 | 1780294 | const SwsCompMask bit = SWS_COMP(idx[i]); | |
| 411 |
2/2✓ Branch 0 taken 102332 times.
✓ Branch 1 taken 1677962 times.
|
1780294 | if (seen & bit) { |
| 412 | 102332 | uop.uop = SWS_UOP_COPY; | |
| 413 | 102332 | break; | |
| 414 | } | ||
| 415 | 1677962 | seen |= bit; | |
| 416 | } | ||
| 417 | |||
| 418 | /* Add any extra unused components to the mask, to prevent generating | ||
| 419 | * duplicate uops like permute_xyz_txy_xyt and permute_xyzw_txy_xyt */ | ||
| 420 |
2/2✓ Branch 0 taken 2507268 times.
✓ Branch 1 taken 626817 times.
|
3134085 | for (int i = 0; i < 4; i++) { |
| 421 | 2507268 | const SwsCompMask bit = SWS_COMP(i); | |
| 422 |
4/4✓ Branch 0 taken 829306 times.
✓ Branch 1 taken 1677962 times.
✓ Branch 2 taken 426980 times.
✓ Branch 3 taken 402326 times.
|
2507268 | if (!(seen & bit) && idx[i] == i) |
| 423 | 426980 | uop.mask |= bit; | |
| 424 | } | ||
| 425 | |||
| 426 | 626817 | return ff_sws_uop_list_append(ops, &uop); | |
| 427 | } | ||
| 428 | |||
| 429 | 648733 | static int translate_dither_op(SwsUOpList *ops, SwsUOpFlags flags, const SwsOp *op) | |
| 430 | { | ||
| 431 | 648733 | SwsUOp uop = { | |
| 432 | 648733 | .type = op->type, | |
| 433 | .uop = SWS_UOP_DITHER, | ||
| 434 | 648733 | .par.dither.size_log2 = op->dither.size_log2, | |
| 435 | }; | ||
| 436 | |||
| 437 |
4/4✓ Branch 0 taken 640205 times.
✓ Branch 1 taken 8528 times.
✓ Branch 2 taken 99056 times.
✓ Branch 3 taken 541149 times.
|
648733 | if ((flags & SWS_UOP_FLAG_ADD) && op->dither.size_log2 == 0) { |
| 438 | /* Constant offset */ | ||
| 439 | 99056 | const SwsPixel val = Q2PIXEL(op->dither.matrix[0]); | |
| 440 | 99056 | uop.uop = SWS_UOP_ADD; | |
| 441 |
2/2✓ Branch 0 taken 396224 times.
✓ Branch 1 taken 99056 times.
|
495280 | for (int i = 0; i < 4; i++) { |
| 442 |
4/4✓ Branch 0 taken 250118 times.
✓ Branch 1 taken 146106 times.
✓ Branch 2 taken 1324 times.
✓ Branch 3 taken 248794 times.
|
396224 | if (!SWS_OP_NEEDED(op, i) || op->dither.y_offset[i] < 0) |
| 443 | 147430 | continue; | |
| 444 | 248794 | uop.mask |= SWS_COMP(i); | |
| 445 | 248794 | uop.data.vec4[i] = val; | |
| 446 | } | ||
| 447 | |||
| 448 | 99056 | return ff_sws_uop_list_append(ops, &uop); | |
| 449 | } | ||
| 450 | |||
| 451 | 549677 | const int size = 1 << op->dither.size_log2; | |
| 452 |
2/2✓ Branch 0 taken 2198708 times.
✓ Branch 1 taken 549677 times.
|
2748385 | for (int i = 0; i < 4; i++) { |
| 453 |
4/4✓ Branch 0 taken 1546450 times.
✓ Branch 1 taken 652258 times.
✓ Branch 2 taken 41884 times.
✓ Branch 3 taken 1504566 times.
|
2198708 | if (!SWS_OP_NEEDED(op, i) || op->dither.y_offset[i] < 0) |
| 454 | 694142 | continue; | |
| 455 | 1504566 | const uint8_t off = op->dither.y_offset[i] & (size - 1); | |
| 456 | 1504566 | uop.mask |= SWS_COMP(i); | |
| 457 | 1504566 | uop.par.dither.y_offset[i] = off; | |
| 458 | } | ||
| 459 | |||
| 460 | /* Allocate extra rows to allow over-reading for row offsets. Note that | ||
| 461 | * y_offset is currently never larger than 5, so the extra space needed | ||
| 462 | * for this over-allocation is bounded by 5 * size * sizeof(float), | ||
| 463 | * typically 320 bytes for a 16x16 dither matrix. */ | ||
| 464 | 549677 | const int stride = size * sizeof(SwsPixel); | |
| 465 | 549677 | const int num_rows = ff_sws_dither_height(&uop.par.dither); | |
| 466 | 549677 | SwsPixel *matrix = uop.data.ptr = av_refstruct_allocz(num_rows * stride); | |
| 467 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 549677 times.
|
549677 | if (!matrix) |
| 468 | ✗ | return AVERROR(ENOMEM); | |
| 469 | |||
| 470 |
2/2✓ Branch 0 taken 140717312 times.
✓ Branch 1 taken 549677 times.
|
141266989 | for (int i = 0; i < size * size; i++) |
| 471 | 140717312 | matrix[i] = Q2PIXEL(op->dither.matrix[i]); | |
| 472 | 549677 | memcpy(&matrix[size * size], matrix, (num_rows - size) * stride); | |
| 473 | |||
| 474 | 549677 | return ff_sws_uop_list_append(ops, &uop); | |
| 475 | } | ||
| 476 | |||
| 477 | 789148 | static int translate_linear_op(SwsContext *ctx, SwsUOpList *ops, | |
| 478 | SwsUOpFlags flags, const SwsOp *op, | ||
| 479 | const SwsComps *input) | ||
| 480 | { | ||
| 481 | 789148 | SwsUOp uop = { | |
| 482 | 789148 | .type = op->type, | |
| 483 | .uop = SWS_UOP_LINEAR, | ||
| 484 | }; | ||
| 485 | |||
| 486 | 789148 | const uint32_t mask = ff_sws_linear_mask(&op->lin); | |
| 487 | 789148 | const bool bitexact = ctx->flags & SWS_BITEXACT; | |
| 488 | 789148 | uint32_t exact = 0; | |
| 489 | |||
| 490 |
2/2✓ Branch 0 taken 3156592 times.
✓ Branch 1 taken 789148 times.
|
3945740 | for (int i = 0; i < 4; i++) { |
| 491 |
4/4✓ Branch 0 taken 2212733 times.
✓ Branch 1 taken 943859 times.
✓ Branch 2 taken 91445 times.
✓ Branch 3 taken 2121288 times.
|
3156592 | if (!SWS_OP_NEEDED(op, i) || !(mask & SWS_MASK_ROW(i))) { |
| 492 | 1035304 | uop.par.lin.zero |= SWS_MASK_ROW(i); | |
| 493 | 1035304 | continue; | |
| 494 | } | ||
| 495 | 2121288 | uop.mask |= SWS_COMP(i); | |
| 496 | 2121288 | bool nonzero = (op->lin.m[i][4].num != 0); | |
| 497 |
2/2✓ Branch 0 taken 10606440 times.
✓ Branch 1 taken 2121288 times.
|
12727728 | for (int j = 0; j < 5; j++) { |
| 498 | 10606440 | const AVRational64 k = op->lin.m[i][j]; | |
| 499 | 10606440 | const SwsPixel px = Q2PIXEL(k); | |
| 500 | 10606440 | uop.data.mat4x5[i][j] = px; | |
| 501 |
2/2✓ Branch 0 taken 4836575 times.
✓ Branch 1 taken 5769865 times.
|
10606440 | if (k.num == 0) |
| 502 | 4836575 | uop.par.lin.zero |= SWS_MASK(i, j); | |
| 503 |
4/4✓ Branch 0 taken 4423732 times.
✓ Branch 1 taken 1346133 times.
✓ Branch 2 taken 1518 times.
✓ Branch 3 taken 4422214 times.
|
5769865 | else if (j < 4 && k.num == k.den) |
| 504 | 1518 | uop.par.lin.one |= SWS_MASK(i, j); | |
| 505 |
8/8✓ Branch 0 taken 4422214 times.
✓ Branch 1 taken 1346133 times.
✓ Branch 2 taken 3647059 times.
✓ Branch 3 taken 775155 times.
✓ Branch 4 taken 897709 times.
✓ Branch 5 taken 2749350 times.
✓ Branch 7 taken 797903 times.
✓ Branch 8 taken 99806 times.
|
5768347 | else if (j < 4 && nonzero && (!bitexact || exact_prod(uop.type, px, input, j))) |
| 506 | 3547253 | exact |= SWS_MASK(i, j); | |
| 507 |
2/2✓ Branch 0 taken 5769865 times.
✓ Branch 1 taken 4836575 times.
|
10606440 | if (k.num != 0) |
| 508 | 5769865 | nonzero = true; | |
| 509 | } | ||
| 510 | } | ||
| 511 | |||
| 512 |
4/4✓ Branch 0 taken 381367 times.
✓ Branch 1 taken 407781 times.
✓ Branch 2 taken 378865 times.
✓ Branch 3 taken 2502 times.
|
789148 | if ((flags & SWS_UOP_FLAG_FMA) && !ff_sws_pixel_type_is_int(op->type)) { |
| 513 | /* multiplication by 1 and 0 are always exact by definition */ | ||
| 514 | 378865 | uop.uop = SWS_UOP_LINEAR_FMA; | |
| 515 | 378865 | uop.par.lin.exact = exact | uop.par.lin.zero | uop.par.lin.one; | |
| 516 | } | ||
| 517 | |||
| 518 | 789148 | return ff_sws_uop_list_append(ops, &uop); | |
| 519 | } | ||
| 520 | |||
| 521 | 11773715 | static int translate_op(SwsContext *ctx, SwsUOpList *uops, SwsUOpFlags flags, | |
| 522 | const SwsOp *op, const SwsComps *input) | ||
| 523 | { | ||
| 524 |
6/6✓ Branch 0 taken 469497 times.
✓ Branch 1 taken 4218692 times.
✓ Branch 2 taken 626817 times.
✓ Branch 3 taken 648733 times.
✓ Branch 4 taken 789148 times.
✓ Branch 5 taken 5020828 times.
|
11773715 | switch (op->op) { |
| 525 | 469497 | case SWS_OP_FILTER_H: | |
| 526 | case SWS_OP_FILTER_V: | ||
| 527 | 469497 | return AVERROR(ENOTSUP); /* always handled by subpass splitting */ | |
| 528 | 4218692 | case SWS_OP_READ: | |
| 529 | case SWS_OP_WRITE: | ||
| 530 | 4218692 | return translate_rw_op(ctx, uops, flags, op); | |
| 531 | 626817 | case SWS_OP_SWIZZLE: | |
| 532 | 626817 | return translate_swizzle(uops, op); | |
| 533 | 648733 | case SWS_OP_DITHER: | |
| 534 | 648733 | return translate_dither_op(uops, flags, op); | |
| 535 | 789148 | case SWS_OP_LINEAR: | |
| 536 | 789148 | return translate_linear_op(ctx, uops, flags, op, input); | |
| 537 | 5020828 | default: | |
| 538 | 5020828 | break; | |
| 539 | } | ||
| 540 | |||
| 541 | /* Default handling for "simple" ops */ | ||
| 542 | 10041656 | SwsUOp uop = { | |
| 543 | 5020828 | .type = op->type, | |
| 544 | .uop = SWS_UOP_INVALID, | ||
| 545 | 5020828 | .mask = ff_sws_comp_mask_needed(op), | |
| 546 | }; | ||
| 547 | |||
| 548 |
8/9✓ Branch 0 taken 1319407 times.
✓ Branch 1 taken 482790 times.
✓ Branch 2 taken 189680 times.
✓ Branch 3 taken 342870 times.
✓ Branch 4 taken 449306 times.
✓ Branch 5 taken 1011111 times.
✓ Branch 6 taken 944704 times.
✓ Branch 7 taken 280960 times.
✗ Branch 8 not taken.
|
5020828 | switch (op->op) { |
| 549 | 1319407 | case SWS_OP_CONVERT: | |
| 550 |
4/5✓ Branch 0 taken 338205 times.
✓ Branch 1 taken 687159 times.
✓ Branch 2 taken 61272 times.
✓ Branch 3 taken 232771 times.
✗ Branch 4 not taken.
|
1319407 | switch (op->convert.to) { |
| 551 | 338205 | case SWS_PIXEL_U8: uop.uop = SWS_UOP_TO_U8; break; | |
| 552 | 687159 | case SWS_PIXEL_U16: uop.uop = SWS_UOP_TO_U16; break; | |
| 553 | 61272 | case SWS_PIXEL_U32: uop.uop = SWS_UOP_TO_U32; break; | |
| 554 | 232771 | case SWS_PIXEL_F32: uop.uop = SWS_UOP_TO_F32; break; | |
| 555 | } | ||
| 556 | 1319407 | break; | |
| 557 | 482790 | case SWS_OP_UNPACK: | |
| 558 | case SWS_OP_PACK: | ||
| 559 |
2/2✓ Branch 0 taken 199680 times.
✓ Branch 1 taken 283110 times.
|
482790 | uop.uop = op->op == SWS_OP_PACK ? SWS_UOP_PACK : SWS_UOP_UNPACK; |
| 560 | 482790 | uop.mask = 0; | |
| 561 |
4/4✓ Branch 0 taken 1931160 times.
✓ Branch 1 taken 150248 times.
✓ Branch 2 taken 1598618 times.
✓ Branch 3 taken 332542 times.
|
2081408 | for (int i = 0; i < 4 && op->pack.pattern[i]; i++) { |
| 562 | 1598618 | uop.par.pack.pattern[i] = op->pack.pattern[i]; | |
| 563 |
4/4✓ Branch 0 taken 937934 times.
✓ Branch 1 taken 660684 times.
✓ Branch 2 taken 839838 times.
✓ Branch 3 taken 98096 times.
|
1598618 | if (op->op == SWS_OP_PACK || SWS_OP_NEEDED(op, i)) |
| 564 | 1500522 | uop.mask |= SWS_COMP(i); | |
| 565 | } | ||
| 566 | 482790 | break; | |
| 567 | 189680 | case SWS_OP_LSHIFT: | |
| 568 | case SWS_OP_RSHIFT: | ||
| 569 |
2/2✓ Branch 0 taken 82215 times.
✓ Branch 1 taken 107465 times.
|
189680 | uop.uop = op->op == SWS_OP_LSHIFT ? SWS_UOP_LSHIFT : SWS_UOP_RSHIFT; |
| 570 | 189680 | uop.par.shift.amount = op->shift.amount; | |
| 571 | 189680 | break; | |
| 572 | 342870 | case SWS_OP_CLEAR: | |
| 573 | 342870 | uop.uop = SWS_UOP_CLEAR; | |
| 574 | 342870 | uop.type = pixel_type_to_int(op->type); | |
| 575 | 342870 | uop.mask &= op->clear.mask; | |
| 576 |
2/2✓ Branch 0 taken 1371480 times.
✓ Branch 1 taken 342870 times.
|
1714350 | for (int i = 0; i < 4; i++) { |
| 577 |
2/2✓ Branch 0 taken 979688 times.
✓ Branch 1 taken 391792 times.
|
1371480 | if (!SWS_COMP_TEST(op->clear.mask, i)) |
| 578 | 979688 | continue; | |
| 579 | 391792 | const AVRational64 v = op->clear.value[i]; | |
| 580 | 391792 | const SwsPixel px = Q2PIXEL(op->clear.value[i]); | |
| 581 | 391792 | uop.data.vec4[i] = px; | |
| 582 |
2/2✓ Branch 0 taken 69240 times.
✓ Branch 1 taken 322552 times.
|
391792 | if (v.num == 0) |
| 583 | 69240 | uop.par.clear.zero |= SWS_COMP(i); | |
| 584 |
2/2✓ Branch 1 taken 84684 times.
✓ Branch 2 taken 237868 times.
|
322552 | else if (ff_sws_pixel_is_1s(op->type, px)) |
| 585 | 84684 | uop.par.clear.one |= SWS_COMP(i); | |
| 586 | } | ||
| 587 | 342870 | break; | |
| 588 | 449306 | case SWS_OP_SCALE: | |
| 589 | 449306 | uop.uop = SWS_UOP_SCALE; | |
| 590 | 449306 | uop.data.scalar = Q2PIXEL(op->scale.factor); | |
| 591 | 449306 | break; | |
| 592 | 1011111 | case SWS_OP_MIN: | |
| 593 | case SWS_OP_MAX: | ||
| 594 |
2/2✓ Branch 0 taken 679368 times.
✓ Branch 1 taken 331743 times.
|
1011111 | uop.uop = op->op == SWS_OP_MIN ? SWS_UOP_MIN : SWS_UOP_MAX; |
| 595 | 1011111 | uop.mask &= ff_sws_comp_mask_q4(op->clamp.limit); | |
| 596 |
2/2✓ Branch 0 taken 4044444 times.
✓ Branch 1 taken 1011111 times.
|
5055555 | for (int i = 0; i < 4; i++) { |
| 597 |
2/2✓ Branch 0 taken 2653088 times.
✓ Branch 1 taken 1391356 times.
|
4044444 | if (SWS_COMP_TEST(uop.mask, i)) |
| 598 | 2653088 | uop.data.vec4[i] = Q2PIXEL(op->clamp.limit[i]); | |
| 599 | } | ||
| 600 | 1011111 | break; | |
| 601 | 944704 | case SWS_OP_SWAP_BYTES: | |
| 602 | 944704 | uop.uop = SWS_UOP_SWAP_BYTES; | |
| 603 | 944704 | uop.type = pixel_type_to_int(op->type); | |
| 604 | 944704 | break; | |
| 605 | 280960 | case SWS_OP_LUT_3D: | |
| 606 | 280960 | uop.uop = SWS_UOP_LUT_3D; | |
| 607 | 280960 | uop.par.lut3d.dynamic = op->lut3d.dynamic; | |
| 608 | 280960 | uop.data.lut3d = av_refstruct_ref_c(op->lut3d.lut); | |
| 609 | 280960 | break; | |
| 610 | ✗ | default: | |
| 611 | ✗ | return AVERROR(ENOTSUP); | |
| 612 | } | ||
| 613 | |||
| 614 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5020828 times.
|
5020828 | av_assert0(uop.uop != SWS_UOP_INVALID); |
| 615 | 5020828 | return ff_sws_uop_list_append(uops, &uop); | |
| 616 | } | ||
| 617 | |||
| 618 | 2388903 | int ff_sws_ops_translate(SwsContext *ctx, const SwsOpList *ops, | |
| 619 | SwsUOpFlags flags, SwsUOpList *uops) | ||
| 620 | { | ||
| 621 | 2388903 | SwsComps input = ops->comps_src; | |
| 622 |
2/2✓ Branch 0 taken 11773715 times.
✓ Branch 1 taken 1919274 times.
|
13692989 | for (int i = 0; i < ops->num_ops; i++) { |
| 623 | 11773715 | const SwsOp *op = &ops->ops[i]; | |
| 624 | 11773715 | const int pixel_size = ff_sws_pixel_type_size(op->type); | |
| 625 |
2/2✓ Branch 0 taken 3411564 times.
✓ Branch 1 taken 8362151 times.
|
11773715 | if (pixel_size > uops->pixel_size_max) |
| 626 | 3411564 | uops->pixel_size_max = pixel_size; | |
| 627 | |||
| 628 | 11773715 | int ret = translate_op(ctx, uops, flags, op, &input); | |
| 629 |
2/2✓ Branch 0 taken 469629 times.
✓ Branch 1 taken 11304086 times.
|
11773715 | if (ret < 0) |
| 630 | 469629 | return ret; | |
| 631 | 11304086 | input = ops->ops[i].comps; | |
| 632 | } | ||
| 633 | |||
| 634 | 1919274 | return ff_sws_uop_list_optimize(ctx, flags, uops); | |
| 635 | } | ||
| 636 |