FFmpeg
swscale.c
Go to the documentation of this file.
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 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  uint8_t *ptr = plane + stride * y;
59  for (i = 0; i < height; i++) {
60  memset(ptr, val, width);
61  ptr += stride;
62  }
63 }
64 
65 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  const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->opts.src_format);
70  int i;
71  int32_t *dst = (int32_t *) _dst;
72  const uint16_t *src = (const uint16_t *) _src;
73  int bits = desc->comp[0].depth - 1;
74  int sh = bits - 4;
75 
76  if ((isAnyRGB(c->opts.src_format) || c->opts.src_format==AV_PIX_FMT_PAL8) && desc->comp[0].depth<16) {
77  sh = 9;
78  } else if (desc->flags & AV_PIX_FMT_FLAG_FLOAT) { /* float input are process like uint 16bpc */
79  sh = 16 - 1 - 4;
80  }
81 
82  for (i = 0; i < dstW; i++) {
83  int j;
84  int srcPos = filterPos[i];
85  int val = 0;
86 
87  for (j = 0; j < filterSize; j++) {
88  val += src[srcPos + j] * filter[filterSize * i + j];
89  }
90  // filter=14 bit, input=16 bit, output=30 bit, >> 11 makes 19 bit
91  dst[i] = FFMIN(val >> sh, (1 << 19) - 1);
92  }
93 }
94 
95 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  const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->opts.src_format);
100  int i;
101  const uint16_t *src = (const uint16_t *) _src;
102  int sh = desc->comp[0].depth - 1;
103 
104  if (sh<15) {
105  sh = isAnyRGB(c->opts.src_format) || c->opts.src_format==AV_PIX_FMT_PAL8 ? 13 : (desc->comp[0].depth - 1);
106  } else if (desc->flags & AV_PIX_FMT_FLAG_FLOAT) { /* float input are process like uint 16bpc */
107  sh = 16 - 1;
108  }
109 
110  for (i = 0; i < dstW; i++) {
111  int j;
112  int srcPos = filterPos[i];
113  int val = 0;
114 
115  for (j = 0; j < filterSize; j++) {
116  val += src[srcPos + j] * filter[filterSize * i + j];
117  }
118  // filter=14 bit, input=16 bit, output=30 bit, >> 15 makes 15 bit
119  dst[i] = FFMIN(val >> sh, (1 << 15) - 1);
120  }
121 }
122 
123 // bilinear / bicubic scaling
124 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  for (i = 0; i < dstW; i++) {
130  int j;
131  int srcPos = filterPos[i];
132  int val = 0;
133  for (j = 0; j < filterSize; j++) {
134  val += ((int)src[srcPos + j]) * filter[filterSize * i + j];
135  }
136  dst[i] = FFMIN(val >> 7, (1 << 15) - 1); // the cubic equation does overflow ...
137  }
138 }
139 
140 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  int32_t *dst = (int32_t *) _dst;
146  for (i = 0; i < dstW; i++) {
147  int j;
148  int srcPos = filterPos[i];
149  int val = 0;
150  for (j = 0; j < filterSize; j++) {
151  val += ((int)src[srcPos + j]) * filter[filterSize * i + j];
152  }
153  dst[i] = FFMIN(val >> 3, (1 << 19) - 1); // the cubic equation does overflow ...
154  }
155 }
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 static void chrRangeToJpeg_c(int16_t *dstU, int16_t *dstV, int width)
160 {
161  int i;
162  for (i = 0; i < width; i++) {
163  dstU[i] = (FFMIN(dstU[i], 30775) * 4663 - 9289992) >> 12; // -264
164  dstV[i] = (FFMIN(dstV[i], 30775) * 4663 - 9289992) >> 12; // -264
165  }
166 }
167 
168 static void chrRangeFromJpeg_c(int16_t *dstU, int16_t *dstV, int width)
169 {
170  int i;
171  for (i = 0; i < width; i++) {
172  dstU[i] = (dstU[i] * 1799 + 4081085) >> 11; // 1469
173  dstV[i] = (dstV[i] * 1799 + 4081085) >> 11; // 1469
174  }
175 }
176 
177 static void lumRangeToJpeg_c(int16_t *dst, int width)
178 {
179  int i;
180  for (i = 0; i < width; i++)
181  dst[i] = (FFMIN(dst[i], 30189) * 19077 - 39057361) >> 14;
182 }
183 
184 static void lumRangeFromJpeg_c(int16_t *dst, int width)
185 {
186  int i;
187  for (i = 0; i < width; i++)
188  dst[i] = (dst[i] * 14071 + 33561947) >> 14;
189 }
190 
191 static void chrRangeToJpeg16_c(int16_t *_dstU, int16_t *_dstV, int width)
192 {
193  int i;
194  int32_t *dstU = (int32_t *) _dstU;
195  int32_t *dstV = (int32_t *) _dstV;
196  for (i = 0; i < width; i++) {
197  dstU[i] = ((int)(FFMIN(dstU[i], 30775 << 4) * 4663U - (9289992 << 4))) >> 12; // -264
198  dstV[i] = ((int)(FFMIN(dstV[i], 30775 << 4) * 4663U - (9289992 << 4))) >> 12; // -264
199  }
200 }
201 
202 static void chrRangeFromJpeg16_c(int16_t *_dstU, int16_t *_dstV, int width)
203 {
204  int i;
205  int32_t *dstU = (int32_t *) _dstU;
206  int32_t *dstV = (int32_t *) _dstV;
207  for (i = 0; i < width; i++) {
208  dstU[i] = (dstU[i] * 1799 + (4081085 << 4)) >> 11; // 1469
209  dstV[i] = (dstV[i] * 1799 + (4081085 << 4)) >> 11; // 1469
210  }
211 }
212 
213 static void lumRangeToJpeg16_c(int16_t *_dst, int width)
214 {
215  int i;
216  int32_t *dst = (int32_t *) _dst;
217  for (i = 0; i < width; i++) {
218  dst[i] = ((int)(FFMIN(dst[i], 30189 << 4) * 4769U - (39057361 << 2))) >> 12;
219  }
220 }
221 
222 static void lumRangeFromJpeg16_c(int16_t *_dst, int width)
223 {
224  int i;
225  int32_t *dst = (int32_t *) _dst;
226  for (i = 0; i < width; i++)
227  dst[i] = ((int)(dst[i]*(14071U/4) + (33561947<<4)/4)) >> 12;
228 }
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 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  const int scale_dst = dstSliceY > 0 || dstSliceH < c->opts.dst_h;
241 
242  /* load a few things into local vars to make the code more readable?
243  * and faster */
244  const int dstW = c->opts.dst_w;
245  int dstH = c->opts.dst_h;
246 
247  const enum AVPixelFormat dstFormat = c->opts.dst_format;
248  const int flags = c->opts.flags;
249  int32_t *vLumFilterPos = c->vLumFilterPos;
250  int32_t *vChrFilterPos = c->vChrFilterPos;
251 
252  const int vLumFilterSize = c->vLumFilterSize;
253  const int vChrFilterSize = c->vChrFilterSize;
254 
255  yuv2planar1_fn yuv2plane1 = c->yuv2plane1;
256  yuv2planarX_fn yuv2planeX = c->yuv2planeX;
257  yuv2interleavedX_fn yuv2nv12cX = c->yuv2nv12cX;
258  yuv2packed1_fn yuv2packed1 = c->yuv2packed1;
259  yuv2packed2_fn yuv2packed2 = c->yuv2packed2;
260  yuv2packedX_fn yuv2packedX = c->yuv2packedX;
261  yuv2anyX_fn yuv2anyX = c->yuv2anyX;
262  const int chrSrcSliceY = srcSliceY >> c->chrSrcVSubSample;
263  const int chrSrcSliceH = AV_CEIL_RSHIFT(srcSliceH, c->chrSrcVSubSample);
264  int should_dither = isNBPS(c->opts.src_format) ||
265  is16BPS(c->opts.src_format);
266  int lastDstY;
267 
268  /* vars which will change and which we need to store back in the context */
269  int dstY = c->dstY;
270  int lastInLumBuf = c->lastInLumBuf;
271  int lastInChrBuf = c->lastInChrBuf;
272 
273  int lumStart = 0;
274  int lumEnd = c->descIndex[0];
275  int chrStart = lumEnd;
276  int chrEnd = c->descIndex[1];
277  int vStart = chrEnd;
278  int vEnd = c->numDesc;
279  SwsSlice *src_slice = &c->slice[lumStart];
280  SwsSlice *hout_slice = &c->slice[c->numSlice-2];
281  SwsSlice *vout_slice = &c->slice[c->numSlice-1];
282  SwsFilterDescriptor *desc = c->desc;
283 
284  int needAlpha = c->needAlpha;
285 
286  int hasLumHoles = 1;
287  int hasChrHoles = 1;
288 
289  const uint8_t *src2[4];
290  int srcStride2[4];
291 
292  if (isPacked(c->opts.src_format)) {
293  src2[0] =
294  src2[1] =
295  src2[2] =
296  src2[3] = src[0];
297  srcStride2[0] =
298  srcStride2[1] =
299  srcStride2[2] =
300  srcStride2[3] = srcStride[0];
301  } else {
302  memcpy(src2, src, sizeof(src2));
303  memcpy(srcStride2, srcStride, sizeof(srcStride2));
304  }
305 
306  srcStride2[1] *= 1 << c->vChrDrop;
307  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  if (dstStride[0]&15 || dstStride[1]&15 ||
320  dstStride[2]&15 || dstStride[3]&15) {
321  SwsInternal *const ctx = c->parent ? sws_internal(c->parent) : c;
322  if (flags & SWS_PRINT_INFO &&
323  !atomic_exchange_explicit(&ctx->stride_unaligned_warned, 1, memory_order_relaxed)) {
325  "Warning: dstStride is not aligned!\n"
326  " ->cannot do aligned memory accesses anymore\n");
327  }
328  }
329 
330 #if ARCH_X86
331  if ( (uintptr_t) dst[0]&15 || (uintptr_t) dst[1]&15 || (uintptr_t) dst[2]&15
332  || (uintptr_t)src2[0]&15 || (uintptr_t)src2[1]&15 || (uintptr_t)src2[2]&15
333  || dstStride[0]&15 || dstStride[1]&15 || dstStride[2]&15 || dstStride[3]&15
334  || srcStride2[0]&15 || srcStride2[1]&15 || srcStride2[2]&15 || srcStride2[3]&15
335  ) {
336  SwsInternal *const ctx = c->parent ? sws_internal(c->parent) : c;
337  int cpu_flags = av_get_cpu_flags();
338  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  if (scale_dst) {
346  dstY = dstSliceY;
347  dstH = dstY + dstSliceH;
348  lastInLumBuf = -1;
349  lastInChrBuf = -1;
350  } 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  dstY = 0;
355  lastInLumBuf = -1;
356  lastInChrBuf = -1;
357  }
358 
359  if (!should_dither) {
360  c->chrDither8 = c->lumDither8 = sws_pb_64;
361  }
362  lastDstY = dstY;
363 
364  ff_init_vscale_pfn(c, yuv2plane1, yuv2planeX, yuv2nv12cX,
365  yuv2packed1, yuv2packed2, yuv2packedX, yuv2anyX, c->use_mmx_vfilter);
366 
367  ff_init_slice_from_src(src_slice, (uint8_t**)src2, srcStride2, c->opts.src_w,
368  srcSliceY, srcSliceH, chrSrcSliceY, chrSrcSliceH, 1);
369 
370  ff_init_slice_from_src(vout_slice, (uint8_t**)dst, dstStride, c->opts.dst_w,
371  dstY, dstSliceH, dstY >> c->chrDstVSubSample,
372  AV_CEIL_RSHIFT(dstSliceH, c->chrDstVSubSample), scale_dst);
373  if (srcSliceY == 0) {
374  hout_slice->plane[0].sliceY = lastInLumBuf + 1;
375  hout_slice->plane[1].sliceY = lastInChrBuf + 1;
376  hout_slice->plane[2].sliceY = lastInChrBuf + 1;
377  hout_slice->plane[3].sliceY = lastInLumBuf + 1;
378 
379  hout_slice->plane[0].sliceH =
380  hout_slice->plane[1].sliceH =
381  hout_slice->plane[2].sliceH =
382  hout_slice->plane[3].sliceH = 0;
383  hout_slice->width = dstW;
384  }
385 
386  for (; dstY < dstH; dstY++) {
387  const int chrDstY = dstY >> c->chrDstVSubSample;
388  int use_mmx_vfilter= c->use_mmx_vfilter;
389 
390  // First line needed as input
391  const int firstLumSrcY = FFMAX(1 - vLumFilterSize, vLumFilterPos[dstY]);
392  const int firstLumSrcY2 = FFMAX(1 - vLumFilterSize, vLumFilterPos[FFMIN(dstY | ((1 << c->chrDstVSubSample) - 1), c->opts.dst_h - 1)]);
393  // First line needed as input
394  const int firstChrSrcY = FFMAX(1 - vChrFilterSize, vChrFilterPos[chrDstY]);
395 
396  // Last line needed as input
397  int lastLumSrcY = FFMIN(c->opts.src_h, firstLumSrcY + vLumFilterSize) - 1;
398  int lastLumSrcY2 = FFMIN(c->opts.src_h, firstLumSrcY2 + vLumFilterSize) - 1;
399  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  if (firstLumSrcY > lastInLumBuf) {
407 
408  hasLumHoles = lastInLumBuf != firstLumSrcY - 1;
409  if (hasLumHoles) {
410  hout_slice->plane[0].sliceY = firstLumSrcY;
411  hout_slice->plane[3].sliceY = firstLumSrcY;
412  hout_slice->plane[0].sliceH =
413  hout_slice->plane[3].sliceH = 0;
414  }
415 
416  lastInLumBuf = firstLumSrcY - 1;
417  }
418  if (firstChrSrcY > lastInChrBuf) {
419 
420  hasChrHoles = lastInChrBuf != firstChrSrcY - 1;
421  if (hasChrHoles) {
422  hout_slice->plane[1].sliceY = firstChrSrcY;
423  hout_slice->plane[2].sliceY = firstChrSrcY;
424  hout_slice->plane[1].sliceH =
425  hout_slice->plane[2].sliceH = 0;
426  }
427 
428  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  enough_lines = lastLumSrcY2 < srcSliceY + srcSliceH &&
439  lastChrSrcY < AV_CEIL_RSHIFT(srcSliceY + srcSliceH, c->chrSrcVSubSample);
440 
441  if (!enough_lines) {
442  lastLumSrcY = srcSliceY + srcSliceH - 1;
443  lastChrSrcY = chrSrcSliceY + chrSrcSliceH - 1;
444  DEBUG_BUFFERS("buffering slice: lastLumSrcY %d lastChrSrcY %d\n",
445  lastLumSrcY, lastChrSrcY);
446  }
447 
448  av_assert0((lastLumSrcY - firstLumSrcY + 1) <= hout_slice->plane[0].available_lines);
449  av_assert0((lastChrSrcY - firstChrSrcY + 1) <= hout_slice->plane[1].available_lines);
450 
451 
452  posY = hout_slice->plane[0].sliceY + hout_slice->plane[0].sliceH;
453  if (posY <= lastLumSrcY && !hasLumHoles) {
454  firstPosY = FFMAX(firstLumSrcY, posY);
455  lastPosY = FFMIN(firstLumSrcY + hout_slice->plane[0].available_lines - 1, srcSliceY + srcSliceH - 1);
456  } else {
457  firstPosY = posY;
458  lastPosY = lastLumSrcY;
459  }
460 
461  cPosY = hout_slice->plane[1].sliceY + hout_slice->plane[1].sliceH;
462  if (cPosY <= lastChrSrcY && !hasChrHoles) {
463  firstCPosY = FFMAX(firstChrSrcY, cPosY);
464  lastCPosY = FFMIN(firstChrSrcY + hout_slice->plane[1].available_lines - 1, AV_CEIL_RSHIFT(srcSliceY + srcSliceH, c->chrSrcVSubSample) - 1);
465  } else {
466  firstCPosY = cPosY;
467  lastCPosY = lastChrSrcY;
468  }
469 
470  ff_rotate_slice(hout_slice, lastPosY, lastCPosY);
471 
472  if (posY < lastLumSrcY + 1) {
473  for (i = lumStart; i < lumEnd; ++i)
474  desc[i].process(c, &desc[i], firstPosY, lastPosY - firstPosY + 1);
475  }
476 
477  lastInLumBuf = lastLumSrcY;
478 
479  if (cPosY < lastChrSrcY + 1) {
480  for (i = chrStart; i < chrEnd; ++i)
481  desc[i].process(c, &desc[i], firstCPosY, lastCPosY - firstCPosY + 1);
482  }
483 
484  lastInChrBuf = lastChrSrcY;
485 
486  if (!enough_lines)
487  break; // we can't output a dstY line so let's try with the next slice
488 
489 #if HAVE_MMX_INLINE
491  c->dstW_mmx = c->opts.dst_w;
492 #endif
493  if (should_dither) {
494  c->chrDither8 = ff_dither_8x8_128[chrDstY & 7];
495  c->lumDither8 = ff_dither_8x8_128[dstY & 7];
496  }
497  if (dstY >= c->opts.dst_h - 2) {
498  /* hmm looks like we can't use MMX here without overwriting
499  * this array's tail */
500  ff_sws_init_output_funcs(c, &yuv2plane1, &yuv2planeX, &yuv2nv12cX,
501  &yuv2packed1, &yuv2packed2, &yuv2packedX, &yuv2anyX);
502  use_mmx_vfilter= 0;
503  ff_init_vscale_pfn(c, yuv2plane1, yuv2planeX, yuv2nv12cX,
504  yuv2packed1, yuv2packed2, yuv2packedX, yuv2anyX, use_mmx_vfilter);
505  }
506 
507  for (i = vStart; i < vEnd; ++i)
508  desc[i].process(c, &desc[i], dstY, 1);
509  }
510  if (isPlanar(dstFormat) && isALPHA(dstFormat) && !needAlpha) {
511  int offset = lastDstY - dstSliceY;
512  int length = dstW;
513  int height = dstY - lastDstY;
514 
515  if (is16BPS(dstFormat) || isNBPS(dstFormat)) {
516  const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(dstFormat);
517  fillPlane16(dst[3], dstStride[3], length, height, offset,
518  1, desc->comp[3].depth,
519  isBE(dstFormat));
520  } else if (is32BPS(dstFormat)) {
521  const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(dstFormat);
522  fillPlane32(dst[3], dstStride[3], length, height, offset,
523  1, desc->comp[3].depth,
524  isBE(dstFormat), desc->flags & AV_PIX_FMT_FLAG_FLOAT);
525  } else
526  fillPlane(dst[3], dstStride[3], length, height, offset, 255);
527  }
528 
529 #if HAVE_MMXEXT_INLINE
531  __asm__ volatile ("sfence" ::: "memory");
532 #endif
533  emms_c();
534 
535  /* store changed local vars back in the context */
536  c->dstY = dstY;
537  c->lastInLumBuf = lastInLumBuf;
538  c->lastInChrBuf = lastInChrBuf;
539 
540  return dstY - lastDstY;
541 }
542 
544 {
545  c->lumConvertRange = NULL;
546  c->chrConvertRange = NULL;
547  if (c->opts.src_range != c->opts.dst_range && !isAnyRGB(c->opts.dst_format)) {
548  if (c->dstBpc <= 14) {
549  if (c->opts.src_range) {
550  c->lumConvertRange = lumRangeFromJpeg_c;
551  c->chrConvertRange = chrRangeFromJpeg_c;
552  } else {
553  c->lumConvertRange = lumRangeToJpeg_c;
554  c->chrConvertRange = chrRangeToJpeg_c;
555  }
556  } else {
557  if (c->opts.src_range) {
558  c->lumConvertRange = lumRangeFromJpeg16_c;
559  c->chrConvertRange = chrRangeFromJpeg16_c;
560  } else {
561  c->lumConvertRange = lumRangeToJpeg16_c;
562  c->chrConvertRange = chrRangeToJpeg16_c;
563  }
564  }
565 
566 #if ARCH_AARCH64
568 #elif ARCH_LOONGARCH64
570 #elif ARCH_RISCV
572 #elif ARCH_X86
574 #endif
575  }
576 }
577 
579 {
580  enum AVPixelFormat srcFormat = c->opts.src_format;
581 
582  ff_sws_init_output_funcs(c, &c->yuv2plane1, &c->yuv2planeX,
583  &c->yuv2nv12cX, &c->yuv2packed1,
584  &c->yuv2packed2, &c->yuv2packedX, &c->yuv2anyX);
585 
586  ff_sws_init_input_funcs(c, &c->lumToYV12, &c->alpToYV12, &c->chrToYV12,
587  &c->readLumPlanar, &c->readAlpPlanar, &c->readChrPlanar);
588 
589  if (c->srcBpc == 8) {
590  if (c->dstBpc <= 14) {
591  c->hyScale = c->hcScale = hScale8To15_c;
592  if (c->opts.flags & SWS_FAST_BILINEAR) {
593  c->hyscale_fast = ff_hyscale_fast_c;
594  c->hcscale_fast = ff_hcscale_fast_c;
595  }
596  } else {
597  c->hyScale = c->hcScale = hScale8To19_c;
598  }
599  } else {
600  c->hyScale = c->hcScale = c->dstBpc > 14 ? hScale16To19_c
601  : hScale16To15_c;
602  }
603 
605 
606  if (!(isGray(srcFormat) || isGray(c->opts.dst_format) ||
607  srcFormat == AV_PIX_FMT_MONOBLACK || srcFormat == AV_PIX_FMT_MONOWHITE))
608  c->needs_hcscale = 1;
609 }
610 
612 {
614 
615 #if ARCH_PPC
617 #elif ARCH_X86
619 #elif ARCH_AARCH64
621 #elif ARCH_ARM
623 #elif ARCH_LOONGARCH64
625 #elif ARCH_RISCV
627 #endif
628 }
629 
630 static void reset_ptr(const uint8_t *src[], enum AVPixelFormat format)
631 {
632  if (!isALPHA(format))
633  src[3] = NULL;
634  if (!isPlanar(format)) {
635  src[3] = src[2] = NULL;
636 
637  if (!usePal(format))
638  src[1] = NULL;
639  }
640 }
641 
642 static int check_image_pointers(const uint8_t * const data[4], enum AVPixelFormat pix_fmt,
643  const int linesizes[4])
644 {
646  int i;
647 
648  av_assert2(desc);
649 
650  for (i = 0; i < 4; i++) {
651  int plane = desc->comp[i].plane;
652  if (!data[plane] || !linesizes[plane])
653  return 0;
654  }
655 
656  return 1;
657 }
658 
659 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  const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->opts.src_format);
663 
664  for (int yp = 0; yp < h; yp++) {
665  const uint16_t *src16 = (const uint16_t *) src;
666  uint16_t *dst16 = (uint16_t *) dst;
667 
668  for (int xp = 0; xp < 3 * w; xp += 3) {
669  int x, y, z, r, g, b;
670 
671  if (desc->flags & AV_PIX_FMT_FLAG_BE) {
672  x = AV_RB16(src16 + xp + 0);
673  y = AV_RB16(src16 + xp + 1);
674  z = AV_RB16(src16 + xp + 2);
675  } else {
676  x = AV_RL16(src16 + xp + 0);
677  y = AV_RL16(src16 + xp + 1);
678  z = AV_RL16(src16 + xp + 2);
679  }
680 
681  x = c->xyzgamma[x >> 4];
682  y = c->xyzgamma[y >> 4];
683  z = c->xyzgamma[z >> 4];
684 
685  // convert from XYZlinear to sRGBlinear
686  r = c->xyz2rgb_matrix[0][0] * x +
687  c->xyz2rgb_matrix[0][1] * y +
688  c->xyz2rgb_matrix[0][2] * z >> 12;
689  g = c->xyz2rgb_matrix[1][0] * x +
690  c->xyz2rgb_matrix[1][1] * y +
691  c->xyz2rgb_matrix[1][2] * z >> 12;
692  b = c->xyz2rgb_matrix[2][0] * x +
693  c->xyz2rgb_matrix[2][1] * y +
694  c->xyz2rgb_matrix[2][2] * z >> 12;
695 
696  // limit values to 12-bit depth
697  r = av_clip_uintp2(r, 12);
698  g = av_clip_uintp2(g, 12);
699  b = av_clip_uintp2(b, 12);
700 
701  // convert from sRGBlinear to RGB and scale from 12bit to 16bit
702  if (desc->flags & AV_PIX_FMT_FLAG_BE) {
703  AV_WB16(dst16 + xp + 0, c->rgbgamma[r] << 4);
704  AV_WB16(dst16 + xp + 1, c->rgbgamma[g] << 4);
705  AV_WB16(dst16 + xp + 2, c->rgbgamma[b] << 4);
706  } else {
707  AV_WL16(dst16 + xp + 0, c->rgbgamma[r] << 4);
708  AV_WL16(dst16 + xp + 1, c->rgbgamma[g] << 4);
709  AV_WL16(dst16 + xp + 2, c->rgbgamma[b] << 4);
710  }
711  }
712 
713  src += src_stride;
714  dst += dst_stride;
715  }
716 }
717 
718 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  const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->opts.dst_format);
722 
723  for (int yp = 0; yp < h; yp++) {
724  uint16_t *src16 = (uint16_t *) src;
725  uint16_t *dst16 = (uint16_t *) dst;
726 
727  for (int xp = 0; xp < 3 * w; xp += 3) {
728  int x, y, z, r, g, b;
729 
730  if (desc->flags & AV_PIX_FMT_FLAG_BE) {
731  r = AV_RB16(src16 + xp + 0);
732  g = AV_RB16(src16 + xp + 1);
733  b = AV_RB16(src16 + xp + 2);
734  } else {
735  r = AV_RL16(src16 + xp + 0);
736  g = AV_RL16(src16 + xp + 1);
737  b = AV_RL16(src16 + xp + 2);
738  }
739 
740  r = c->rgbgammainv[r>>4];
741  g = c->rgbgammainv[g>>4];
742  b = c->rgbgammainv[b>>4];
743 
744  // convert from sRGBlinear to XYZlinear
745  x = c->rgb2xyz_matrix[0][0] * r +
746  c->rgb2xyz_matrix[0][1] * g +
747  c->rgb2xyz_matrix[0][2] * b >> 12;
748  y = c->rgb2xyz_matrix[1][0] * r +
749  c->rgb2xyz_matrix[1][1] * g +
750  c->rgb2xyz_matrix[1][2] * b >> 12;
751  z = c->rgb2xyz_matrix[2][0] * r +
752  c->rgb2xyz_matrix[2][1] * g +
753  c->rgb2xyz_matrix[2][2] * b >> 12;
754 
755  // limit values to 12-bit depth
756  x = av_clip_uintp2(x, 12);
757  y = av_clip_uintp2(y, 12);
758  z = av_clip_uintp2(z, 12);
759 
760  // convert from XYZlinear to X'Y'Z' and scale from 12bit to 16bit
761  if (desc->flags & AV_PIX_FMT_FLAG_BE) {
762  AV_WB16(dst16 + xp + 0, c->xyzgammainv[x] << 4);
763  AV_WB16(dst16 + xp + 1, c->xyzgammainv[y] << 4);
764  AV_WB16(dst16 + xp + 2, c->xyzgammainv[z] << 4);
765  } else {
766  AV_WL16(dst16 + xp + 0, c->xyzgammainv[x] << 4);
767  AV_WL16(dst16 + xp + 1, c->xyzgammainv[y] << 4);
768  AV_WL16(dst16 + xp + 2, c->xyzgammainv[z] << 4);
769  }
770  }
771 
772  src += src_stride;
773  dst += dst_stride;
774  }
775 }
776 
777 void ff_update_palette(SwsInternal *c, const uint32_t *pal)
778 {
779  for (int i = 0; i < 256; i++) {
780  int r, g, b, y, u, v, a = 0xff;
781  if (c->opts.src_format == AV_PIX_FMT_PAL8) {
782  uint32_t p = pal[i];
783  a = (p >> 24) & 0xFF;
784  r = (p >> 16) & 0xFF;
785  g = (p >> 8) & 0xFF;
786  b = p & 0xFF;
787  } else if (c->opts.src_format == AV_PIX_FMT_RGB8) {
788  r = ( i >> 5 ) * 36;
789  g = ((i >> 2) & 7) * 36;
790  b = ( i & 3) * 85;
791  } else if (c->opts.src_format == AV_PIX_FMT_BGR8) {
792  b = ( i >> 6 ) * 85;
793  g = ((i >> 3) & 7) * 36;
794  r = ( i & 7) * 36;
795  } else if (c->opts.src_format == AV_PIX_FMT_RGB4_BYTE) {
796  r = ( i >> 3 ) * 255;
797  g = ((i >> 1) & 3) * 85;
798  b = ( i & 1) * 255;
799  } else if (c->opts.src_format == AV_PIX_FMT_GRAY8 || c->opts.src_format == AV_PIX_FMT_GRAY8A) {
800  r = g = b = i;
801  } else {
802  av_assert1(c->opts.src_format == AV_PIX_FMT_BGR4_BYTE);
803  b = ( i >> 3 ) * 255;
804  g = ((i >> 1) & 3) * 85;
805  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  y = av_clip_uint8((RY * r + GY * g + BY * b + ( 33 << (RGB2YUV_SHIFT - 1))) >> RGB2YUV_SHIFT);
819  u = av_clip_uint8((RU * r + GU * g + BU * b + (257 << (RGB2YUV_SHIFT - 1))) >> RGB2YUV_SHIFT);
820  v = av_clip_uint8((RV * r + GV * g + BV * b + (257 << (RGB2YUV_SHIFT - 1))) >> RGB2YUV_SHIFT);
821  c->pal_yuv[i]= y + (u<<8) + (v<<16) + ((unsigned)a<<24);
822 
823  switch (c->opts.dst_format) {
824  case AV_PIX_FMT_BGR32:
825 #if !HAVE_BIGENDIAN
826  case AV_PIX_FMT_RGB24:
827 #endif
828  c->pal_rgb[i]= r + (g<<8) + (b<<16) + ((unsigned)a<<24);
829  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  case AV_PIX_FMT_RGB32:
843 #if !HAVE_BIGENDIAN
844  case AV_PIX_FMT_BGR24:
845 #endif
846  default:
847  c->pal_rgb[i]= b + (g<<8) + (r<<16) + ((unsigned)a<<24);
848  }
849  }
850 }
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 
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->opts.src_h);
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->opts.dst_h);
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 
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  const int dstH0 = sws_internal(c->cascaded_context[0])->opts.dst_h;
899  int ret = scale_internal(c->cascaded_context[0],
900  srcSlice, srcStride, srcSliceY, srcSliceH,
901  c->cascaded_tmp[0], c->cascaded_tmpStride[0],
902  0, dstH0);
903  if (ret < 0)
904  return ret;
905  ret = scale_internal(c->cascaded_context[1],
906  (const uint8_t * const * )c->cascaded_tmp[0], c->cascaded_tmpStride[0],
907  0, dstH0, dstSlice, dstStride, dstSliceY, dstSliceH);
908  return ret;
909 }
910 
911 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  SwsInternal *c = sws_internal(sws);
918  const int scale_dst = dstSliceY > 0 || dstSliceH < c->opts.dst_h;
919  const int frame_start = scale_dst || !c->sliceDir;
920  int i, ret;
921  const uint8_t *src2[4];
922  uint8_t *dst2[4];
923  int macro_height_src = isBayer(c->opts.src_format) ? 2 : (1 << c->chrSrcVSubSample);
924  int macro_height_dst = isBayer(c->opts.dst_format) ? 2 : (1 << c->chrDstVSubSample);
925  // copy strides, so they can safely be modified
926  int srcStride2[4];
927  int dstStride2[4];
928  int srcSliceY_internal = srcSliceY;
929 
930  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  if ((srcSliceY & (macro_height_src - 1)) ||
936  ((srcSliceH & (macro_height_src - 1)) && srcSliceY + srcSliceH != c->opts.src_h) ||
937  srcSliceY + srcSliceH > c->opts.src_h ||
938  (isBayer(c->opts.src_format) && 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  if ((dstSliceY & (macro_height_dst - 1)) ||
944  ((dstSliceH & (macro_height_dst - 1)) && dstSliceY + dstSliceH != c->opts.dst_h) ||
945  dstSliceY + dstSliceH > c->opts.dst_h) {
946  av_log(c, AV_LOG_ERROR, "Slice parameters %d, %d are invalid\n", dstSliceY, dstSliceH);
947  return AVERROR(EINVAL);
948  }
949 
950  if (!check_image_pointers(srcSlice, c->opts.src_format, srcStride)) {
951  av_log(c, AV_LOG_ERROR, "bad src image pointers\n");
952  return AVERROR(EINVAL);
953  }
954  if (!check_image_pointers((const uint8_t* const*)dstSlice, c->opts.dst_format, 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  if (srcSliceH == 0)
961  return 0;
962 
963  if (c->opts.gamma_flag && c->cascaded_context[0])
964  return scale_gamma(c, srcSlice, srcStride, srcSliceY, srcSliceH,
965  dstSlice, dstStride, dstSliceY, dstSliceH);
966 
967  if (c->cascaded_context[0] && srcSliceY == 0 &&
968  srcSliceH == sws_internal(c->cascaded_context[0])->opts.src_h)
969  {
970  return scale_cascaded(c, srcSlice, srcStride, srcSliceY, srcSliceH,
971  dstSlice, dstStride, dstSliceY, dstSliceH);
972  }
973 
974  if (!srcSliceY && (c->opts.flags & SWS_BITEXACT) && c->opts.dither == SWS_DITHER_ED && c->dither_error[0])
975  for (i = 0; i < 4; i++)
976  memset(c->dither_error[i], 0, sizeof(c->dither_error[0][0]) * (c->opts.dst_w+2));
977 
978  if (usePal(c->opts.src_format))
979  ff_update_palette(c, (const uint32_t *)srcSlice[1]);
980 
981  memcpy(src2, srcSlice, sizeof(src2));
982  memcpy(dst2, dstSlice, sizeof(dst2));
983  memcpy(srcStride2, srcStride, sizeof(srcStride2));
984  memcpy(dstStride2, dstStride, sizeof(dstStride2));
985 
986  if (frame_start && !scale_dst) {
987  if (srcSliceY != 0 && srcSliceY + srcSliceH != c->opts.src_h) {
988  av_log(c, AV_LOG_ERROR, "Slices start in the middle!\n");
989  return AVERROR(EINVAL);
990  }
991 
992  c->sliceDir = (srcSliceY == 0) ? 1 : -1;
993  } else if (scale_dst)
994  c->sliceDir = 1;
995 
996  if (c->src0Alpha && !c->dst0Alpha && isALPHA(c->opts.dst_format)) {
997  uint8_t *base;
998  int x,y;
999 
1000  av_fast_malloc(&c->rgb0_scratch, &c->rgb0_scratch_allocated,
1001  FFABS(srcStride[0]) * srcSliceH + 32);
1002  if (!c->rgb0_scratch)
1003  return AVERROR(ENOMEM);
1004 
1005  base = srcStride[0] < 0 ? c->rgb0_scratch - srcStride[0] * (srcSliceH-1) :
1006  c->rgb0_scratch;
1007  for (y=0; y<srcSliceH; y++){
1008  memcpy(base + srcStride[0]*y, src2[0] + srcStride[0]*y, 4*c->opts.src_w);
1009  for (x=c->src0Alpha-1; x<4*c->opts.src_w; x+=4) {
1010  base[ srcStride[0]*y + x] = 0xFF;
1011  }
1012  }
1013  src2[0] = base;
1014  }
1015 
1016  if (c->srcXYZ && !(c->dstXYZ && c->opts.src_w==c->opts.dst_w && c->opts.src_h==c->opts.dst_h)) {
1017  uint8_t *base;
1018 
1019  av_fast_malloc(&c->xyz_scratch, &c->xyz_scratch_allocated,
1020  FFABS(srcStride[0]) * srcSliceH + 32);
1021  if (!c->xyz_scratch)
1022  return AVERROR(ENOMEM);
1023 
1024  base = srcStride[0] < 0 ? c->xyz_scratch - srcStride[0] * (srcSliceH-1) :
1025  c->xyz_scratch;
1026 
1027  ff_xyz12Torgb48(c, base, srcStride[0], src2[0], srcStride[0], c->opts.src_w, srcSliceH);
1028  src2[0] = base;
1029  }
1030 
1031  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->opts.src_format))
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->opts.dst_h - 1) * dstStride[0];
1044  dst2[1] += ((c->opts.dst_h >> c->chrDstVSubSample) - 1) * dstStride[1];
1045  dst2[2] += ((c->opts.dst_h >> c->chrDstVSubSample) - 1) * dstStride[2];
1046  dst2[3] += ( c->opts.dst_h - 1) * dstStride[3];
1047 
1048  srcSliceY_internal = c->opts.src_h-srcSliceY-srcSliceH;
1049  }
1050  reset_ptr(src2, c->opts.src_format);
1051  reset_ptr((void*)dst2, c->opts.dst_format);
1052 
1053  if (c->convert_unscaled) {
1054  int offset = srcSliceY_internal;
1055  int slice_h = srcSliceH;
1056 
1057  // for dst slice scaling, offset the pointers to match the unscaled API
1058  if (scale_dst) {
1059  av_assert0(offset == 0);
1060  for (i = 0; i < 4 && src2[i]; i++) {
1061  if (!src2[i] || (i > 0 && usePal(c->opts.src_format)))
1062  break;
1063  src2[i] += (dstSliceY >> ((i == 1 || i == 2) ? c->chrSrcVSubSample : 0)) * srcStride2[i];
1064  }
1065 
1066  for (i = 0; i < 4 && dst2[i]; i++) {
1067  if (!dst2[i] || (i > 0 && usePal(c->opts.dst_format)))
1068  break;
1069  dst2[i] -= (dstSliceY >> ((i == 1 || i == 2) ? c->chrDstVSubSample : 0)) * dstStride2[i];
1070  }
1071  offset = dstSliceY;
1072  slice_h = dstSliceH;
1073  }
1074 
1075  ret = c->convert_unscaled(c, src2, srcStride2, offset, slice_h,
1076  dst2, dstStride2);
1077  if (scale_dst)
1078  dst2[0] += dstSliceY * dstStride2[0];
1079  } else {
1080  ret = ff_swscale(c, src2, srcStride2, srcSliceY_internal, srcSliceH,
1081  dst2, dstStride2, dstSliceY, dstSliceH);
1082  }
1083 
1084  if (c->dstXYZ && !(c->srcXYZ && c->opts.src_w==c->opts.dst_w && c->opts.src_h==c->opts.dst_h)) {
1085  uint8_t *dst;
1086 
1087  if (scale_dst) {
1088  dst = dst2[0];
1089  } else {
1090  int dstY = c->dstY ? c->dstY : srcSliceY + srcSliceH;
1091 
1092  av_assert0(dstY >= ret);
1093  av_assert0(ret >= 0);
1094  av_assert0(c->opts.dst_h >= dstY);
1095  dst = dst2[0] + (dstY - ret) * dstStride2[0];
1096  }
1097 
1098  /* replace on the same data */
1099  ff_rgb48Toxyz12(c, dst, dstStride2[0], dst, dstStride2[0], c->opts.dst_w, ret);
1100  }
1101 
1102  /* reset slice direction at end of frame */
1103  if ((srcSliceY_internal + srcSliceH == c->opts.src_h) || scale_dst)
1104  c->sliceDir = 0;
1105 
1106  return ret;
1107 }
1108 
1110 {
1111  SwsInternal *c = sws_internal(sws);
1112  av_frame_unref(c->frame_src);
1113  av_frame_unref(c->frame_dst);
1114  c->src_ranges.nb_ranges = 0;
1115 }
1116 
1118 {
1119  SwsInternal *c = sws_internal(sws);
1120  int ret, allocated = 0;
1121 
1122  ret = av_frame_ref(c->frame_src, src);
1123  if (ret < 0)
1124  return ret;
1125 
1126  if (!dst->buf[0]) {
1127  dst->width = c->opts.dst_w;
1128  dst->height = c->opts.dst_h;
1129  dst->format = c->opts.dst_format;
1130 
1131  ret = av_frame_get_buffer(dst, 0);
1132  if (ret < 0)
1133  return ret;
1134  allocated = 1;
1135  }
1136 
1137  ret = av_frame_ref(c->frame_dst, dst);
1138  if (ret < 0) {
1139  if (allocated)
1141 
1142  return ret;
1143  }
1144 
1145  return 0;
1146 }
1147 
1148 int sws_send_slice(SwsContext *sws, unsigned int slice_start,
1149  unsigned int slice_height)
1150 {
1151  SwsInternal *c = sws_internal(sws);
1152  int ret;
1153 
1154  ret = ff_range_add(&c->src_ranges, slice_start, slice_height);
1155  if (ret < 0)
1156  return ret;
1157 
1158  return 0;
1159 }
1160 
1161 unsigned int sws_receive_slice_alignment(const SwsContext *sws)
1162 {
1163  SwsInternal *c = sws_internal(sws);
1164  if (c->slice_ctx)
1165  return sws_internal(c->slice_ctx[0])->dst_slice_align;
1166 
1167  return c->dst_slice_align;
1168 }
1169 
1171  unsigned int slice_height)
1172 {
1173  SwsInternal *c = sws_internal(sws);
1174  unsigned int align = sws_receive_slice_alignment(sws);
1175  uint8_t *dst[4];
1176 
1177  /* wait until complete input has been received */
1178  if (!(c->src_ranges.nb_ranges == 1 &&
1179  c->src_ranges.ranges[0].start == 0 &&
1180  c->src_ranges.ranges[0].len == c->opts.src_h))
1181  return AVERROR(EAGAIN);
1182 
1183  if ((slice_start > 0 || slice_height < c->opts.dst_h) &&
1184  (slice_start % align || slice_height % align)) {
1186  "Incorrectly aligned output: %u/%u not multiples of %u\n",
1187  slice_start, slice_height, align);
1188  return AVERROR(EINVAL);
1189  }
1190 
1191  if (c->slicethread) {
1192  int nb_jobs = c->nb_slice_ctx;
1193  int ret = 0;
1194 
1195  if (sws_internal(c->slice_ctx[0])->opts.dither == SWS_DITHER_ED)
1196  nb_jobs = 1;
1197 
1198  c->dst_slice_start = slice_start;
1199  c->dst_slice_height = slice_height;
1200 
1201  avpriv_slicethread_execute(c->slicethread, nb_jobs, 0);
1202 
1203  for (int i = 0; i < c->nb_slice_ctx; i++) {
1204  if (c->slice_err[i] < 0) {
1205  ret = c->slice_err[i];
1206  break;
1207  }
1208  }
1209 
1210  memset(c->slice_err, 0, c->nb_slice_ctx * sizeof(*c->slice_err));
1211 
1212  return ret;
1213  }
1214 
1215  for (int i = 0; i < FF_ARRAY_ELEMS(dst); i++) {
1216  ptrdiff_t offset = c->frame_dst->linesize[i] * (ptrdiff_t)(slice_start >> c->chrDstVSubSample);
1217  dst[i] = FF_PTR_ADD(c->frame_dst->data[i], offset);
1218  }
1219 
1220  return scale_internal(sws, (const uint8_t * const *)c->frame_src->data,
1221  c->frame_src->linesize, 0, c->opts.src_h,
1222  dst, c->frame_dst->linesize, slice_start, slice_height);
1223 }
1224 
1226 {
1227  int ret;
1228 
1229  ret = sws_frame_start(sws, dst, src);
1230  if (ret < 0)
1231  return ret;
1232 
1233  ret = sws_send_slice(sws, 0, src->height);
1234  if (ret >= 0)
1235  ret = sws_receive_slice(sws, 0, dst->height);
1236 
1237  sws_frame_end(sws);
1238 
1239  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  */
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  SwsInternal *c = sws_internal(sws);
1253  if (c->nb_slice_ctx) {
1254  sws = c->slice_ctx[0];
1255  c = sws_internal(sws);
1256  }
1257 
1258  return scale_internal(sws, srcSlice, srcStride, srcSliceY, srcSliceH,
1259  dst, dstStride, 0, c->opts.dst_h);
1260 }
1261 
1262 void ff_sws_slice_worker(void *priv, int jobnr, int threadnr,
1263  int nb_jobs, int nb_threads)
1264 {
1265  SwsInternal *parent = priv;
1266  SwsContext *sws = parent->slice_ctx[threadnr];
1267  SwsInternal *c = sws_internal(sws);
1268 
1269  const int slice_height = FFALIGN(FFMAX((parent->dst_slice_height + nb_jobs - 1) / nb_jobs, 1),
1270  c->dst_slice_align);
1271  const int slice_start = jobnr * slice_height;
1272  const int slice_end = FFMIN((jobnr + 1) * slice_height, parent->dst_slice_height);
1273  int err = 0;
1274 
1275  if (slice_end > slice_start) {
1276  uint8_t *dst[4] = { NULL };
1277 
1278  for (int i = 0; i < FF_ARRAY_ELEMS(dst) && parent->frame_dst->data[i]; i++) {
1279  const int vshift = (i == 1 || i == 2) ? c->chrDstVSubSample : 0;
1280  const ptrdiff_t offset = parent->frame_dst->linesize[i] *
1281  (ptrdiff_t)((slice_start + parent->dst_slice_start) >> vshift);
1282 
1283  dst[i] = parent->frame_dst->data[i] + offset;
1284  }
1285 
1286  err = scale_internal(sws, (const uint8_t * const *)parent->frame_src->data,
1287  parent->frame_src->linesize, 0, c->opts.src_h,
1288  dst, parent->frame_dst->linesize,
1290  }
1291 
1292  parent->slice_err[threadnr] = err;
1293 }
sws_init_swscale
static av_cold void sws_init_swscale(SwsInternal *c)
Definition: swscale.c:578
isBayer
static av_always_inline int isBayer(enum AVPixelFormat pix_fmt)
Definition: swscale_internal.h:856
_dst
uint8_t * _dst
Definition: dsp.h:52
yuv2planar1_fn
void(* yuv2planar1_fn)(const int16_t *src, uint8_t *dest, int dstW, const uint8_t *dither, int offset)
Write one line of horizontally scaled data to planar output without any additional vertical scaling (...
Definition: swscale_internal.h:122
AV_LOG_WARNING
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:215
process
static void process(NormalizeContext *s, AVFrame *in, AVFrame *out)
Definition: vf_normalize.c:155
AVPixelFormat
AVPixelFormat
Pixel format.
Definition: pixfmt.h:71
SwsPlane::sliceH
int sliceH
number of lines
Definition: swscale_internal.h:1105
isPacked
static av_always_inline int isPacked(enum AVPixelFormat pix_fmt)
Definition: swscale_internal.h:901
r
const char * r
Definition: vf_curves.c:127
AVERROR
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
mem_internal.h
av_frame_get_buffer
int av_frame_get_buffer(AVFrame *frame, int align)
Allocate new buffer(s) for audio or video data.
Definition: frame.c:292
chrRangeFromJpeg16_c
static void chrRangeFromJpeg16_c(int16_t *_dstU, int16_t *_dstV, int width)
Definition: swscale.c:202
AV_PIX_FMT_BGR32
#define AV_PIX_FMT_BGR32
Definition: pixfmt.h:477
u
#define u(width, name, range_min, range_max)
Definition: cbs_h2645.c:251
ff_rgb48Toxyz12
void ff_rgb48Toxyz12(const SwsInternal *c, uint8_t *dst, int dst_stride, const uint8_t *src, int src_stride, int w, int h)
Definition: swscale.c:718
ff_sws_init_range_convert_aarch64
av_cold void ff_sws_init_range_convert_aarch64(SwsInternal *c)
Definition: swscale.c:226
av_pix_fmt_desc_get
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition: pixdesc.c:3170
av_clip_uintp2
#define av_clip_uintp2
Definition: common.h:124
ff_rotate_slice
int ff_rotate_slice(SwsSlice *s, int lum, int chr)
Definition: slice.c:120
AV_PIX_FMT_FLAG_FLOAT
#define AV_PIX_FMT_FLAG_FLOAT
The pixel format contains IEEE-754 floating point values.
Definition: pixdesc.h:158
SwsSlice::plane
SwsPlane plane[MAX_SLICE_PLANES]
color planes
Definition: swscale_internal.h:1123
avpriv_slicethread_execute
void avpriv_slicethread_execute(AVSliceThread *ctx, int nb_jobs, int execute_main)
Execute slice threading.
Definition: slicethread.c:271
ff_sws_init_range_convert_loongarch
av_cold void ff_sws_init_range_convert_loongarch(SwsInternal *c)
Definition: swscale_init_loongarch.c:27
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:389
pixdesc.h
w
uint8_t w
Definition: llviddspenc.c:38
GV
#define GV
b
#define b
Definition: input.c:41
SwsFilterDescriptor
Struct which holds all necessary data for processing a slice.
Definition: swscale_internal.h:1130
yuv2planeX
static void FUNC() yuv2planeX(const int16_t *filter, int filterSize, const int16_t **src, uint8_t *dest, int dstW, const uint8_t *dither, int offset)
Definition: swscale_ppc_template.c:84
data
const char data[16]
Definition: mxf.c:149
AV_PIX_FMT_MONOWHITE
@ AV_PIX_FMT_MONOWHITE
Y , 1bpp, 0 is white, 1 is black, in each byte pixels are ordered from the msb to the lsb.
Definition: pixfmt.h:82
isGray
#define isGray(x)
Definition: swscale.c:42
AV_PIX_FMT_RGB32_1
#define AV_PIX_FMT_RGB32_1
Definition: pixfmt.h:476
base
uint8_t base
Definition: vp3data.h:128
filter
void(* filter)(uint8_t *src, int stride, int qscale)
Definition: h263dsp.c:29
sws_receive_slice
int sws_receive_slice(SwsContext *sws, unsigned int slice_start, unsigned int slice_height)
Request a horizontal slice of the output data to be written into the frame previously provided to sws...
Definition: swscale.c:1170
AV_PIX_FMT_BGR24
@ AV_PIX_FMT_BGR24
packed RGB 8:8:8, 24bpp, BGRBGR...
Definition: pixfmt.h:76
ff_sws_init_swscale_riscv
av_cold void ff_sws_init_swscale_riscv(SwsInternal *c)
Definition: swscale.c:69
RV
#define RV
FFMAX
#define FFMAX(a, b)
Definition: macros.h:47
av_get_cpu_flags
int av_get_cpu_flags(void)
Return the flags which specify extensions supported by the CPU.
Definition: cpu.c:107
DEBUG_BUFFERS
#define DEBUG_BUFFERS(...)
Definition: swscale.c:232
cpu_flags
static atomic_int cpu_flags
Definition: cpu.c:56
hScale16To15_c
static void hScale16To15_c(SwsInternal *c, int16_t *dst, int dstW, const uint8_t *_src, const int16_t *filter, const int32_t *filterPos, int filterSize)
Definition: swscale.c:95
_src
uint8_t ptrdiff_t const uint8_t * _src
Definition: dsp.h:52
SwsInternal::frame_dst
AVFrame * frame_dst
Definition: swscale_internal.h:391
AVFrame::data
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:410
SWS_FAST_BILINEAR
#define SWS_FAST_BILINEAR
Definition: swscale.h:150
is16BPS
static av_always_inline int is16BPS(enum AVPixelFormat pix_fmt)
Definition: swscale_internal.h:741
SWS_BITEXACT
#define SWS_BITEXACT
Definition: swscale.h:200
ff_sws_init_input_funcs
void ff_sws_init_input_funcs(SwsInternal *c, planar1_YV12_fn *lumToYV12, planar1_YV12_fn *alpToYV12, planar2_YV12_fn *chrToYV12, planarX_YV12_fn *readLumPlanar, planarX_YV12_fn *readAlpPlanar, planarX2_YV12_fn *readChrPlanar)
slice_end
static int slice_end(AVCodecContext *avctx, AVFrame *pict, int *got_output)
Handle slice ends.
Definition: mpeg12dec.c:1719
frame_start
static void frame_start(MpegEncContext *s)
Definition: mpegvideo_enc.c:1778
SwsInternal::opts
struct SwsInternal::@459 opts
SwsInternal::frame_src
AVFrame * frame_src
Definition: swscale_internal.h:390
val
static double val(void *priv, double ch)
Definition: aeval.c:77
isNBPS
static av_always_inline int isNBPS(enum AVPixelFormat pix_fmt)
Definition: swscale_internal.h:755
RY
#define RY
AV_PIX_FMT_BGR8
@ AV_PIX_FMT_BGR8
packed RGB 3:3:2, 8bpp, (msb)2B 3G 3R(lsb)
Definition: pixfmt.h:90
avassert.h
hScale8To19_c
static void hScale8To19_c(SwsInternal *c, int16_t *_dst, int dstW, const uint8_t *src, const int16_t *filter, const int32_t *filterPos, int filterSize)
Definition: swscale.c:140
SwsContext
struct SwsContext SwsContext
Definition: swscale.h:45
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:209
FF_ARRAY_ELEMS
#define FF_ARRAY_ELEMS(a)
Definition: sinewin_tablegen.c:29
av_cold
#define av_cold
Definition: attributes.h:90
yuv2packed2_fn
void(* yuv2packed2_fn)(SwsInternal *c, const int16_t *lumSrc[2], const int16_t *chrUSrc[2], const int16_t *chrVSrc[2], const int16_t *alpSrc[2], uint8_t *dest, int dstW, int yalpha, int uvalpha, int y)
Write one line of horizontally scaled Y/U/V/A to packed-pixel YUV/RGB output by doing bilinear scalin...
Definition: swscale_internal.h:228
SWS_DITHER_ED
@ SWS_DITHER_ED
Definition: swscale_internal.h:80
SwsInternal::slice_err
int * slice_err
Definition: swscale_internal.h:362
emms_c
#define emms_c()
Definition: emms.h:63
intreadwrite.h
SwsInternal::slice_ctx
SwsContext ** slice_ctx
Definition: swscale_internal.h:361
GU
#define GU
ff_update_palette
void ff_update_palette(SwsInternal *c, const uint32_t *pal)
Definition: swscale.c:777
AV_CEIL_RSHIFT
#define AV_CEIL_RSHIFT(a, b)
Definition: common.h:60
ff_sws_init_swscale_arm
av_cold void ff_sws_init_swscale_arm(SwsInternal *c)
Definition: swscale.c:33
format
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample format(the sample packing is implied by the sample format) and sample rate. The lists are not just lists
g
const char * g
Definition: vf_curves.c:128
pix_fmt
static enum AVPixelFormat pix_fmt
Definition: demux_decode.c:41
SwsSlice::width
int width
Slice line width.
Definition: swscale_internal.h:1117
bits
uint8_t bits
Definition: vp3data.h:128
av_assert0
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:40
ctx
AVFormatContext * ctx
Definition: movenc.c:49
AV_RL16
uint64_t_TMPL AV_WL64 unsigned int_TMPL AV_WL32 unsigned int_TMPL AV_WL24 unsigned int_TMPL AV_RL16
Definition: bytestream.h:94
ff_hcscale_fast_c
void ff_hcscale_fast_c(SwsInternal *c, int16_t *dst1, int16_t *dst2, int dstWidth, const uint8_t *src1, const uint8_t *src2, int srcW, int xInc)
Definition: hscale_fast_bilinear.c:38
lumRangeFromJpeg_c
static void lumRangeFromJpeg_c(int16_t *dst, int width)
Definition: swscale.c:184
ff_xyz12Torgb48
void ff_xyz12Torgb48(const SwsInternal *c, uint8_t *dst, int dst_stride, const uint8_t *src, int src_stride, int w, int h)
Definition: swscale.c:659
ff_sws_init_range_convert_riscv
av_cold void ff_sws_init_range_convert_riscv(SwsInternal *c)
Definition: swscale.c:29
AV_PIX_FMT_BGR32_1
#define AV_PIX_FMT_BGR32_1
Definition: pixfmt.h:478
sws_frame_end
void sws_frame_end(SwsContext *sws)
Finish the scaling process for a pair of source/destination frames previously submitted with sws_fram...
Definition: swscale.c:1109
FFABS
#define FFABS(a)
Absolute value, Note, INT_MIN / INT64_MIN result in undefined behavior as they are not representable ...
Definition: common.h:74
ff_sws_init_range_convert_x86
av_cold void ff_sws_init_range_convert_x86(SwsInternal *c)
Definition: swscale.c:475
AV_PIX_FMT_GRAY8A
@ AV_PIX_FMT_GRAY8A
alias for AV_PIX_FMT_YA8
Definition: pixfmt.h:143
scale_internal
static int scale_internal(SwsContext *sws, const uint8_t *const srcSlice[], const int srcStride[], int srcSliceY, int srcSliceH, uint8_t *const dstSlice[], const int dstStride[], int dstSliceY, int dstSliceH)
Definition: swscale.c:911
opts
AVDictionary * opts
Definition: movenc.c:51
fillPlane
static av_always_inline void fillPlane(uint8_t *plane, int stride, int width, int height, int y, uint8_t val)
Definition: swscale.c:54
NULL
#define NULL
Definition: coverity.c:32
SwsPlane::available_lines
int available_lines
max number of lines that can be hold by this plane
Definition: swscale_internal.h:1103
AV_WB16
#define AV_WB16(p, v)
Definition: intreadwrite.h:401
AV_PIX_FMT_MONOBLACK
@ AV_PIX_FMT_MONOBLACK
Y , 1bpp, 0 is black, 1 is white, in each byte pixels are ordered from the msb to the lsb.
Definition: pixfmt.h:83
FF_PTR_ADD
#define FF_PTR_ADD(ptr, off)
Definition: internal.h:80
AV_PIX_FMT_RGB8
@ AV_PIX_FMT_RGB8
packed RGB 3:3:2, 8bpp, (msb)3R 3G 2B(lsb)
Definition: pixfmt.h:93
hScale8To15_c
static void hScale8To15_c(SwsInternal *c, int16_t *dst, int dstW, const uint8_t *src, const int16_t *filter, const int32_t *filterPos, int filterSize)
Definition: swscale.c:124
ff_sws_init_range_convert
av_cold void ff_sws_init_range_convert(SwsInternal *c)
Definition: swscale.c:543
AV_PIX_FMT_GRAY8
@ AV_PIX_FMT_GRAY8
Y , 8bpp.
Definition: pixfmt.h:81
hScale16To19_c
static void hScale16To19_c(SwsInternal *c, int16_t *_dst, int dstW, const uint8_t *_src, const int16_t *filter, const int32_t *filterPos, int filterSize)
Definition: swscale.c:65
c
Undefined Behavior In the C some operations are like signed integer dereferencing freed accessing outside allocated Undefined Behavior must not occur in a C it is not safe even if the output of undefined operations is unused The unsafety may seem nit picking but Optimizing compilers have in fact optimized code on the assumption that no undefined Behavior occurs Optimizing code based on wrong assumptions can and has in some cases lead to effects beyond the output of computations The signed integer overflow problem in speed critical code Code which is highly optimized and works with signed integers sometimes has the problem that often the output of the computation does not c
Definition: undefined.txt:32
SwsInternal::dstY
int dstY
Last destination vertical line output from last slice.
Definition: swscale_internal.h:473
AV_PIX_FMT_BGR4_BYTE
@ AV_PIX_FMT_BGR4_BYTE
packed RGB 1:2:1, 8bpp, (msb)1B 2G 1R(lsb)
Definition: pixfmt.h:92
ff_range_add
int ff_range_add(RangeList *r, unsigned int start, unsigned int len)
Definition: utils.c:2603
chrRangeToJpeg_c
static void chrRangeToJpeg_c(int16_t *dstU, int16_t *dstV, int width)
Definition: swscale.c:159
attribute_align_arg
#define attribute_align_arg
Definition: internal.h:50
yuv2packedX_fn
void(* yuv2packedX_fn)(SwsInternal *c, const int16_t *lumFilter, const int16_t **lumSrc, int lumFilterSize, const int16_t *chrFilter, const int16_t **chrUSrc, const int16_t **chrVSrc, int chrFilterSize, const int16_t **alpSrc, uint8_t *dest, int dstW, int y)
Write one line of horizontally scaled Y/U/V/A to packed-pixel YUV/RGB output by doing multi-point ver...
Definition: swscale_internal.h:260
AV_CPU_FLAG_SSE2
#define AV_CPU_FLAG_SSE2
PIV SSE2 functions.
Definition: cpu.h:35
ff_sws_slice_worker
void ff_sws_slice_worker(void *priv, int jobnr, int threadnr, int nb_jobs, int nb_threads)
Definition: swscale.c:1262
isBE
static av_always_inline int isBE(enum AVPixelFormat pix_fmt)
Definition: swscale_internal.h:762
AV_PIX_FMT_RGB24
@ AV_PIX_FMT_RGB24
packed RGB 8:8:8, 24bpp, RGBRGB...
Definition: pixfmt.h:75
ff_sws_init_swscale_loongarch
av_cold void ff_sws_init_swscale_loongarch(SwsInternal *c)
Definition: swscale_init_loongarch.c:57
height
#define height
Definition: dsp.h:85
av_frame_ref
int av_frame_ref(AVFrame *dst, const AVFrame *src)
Set up a new reference to the data described by the source frame.
Definition: frame.c:388
DECLARE_ALIGNED
#define DECLARE_ALIGNED(n, t, v)
Definition: mem_internal.h:109
fillPlane16
static void fillPlane16(uint8_t *plane, int stride, int width, int height, int y, int alpha, int bits, const int big_endian)
Definition: swscale_internal.h:1063
dst
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
Definition: dsp.h:83
usePal
static av_always_inline int usePal(enum AVPixelFormat pix_fmt)
Definition: swscale_internal.h:932
BV
#define BV
cpu.h
isAnyRGB
static av_always_inline int isAnyRGB(enum AVPixelFormat pix_fmt)
Definition: swscale_internal.h:870
for
for(k=2;k<=8;++k)
Definition: h264pred_template.c:425
chrRangeToJpeg16_c
static void chrRangeToJpeg16_c(int16_t *_dstU, int16_t *_dstV, int width)
Definition: swscale.c:191
RGB2YUV_SHIFT
#define RGB2YUV_SHIFT
align
static const uint8_t *BS_FUNC() align(BSCTX *bc)
Skip bits to a byte boundary.
Definition: bitstream_template.h:411
is32BPS
static av_always_inline int is32BPS(enum AVPixelFormat pix_fmt)
Definition: swscale_internal.h:748
AV_WL16
#define AV_WL16(p, v)
Definition: intreadwrite.h:408
AV_PIX_FMT_RGB32
#define AV_PIX_FMT_RGB32
Definition: pixfmt.h:475
a
The reader does not expect b to be semantically here and if the code is changed by maybe adding a a division or other the signedness will almost certainly be mistaken To avoid this confusion a new type was SUINT is the C unsigned type but it holds a signed int to use the same example SUINT a
Definition: undefined.txt:41
offset
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf offset
Definition: writing_filters.txt:86
ff_sws_init_swscale_ppc
av_cold void ff_sws_init_swscale_ppc(SwsInternal *c)
Definition: swscale_altivec.c:232
fillPlane32
static void fillPlane32(uint8_t *plane, int stride, int width, int height, int y, int alpha, int bits, const int big_endian, int is_float)
Definition: swscale_internal.h:1077
GY
#define GY
yuv2anyX_fn
void(* yuv2anyX_fn)(SwsInternal *c, const int16_t *lumFilter, const int16_t **lumSrc, int lumFilterSize, const int16_t *chrFilter, const int16_t **chrUSrc, const int16_t **chrVSrc, int chrFilterSize, const int16_t **alpSrc, uint8_t **dest, int dstW, int y)
Write one line of horizontally scaled Y/U/V/A to YUV/RGB output by doing multi-point vertical scaling...
Definition: swscale_internal.h:294
ff_sws_init_swscale_x86
av_cold void ff_sws_init_swscale_x86(SwsInternal *c)
Definition: swscale.c:485
scale_cascaded
static int scale_cascaded(SwsInternal *c, const uint8_t *const srcSlice[], const int srcStride[], int srcSliceY, int srcSliceH, uint8_t *const dstSlice[], const int dstStride[], int dstSliceY, int dstSliceH)
Definition: swscale.c:892
emms.h
SwsInternal::dst_slice_align
unsigned int dst_slice_align
Definition: swscale_internal.h:702
av_assert2
#define av_assert2(cond)
assert() equivalent, that does lie in speed critical code.
Definition: avassert.h:67
sws_send_slice
int sws_send_slice(SwsContext *sws, unsigned int slice_start, unsigned int slice_height)
Indicate that a horizontal slice of input data is available in the source frame previously provided t...
Definition: swscale.c:1148
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:256
ff_sws_init_scale
void ff_sws_init_scale(SwsInternal *c)
Definition: swscale.c:611
src2
const pixel * src2
Definition: h264pred_template.c:422
common.h
av_assert1
#define av_assert1(cond)
assert() equivalent, that does not lie in speed critical code.
Definition: avassert.h:56
check_image_pointers
static int check_image_pointers(const uint8_t *const data[4], enum AVPixelFormat pix_fmt, const int linesizes[4])
Definition: swscale.c:642
av_always_inline
#define av_always_inline
Definition: attributes.h:49
swscale_internal.h
SwsInternal::src_h
int src_h
Height of source luma/alpha planes.
Definition: swscale_internal.h:341
yuv2interleavedX_fn
void(* yuv2interleavedX_fn)(enum AVPixelFormat dstFormat, const uint8_t *chrDither, const int16_t *chrFilter, int chrFilterSize, const int16_t **chrUSrc, const int16_t **chrVSrc, uint8_t *dest, int dstW)
Write one line of horizontally scaled chroma to interleaved output with multi-point vertical scaling ...
Definition: swscale_internal.h:158
FFMIN
#define FFMIN(a, b)
Definition: macros.h:49
AV_PIX_FMT_FLAG_BE
#define AV_PIX_FMT_FLAG_BE
Pixel format is big-endian.
Definition: pixdesc.h:116
av_frame_unref
void av_frame_unref(AVFrame *frame)
Unreference all the buffers referenced by frame and reset the frame fields.
Definition: frame.c:610
ff_updateMMXDitherTables
void ff_updateMMXDitherTables(SwsInternal *c, int dstY)
AV_PIX_FMT_RGB4_BYTE
@ AV_PIX_FMT_RGB4_BYTE
packed RGB 1:2:1, 8bpp, (msb)1R 2G 1B(lsb)
Definition: pixfmt.h:95
SwsSlice
Struct which defines a slice of an image to be scaled or an output for a scaled slice.
Definition: swscale_internal.h:1115
slice_start
static int slice_start(SliceContext *sc, VVCContext *s, VVCFrameContext *fc, const CodedBitstreamUnit *unit, const int is_first_slice)
Definition: dec.c:738
stride
#define stride
Definition: h264pred_template.c:537
ff_init_slice_from_src
int ff_init_slice_from_src(SwsSlice *s, uint8_t *const src[4], const int stride[4], int srcW, int lumY, int lumH, int chrY, int chrH, int relative)
Definition: slice.c:148
AV_PIX_FMT_PAL8
@ AV_PIX_FMT_PAL8
8 bits with AV_PIX_FMT_RGB32 palette
Definition: pixfmt.h:84
yuv2packed1_fn
void(* yuv2packed1_fn)(SwsInternal *c, const int16_t *lumSrc, const int16_t *chrUSrc[2], const int16_t *chrVSrc[2], const int16_t *alpSrc, uint8_t *dest, int dstW, int uvalpha, int y)
Write one line of horizontally scaled Y/U/V/A to packed-pixel YUV/RGB output without any additional v...
Definition: swscale_internal.h:195
SwsInternal
Definition: swscale_internal.h:331
ret
ret
Definition: filter_design.txt:187
sws_receive_slice_alignment
unsigned int sws_receive_slice_alignment(const SwsContext *sws)
Get the alignment required for slices.
Definition: swscale.c:1161
__asm__
__asm__(".macro parse_r var r\n\t" "\\var = -1\n\t" _IFC_REG(0) _IFC_REG(1) _IFC_REG(2) _IFC_REG(3) _IFC_REG(4) _IFC_REG(5) _IFC_REG(6) _IFC_REG(7) _IFC_REG(8) _IFC_REG(9) _IFC_REG(10) _IFC_REG(11) _IFC_REG(12) _IFC_REG(13) _IFC_REG(14) _IFC_REG(15) _IFC_REG(16) _IFC_REG(17) _IFC_REG(18) _IFC_REG(19) _IFC_REG(20) _IFC_REG(21) _IFC_REG(22) _IFC_REG(23) _IFC_REG(24) _IFC_REG(25) _IFC_REG(26) _IFC_REG(27) _IFC_REG(28) _IFC_REG(29) _IFC_REG(30) _IFC_REG(31) ".iflt \\var\n\t" ".error \"Unable to parse register name \\r\"\n\t" ".endif\n\t" ".endm")
bswap.h
sws_frame_start
int sws_frame_start(SwsContext *sws, AVFrame *dst, const AVFrame *src)
Initialize the scaling process for a given pair of source/destination frames.
Definition: swscale.c:1117
sws_pb_64
static const uint8_t sws_pb_64[8]
Definition: swscale.c:50
U
#define U(x)
Definition: vpx_arith.h:37
yuv2planarX_fn
void(* yuv2planarX_fn)(const int16_t *filter, int filterSize, const int16_t **src, uint8_t *dest, int dstW, const uint8_t *dither, int offset)
Write one line of horizontally scaled data to planar output with multi-point vertical scaling between...
Definition: swscale_internal.h:138
isALPHA
static av_always_inline int isALPHA(enum AVPixelFormat pix_fmt)
Definition: swscale.c:54
reset_ptr
static void reset_ptr(const uint8_t *src[], enum AVPixelFormat format)
Definition: swscale.c:630
ff_init_vscale_pfn
void ff_init_vscale_pfn(SwsInternal *c, yuv2planar1_fn yuv2plane1, yuv2planarX_fn yuv2planeX, yuv2interleavedX_fn yuv2nv12cX, yuv2packed1_fn yuv2packed1, yuv2packed2_fn yuv2packed2, yuv2packedX_fn yuv2packedX, yuv2anyX_fn yuv2anyX, int use_mmx)
setup vertical scaler functions
Definition: vscale.c:258
sws_scale
int attribute_align_arg sws_scale(SwsContext *sws, const uint8_t *const srcSlice[], const int srcStride[], int srcSliceY, int srcSliceH, uint8_t *const dst[], const int dstStride[])
swscale wrapper, so we don't need to export the SwsContext.
Definition: swscale.c:1246
atomic_exchange_explicit
#define atomic_exchange_explicit(object, desired, order)
Definition: stdatomic.h:106
ff_dither_8x8_128
const uint8_t ff_dither_8x8_128[9][8]
Definition: swscale.c:38
AV_CPU_FLAG_MMXEXT
#define AV_CPU_FLAG_MMXEXT
SSE integer functions or AMD MMX ext.
Definition: cpu.h:31
ff_swscale
int ff_swscale(SwsInternal *c, const uint8_t *const src[], const int srcStride[], int srcSliceY, int srcSliceH, uint8_t *const dst[], const int dstStride[], int dstSliceY, int dstSliceH)
Definition: swscale.c:236
av_clip_uint8
#define av_clip_uint8
Definition: common.h:106
RU
#define RU
lumRangeToJpeg_c
static void lumRangeToJpeg_c(int16_t *dst, int width)
Definition: swscale.c:177
BU
#define BU
lumRangeFromJpeg16_c
static void lumRangeFromJpeg16_c(int16_t *_dst, int width)
Definition: swscale.c:222
desc
const char * desc
Definition: libsvtav1.c:79
SWS_PRINT_INFO
#define SWS_PRINT_INFO
Definition: swscale.h:167
SwsInternal::dst_h
int dst_h
Height of destination luma/alpha planes.
Definition: swscale_internal.h:343
scale_gamma
static int scale_gamma(SwsInternal *c, const uint8_t *const srcSlice[], const int srcStride[], int srcSliceY, int srcSliceH, uint8_t *const dstSlice[], const int dstStride[], int dstSliceY, int dstSliceH)
Definition: swscale.c:858
mem.h
lumRangeToJpeg16_c
static void lumRangeToJpeg16_c(int16_t *_dst, int width)
Definition: swscale.c:213
SwsPlane::sliceY
int sliceY
index of first line
Definition: swscale_internal.h:1104
SwsInternal::dst_slice_height
int dst_slice_height
Definition: swscale_internal.h:367
AVPixFmtDescriptor
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
Definition: pixdesc.h:69
ff_hyscale_fast_c
void ff_hyscale_fast_c(SwsInternal *c, int16_t *dst, int dstWidth, const uint8_t *src, int srcW, int xInc)
Definition: hscale_fast_bilinear.c:23
BY
#define BY
chrRangeFromJpeg_c
static void chrRangeFromJpeg_c(int16_t *dstU, int16_t *dstV, int width)
Definition: swscale.c:168
FFALIGN
#define FFALIGN(x, a)
Definition: macros.h:78
ff_sws_init_output_funcs
av_cold void ff_sws_init_output_funcs(SwsInternal *c, yuv2planar1_fn *yuv2plane1, yuv2planarX_fn *yuv2planeX, yuv2interleavedX_fn *yuv2nv12cX, yuv2packed1_fn *yuv2packed1, yuv2packed2_fn *yuv2packed2, yuv2packedX_fn *yuv2packedX, yuv2anyX_fn *yuv2anyX)
Definition: output.c:3169
av_fast_malloc
void av_fast_malloc(void *ptr, unsigned int *size, size_t min_size)
Allocate a buffer, reusing the given one if large enough.
Definition: mem.c:557
ff_sws_init_swscale_aarch64
av_cold void ff_sws_init_swscale_aarch64(SwsInternal *c)
Definition: swscale.c:243
SwsInternal::dst_slice_start
int dst_slice_start
Definition: swscale_internal.h:366
int32_t
int32_t
Definition: audioconvert.c:56
flags
#define flags(name, subs,...)
Definition: cbs_av1.c:482
AVFrame::linesize
int linesize[AV_NUM_DATA_POINTERS]
For video, a positive or negative value, which is typically indicating the size in bytes of each pict...
Definition: frame.h:434
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
sws_internal
static SwsInternal * sws_internal(const SwsContext *sws)
Definition: swscale_internal.h:71
sws_scale_frame
int sws_scale_frame(SwsContext *sws, AVFrame *dst, const AVFrame *src)
Scale source data from src and write the output to dst.
Definition: swscale.c:1225
h
h
Definition: vp9dsp_template.c:2070
isPlanar
static av_always_inline int isPlanar(enum AVPixelFormat pix_fmt)
Definition: swscale_internal.h:910
width
#define width
Definition: dsp.h:85
src
#define src
Definition: vp8dsp.c:248
swscale.h
AV_RB16
uint64_t_TMPL AV_WL64 unsigned int_TMPL AV_WL32 unsigned int_TMPL AV_WL24 unsigned int_TMPL AV_WL16 uint64_t_TMPL AV_WB64 unsigned int_TMPL AV_WB32 unsigned int_TMPL AV_WB24 unsigned int_TMPL AV_RB16
Definition: bytestream.h:98
SwsInternal::dither
SwsDither dither
Definition: swscale_internal.h:354