FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libswscale/swscale.c
Date: 2024-11-20 23:03:26
Exec Total Coverage
Lines: 610 693 88.0%
Functions: 32 33 97.0%
Branches: 379 488 77.7%

Line Branch Exec Source
1 /*
2 * Copyright (C) 2001-2011 Michael Niedermayer <michaelni@gmx.at>
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 <stdint.h>
22 #include <stdio.h>
23 #include <string.h>
24
25 #include "libavutil/avassert.h"
26 #include "libavutil/bswap.h"
27 #include "libavutil/common.h"
28 #include "libavutil/cpu.h"
29 #include "libavutil/emms.h"
30 #include "libavutil/intreadwrite.h"
31 #include "libavutil/mem.h"
32 #include "libavutil/mem_internal.h"
33 #include "libavutil/pixdesc.h"
34 #include "config.h"
35 #include "swscale_internal.h"
36 #include "swscale.h"
37
38 DECLARE_ALIGNED(8, const uint8_t, ff_dither_8x8_128)[9][8] = {
39 { 36, 68, 60, 92, 34, 66, 58, 90, },
40 { 100, 4, 124, 28, 98, 2, 122, 26, },
41 { 52, 84, 44, 76, 50, 82, 42, 74, },
42 { 116, 20, 108, 12, 114, 18, 106, 10, },
43 { 32, 64, 56, 88, 38, 70, 62, 94, },
44 { 96, 0, 120, 24, 102, 6, 126, 30, },
45 { 48, 80, 40, 72, 54, 86, 46, 78, },
46 { 112, 16, 104, 8, 118, 22, 110, 14, },
47 { 36, 68, 60, 92, 34, 66, 58, 90, },
48 };
49
50 DECLARE_ALIGNED(8, static const uint8_t, sws_pb_64)[8] = {
51 64, 64, 64, 64, 64, 64, 64, 64
52 };
53
54 5566 static av_always_inline void fillPlane(uint8_t *plane, int stride, int width,
55 int height, int y, uint8_t val)
56 {
57 int i;
58 5566 uint8_t *ptr = plane + stride * y;
59
2/2
✓ Branch 0 taken 140692 times.
✓ Branch 1 taken 5566 times.
146258 for (i = 0; i < height; i++) {
60 140692 memset(ptr, val, width);
61 140692 ptr += stride;
62 }
63 5566 }
64
65 6046854 static void hScale16To19_c(SwsInternal *c, int16_t *_dst, int dstW,
66 const uint8_t *_src, const int16_t *filter,
67 const int32_t *filterPos, int filterSize)
68 {
69 6046854 const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->srcFormat);
70 int i;
71 6046854 int32_t *dst = (int32_t *) _dst;
72 6046854 const uint16_t *src = (const uint16_t *) _src;
73 6046854 int bits = desc->comp[0].depth - 1;
74 6046854 int sh = bits - 4;
75
76
5/6
✓ Branch 1 taken 3152606 times.
✓ Branch 2 taken 2894248 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3152606 times.
✓ Branch 5 taken 2015038 times.
✓ Branch 6 taken 879210 times.
6046854 if ((isAnyRGB(c->srcFormat) || c->srcFormat==AV_PIX_FMT_PAL8) && desc->comp[0].depth<16) {
77 2015038 sh = 9;
78
2/2
✓ Branch 0 taken 4608 times.
✓ Branch 1 taken 4027208 times.
4031816 } else if (desc->flags & AV_PIX_FMT_FLAG_FLOAT) { /* float input are process like uint 16bpc */
79 4608 sh = 16 - 1 - 4;
80 }
81
82
2/2
✓ Branch 0 taken 1809529088 times.
✓ Branch 1 taken 6046854 times.
1815575942 for (i = 0; i < dstW; i++) {
83 int j;
84 1809529088 int srcPos = filterPos[i];
85 1809529088 int val = 0;
86
87
2/2
✓ Branch 0 taken 3282093696 times.
✓ Branch 1 taken 1809529088 times.
5091622784 for (j = 0; j < filterSize; j++) {
88 3282093696 val += src[srcPos + j] * filter[filterSize * i + j];
89 }
90 // filter=14 bit, input=16 bit, output=30 bit, >> 11 makes 19 bit
91 1809529088 dst[i] = FFMIN(val >> sh, (1 << 19) - 1);
92 }
93 6046854 }
94
95 27860660 static void hScale16To15_c(SwsInternal *c, int16_t *dst, int dstW,
96 const uint8_t *_src, const int16_t *filter,
97 const int32_t *filterPos, int filterSize)
98 {
99 27860660 const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->srcFormat);
100 int i;
101 27860660 const uint16_t *src = (const uint16_t *) _src;
102 27860660 int sh = desc->comp[0].depth - 1;
103
104
2/2
✓ Branch 0 taken 22719750 times.
✓ Branch 1 taken 5140910 times.
27860660 if (sh<15) {
105
4/4
✓ Branch 1 taken 10963857 times.
✓ Branch 2 taken 11755893 times.
✓ Branch 3 taken 10423873 times.
✓ Branch 4 taken 539984 times.
22719750 sh = isAnyRGB(c->srcFormat) || c->srcFormat==AV_PIX_FMT_PAL8 ? 13 : (desc->comp[0].depth - 1);
106
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5140910 times.
5140910 } else if (desc->flags & AV_PIX_FMT_FLAG_FLOAT) { /* float input are process like uint 16bpc */
107 sh = 16 - 1;
108 }
109
110
2/2
✓ Branch 0 taken 8380005357 times.
✓ Branch 1 taken 27860660 times.
8407866017 for (i = 0; i < dstW; i++) {
111 int j;
112 8380005357 int srcPos = filterPos[i];
113 8380005357 int val = 0;
114
115
2/2
✓ Branch 0 taken 15197962989 times.
✓ Branch 1 taken 8380005357 times.
23577968346 for (j = 0; j < filterSize; j++) {
116 15197962989 val += src[srcPos + j] * filter[filterSize * i + j];
117 }
118 // filter=14 bit, input=16 bit, output=30 bit, >> 15 makes 15 bit
119 8380005357 dst[i] = FFMIN(val >> sh, (1 << 15) - 1);
120 }
121 27860660 }
122
123 // bilinear / bicubic scaling
124 18275995 static void hScale8To15_c(SwsInternal *c, int16_t *dst, int dstW,
125 const uint8_t *src, const int16_t *filter,
126 const int32_t *filterPos, int filterSize)
127 {
128 int i;
129
2/2
✓ Branch 0 taken 5509200976 times.
✓ Branch 1 taken 18275995 times.
5527476971 for (i = 0; i < dstW; i++) {
130 int j;
131 5509200976 int srcPos = filterPos[i];
132 5509200976 int val = 0;
133
2/2
✓ Branch 0 taken 14216477110 times.
✓ Branch 1 taken 5509200976 times.
19725678086 for (j = 0; j < filterSize; j++) {
134 14216477110 val += ((int)src[srcPos + j]) * filter[filterSize * i + j];
135 }
136 5509200976 dst[i] = FFMIN(val >> 7, (1 << 15) - 1); // the cubic equation does overflow ...
137 }
138 18275995 }
139
140 1889003 static void hScale8To19_c(SwsInternal *c, int16_t *_dst, int dstW,
141 const uint8_t *src, const int16_t *filter,
142 const int32_t *filterPos, int filterSize)
143 {
144 int i;
145 1889003 int32_t *dst = (int32_t *) _dst;
146
2/2
✓ Branch 0 taken 571506972 times.
✓ Branch 1 taken 1889003 times.
573395975 for (i = 0; i < dstW; i++) {
147 int j;
148 571506972 int srcPos = filterPos[i];
149 571506972 int val = 0;
150
2/2
✓ Branch 0 taken 1055363244 times.
✓ Branch 1 taken 571506972 times.
1626870216 for (j = 0; j < filterSize; j++) {
151 1055363244 val += ((int)src[srcPos + j]) * filter[filterSize * i + j];
152 }
153 571506972 dst[i] = FFMIN(val >> 3, (1 << 19) - 1); // the cubic equation does overflow ...
154 }
155 1889003 }
156
157 // FIXME all pal and rgb srcFormats could do this conversion as well
158 // FIXME all scalers more complex than bilinear could do half of this transform
159 485274 static void chrRangeToJpeg_c(int16_t *dstU, int16_t *dstV, int width)
160 {
161 int i;
162
2/2
✓ Branch 0 taken 115868488 times.
✓ Branch 1 taken 485274 times.
116353762 for (i = 0; i < width; i++) {
163 115868488 dstU[i] = (FFMIN(dstU[i], 30775) * 4663 - 9289992) >> 12; // -264
164 115868488 dstV[i] = (FFMIN(dstV[i], 30775) * 4663 - 9289992) >> 12; // -264
165 }
166 485274 }
167
168 285159 static void chrRangeFromJpeg_c(int16_t *dstU, int16_t *dstV, int width)
169 {
170 int i;
171
2/2
✓ Branch 0 taken 62727258 times.
✓ Branch 1 taken 285159 times.
63012417 for (i = 0; i < width; i++) {
172 62727258 dstU[i] = (dstU[i] * 1799 + 4081085) >> 11; // 1469
173 62727258 dstV[i] = (dstV[i] * 1799 + 4081085) >> 11; // 1469
174 }
175 285159 }
176
177 1247417 static void lumRangeToJpeg_c(int16_t *dst, int width)
178 {
179 int i;
180
2/2
✓ Branch 0 taken 430341192 times.
✓ Branch 1 taken 1247417 times.
431588609 for (i = 0; i < width; i++)
181 430341192 dst[i] = (FFMIN(dst[i], 30189) * 19077 - 39057361) >> 14;
182 1247417 }
183
184 612163 static void lumRangeFromJpeg_c(int16_t *dst, int width)
185 {
186 int i;
187
2/2
✓ Branch 0 taken 212685168 times.
✓ Branch 1 taken 612163 times.
213297331 for (i = 0; i < width; i++)
188 212685168 dst[i] = (dst[i] * 14071 + 33561947) >> 14;
189 612163 }
190
191 4 static void chrRangeToJpeg16_c(int16_t *_dstU, int16_t *_dstV, int width)
192 {
193 int i;
194 4 int32_t *dstU = (int32_t *) _dstU;
195 4 int32_t *dstV = (int32_t *) _dstV;
196
2/2
✓ Branch 0 taken 3856 times.
✓ Branch 1 taken 4 times.
3860 for (i = 0; i < width; i++) {
197 3856 dstU[i] = ((int)(FFMIN(dstU[i], 30775 << 4) * 4663U - (9289992 << 4))) >> 12; // -264
198 3856 dstV[i] = ((int)(FFMIN(dstV[i], 30775 << 4) * 4663U - (9289992 << 4))) >> 12; // -264
199 }
200 4 }
201
202 4 static void chrRangeFromJpeg16_c(int16_t *_dstU, int16_t *_dstV, int width)
203 {
204 int i;
205 4 int32_t *dstU = (int32_t *) _dstU;
206 4 int32_t *dstV = (int32_t *) _dstV;
207
2/2
✓ Branch 0 taken 3856 times.
✓ Branch 1 taken 4 times.
3860 for (i = 0; i < width; i++) {
208 3856 dstU[i] = (dstU[i] * 1799 + (4081085 << 4)) >> 11; // 1469
209 3856 dstV[i] = (dstV[i] * 1799 + (4081085 << 4)) >> 11; // 1469
210 }
211 4 }
212
213 205019 static void lumRangeToJpeg16_c(int16_t *_dst, int width)
214 {
215 int i;
216 205019 int32_t *dst = (int32_t *) _dst;
217
2/2
✓ Branch 0 taken 72097736 times.
✓ Branch 1 taken 205019 times.
72302755 for (i = 0; i < width; i++) {
218 72097736 dst[i] = ((int)(FFMIN(dst[i], 30189 << 4) * 4769U - (39057361 << 2))) >> 12;
219 }
220 205019 }
221
222 16592 static void lumRangeFromJpeg16_c(int16_t *_dst, int width)
223 {
224 int i;
225 16592 int32_t *dst = (int32_t *) _dst;
226
2/2
✓ Branch 0 taken 5842832 times.
✓ Branch 1 taken 16592 times.
5859424 for (i = 0; i < width; i++)
227 5842832 dst[i] = ((int)(dst[i]*(14071U/4) + (33561947<<4)/4)) >> 12;
228 16592 }
229
230
231 #define DEBUG_SWSCALE_BUFFERS 0
232 #define DEBUG_BUFFERS(...) \
233 if (DEBUG_SWSCALE_BUFFERS) \
234 av_log(c, AV_LOG_DEBUG, __VA_ARGS__)
235
236 406705 int ff_swscale(SwsInternal *c, const uint8_t *const src[], const int srcStride[],
237 int srcSliceY, int srcSliceH, uint8_t *const dst[],
238 const int dstStride[], int dstSliceY, int dstSliceH)
239 {
240
4/4
✓ Branch 0 taken 74900 times.
✓ Branch 1 taken 331805 times.
✓ Branch 2 taken 41493 times.
✓ Branch 3 taken 33407 times.
406705 const int scale_dst = dstSliceY > 0 || dstSliceH < c->dstH;
241
242 /* load a few things into local vars to make the code more readable?
243 * and faster */
244 406705 const int dstW = c->dstW;
245 406705 int dstH = c->dstH;
246
247 406705 const enum AVPixelFormat dstFormat = c->dstFormat;
248 406705 const int flags = c->flags;
249 406705 int32_t *vLumFilterPos = c->vLumFilterPos;
250 406705 int32_t *vChrFilterPos = c->vChrFilterPos;
251
252 406705 const int vLumFilterSize = c->vLumFilterSize;
253 406705 const int vChrFilterSize = c->vChrFilterSize;
254
255 406705 yuv2planar1_fn yuv2plane1 = c->yuv2plane1;
256 406705 yuv2planarX_fn yuv2planeX = c->yuv2planeX;
257 406705 yuv2interleavedX_fn yuv2nv12cX = c->yuv2nv12cX;
258 406705 yuv2packed1_fn yuv2packed1 = c->yuv2packed1;
259 406705 yuv2packed2_fn yuv2packed2 = c->yuv2packed2;
260 406705 yuv2packedX_fn yuv2packedX = c->yuv2packedX;
261 406705 yuv2anyX_fn yuv2anyX = c->yuv2anyX;
262 406705 const int chrSrcSliceY = srcSliceY >> c->chrSrcVSubSample;
263 406705 const int chrSrcSliceH = AV_CEIL_RSHIFT(srcSliceH, c->chrSrcVSubSample);
264
4/4
✓ Branch 1 taken 241631 times.
✓ Branch 2 taken 165074 times.
✓ Branch 3 taken 72959 times.
✓ Branch 4 taken 168672 times.
648336 int should_dither = isNBPS(c->srcFormat) ||
265 241631 is16BPS(c->srcFormat);
266 int lastDstY;
267
268 /* vars which will change and which we need to store back in the context */
269 406705 int dstY = c->dstY;
270 406705 int lastInLumBuf = c->lastInLumBuf;
271 406705 int lastInChrBuf = c->lastInChrBuf;
272
273 406705 int lumStart = 0;
274 406705 int lumEnd = c->descIndex[0];
275 406705 int chrStart = lumEnd;
276 406705 int chrEnd = c->descIndex[1];
277 406705 int vStart = chrEnd;
278 406705 int vEnd = c->numDesc;
279 406705 SwsSlice *src_slice = &c->slice[lumStart];
280 406705 SwsSlice *hout_slice = &c->slice[c->numSlice-2];
281 406705 SwsSlice *vout_slice = &c->slice[c->numSlice-1];
282 406705 SwsFilterDescriptor *desc = c->desc;
283
284 406705 int needAlpha = c->needAlpha;
285
286 406705 int hasLumHoles = 1;
287 406705 int hasChrHoles = 1;
288
289 const uint8_t *src2[4];
290 int srcStride2[4];
291
292
2/2
✓ Branch 1 taken 95564 times.
✓ Branch 2 taken 311141 times.
406705 if (isPacked(c->srcFormat)) {
293 95564 src2[0] =
294 95564 src2[1] =
295 95564 src2[2] =
296 95564 src2[3] = src[0];
297 95564 srcStride2[0] =
298 95564 srcStride2[1] =
299 95564 srcStride2[2] =
300 95564 srcStride2[3] = srcStride[0];
301 } else {
302 311141 memcpy(src2, src, sizeof(src2));
303 311141 memcpy(srcStride2, srcStride, sizeof(srcStride2));
304 }
305
306 406705 srcStride2[1] *= 1 << c->vChrDrop;
307 406705 srcStride2[2] *= 1 << c->vChrDrop;
308
309 DEBUG_BUFFERS("swscale() %p[%d] %p[%d] %p[%d] %p[%d] -> %p[%d] %p[%d] %p[%d] %p[%d]\n",
310 src2[0], srcStride2[0], src2[1], srcStride2[1],
311 src2[2], srcStride2[2], src2[3], srcStride2[3],
312 dst[0], dstStride[0], dst[1], dstStride[1],
313 dst[2], dstStride[2], dst[3], dstStride[3]);
314 DEBUG_BUFFERS("srcSliceY: %d srcSliceH: %d dstY: %d dstH: %d\n",
315 srcSliceY, srcSliceH, dstY, dstH);
316 DEBUG_BUFFERS("vLumFilterSize: %d vChrFilterSize: %d\n",
317 vLumFilterSize, vChrFilterSize);
318
319
4/4
✓ Branch 0 taken 401702 times.
✓ Branch 1 taken 5003 times.
✓ Branch 2 taken 391846 times.
✓ Branch 3 taken 9856 times.
406705 if (dstStride[0]&15 || dstStride[1]&15 ||
320
2/4
✓ Branch 0 taken 391846 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 391846 times.
391846 dstStride[2]&15 || dstStride[3]&15) {
321
2/2
✓ Branch 0 taken 8496 times.
✓ Branch 1 taken 6363 times.
14859 SwsInternal *const ctx = c->parent ? sws_internal(c->parent) : c;
322
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 14859 times.
14859 if (flags & SWS_PRINT_INFO &&
323 !atomic_exchange_explicit(&ctx->stride_unaligned_warned, 1, memory_order_relaxed)) {
324 av_log(c, AV_LOG_WARNING,
325 "Warning: dstStride is not aligned!\n"
326 " ->cannot do aligned memory accesses anymore\n");
327 }
328 }
329
330 #if ARCH_X86
331
5/6
✓ Branch 0 taken 404297 times.
✓ Branch 1 taken 2408 times.
✓ Branch 2 taken 402614 times.
✓ Branch 3 taken 1683 times.
✓ Branch 4 taken 402614 times.
✗ Branch 5 not taken.
406705 if ( (uintptr_t) dst[0]&15 || (uintptr_t) dst[1]&15 || (uintptr_t) dst[2]&15
332
5/6
✓ Branch 0 taken 402599 times.
✓ Branch 1 taken 15 times.
✓ Branch 2 taken 399789 times.
✓ Branch 3 taken 2810 times.
✓ Branch 4 taken 399789 times.
✗ Branch 5 not taken.
402614 || (uintptr_t)src2[0]&15 || (uintptr_t)src2[1]&15 || (uintptr_t)src2[2]&15
333
6/8
✓ Branch 0 taken 396289 times.
✓ Branch 1 taken 3500 times.
✓ Branch 2 taken 388540 times.
✓ Branch 3 taken 7749 times.
✓ Branch 4 taken 388540 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 388540 times.
✗ Branch 7 not taken.
399789 || dstStride[0]&15 || dstStride[1]&15 || dstStride[2]&15 || dstStride[3]&15
334
6/8
✓ Branch 0 taken 388535 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 384789 times.
✓ Branch 3 taken 3746 times.
✓ Branch 4 taken 384789 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 384789 times.
388540 || srcStride2[0]&15 || srcStride2[1]&15 || srcStride2[2]&15 || srcStride2[3]&15
335 ) {
336
2/2
✓ Branch 0 taken 14571 times.
✓ Branch 1 taken 7345 times.
21916 SwsInternal *const ctx = c->parent ? sws_internal(c->parent) : c;
337 21916 int cpu_flags = av_get_cpu_flags();
338
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 21916 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
21916 if (flags & SWS_PRINT_INFO && HAVE_MMXEXT && (cpu_flags & AV_CPU_FLAG_SSE2) &&
339 !atomic_exchange_explicit(&ctx->stride_unaligned_warned,1, memory_order_relaxed)) {
340 av_log(c, AV_LOG_WARNING, "Warning: data is not aligned! This can lead to a speed loss\n");
341 }
342 }
343 #endif
344
345
2/2
✓ Branch 0 taken 373298 times.
✓ Branch 1 taken 33407 times.
406705 if (scale_dst) {
346 373298 dstY = dstSliceY;
347 373298 dstH = dstY + dstSliceH;
348 373298 lastInLumBuf = -1;
349 373298 lastInChrBuf = -1;
350
2/2
✓ Branch 0 taken 33356 times.
✓ Branch 1 taken 51 times.
33407 } else if (srcSliceY == 0) {
351 /* Note the user might start scaling the picture in the middle so this
352 * will not get executed. This is not really intended but works
353 * currently, so people might do it. */
354 33356 dstY = 0;
355 33356 lastInLumBuf = -1;
356 33356 lastInChrBuf = -1;
357 }
358
359
2/2
✓ Branch 0 taken 168672 times.
✓ Branch 1 taken 238033 times.
406705 if (!should_dither) {
360 168672 c->chrDither8 = c->lumDither8 = sws_pb_64;
361 }
362 406705 lastDstY = dstY;
363
364 406705 ff_init_vscale_pfn(c, yuv2plane1, yuv2planeX, yuv2nv12cX,
365 yuv2packed1, yuv2packed2, yuv2packedX, yuv2anyX, c->use_mmx_vfilter);
366
367 406705 ff_init_slice_from_src(src_slice, (uint8_t**)src2, srcStride2, c->srcW,
368 srcSliceY, srcSliceH, chrSrcSliceY, chrSrcSliceH, 1);
369
370 406705 ff_init_slice_from_src(vout_slice, (uint8_t**)dst, dstStride, c->dstW,
371 406705 dstY, dstSliceH, dstY >> c->chrDstVSubSample,
372 406705 AV_CEIL_RSHIFT(dstSliceH, c->chrDstVSubSample), scale_dst);
373
2/2
✓ Branch 0 taken 406654 times.
✓ Branch 1 taken 51 times.
406705 if (srcSliceY == 0) {
374 406654 hout_slice->plane[0].sliceY = lastInLumBuf + 1;
375 406654 hout_slice->plane[1].sliceY = lastInChrBuf + 1;
376 406654 hout_slice->plane[2].sliceY = lastInChrBuf + 1;
377 406654 hout_slice->plane[3].sliceY = lastInLumBuf + 1;
378
379 406654 hout_slice->plane[0].sliceH =
380 406654 hout_slice->plane[1].sliceH =
381 406654 hout_slice->plane[2].sliceH =
382 406654 hout_slice->plane[3].sliceH = 0;
383 406654 hout_slice->width = dstW;
384 }
385
386
2/2
✓ Branch 0 taken 22621742 times.
✓ Branch 1 taken 406654 times.
23028396 for (; dstY < dstH; dstY++) {
387 22621742 const int chrDstY = dstY >> c->chrDstVSubSample;
388 22621742 int use_mmx_vfilter= c->use_mmx_vfilter;
389
390 // First line needed as input
391 22621742 const int firstLumSrcY = FFMAX(1 - vLumFilterSize, vLumFilterPos[dstY]);
392
2/2
✓ Branch 0 taken 100 times.
✓ Branch 1 taken 22621642 times.
22621742 const int firstLumSrcY2 = FFMAX(1 - vLumFilterSize, vLumFilterPos[FFMIN(dstY | ((1 << c->chrDstVSubSample) - 1), c->dstH - 1)]);
393 // First line needed as input
394 22621742 const int firstChrSrcY = FFMAX(1 - vChrFilterSize, vChrFilterPos[chrDstY]);
395
396 // Last line needed as input
397 22621742 int lastLumSrcY = FFMIN(c->srcH, firstLumSrcY + vLumFilterSize) - 1;
398 22621742 int lastLumSrcY2 = FFMIN(c->srcH, firstLumSrcY2 + vLumFilterSize) - 1;
399 22621742 int lastChrSrcY = FFMIN(c->chrSrcH, firstChrSrcY + vChrFilterSize) - 1;
400 int enough_lines;
401
402 int i;
403 int posY, cPosY, firstPosY, lastPosY, firstCPosY, lastCPosY;
404
405 // handle holes (FAST_BILINEAR & weird filters)
406
2/2
✓ Branch 0 taken 18796275 times.
✓ Branch 1 taken 3825467 times.
22621742 if (firstLumSrcY > lastInLumBuf) {
407
408 18796275 hasLumHoles = lastInLumBuf != firstLumSrcY - 1;
409
2/2
✓ Branch 0 taken 515905 times.
✓ Branch 1 taken 18280370 times.
18796275 if (hasLumHoles) {
410 515905 hout_slice->plane[0].sliceY = firstLumSrcY;
411 515905 hout_slice->plane[3].sliceY = firstLumSrcY;
412 515905 hout_slice->plane[0].sliceH =
413 515905 hout_slice->plane[3].sliceH = 0;
414 }
415
416 18796275 lastInLumBuf = firstLumSrcY - 1;
417 }
418
2/2
✓ Branch 0 taken 9555286 times.
✓ Branch 1 taken 13066456 times.
22621742 if (firstChrSrcY > lastInChrBuf) {
419
420 9555286 hasChrHoles = lastInChrBuf != firstChrSrcY - 1;
421
2/2
✓ Branch 0 taken 652455 times.
✓ Branch 1 taken 8902831 times.
9555286 if (hasChrHoles) {
422 652455 hout_slice->plane[1].sliceY = firstChrSrcY;
423 652455 hout_slice->plane[2].sliceY = firstChrSrcY;
424 652455 hout_slice->plane[1].sliceH =
425 652455 hout_slice->plane[2].sliceH = 0;
426 }
427
428 9555286 lastInChrBuf = firstChrSrcY - 1;
429 }
430
431 DEBUG_BUFFERS("dstY: %d\n", dstY);
432 DEBUG_BUFFERS("\tfirstLumSrcY: %d lastLumSrcY: %d lastInLumBuf: %d\n",
433 firstLumSrcY, lastLumSrcY, lastInLumBuf);
434 DEBUG_BUFFERS("\tfirstChrSrcY: %d lastChrSrcY: %d lastInChrBuf: %d\n",
435 firstChrSrcY, lastChrSrcY, lastInChrBuf);
436
437 // Do we have enough lines in this slice to output the dstY line
438
2/2
✓ Branch 0 taken 22621697 times.
✓ Branch 1 taken 45 times.
45243439 enough_lines = lastLumSrcY2 < srcSliceY + srcSliceH &&
439
2/2
✓ Branch 0 taken 22621691 times.
✓ Branch 1 taken 6 times.
22621697 lastChrSrcY < AV_CEIL_RSHIFT(srcSliceY + srcSliceH, c->chrSrcVSubSample);
440
441
2/2
✓ Branch 0 taken 51 times.
✓ Branch 1 taken 22621691 times.
22621742 if (!enough_lines) {
442 51 lastLumSrcY = srcSliceY + srcSliceH - 1;
443 51 lastChrSrcY = chrSrcSliceY + chrSrcSliceH - 1;
444 DEBUG_BUFFERS("buffering slice: lastLumSrcY %d lastChrSrcY %d\n",
445 lastLumSrcY, lastChrSrcY);
446 }
447
448
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 22621742 times.
22621742 av_assert0((lastLumSrcY - firstLumSrcY + 1) <= hout_slice->plane[0].available_lines);
449
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 22621742 times.
22621742 av_assert0((lastChrSrcY - firstChrSrcY + 1) <= hout_slice->plane[1].available_lines);
450
451
452 22621742 posY = hout_slice->plane[0].sliceY + hout_slice->plane[0].sliceH;
453
4/4
✓ Branch 0 taken 4487384 times.
✓ Branch 1 taken 18134358 times.
✓ Branch 2 taken 3694794 times.
✓ Branch 3 taken 792590 times.
22621742 if (posY <= lastLumSrcY && !hasLumHoles) {
454 3694794 firstPosY = FFMAX(firstLumSrcY, posY);
455
2/2
✓ Branch 0 taken 60454 times.
✓ Branch 1 taken 3634340 times.
3694794 lastPosY = FFMIN(firstLumSrcY + hout_slice->plane[0].available_lines - 1, srcSliceY + srcSliceH - 1);
456 } else {
457 18926948 firstPosY = posY;
458 18926948 lastPosY = lastLumSrcY;
459 }
460
461 22621742 cPosY = hout_slice->plane[1].sliceY + hout_slice->plane[1].sliceH;
462
4/4
✓ Branch 0 taken 4935735 times.
✓ Branch 1 taken 17686007 times.
✓ Branch 2 taken 2720932 times.
✓ Branch 3 taken 2214803 times.
22621742 if (cPosY <= lastChrSrcY && !hasChrHoles) {
463 2720932 firstCPosY = FFMAX(firstChrSrcY, cPosY);
464 2720932 lastCPosY = FFMIN(firstChrSrcY + hout_slice->plane[1].available_lines - 1, AV_CEIL_RSHIFT(srcSliceY + srcSliceH, c->chrSrcVSubSample) - 1);
465 } else {
466 19900810 firstCPosY = cPosY;
467 19900810 lastCPosY = lastChrSrcY;
468 }
469
470 22621742 ff_rotate_slice(hout_slice, lastPosY, lastCPosY);
471
472
2/2
✓ Branch 0 taken 4487384 times.
✓ Branch 1 taken 18134358 times.
22621742 if (posY < lastLumSrcY + 1) {
473
2/2
✓ Branch 0 taken 6395235 times.
✓ Branch 1 taken 4487384 times.
10882619 for (i = lumStart; i < lumEnd; ++i)
474 6395235 desc[i].process(c, &desc[i], firstPosY, lastPosY - firstPosY + 1);
475 }
476
477 22621742 lastInLumBuf = lastLumSrcY;
478
479
2/2
✓ Branch 0 taken 4935735 times.
✓ Branch 1 taken 17686007 times.
22621742 if (cPosY < lastChrSrcY + 1) {
480
2/2
✓ Branch 0 taken 7419704 times.
✓ Branch 1 taken 4935735 times.
12355439 for (i = chrStart; i < chrEnd; ++i)
481 7419704 desc[i].process(c, &desc[i], firstCPosY, lastCPosY - firstCPosY + 1);
482 }
483
484 22621742 lastInChrBuf = lastChrSrcY;
485
486
2/2
✓ Branch 0 taken 51 times.
✓ Branch 1 taken 22621691 times.
22621742 if (!enough_lines)
487 51 break; // we can't output a dstY line so let's try with the next slice
488
489 #if HAVE_MMX_INLINE
490 22621691 ff_updateMMXDitherTables(c, dstY);
491 22621691 c->dstW_mmx = c->dstW;
492 #endif
493
2/2
✓ Branch 0 taken 10381362 times.
✓ Branch 1 taken 12240329 times.
22621691 if (should_dither) {
494 10381362 c->chrDither8 = ff_dither_8x8_128[chrDstY & 7];
495 10381362 c->lumDither8 = ff_dither_8x8_128[dstY & 7];
496 }
497
2/2
✓ Branch 0 taken 149698 times.
✓ Branch 1 taken 22471993 times.
22621691 if (dstY >= c->dstH - 2) {
498 /* hmm looks like we can't use MMX here without overwriting
499 * this array's tail */
500 149698 ff_sws_init_output_funcs(c, &yuv2plane1, &yuv2planeX, &yuv2nv12cX,
501 &yuv2packed1, &yuv2packed2, &yuv2packedX, &yuv2anyX);
502 149698 use_mmx_vfilter= 0;
503 149698 ff_init_vscale_pfn(c, yuv2plane1, yuv2planeX, yuv2nv12cX,
504 yuv2packed1, yuv2packed2, yuv2packedX, yuv2anyX, use_mmx_vfilter);
505 }
506
507
2/2
✓ Branch 0 taken 36898689 times.
✓ Branch 1 taken 22621691 times.
59520380 for (i = vStart; i < vEnd; ++i)
508 36898689 desc[i].process(c, &desc[i], dstY, 1);
509 }
510
6/6
✓ Branch 1 taken 289403 times.
✓ Branch 2 taken 117302 times.
✓ Branch 4 taken 8173 times.
✓ Branch 5 taken 281230 times.
✓ Branch 6 taken 6438 times.
✓ Branch 7 taken 1735 times.
406705 if (isPlanar(dstFormat) && isALPHA(dstFormat) && !needAlpha) {
511 6438 int offset = lastDstY - dstSliceY;
512 6438 int length = dstW;
513 6438 int height = dstY - lastDstY;
514
515
4/4
✓ Branch 1 taken 6082 times.
✓ Branch 2 taken 356 times.
✓ Branch 4 taken 424 times.
✓ Branch 5 taken 5658 times.
7218 if (is16BPS(dstFormat) || isNBPS(dstFormat)) {
516 780 const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(dstFormat);
517 780 fillPlane16(dst[3], dstStride[3], length, height, offset,
518 780 1, desc->comp[3].depth,
519 isBE(dstFormat));
520
2/2
✓ Branch 1 taken 92 times.
✓ Branch 2 taken 5566 times.
5658 } else if (is32BPS(dstFormat)) {
521 92 const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(dstFormat);
522 184 fillPlane32(dst[3], dstStride[3], length, height, offset,
523 92 1, desc->comp[3].depth,
524 92 isBE(dstFormat), desc->flags & AV_PIX_FMT_FLAG_FLOAT);
525 } else
526 5566 fillPlane(dst[3], dstStride[3], length, height, offset, 255);
527 }
528
529 #if HAVE_MMXEXT_INLINE
530
2/2
✓ Branch 1 taken 133 times.
✓ Branch 2 taken 406572 times.
406705 if (av_get_cpu_flags() & AV_CPU_FLAG_MMXEXT)
531 133 __asm__ volatile ("sfence" ::: "memory");
532 #endif
533 406705 emms_c();
534
535 /* store changed local vars back in the context */
536 406705 c->dstY = dstY;
537 406705 c->lastInLumBuf = lastInLumBuf;
538 406705 c->lastInChrBuf = lastInChrBuf;
539
540 406705 return dstY - lastDstY;
541 }
542
543 53129 av_cold void ff_sws_init_range_convert(SwsInternal *c)
544 {
545 53129 c->lumConvertRange = NULL;
546 53129 c->chrConvertRange = NULL;
547
4/4
✓ Branch 0 taken 4966 times.
✓ Branch 1 taken 48163 times.
✓ Branch 3 taken 3620 times.
✓ Branch 4 taken 1346 times.
53129 if (c->srcRange != c->dstRange && !isAnyRGB(c->dstFormat)) {
548
2/2
✓ Branch 0 taken 3307 times.
✓ Branch 1 taken 313 times.
3620 if (c->dstBpc <= 14) {
549
2/2
✓ Branch 0 taken 904 times.
✓ Branch 1 taken 2403 times.
3307 if (c->srcRange) {
550 904 c->lumConvertRange = lumRangeFromJpeg_c;
551 904 c->chrConvertRange = chrRangeFromJpeg_c;
552 } else {
553 2403 c->lumConvertRange = lumRangeToJpeg_c;
554 2403 c->chrConvertRange = chrRangeToJpeg_c;
555 }
556 } else {
557
2/2
✓ Branch 0 taken 44 times.
✓ Branch 1 taken 269 times.
313 if (c->srcRange) {
558 44 c->lumConvertRange = lumRangeFromJpeg16_c;
559 44 c->chrConvertRange = chrRangeFromJpeg16_c;
560 } else {
561 269 c->lumConvertRange = lumRangeToJpeg16_c;
562 269 c->chrConvertRange = chrRangeToJpeg16_c;
563 }
564 }
565
566 #if ARCH_AARCH64
567 ff_sws_init_range_convert_aarch64(c);
568 #elif ARCH_LOONGARCH64
569 ff_sws_init_range_convert_loongarch(c);
570 #elif ARCH_RISCV
571 ff_sws_init_range_convert_riscv(c);
572 #elif ARCH_X86
573 3620 ff_sws_init_range_convert_x86(c);
574 #endif
575 }
576 53129 }
577
578 30303 static av_cold void sws_init_swscale(SwsInternal *c)
579 {
580 30303 enum AVPixelFormat srcFormat = c->srcFormat;
581
582 30303 ff_sws_init_output_funcs(c, &c->yuv2plane1, &c->yuv2planeX,
583 &c->yuv2nv12cX, &c->yuv2packed1,
584 &c->yuv2packed2, &c->yuv2packedX, &c->yuv2anyX);
585
586 30303 ff_sws_init_input_funcs(c, &c->lumToYV12, &c->alpToYV12, &c->chrToYV12,
587 &c->readLumPlanar, &c->readAlpPlanar, &c->readChrPlanar);
588
589
2/2
✓ Branch 0 taken 18267 times.
✓ Branch 1 taken 12036 times.
30303 if (c->srcBpc == 8) {
590
2/2
✓ Branch 0 taken 16818 times.
✓ Branch 1 taken 1449 times.
18267 if (c->dstBpc <= 14) {
591 16818 c->hyScale = c->hcScale = hScale8To15_c;
592
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 16818 times.
16818 if (c->flags & SWS_FAST_BILINEAR) {
593 c->hyscale_fast = ff_hyscale_fast_c;
594 c->hcscale_fast = ff_hcscale_fast_c;
595 }
596 } else {
597 1449 c->hyScale = c->hcScale = hScale8To19_c;
598 }
599 } else {
600 12036 c->hyScale = c->hcScale = c->dstBpc > 14 ? hScale16To19_c
601
2/2
✓ Branch 0 taken 2514 times.
✓ Branch 1 taken 9522 times.
12036 : hScale16To15_c;
602 }
603
604 30303 ff_sws_init_range_convert(c);
605
606
8/8
✓ Branch 1 taken 29584 times.
✓ Branch 2 taken 719 times.
✓ Branch 4 taken 28759 times.
✓ Branch 5 taken 825 times.
✓ Branch 6 taken 28685 times.
✓ Branch 7 taken 74 times.
✓ Branch 8 taken 28607 times.
✓ Branch 9 taken 78 times.
30303 if (!(isGray(srcFormat) || isGray(c->dstFormat) ||
607 srcFormat == AV_PIX_FMT_MONOBLACK || srcFormat == AV_PIX_FMT_MONOWHITE))
608 28607 c->needs_hcscale = 1;
609 30303 }
610
611 30303 void ff_sws_init_scale(SwsInternal *c)
612 {
613 30303 sws_init_swscale(c);
614
615 #if ARCH_PPC
616 ff_sws_init_swscale_ppc(c);
617 #elif ARCH_X86
618 30303 ff_sws_init_swscale_x86(c);
619 #elif ARCH_AARCH64
620 ff_sws_init_swscale_aarch64(c);
621 #elif ARCH_ARM
622 ff_sws_init_swscale_arm(c);
623 #elif ARCH_LOONGARCH64
624 ff_sws_init_swscale_loongarch(c);
625 #elif ARCH_RISCV
626 ff_sws_init_swscale_riscv(c);
627 #endif
628 30303 }
629
630 972406 static void reset_ptr(const uint8_t *src[], enum AVPixelFormat format)
631 {
632
2/2
✓ Branch 1 taken 899086 times.
✓ Branch 2 taken 73320 times.
972406 if (!isALPHA(format))
633 899086 src[3] = NULL;
634
2/2
✓ Branch 1 taken 344665 times.
✓ Branch 2 taken 627741 times.
972406 if (!isPlanar(format)) {
635 344665 src[3] = src[2] = NULL;
636
637
2/2
✓ Branch 1 taken 303175 times.
✓ Branch 2 taken 41490 times.
344665 if (!usePal(format))
638 303175 src[1] = NULL;
639 }
640 972406 }
641
642 972424 static int check_image_pointers(const uint8_t * const data[4], enum AVPixelFormat pix_fmt,
643 const int linesizes[4])
644 {
645 972424 const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt);
646 int i;
647
648 av_assert2(desc);
649
650
2/2
✓ Branch 0 taken 3889696 times.
✓ Branch 1 taken 972424 times.
4862120 for (i = 0; i < 4; i++) {
651 3889696 int plane = desc->comp[i].plane;
652
2/4
✓ Branch 0 taken 3889696 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3889696 times.
3889696 if (!data[plane] || !linesizes[plane])
653 return 0;
654 }
655
656 972424 return 1;
657 }
658
659 1875 void ff_xyz12Torgb48(const SwsInternal *c, uint8_t *dst, int dst_stride,
660 const uint8_t *src, int src_stride, int w, int h)
661 {
662 1875 const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->srcFormat);
663
664
2/2
✓ Branch 0 taken 540000 times.
✓ Branch 1 taken 1875 times.
541875 for (int yp = 0; yp < h; yp++) {
665 540000 const uint16_t *src16 = (const uint16_t *) src;
666 540000 uint16_t *dst16 = (uint16_t *) dst;
667
668
2/2
✓ Branch 0 taken 190080000 times.
✓ Branch 1 taken 540000 times.
190620000 for (int xp = 0; xp < 3 * w; xp += 3) {
669 int x, y, z, r, g, b;
670
671
2/2
✓ Branch 0 taken 101376 times.
✓ Branch 1 taken 189978624 times.
190080000 if (desc->flags & AV_PIX_FMT_FLAG_BE) {
672 101376 x = AV_RB16(src16 + xp + 0);
673 101376 y = AV_RB16(src16 + xp + 1);
674 101376 z = AV_RB16(src16 + xp + 2);
675 } else {
676 189978624 x = AV_RL16(src16 + xp + 0);
677 189978624 y = AV_RL16(src16 + xp + 1);
678 189978624 z = AV_RL16(src16 + xp + 2);
679 }
680
681 190080000 x = c->xyzgamma[x >> 4];
682 190080000 y = c->xyzgamma[y >> 4];
683 190080000 z = c->xyzgamma[z >> 4];
684
685 // convert from XYZlinear to sRGBlinear
686 190080000 r = c->xyz2rgb_matrix[0][0] * x +
687 190080000 c->xyz2rgb_matrix[0][1] * y +
688 190080000 c->xyz2rgb_matrix[0][2] * z >> 12;
689 190080000 g = c->xyz2rgb_matrix[1][0] * x +
690 190080000 c->xyz2rgb_matrix[1][1] * y +
691 190080000 c->xyz2rgb_matrix[1][2] * z >> 12;
692 190080000 b = c->xyz2rgb_matrix[2][0] * x +
693 190080000 c->xyz2rgb_matrix[2][1] * y +
694 190080000 c->xyz2rgb_matrix[2][2] * z >> 12;
695
696 // limit values to 12-bit depth
697 190080000 r = av_clip_uintp2(r, 12);
698 190080000 g = av_clip_uintp2(g, 12);
699 190080000 b = av_clip_uintp2(b, 12);
700
701 // convert from sRGBlinear to RGB and scale from 12bit to 16bit
702
2/2
✓ Branch 0 taken 101376 times.
✓ Branch 1 taken 189978624 times.
190080000 if (desc->flags & AV_PIX_FMT_FLAG_BE) {
703 101376 AV_WB16(dst16 + xp + 0, c->rgbgamma[r] << 4);
704 101376 AV_WB16(dst16 + xp + 1, c->rgbgamma[g] << 4);
705 101376 AV_WB16(dst16 + xp + 2, c->rgbgamma[b] << 4);
706 } else {
707 189978624 AV_WL16(dst16 + xp + 0, c->rgbgamma[r] << 4);
708 189978624 AV_WL16(dst16 + xp + 1, c->rgbgamma[g] << 4);
709 189978624 AV_WL16(dst16 + xp + 2, c->rgbgamma[b] << 4);
710 }
711 }
712
713 540000 src += src_stride;
714 540000 dst += dst_stride;
715 }
716 1875 }
717
718 1916 void ff_rgb48Toxyz12(const SwsInternal *c, uint8_t *dst, int dst_stride,
719 const uint8_t *src, int src_stride, int w, int h)
720 {
721 1916 const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->dstFormat);
722
723
2/2
✓ Branch 0 taken 72200 times.
✓ Branch 1 taken 1916 times.
74116 for (int yp = 0; yp < h; yp++) {
724 72200 uint16_t *src16 = (uint16_t *) src;
725 72200 uint16_t *dst16 = (uint16_t *) dst;
726
727
2/2
✓ Branch 0 taken 25384000 times.
✓ Branch 1 taken 72200 times.
25456200 for (int xp = 0; xp < 3 * w; xp += 3) {
728 int x, y, z, r, g, b;
729
730
2/2
✓ Branch 0 taken 2047520 times.
✓ Branch 1 taken 23336480 times.
25384000 if (desc->flags & AV_PIX_FMT_FLAG_BE) {
731 2047520 r = AV_RB16(src16 + xp + 0);
732 2047520 g = AV_RB16(src16 + xp + 1);
733 2047520 b = AV_RB16(src16 + xp + 2);
734 } else {
735 23336480 r = AV_RL16(src16 + xp + 0);
736 23336480 g = AV_RL16(src16 + xp + 1);
737 23336480 b = AV_RL16(src16 + xp + 2);
738 }
739
740 25384000 r = c->rgbgammainv[r>>4];
741 25384000 g = c->rgbgammainv[g>>4];
742 25384000 b = c->rgbgammainv[b>>4];
743
744 // convert from sRGBlinear to XYZlinear
745 25384000 x = c->rgb2xyz_matrix[0][0] * r +
746 25384000 c->rgb2xyz_matrix[0][1] * g +
747 25384000 c->rgb2xyz_matrix[0][2] * b >> 12;
748 25384000 y = c->rgb2xyz_matrix[1][0] * r +
749 25384000 c->rgb2xyz_matrix[1][1] * g +
750 25384000 c->rgb2xyz_matrix[1][2] * b >> 12;
751 25384000 z = c->rgb2xyz_matrix[2][0] * r +
752 25384000 c->rgb2xyz_matrix[2][1] * g +
753 25384000 c->rgb2xyz_matrix[2][2] * b >> 12;
754
755 // limit values to 12-bit depth
756 25384000 x = av_clip_uintp2(x, 12);
757 25384000 y = av_clip_uintp2(y, 12);
758 25384000 z = av_clip_uintp2(z, 12);
759
760 // convert from XYZlinear to X'Y'Z' and scale from 12bit to 16bit
761
2/2
✓ Branch 0 taken 2047520 times.
✓ Branch 1 taken 23336480 times.
25384000 if (desc->flags & AV_PIX_FMT_FLAG_BE) {
762 2047520 AV_WB16(dst16 + xp + 0, c->xyzgammainv[x] << 4);
763 2047520 AV_WB16(dst16 + xp + 1, c->xyzgammainv[y] << 4);
764 2047520 AV_WB16(dst16 + xp + 2, c->xyzgammainv[z] << 4);
765 } else {
766 23336480 AV_WL16(dst16 + xp + 0, c->xyzgammainv[x] << 4);
767 23336480 AV_WL16(dst16 + xp + 1, c->xyzgammainv[y] << 4);
768 23336480 AV_WL16(dst16 + xp + 2, c->xyzgammainv[z] << 4);
769 }
770 }
771
772 72200 src += src_stride;
773 72200 dst += dst_stride;
774 }
775 1916 }
776
777 35173 void ff_update_palette(SwsInternal *c, const uint32_t *pal)
778 {
779
2/2
✓ Branch 0 taken 9004288 times.
✓ Branch 1 taken 35173 times.
9039461 for (int i = 0; i < 256; i++) {
780 9004288 int r, g, b, y, u, v, a = 0xff;
781
2/2
✓ Branch 0 taken 8518656 times.
✓ Branch 1 taken 485632 times.
9004288 if (c->srcFormat == AV_PIX_FMT_PAL8) {
782 8518656 uint32_t p = pal[i];
783 8518656 a = (p >> 24) & 0xFF;
784 8518656 r = (p >> 16) & 0xFF;
785 8518656 g = (p >> 8) & 0xFF;
786 8518656 b = p & 0xFF;
787
2/2
✓ Branch 0 taken 256 times.
✓ Branch 1 taken 485376 times.
485632 } else if (c->srcFormat == AV_PIX_FMT_RGB8) {
788 256 r = ( i >> 5 ) * 36;
789 256 g = ((i >> 2) & 7) * 36;
790 256 b = ( i & 3) * 85;
791
2/2
✓ Branch 0 taken 256 times.
✓ Branch 1 taken 485120 times.
485376 } else if (c->srcFormat == AV_PIX_FMT_BGR8) {
792 256 b = ( i >> 6 ) * 85;
793 256 g = ((i >> 3) & 7) * 36;
794 256 r = ( i & 7) * 36;
795
2/2
✓ Branch 0 taken 256 times.
✓ Branch 1 taken 484864 times.
485120 } else if (c->srcFormat == AV_PIX_FMT_RGB4_BYTE) {
796 256 r = ( i >> 3 ) * 255;
797 256 g = ((i >> 1) & 3) * 85;
798 256 b = ( i & 1) * 255;
799
3/4
✓ Branch 0 taken 256 times.
✓ Branch 1 taken 484608 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 256 times.
484864 } else if (c->srcFormat == AV_PIX_FMT_GRAY8 || c->srcFormat == AV_PIX_FMT_GRAY8A) {
800 484608 r = g = b = i;
801 } else {
802 av_assert1(c->srcFormat == AV_PIX_FMT_BGR4_BYTE);
803 256 b = ( i >> 3 ) * 255;
804 256 g = ((i >> 1) & 3) * 85;
805 256 r = ( i & 1) * 255;
806 }
807 #define RGB2YUV_SHIFT 15
808 #define BY ( (int) (0.114 * 219 / 255 * (1 << RGB2YUV_SHIFT) + 0.5))
809 #define BV (-(int) (0.081 * 224 / 255 * (1 << RGB2YUV_SHIFT) + 0.5))
810 #define BU ( (int) (0.500 * 224 / 255 * (1 << RGB2YUV_SHIFT) + 0.5))
811 #define GY ( (int) (0.587 * 219 / 255 * (1 << RGB2YUV_SHIFT) + 0.5))
812 #define GV (-(int) (0.419 * 224 / 255 * (1 << RGB2YUV_SHIFT) + 0.5))
813 #define GU (-(int) (0.331 * 224 / 255 * (1 << RGB2YUV_SHIFT) + 0.5))
814 #define RY ( (int) (0.299 * 219 / 255 * (1 << RGB2YUV_SHIFT) + 0.5))
815 #define RV ( (int) (0.500 * 224 / 255 * (1 << RGB2YUV_SHIFT) + 0.5))
816 #define RU (-(int) (0.169 * 224 / 255 * (1 << RGB2YUV_SHIFT) + 0.5))
817
818 9004288 y = av_clip_uint8((RY * r + GY * g + BY * b + ( 33 << (RGB2YUV_SHIFT - 1))) >> RGB2YUV_SHIFT);
819 9004288 u = av_clip_uint8((RU * r + GU * g + BU * b + (257 << (RGB2YUV_SHIFT - 1))) >> RGB2YUV_SHIFT);
820 9004288 v = av_clip_uint8((RV * r + GV * g + BV * b + (257 << (RGB2YUV_SHIFT - 1))) >> RGB2YUV_SHIFT);
821 9004288 c->pal_yuv[i]= y + (u<<8) + (v<<16) + ((unsigned)a<<24);
822
823
2/4
✓ Branch 0 taken 7690496 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1313792 times.
9004288 switch (c->dstFormat) {
824 7690496 case AV_PIX_FMT_BGR32:
825 #if !HAVE_BIGENDIAN
826 case AV_PIX_FMT_RGB24:
827 #endif
828 7690496 c->pal_rgb[i]= r + (g<<8) + (b<<16) + ((unsigned)a<<24);
829 7690496 break;
830 case AV_PIX_FMT_BGR32_1:
831 #if HAVE_BIGENDIAN
832 case AV_PIX_FMT_BGR24:
833 #endif
834 c->pal_rgb[i]= a + (r<<8) + (g<<16) + ((unsigned)b<<24);
835 break;
836 case AV_PIX_FMT_RGB32_1:
837 #if HAVE_BIGENDIAN
838 case AV_PIX_FMT_RGB24:
839 #endif
840 c->pal_rgb[i]= a + (b<<8) + (g<<16) + ((unsigned)r<<24);
841 break;
842 1313792 case AV_PIX_FMT_RGB32:
843 #if !HAVE_BIGENDIAN
844 case AV_PIX_FMT_BGR24:
845 #endif
846 default:
847 1313792 c->pal_rgb[i]= b + (g<<8) + (r<<16) + ((unsigned)a<<24);
848 }
849 }
850 35173 }
851
852 static int scale_internal(SwsContext *sws,
853 const uint8_t * const srcSlice[], const int srcStride[],
854 int srcSliceY, int srcSliceH,
855 uint8_t *const dstSlice[], const int dstStride[],
856 int dstSliceY, int dstSliceH);
857
858 static int scale_gamma(SwsInternal *c,
859 const uint8_t * const srcSlice[], const int srcStride[],
860 int srcSliceY, int srcSliceH,
861 uint8_t * const dstSlice[], const int dstStride[],
862 int dstSliceY, int dstSliceH)
863 {
864 int ret = scale_internal(c->cascaded_context[0],
865 srcSlice, srcStride, srcSliceY, srcSliceH,
866 c->cascaded_tmp[0], c->cascaded_tmpStride[0], 0, c->srcH);
867
868 if (ret < 0)
869 return ret;
870
871 if (c->cascaded_context[2])
872 ret = scale_internal(c->cascaded_context[1], (const uint8_t * const *)c->cascaded_tmp[0],
873 c->cascaded_tmpStride[0], srcSliceY, srcSliceH,
874 c->cascaded_tmp[1], c->cascaded_tmpStride[1], 0, c->dstH);
875 else
876 ret = scale_internal(c->cascaded_context[1], (const uint8_t * const *)c->cascaded_tmp[0],
877 c->cascaded_tmpStride[0], srcSliceY, srcSliceH,
878 dstSlice, dstStride, dstSliceY, dstSliceH);
879
880 if (ret < 0)
881 return ret;
882
883 if (c->cascaded_context[2]) {
884 const int dstY1 = sws_internal(c->cascaded_context[1])->dstY;
885 ret = scale_internal(c->cascaded_context[2], (const uint8_t * const *)c->cascaded_tmp[1],
886 c->cascaded_tmpStride[1], dstY1 - ret, dstY1,
887 dstSlice, dstStride, dstSliceY, dstSliceH);
888 }
889 return ret;
890 }
891
892 9 static int scale_cascaded(SwsInternal *c,
893 const uint8_t * const srcSlice[], const int srcStride[],
894 int srcSliceY, int srcSliceH,
895 uint8_t * const dstSlice[], const int dstStride[],
896 int dstSliceY, int dstSliceH)
897 {
898 9 const int dstH0 = sws_internal(c->cascaded_context[0])->dstH;
899 9 int ret = scale_internal(c->cascaded_context[0],
900 srcSlice, srcStride, srcSliceY, srcSliceH,
901 9 c->cascaded_tmp[0], c->cascaded_tmpStride[0],
902 0, dstH0);
903
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 if (ret < 0)
904 return ret;
905 9 ret = scale_internal(c->cascaded_context[1],
906 9 (const uint8_t * const * )c->cascaded_tmp[0], c->cascaded_tmpStride[0],
907 0, dstH0, dstSlice, dstStride, dstSliceY, dstSliceH);
908 9 return ret;
909 }
910
911 486212 static int scale_internal(SwsContext *sws,
912 const uint8_t * const srcSlice[], const int srcStride[],
913 int srcSliceY, int srcSliceH,
914 uint8_t *const dstSlice[], const int dstStride[],
915 int dstSliceY, int dstSliceH)
916 {
917 486212 SwsInternal *c = sws_internal(sws);
918
4/4
✓ Branch 0 taken 84740 times.
✓ Branch 1 taken 401472 times.
✓ Branch 2 taken 50247 times.
✓ Branch 3 taken 34493 times.
486212 const int scale_dst = dstSliceY > 0 || dstSliceH < c->dstH;
919
4/4
✓ Branch 0 taken 34493 times.
✓ Branch 1 taken 451719 times.
✓ Branch 2 taken 34442 times.
✓ Branch 3 taken 51 times.
486212 const int frame_start = scale_dst || !c->sliceDir;
920 int i, ret;
921 const uint8_t *src2[4];
922 uint8_t *dst2[4];
923
1/2
✓ Branch 1 taken 486212 times.
✗ Branch 2 not taken.
486212 int macro_height_src = isBayer(c->srcFormat) ? 2 : (1 << c->chrSrcVSubSample);
924
1/2
✓ Branch 1 taken 486212 times.
✗ Branch 2 not taken.
486212 int macro_height_dst = isBayer(c->dstFormat) ? 2 : (1 << c->chrDstVSubSample);
925 // copy strides, so they can safely be modified
926 int srcStride2[4];
927 int dstStride2[4];
928 486212 int srcSliceY_internal = srcSliceY;
929
930
4/8
✓ Branch 0 taken 486212 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 486212 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 486212 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 486212 times.
486212 if (!srcStride || !dstStride || !dstSlice || !srcSlice) {
931 av_log(c, AV_LOG_ERROR, "One of the input parameters to sws_scale() is NULL, please check the calling code\n");
932 return AVERROR(EINVAL);
933 }
934
935
1/2
✓ Branch 0 taken 486212 times.
✗ Branch 1 not taken.
486212 if ((srcSliceY & (macro_height_src - 1)) ||
936
3/4
✓ Branch 0 taken 81 times.
✓ Branch 1 taken 486131 times.
✓ Branch 2 taken 81 times.
✗ Branch 3 not taken.
486212 ((srcSliceH & (macro_height_src - 1)) && srcSliceY + srcSliceH != c->srcH) ||
937
2/4
✓ Branch 0 taken 486212 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 486212 times.
972424 srcSliceY + srcSliceH > c->srcH ||
938
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
486212 (isBayer(c->srcFormat) && srcSliceH <= 1)) {
939 av_log(c, AV_LOG_ERROR, "Slice parameters %d, %d are invalid\n", srcSliceY, srcSliceH);
940 return AVERROR(EINVAL);
941 }
942
943
1/2
✓ Branch 0 taken 486212 times.
✗ Branch 1 not taken.
486212 if ((dstSliceY & (macro_height_dst - 1)) ||
944
3/4
✓ Branch 0 taken 50 times.
✓ Branch 1 taken 486162 times.
✓ Branch 2 taken 50 times.
✗ Branch 3 not taken.
486212 ((dstSliceH & (macro_height_dst - 1)) && dstSliceY + dstSliceH != c->dstH) ||
945
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 486212 times.
486212 dstSliceY + dstSliceH > c->dstH) {
946 av_log(c, AV_LOG_ERROR, "Slice parameters %d, %d are invalid\n", dstSliceY, dstSliceH);
947 return AVERROR(EINVAL);
948 }
949
950
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 486212 times.
486212 if (!check_image_pointers(srcSlice, c->srcFormat, srcStride)) {
951 av_log(c, AV_LOG_ERROR, "bad src image pointers\n");
952 return AVERROR(EINVAL);
953 }
954
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 486212 times.
486212 if (!check_image_pointers((const uint8_t* const*)dstSlice, c->dstFormat, dstStride)) {
955 av_log(c, AV_LOG_ERROR, "bad dst image pointers\n");
956 return AVERROR(EINVAL);
957 }
958
959 // do not mess up sliceDir if we have a "trailing" 0-size slice
960
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 486212 times.
486212 if (srcSliceH == 0)
961 return 0;
962
963
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 486212 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
486212 if (c->gamma_flag && c->cascaded_context[0])
964 return scale_gamma(c, srcSlice, srcStride, srcSliceY, srcSliceH,
965 dstSlice, dstStride, dstSliceY, dstSliceH);
966
967
3/4
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 486203 times.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
486212 if (c->cascaded_context[0] && srcSliceY == 0 &&
968
1/2
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
9 srcSliceH == sws_internal(c->cascaded_context[0])->srcH)
969 {
970 9 return scale_cascaded(c, srcSlice, srcStride, srcSliceY, srcSliceH,
971 dstSlice, dstStride, dstSliceY, dstSliceH);
972 }
973
974
7/8
✓ Branch 0 taken 486152 times.
✓ Branch 1 taken 51 times.
✓ Branch 2 taken 420154 times.
✓ Branch 3 taken 65998 times.
✓ Branch 4 taken 870 times.
✓ Branch 5 taken 419284 times.
✓ Branch 6 taken 870 times.
✗ Branch 7 not taken.
486203 if (!srcSliceY && (c->flags & SWS_BITEXACT) && c->dither == SWS_DITHER_ED && c->dither_error[0])
975
2/2
✓ Branch 0 taken 3480 times.
✓ Branch 1 taken 870 times.
4350 for (i = 0; i < 4; i++)
976 3480 memset(c->dither_error[i], 0, sizeof(c->dither_error[0][0]) * (c->dstW+2));
977
978
2/2
✓ Branch 1 taken 35173 times.
✓ Branch 2 taken 451030 times.
486203 if (usePal(c->srcFormat))
979 35173 ff_update_palette(c, (const uint32_t *)srcSlice[1]);
980
981 486203 memcpy(src2, srcSlice, sizeof(src2));
982 486203 memcpy(dst2, dstSlice, sizeof(dst2));
983 486203 memcpy(srcStride2, srcStride, sizeof(srcStride2));
984 486203 memcpy(dstStride2, dstStride, sizeof(dstStride2));
985
986
4/4
✓ Branch 0 taken 486152 times.
✓ Branch 1 taken 51 times.
✓ Branch 2 taken 34442 times.
✓ Branch 3 taken 451710 times.
486203 if (frame_start && !scale_dst) {
987
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 34442 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
34442 if (srcSliceY != 0 && srcSliceY + srcSliceH != c->srcH) {
988 av_log(c, AV_LOG_ERROR, "Slices start in the middle!\n");
989 return AVERROR(EINVAL);
990 }
991
992
1/2
✓ Branch 0 taken 34442 times.
✗ Branch 1 not taken.
34442 c->sliceDir = (srcSliceY == 0) ? 1 : -1;
993
2/2
✓ Branch 0 taken 451710 times.
✓ Branch 1 taken 51 times.
451761 } else if (scale_dst)
994 451710 c->sliceDir = 1;
995
996
6/6
✓ Branch 0 taken 4698 times.
✓ Branch 1 taken 481505 times.
✓ Branch 2 taken 4694 times.
✓ Branch 3 taken 4 times.
✓ Branch 5 taken 54 times.
✓ Branch 6 taken 4640 times.
486203 if (c->src0Alpha && !c->dst0Alpha && isALPHA(c->dstFormat)) {
997 uint8_t *base;
998 int x,y;
999
1000 54 av_fast_malloc(&c->rgb0_scratch, &c->rgb0_scratch_allocated,
1001 54 FFABS(srcStride[0]) * srcSliceH + 32);
1002
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 54 times.
54 if (!c->rgb0_scratch)
1003 return AVERROR(ENOMEM);
1004
1005
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 54 times.
54 base = srcStride[0] < 0 ? c->rgb0_scratch - srcStride[0] * (srcSliceH-1) :
1006 c->rgb0_scratch;
1007
2/2
✓ Branch 0 taken 41958 times.
✓ Branch 1 taken 54 times.
42012 for (y=0; y<srcSliceH; y++){
1008 41958 memcpy(base + srcStride[0]*y, src2[0] + srcStride[0]*y, 4*c->srcW);
1009
2/2
✓ Branch 0 taken 25822818 times.
✓ Branch 1 taken 41958 times.
25864776 for (x=c->src0Alpha-1; x<4*c->srcW; x+=4) {
1010 25822818 base[ srcStride[0]*y + x] = 0xFF;
1011 }
1012 }
1013 54 src2[0] = base;
1014 }
1015
1016
5/8
✓ Branch 0 taken 1875 times.
✓ Branch 1 taken 484328 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 1873 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
486203 if (c->srcXYZ && !(c->dstXYZ && c->srcW==c->dstW && c->srcH==c->dstH)) {
1017 uint8_t *base;
1018
1019 1875 av_fast_malloc(&c->xyz_scratch, &c->xyz_scratch_allocated,
1020 1875 FFABS(srcStride[0]) * srcSliceH + 32);
1021
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1875 times.
1875 if (!c->xyz_scratch)
1022 return AVERROR(ENOMEM);
1023
1024
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1875 times.
1875 base = srcStride[0] < 0 ? c->xyz_scratch - srcStride[0] * (srcSliceH-1) :
1025 c->xyz_scratch;
1026
1027 1875 ff_xyz12Torgb48(c, base, srcStride[0], src2[0], srcStride[0], c->srcW, srcSliceH);
1028 1875 src2[0] = base;
1029 }
1030
1031
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 486203 times.
486203 if (c->sliceDir != 1) {
1032 // slices go from bottom to top => we flip the image internally
1033 for (i=0; i<4; i++) {
1034 srcStride2[i] *= -1;
1035 dstStride2[i] *= -1;
1036 }
1037
1038 src2[0] += (srcSliceH - 1) * srcStride[0];
1039 if (!usePal(c->srcFormat))
1040 src2[1] += ((srcSliceH >> c->chrSrcVSubSample) - 1) * srcStride[1];
1041 src2[2] += ((srcSliceH >> c->chrSrcVSubSample) - 1) * srcStride[2];
1042 src2[3] += (srcSliceH - 1) * srcStride[3];
1043 dst2[0] += ( c->dstH - 1) * dstStride[0];
1044 dst2[1] += ((c->dstH >> c->chrDstVSubSample) - 1) * dstStride[1];
1045 dst2[2] += ((c->dstH >> c->chrDstVSubSample) - 1) * dstStride[2];
1046 dst2[3] += ( c->dstH - 1) * dstStride[3];
1047
1048 srcSliceY_internal = c->srcH-srcSliceY-srcSliceH;
1049 }
1050 486203 reset_ptr(src2, c->srcFormat);
1051 486203 reset_ptr((void*)dst2, c->dstFormat);
1052
1053
2/2
✓ Branch 0 taken 79498 times.
✓ Branch 1 taken 406705 times.
486203 if (c->convert_unscaled) {
1054 79498 int offset = srcSliceY_internal;
1055 79498 int slice_h = srcSliceH;
1056
1057 // for dst slice scaling, offset the pointers to match the unscaled API
1058
2/2
✓ Branch 0 taken 78412 times.
✓ Branch 1 taken 1086 times.
79498 if (scale_dst) {
1059
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 78412 times.
78412 av_assert0(offset == 0);
1060
4/4
✓ Branch 0 taken 195140 times.
✓ Branch 1 taken 288 times.
✓ Branch 2 taken 149361 times.
✓ Branch 3 taken 45779 times.
195428 for (i = 0; i < 4 && src2[i]; i++) {
1061
5/6
✓ Branch 0 taken 149361 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 70949 times.
✓ Branch 3 taken 78412 times.
✓ Branch 5 taken 38604 times.
✓ Branch 6 taken 32345 times.
149361 if (!src2[i] || (i > 0 && usePal(c->srcFormat)))
1062 break;
1063
4/4
✓ Branch 0 taken 97291 times.
✓ Branch 1 taken 19725 times.
✓ Branch 2 taken 18591 times.
✓ Branch 3 taken 78700 times.
117016 src2[i] += (dstSliceY >> ((i == 1 || i == 2) ? c->chrSrcVSubSample : 0)) * srcStride2[i];
1064 }
1065
1066
4/4
✓ Branch 0 taken 195410 times.
✓ Branch 1 taken 618 times.
✓ Branch 2 taken 117616 times.
✓ Branch 3 taken 77794 times.
196028 for (i = 0; i < 4 && dst2[i]; i++) {
1067
4/6
✓ Branch 0 taken 117616 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 39204 times.
✓ Branch 3 taken 78412 times.
✓ Branch 5 taken 39204 times.
✗ Branch 6 not taken.
117616 if (!dst2[i] || (i > 0 && usePal(c->dstFormat)))
1068 break;
1069
4/4
✓ Branch 0 taken 97756 times.
✓ Branch 1 taken 19860 times.
✓ Branch 2 taken 18726 times.
✓ Branch 3 taken 79030 times.
117616 dst2[i] -= (dstSliceY >> ((i == 1 || i == 2) ? c->chrDstVSubSample : 0)) * dstStride2[i];
1070 }
1071 78412 offset = dstSliceY;
1072 78412 slice_h = dstSliceH;
1073 }
1074
1075 79498 ret = c->convert_unscaled(c, src2, srcStride2, offset, slice_h,
1076 dst2, dstStride2);
1077
2/2
✓ Branch 0 taken 78412 times.
✓ Branch 1 taken 1086 times.
79498 if (scale_dst)
1078 78412 dst2[0] += dstSliceY * dstStride2[0];
1079 } else {
1080 406705 ret = ff_swscale(c, src2, srcStride2, srcSliceY_internal, srcSliceH,
1081 dst2, dstStride2, dstSliceY, dstSliceH);
1082 }
1083
1084
5/8
✓ Branch 0 taken 1916 times.
✓ Branch 1 taken 484287 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 1914 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
486203 if (c->dstXYZ && !(c->srcXYZ && c->srcW==c->dstW && c->srcH==c->dstH)) {
1085 uint8_t *dst;
1086
1087
2/2
✓ Branch 0 taken 1872 times.
✓ Branch 1 taken 44 times.
1916 if (scale_dst) {
1088 1872 dst = dst2[0];
1089 } else {
1090
1/2
✓ Branch 0 taken 44 times.
✗ Branch 1 not taken.
44 int dstY = c->dstY ? c->dstY : srcSliceY + srcSliceH;
1091
1092
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 44 times.
44 av_assert0(dstY >= ret);
1093
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 44 times.
44 av_assert0(ret >= 0);
1094
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 44 times.
44 av_assert0(c->dstH >= dstY);
1095 44 dst = dst2[0] + (dstY - ret) * dstStride2[0];
1096 }
1097
1098 /* replace on the same data */
1099 1916 ff_rgb48Toxyz12(c, dst, dstStride2[0], dst, dstStride2[0], c->dstW, ret);
1100 }
1101
1102 /* reset slice direction at end of frame */
1103
3/4
✓ Branch 0 taken 51 times.
✓ Branch 1 taken 486152 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 51 times.
486203 if ((srcSliceY_internal + srcSliceH == c->srcH) || scale_dst)
1104 486152 c->sliceDir = 0;
1105
1106 486203 return ret;
1107 }
1108
1109 84597 void sws_frame_end(SwsContext *sws)
1110 {
1111 84597 SwsInternal *c = sws_internal(sws);
1112 84597 av_frame_unref(c->frame_src);
1113 84597 av_frame_unref(c->frame_dst);
1114 84597 c->src_ranges.nb_ranges = 0;
1115 84597 }
1116
1117 84597 int sws_frame_start(SwsContext *sws, AVFrame *dst, const AVFrame *src)
1118 {
1119 84597 SwsInternal *c = sws_internal(sws);
1120 84597 int ret, allocated = 0;
1121
1122 84597 ret = av_frame_ref(c->frame_src, src);
1123
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 84597 times.
84597 if (ret < 0)
1124 return ret;
1125
1126
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 84597 times.
84597 if (!dst->buf[0]) {
1127 dst->width = c->dstW;
1128 dst->height = c->dstH;
1129 dst->format = c->dstFormat;
1130
1131 ret = av_frame_get_buffer(dst, 0);
1132 if (ret < 0)
1133 return ret;
1134 allocated = 1;
1135 }
1136
1137 84597 ret = av_frame_ref(c->frame_dst, dst);
1138
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 84597 times.
84597 if (ret < 0) {
1139 if (allocated)
1140 av_frame_unref(dst);
1141
1142 return ret;
1143 }
1144
1145 84597 return 0;
1146 }
1147
1148 84597 int sws_send_slice(SwsContext *sws, unsigned int slice_start,
1149 unsigned int slice_height)
1150 {
1151 84597 SwsInternal *c = sws_internal(sws);
1152 int ret;
1153
1154 84597 ret = ff_range_add(&c->src_ranges, slice_start, slice_height);
1155
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 84597 times.
84597 if (ret < 0)
1156 return ret;
1157
1158 84597 return 0;
1159 }
1160
1161 84597 unsigned int sws_receive_slice_alignment(const SwsContext *sws)
1162 {
1163 84597 SwsInternal *c = sws_internal(sws);
1164
2/2
✓ Branch 0 taken 51111 times.
✓ Branch 1 taken 33486 times.
84597 if (c->slice_ctx)
1165 51111 return sws_internal(c->slice_ctx[0])->dst_slice_align;
1166
1167 33486 return c->dst_slice_align;
1168 }
1169
1170 84597 int sws_receive_slice(SwsContext *sws, unsigned int slice_start,
1171 unsigned int slice_height)
1172 {
1173 84597 SwsInternal *c = sws_internal(sws);
1174 84597 unsigned int align = sws_receive_slice_alignment(sws);
1175 uint8_t *dst[4];
1176
1177 /* wait until complete input has been received */
1178
1/2
✓ Branch 0 taken 84597 times.
✗ Branch 1 not taken.
84597 if (!(c->src_ranges.nb_ranges == 1 &&
1179
1/2
✓ Branch 0 taken 84597 times.
✗ Branch 1 not taken.
84597 c->src_ranges.ranges[0].start == 0 &&
1180
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 84597 times.
84597 c->src_ranges.ranges[0].len == c->srcH))
1181 return AVERROR(EAGAIN);
1182
1183
2/4
✓ Branch 0 taken 84597 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 84597 times.
84597 if ((slice_start > 0 || slice_height < c->dstH) &&
1184 (slice_start % align || slice_height % align)) {
1185 av_log(c, AV_LOG_ERROR,
1186 "Incorrectly aligned output: %u/%u not multiples of %u\n",
1187 slice_start, slice_height, align);
1188 return AVERROR(EINVAL);
1189 }
1190
1191
2/2
✓ Branch 0 taken 51111 times.
✓ Branch 1 taken 33486 times.
84597 if (c->slicethread) {
1192 51111 int nb_jobs = c->nb_slice_ctx;
1193 51111 int ret = 0;
1194
1195
2/2
✓ Branch 1 taken 865 times.
✓ Branch 2 taken 50246 times.
51111 if (sws_internal(c->slice_ctx[0])->dither == SWS_DITHER_ED)
1196 865 nb_jobs = 1;
1197
1198 51111 c->dst_slice_start = slice_start;
1199 51111 c->dst_slice_height = slice_height;
1200
1201 51111 avpriv_slicethread_execute(c->slicethread, nb_jobs, 0);
1202
1203
2/2
✓ Branch 0 taken 453004 times.
✓ Branch 1 taken 51111 times.
504115 for (int i = 0; i < c->nb_slice_ctx; i++) {
1204
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 453004 times.
453004 if (c->slice_err[i] < 0) {
1205 ret = c->slice_err[i];
1206 break;
1207 }
1208 }
1209
1210 51111 memset(c->slice_err, 0, c->nb_slice_ctx * sizeof(*c->slice_err));
1211
1212 51111 return ret;
1213 }
1214
1215
2/2
✓ Branch 0 taken 133944 times.
✓ Branch 1 taken 33486 times.
167430 for (int i = 0; i < FF_ARRAY_ELEMS(dst); i++) {
1216 133944 ptrdiff_t offset = c->frame_dst->linesize[i] * (ptrdiff_t)(slice_start >> c->chrDstVSubSample);
1217
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 133944 times.
133944 dst[i] = FF_PTR_ADD(c->frame_dst->data[i], offset);
1218 }
1219
1220 33486 return scale_internal(sws, (const uint8_t * const *)c->frame_src->data,
1221 33486 c->frame_src->linesize, 0, c->srcH,
1222 33486 dst, c->frame_dst->linesize, slice_start, slice_height);
1223 }
1224
1225 84597 int sws_scale_frame(SwsContext *sws, AVFrame *dst, const AVFrame *src)
1226 {
1227 int ret;
1228
1229 84597 ret = sws_frame_start(sws, dst, src);
1230
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 84597 times.
84597 if (ret < 0)
1231 return ret;
1232
1233 84597 ret = sws_send_slice(sws, 0, src->height);
1234
1/2
✓ Branch 0 taken 84597 times.
✗ Branch 1 not taken.
84597 if (ret >= 0)
1235 84597 ret = sws_receive_slice(sws, 0, dst->height);
1236
1237 84597 sws_frame_end(sws);
1238
1239 84597 return ret;
1240 }
1241
1242 /**
1243 * swscale wrapper, so we don't need to export the SwsContext.
1244 * Assumes planar YUV to be in YUV order instead of YVU.
1245 */
1246 133 int attribute_align_arg sws_scale(SwsContext *sws,
1247 const uint8_t * const srcSlice[],
1248 const int srcStride[], int srcSliceY,
1249 int srcSliceH, uint8_t *const dst[],
1250 const int dstStride[])
1251 {
1252 133 SwsInternal *c = sws_internal(sws);
1253
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 133 times.
133 if (c->nb_slice_ctx) {
1254 sws = c->slice_ctx[0];
1255 c = sws_internal(sws);
1256 }
1257
1258 133 return scale_internal(sws, srcSlice, srcStride, srcSliceY, srcSliceH,
1259 dst, dstStride, 0, c->dstH);
1260 }
1261
1262 453004 void ff_sws_slice_worker(void *priv, int jobnr, int threadnr,
1263 int nb_jobs, int nb_threads)
1264 {
1265 453004 SwsInternal *parent = priv;
1266 453004 SwsContext *sws = parent->slice_ctx[threadnr];
1267 453004 SwsInternal *c = sws_internal(sws);
1268
1269 453004 const int slice_height = FFALIGN(FFMAX((parent->dst_slice_height + nb_jobs - 1) / nb_jobs, 1),
1270 c->dst_slice_align);
1271 453004 const int slice_start = jobnr * slice_height;
1272 453004 const int slice_end = FFMIN((jobnr + 1) * slice_height, parent->dst_slice_height);
1273 453004 int err = 0;
1274
1275
2/2
✓ Branch 0 taken 452575 times.
✓ Branch 1 taken 429 times.
453004 if (slice_end > slice_start) {
1276 452575 uint8_t *dst[4] = { NULL };
1277
1278
4/4
✓ Branch 0 taken 1432187 times.
✓ Branch 1 taken 7798 times.
✓ Branch 2 taken 987410 times.
✓ Branch 3 taken 444777 times.
1439985 for (int i = 0; i < FF_ARRAY_ELEMS(dst) && parent->frame_dst->data[i]; i++) {
1279
4/4
✓ Branch 0 taken 702295 times.
✓ Branch 1 taken 285115 times.
✓ Branch 2 taken 241922 times.
✓ Branch 3 taken 460373 times.
987410 const int vshift = (i == 1 || i == 2) ? c->chrDstVSubSample : 0;
1280 987410 const ptrdiff_t offset = parent->frame_dst->linesize[i] *
1281 987410 (ptrdiff_t)((slice_start + parent->dst_slice_start) >> vshift);
1282
1283 987410 dst[i] = parent->frame_dst->data[i] + offset;
1284 }
1285
1286 452575 err = scale_internal(sws, (const uint8_t * const *)parent->frame_src->data,
1287 452575 parent->frame_src->linesize, 0, c->srcH,
1288 452575 dst, parent->frame_dst->linesize,
1289 452575 parent->dst_slice_start + slice_start, slice_end - slice_start);
1290 }
1291
1292 453004 parent->slice_err[threadnr] = err;
1293 453004 }
1294