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(SwsContext *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->srcFormat);
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->srcFormat) || c->srcFormat==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(SwsContext *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->srcFormat);
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->srcFormat) || c->srcFormat==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(SwsContext *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(SwsContext *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] = (FFMIN(dstU[i], 30775 << 4) * 4663 - (9289992 << 4)) >> 12; // -264
198  dstV[i] = (FFMIN(dstV[i], 30775 << 4) * 4663 - (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(SwsContext *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->dstH;
241 
242  /* load a few things into local vars to make the code more readable?
243  * and faster */
244  const int dstW = c->dstW;
245  int dstH = c->dstH;
246 
247  const enum AVPixelFormat dstFormat = c->dstFormat;
248  const int flags = c->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->srcFormat) ||
265  is16BPS(c->srcFormat);
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->srcFormat)) {
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  SwsContext *const ctx = c->parent ? 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  SwsContext *const ctx = c->parent ? 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->srcW,
368  srcSliceY, srcSliceH, chrSrcSliceY, chrSrcSliceH, 1);
369 
370  ff_init_slice_from_src(vout_slice, (uint8_t**)dst, dstStride, c->dstW,
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->dstH - 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->srcH, firstLumSrcY + vLumFilterSize) - 1;
398  int lastLumSrcY2 = FFMIN(c->srcH, 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 #endif
492  if (should_dither) {
493  c->chrDither8 = ff_dither_8x8_128[chrDstY & 7];
494  c->lumDither8 = ff_dither_8x8_128[dstY & 7];
495  }
496  if (dstY >= c->dstH - 2) {
497  /* hmm looks like we can't use MMX here without overwriting
498  * this array's tail */
499  ff_sws_init_output_funcs(c, &yuv2plane1, &yuv2planeX, &yuv2nv12cX,
500  &yuv2packed1, &yuv2packed2, &yuv2packedX, &yuv2anyX);
501  use_mmx_vfilter= 0;
502  ff_init_vscale_pfn(c, yuv2plane1, yuv2planeX, yuv2nv12cX,
503  yuv2packed1, yuv2packed2, yuv2packedX, yuv2anyX, use_mmx_vfilter);
504  }
505 
506  for (i = vStart; i < vEnd; ++i)
507  desc[i].process(c, &desc[i], dstY, 1);
508  }
509  if (isPlanar(dstFormat) && isALPHA(dstFormat) && !needAlpha) {
510  int offset = lastDstY - dstSliceY;
511  int length = dstW;
512  int height = dstY - lastDstY;
513 
514  if (is16BPS(dstFormat) || isNBPS(dstFormat)) {
515  const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(dstFormat);
516  fillPlane16(dst[3], dstStride[3], length, height, offset,
517  1, desc->comp[3].depth,
518  isBE(dstFormat));
519  } else if (is32BPS(dstFormat)) {
520  const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(dstFormat);
521  fillPlane32(dst[3], dstStride[3], length, height, offset,
522  1, desc->comp[3].depth,
523  isBE(dstFormat), desc->flags & AV_PIX_FMT_FLAG_FLOAT);
524  } else
525  fillPlane(dst[3], dstStride[3], length, height, offset, 255);
526  }
527 
528 #if HAVE_MMXEXT_INLINE
530  __asm__ volatile ("sfence" ::: "memory");
531 #endif
532  emms_c();
533 
534  /* store changed local vars back in the context */
535  c->dstY = dstY;
536  c->lastInLumBuf = lastInLumBuf;
537  c->lastInChrBuf = lastInChrBuf;
538 
539  return dstY - lastDstY;
540 }
541 
543 {
544  c->lumConvertRange = NULL;
545  c->chrConvertRange = NULL;
546  if (c->srcRange != c->dstRange && !isAnyRGB(c->dstFormat)) {
547  if (c->dstBpc <= 14) {
548  if (c->srcRange) {
549  c->lumConvertRange = lumRangeFromJpeg_c;
550  c->chrConvertRange = chrRangeFromJpeg_c;
551  } else {
552  c->lumConvertRange = lumRangeToJpeg_c;
553  c->chrConvertRange = chrRangeToJpeg_c;
554  }
555  } else {
556  if (c->srcRange) {
557  c->lumConvertRange = lumRangeFromJpeg16_c;
558  c->chrConvertRange = chrRangeFromJpeg16_c;
559  } else {
560  c->lumConvertRange = lumRangeToJpeg16_c;
561  c->chrConvertRange = chrRangeToJpeg16_c;
562  }
563  }
564  }
565 }
566 
568 {
569  enum AVPixelFormat srcFormat = c->srcFormat;
570 
571  ff_sws_init_output_funcs(c, &c->yuv2plane1, &c->yuv2planeX,
572  &c->yuv2nv12cX, &c->yuv2packed1,
573  &c->yuv2packed2, &c->yuv2packedX, &c->yuv2anyX);
574 
575  ff_sws_init_input_funcs(c, &c->lumToYV12, &c->alpToYV12, &c->chrToYV12,
576  &c->readLumPlanar, &c->readAlpPlanar, &c->readChrPlanar);
577 
578  if (c->srcBpc == 8) {
579  if (c->dstBpc <= 14) {
580  c->hyScale = c->hcScale = hScale8To15_c;
581  if (c->flags & SWS_FAST_BILINEAR) {
582  c->hyscale_fast = ff_hyscale_fast_c;
583  c->hcscale_fast = ff_hcscale_fast_c;
584  }
585  } else {
586  c->hyScale = c->hcScale = hScale8To19_c;
587  }
588  } else {
589  c->hyScale = c->hcScale = c->dstBpc > 14 ? hScale16To19_c
590  : hScale16To15_c;
591  }
592 
594 
595  if (!(isGray(srcFormat) || isGray(c->dstFormat) ||
596  srcFormat == AV_PIX_FMT_MONOBLACK || srcFormat == AV_PIX_FMT_MONOWHITE))
597  c->needs_hcscale = 1;
598 }
599 
601 {
603 
604 #if ARCH_PPC
606 #elif ARCH_X86
608 #elif ARCH_AARCH64
610 #elif ARCH_ARM
612 #elif ARCH_LOONGARCH64
614 #elif ARCH_RISCV
616 #endif
617 }
618 
619 static void reset_ptr(const uint8_t *src[], enum AVPixelFormat format)
620 {
621  if (!isALPHA(format))
622  src[3] = NULL;
623  if (!isPlanar(format)) {
624  src[3] = src[2] = NULL;
625 
626  if (!usePal(format))
627  src[1] = NULL;
628  }
629 }
630 
631 static int check_image_pointers(const uint8_t * const data[4], enum AVPixelFormat pix_fmt,
632  const int linesizes[4])
633 {
635  int i;
636 
637  av_assert2(desc);
638 
639  for (i = 0; i < 4; i++) {
640  int plane = desc->comp[i].plane;
641  if (!data[plane] || !linesizes[plane])
642  return 0;
643  }
644 
645  return 1;
646 }
647 
648 void ff_xyz12Torgb48(const SwsContext *c, uint8_t *dst, int dst_stride,
649  const uint8_t *src, int src_stride, int w, int h)
650 {
651  const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->srcFormat);
652 
653  for (int yp = 0; yp < h; yp++) {
654  const uint16_t *src16 = (const uint16_t *) src;
655  uint16_t *dst16 = (uint16_t *) dst;
656 
657  for (int xp = 0; xp < 3 * w; xp += 3) {
658  int x, y, z, r, g, b;
659 
660  if (desc->flags & AV_PIX_FMT_FLAG_BE) {
661  x = AV_RB16(src16 + xp + 0);
662  y = AV_RB16(src16 + xp + 1);
663  z = AV_RB16(src16 + xp + 2);
664  } else {
665  x = AV_RL16(src16 + xp + 0);
666  y = AV_RL16(src16 + xp + 1);
667  z = AV_RL16(src16 + xp + 2);
668  }
669 
670  x = c->xyzgamma[x >> 4];
671  y = c->xyzgamma[y >> 4];
672  z = c->xyzgamma[z >> 4];
673 
674  // convert from XYZlinear to sRGBlinear
675  r = c->xyz2rgb_matrix[0][0] * x +
676  c->xyz2rgb_matrix[0][1] * y +
677  c->xyz2rgb_matrix[0][2] * z >> 12;
678  g = c->xyz2rgb_matrix[1][0] * x +
679  c->xyz2rgb_matrix[1][1] * y +
680  c->xyz2rgb_matrix[1][2] * z >> 12;
681  b = c->xyz2rgb_matrix[2][0] * x +
682  c->xyz2rgb_matrix[2][1] * y +
683  c->xyz2rgb_matrix[2][2] * z >> 12;
684 
685  // limit values to 12-bit depth
686  r = av_clip_uintp2(r, 12);
687  g = av_clip_uintp2(g, 12);
688  b = av_clip_uintp2(b, 12);
689 
690  // convert from sRGBlinear to RGB and scale from 12bit to 16bit
691  if (desc->flags & AV_PIX_FMT_FLAG_BE) {
692  AV_WB16(dst16 + xp + 0, c->rgbgamma[r] << 4);
693  AV_WB16(dst16 + xp + 1, c->rgbgamma[g] << 4);
694  AV_WB16(dst16 + xp + 2, c->rgbgamma[b] << 4);
695  } else {
696  AV_WL16(dst16 + xp + 0, c->rgbgamma[r] << 4);
697  AV_WL16(dst16 + xp + 1, c->rgbgamma[g] << 4);
698  AV_WL16(dst16 + xp + 2, c->rgbgamma[b] << 4);
699  }
700  }
701 
702  src += src_stride;
703  dst += dst_stride;
704  }
705 }
706 
707 void ff_rgb48Toxyz12(const SwsContext *c, uint8_t *dst, int dst_stride,
708  const uint8_t *src, int src_stride, int w, int h)
709 {
710  const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->dstFormat);
711 
712  for (int yp = 0; yp < h; yp++) {
713  uint16_t *src16 = (uint16_t *) src;
714  uint16_t *dst16 = (uint16_t *) dst;
715 
716  for (int xp = 0; xp < 3 * w; xp += 3) {
717  int x, y, z, r, g, b;
718 
719  if (desc->flags & AV_PIX_FMT_FLAG_BE) {
720  r = AV_RB16(src16 + xp + 0);
721  g = AV_RB16(src16 + xp + 1);
722  b = AV_RB16(src16 + xp + 2);
723  } else {
724  r = AV_RL16(src16 + xp + 0);
725  g = AV_RL16(src16 + xp + 1);
726  b = AV_RL16(src16 + xp + 2);
727  }
728 
729  r = c->rgbgammainv[r>>4];
730  g = c->rgbgammainv[g>>4];
731  b = c->rgbgammainv[b>>4];
732 
733  // convert from sRGBlinear to XYZlinear
734  x = c->rgb2xyz_matrix[0][0] * r +
735  c->rgb2xyz_matrix[0][1] * g +
736  c->rgb2xyz_matrix[0][2] * b >> 12;
737  y = c->rgb2xyz_matrix[1][0] * r +
738  c->rgb2xyz_matrix[1][1] * g +
739  c->rgb2xyz_matrix[1][2] * b >> 12;
740  z = c->rgb2xyz_matrix[2][0] * r +
741  c->rgb2xyz_matrix[2][1] * g +
742  c->rgb2xyz_matrix[2][2] * b >> 12;
743 
744  // limit values to 12-bit depth
745  x = av_clip_uintp2(x, 12);
746  y = av_clip_uintp2(y, 12);
747  z = av_clip_uintp2(z, 12);
748 
749  // convert from XYZlinear to X'Y'Z' and scale from 12bit to 16bit
750  if (desc->flags & AV_PIX_FMT_FLAG_BE) {
751  AV_WB16(dst16 + xp + 0, c->xyzgammainv[x] << 4);
752  AV_WB16(dst16 + xp + 1, c->xyzgammainv[y] << 4);
753  AV_WB16(dst16 + xp + 2, c->xyzgammainv[z] << 4);
754  } else {
755  AV_WL16(dst16 + xp + 0, c->xyzgammainv[x] << 4);
756  AV_WL16(dst16 + xp + 1, c->xyzgammainv[y] << 4);
757  AV_WL16(dst16 + xp + 2, c->xyzgammainv[z] << 4);
758  }
759  }
760 
761  src += src_stride;
762  dst += dst_stride;
763  }
764 }
765 
766 void ff_update_palette(SwsContext *c, const uint32_t *pal)
767 {
768  for (int i = 0; i < 256; i++) {
769  int r, g, b, y, u, v, a = 0xff;
770  if (c->srcFormat == AV_PIX_FMT_PAL8) {
771  uint32_t p = pal[i];
772  a = (p >> 24) & 0xFF;
773  r = (p >> 16) & 0xFF;
774  g = (p >> 8) & 0xFF;
775  b = p & 0xFF;
776  } else if (c->srcFormat == AV_PIX_FMT_RGB8) {
777  r = ( i >> 5 ) * 36;
778  g = ((i >> 2) & 7) * 36;
779  b = ( i & 3) * 85;
780  } else if (c->srcFormat == AV_PIX_FMT_BGR8) {
781  b = ( i >> 6 ) * 85;
782  g = ((i >> 3) & 7) * 36;
783  r = ( i & 7) * 36;
784  } else if (c->srcFormat == AV_PIX_FMT_RGB4_BYTE) {
785  r = ( i >> 3 ) * 255;
786  g = ((i >> 1) & 3) * 85;
787  b = ( i & 1) * 255;
788  } else if (c->srcFormat == AV_PIX_FMT_GRAY8 || c->srcFormat == AV_PIX_FMT_GRAY8A) {
789  r = g = b = i;
790  } else {
791  av_assert1(c->srcFormat == AV_PIX_FMT_BGR4_BYTE);
792  b = ( i >> 3 ) * 255;
793  g = ((i >> 1) & 3) * 85;
794  r = ( i & 1) * 255;
795  }
796 #define RGB2YUV_SHIFT 15
797 #define BY ( (int) (0.114 * 219 / 255 * (1 << RGB2YUV_SHIFT) + 0.5))
798 #define BV (-(int) (0.081 * 224 / 255 * (1 << RGB2YUV_SHIFT) + 0.5))
799 #define BU ( (int) (0.500 * 224 / 255 * (1 << RGB2YUV_SHIFT) + 0.5))
800 #define GY ( (int) (0.587 * 219 / 255 * (1 << RGB2YUV_SHIFT) + 0.5))
801 #define GV (-(int) (0.419 * 224 / 255 * (1 << RGB2YUV_SHIFT) + 0.5))
802 #define GU (-(int) (0.331 * 224 / 255 * (1 << RGB2YUV_SHIFT) + 0.5))
803 #define RY ( (int) (0.299 * 219 / 255 * (1 << RGB2YUV_SHIFT) + 0.5))
804 #define RV ( (int) (0.500 * 224 / 255 * (1 << RGB2YUV_SHIFT) + 0.5))
805 #define RU (-(int) (0.169 * 224 / 255 * (1 << RGB2YUV_SHIFT) + 0.5))
806 
807  y = av_clip_uint8((RY * r + GY * g + BY * b + ( 33 << (RGB2YUV_SHIFT - 1))) >> RGB2YUV_SHIFT);
808  u = av_clip_uint8((RU * r + GU * g + BU * b + (257 << (RGB2YUV_SHIFT - 1))) >> RGB2YUV_SHIFT);
809  v = av_clip_uint8((RV * r + GV * g + BV * b + (257 << (RGB2YUV_SHIFT - 1))) >> RGB2YUV_SHIFT);
810  c->pal_yuv[i]= y + (u<<8) + (v<<16) + ((unsigned)a<<24);
811 
812  switch (c->dstFormat) {
813  case AV_PIX_FMT_BGR32:
814 #if !HAVE_BIGENDIAN
815  case AV_PIX_FMT_RGB24:
816 #endif
817  c->pal_rgb[i]= r + (g<<8) + (b<<16) + ((unsigned)a<<24);
818  break;
819  case AV_PIX_FMT_BGR32_1:
820 #if HAVE_BIGENDIAN
821  case AV_PIX_FMT_BGR24:
822 #endif
823  c->pal_rgb[i]= a + (r<<8) + (g<<16) + ((unsigned)b<<24);
824  break;
825  case AV_PIX_FMT_RGB32_1:
826 #if HAVE_BIGENDIAN
827  case AV_PIX_FMT_RGB24:
828 #endif
829  c->pal_rgb[i]= a + (b<<8) + (g<<16) + ((unsigned)r<<24);
830  break;
831  case AV_PIX_FMT_RGB32:
832 #if !HAVE_BIGENDIAN
833  case AV_PIX_FMT_BGR24:
834 #endif
835  default:
836  c->pal_rgb[i]= b + (g<<8) + (r<<16) + ((unsigned)a<<24);
837  }
838  }
839 }
840 
841 static int scale_internal(SwsContext *c,
842  const uint8_t * const srcSlice[], const int srcStride[],
843  int srcSliceY, int srcSliceH,
844  uint8_t *const dstSlice[], const int dstStride[],
845  int dstSliceY, int dstSliceH);
846 
848  const uint8_t * const srcSlice[], const int srcStride[],
849  int srcSliceY, int srcSliceH,
850  uint8_t * const dstSlice[], const int dstStride[],
851  int dstSliceY, int dstSliceH)
852 {
853  int ret = scale_internal(c->cascaded_context[0],
854  srcSlice, srcStride, srcSliceY, srcSliceH,
855  c->cascaded_tmp[0], c->cascaded_tmpStride[0], 0, c->srcH);
856 
857  if (ret < 0)
858  return ret;
859 
860  if (c->cascaded_context[2])
861  ret = scale_internal(c->cascaded_context[1], (const uint8_t * const *)c->cascaded_tmp[0],
862  c->cascaded_tmpStride[0], srcSliceY, srcSliceH,
863  c->cascaded_tmp[1], c->cascaded_tmpStride[1], 0, c->dstH);
864  else
865  ret = scale_internal(c->cascaded_context[1], (const uint8_t * const *)c->cascaded_tmp[0],
866  c->cascaded_tmpStride[0], srcSliceY, srcSliceH,
867  dstSlice, dstStride, dstSliceY, dstSliceH);
868 
869  if (ret < 0)
870  return ret;
871 
872  if (c->cascaded_context[2]) {
873  ret = scale_internal(c->cascaded_context[2], (const uint8_t * const *)c->cascaded_tmp[1],
874  c->cascaded_tmpStride[1], c->cascaded_context[1]->dstY - ret,
875  c->cascaded_context[1]->dstY,
876  dstSlice, dstStride, dstSliceY, dstSliceH);
877  }
878  return ret;
879 }
880 
882  const uint8_t * const srcSlice[], const int srcStride[],
883  int srcSliceY, int srcSliceH,
884  uint8_t * const dstSlice[], const int dstStride[],
885  int dstSliceY, int dstSliceH)
886 {
887  int ret = scale_internal(c->cascaded_context[0],
888  srcSlice, srcStride, srcSliceY, srcSliceH,
889  c->cascaded_tmp[0], c->cascaded_tmpStride[0],
890  0, c->cascaded_context[0]->dstH);
891  if (ret < 0)
892  return ret;
893  ret = scale_internal(c->cascaded_context[1],
894  (const uint8_t * const * )c->cascaded_tmp[0], c->cascaded_tmpStride[0],
895  0, c->cascaded_context[0]->dstH,
896  dstSlice, dstStride, dstSliceY, dstSliceH);
897  return ret;
898 }
899 
901  const uint8_t * const srcSlice[], const int srcStride[],
902  int srcSliceY, int srcSliceH,
903  uint8_t *const dstSlice[], const int dstStride[],
904  int dstSliceY, int dstSliceH)
905 {
906  const int scale_dst = dstSliceY > 0 || dstSliceH < c->dstH;
907  const int frame_start = scale_dst || !c->sliceDir;
908  int i, ret;
909  const uint8_t *src2[4];
910  uint8_t *dst2[4];
911  int macro_height_src = isBayer(c->srcFormat) ? 2 : (1 << c->chrSrcVSubSample);
912  int macro_height_dst = isBayer(c->dstFormat) ? 2 : (1 << c->chrDstVSubSample);
913  // copy strides, so they can safely be modified
914  int srcStride2[4];
915  int dstStride2[4];
916  int srcSliceY_internal = srcSliceY;
917 
918  if (!srcStride || !dstStride || !dstSlice || !srcSlice) {
919  av_log(c, AV_LOG_ERROR, "One of the input parameters to sws_scale() is NULL, please check the calling code\n");
920  return AVERROR(EINVAL);
921  }
922 
923  if ((srcSliceY & (macro_height_src - 1)) ||
924  ((srcSliceH & (macro_height_src - 1)) && srcSliceY + srcSliceH != c->srcH) ||
925  srcSliceY + srcSliceH > c->srcH ||
926  (isBayer(c->srcFormat) && srcSliceH <= 1)) {
927  av_log(c, AV_LOG_ERROR, "Slice parameters %d, %d are invalid\n", srcSliceY, srcSliceH);
928  return AVERROR(EINVAL);
929  }
930 
931  if ((dstSliceY & (macro_height_dst - 1)) ||
932  ((dstSliceH & (macro_height_dst - 1)) && dstSliceY + dstSliceH != c->dstH) ||
933  dstSliceY + dstSliceH > c->dstH) {
934  av_log(c, AV_LOG_ERROR, "Slice parameters %d, %d are invalid\n", dstSliceY, dstSliceH);
935  return AVERROR(EINVAL);
936  }
937 
938  if (!check_image_pointers(srcSlice, c->srcFormat, srcStride)) {
939  av_log(c, AV_LOG_ERROR, "bad src image pointers\n");
940  return AVERROR(EINVAL);
941  }
942  if (!check_image_pointers((const uint8_t* const*)dstSlice, c->dstFormat, dstStride)) {
943  av_log(c, AV_LOG_ERROR, "bad dst image pointers\n");
944  return AVERROR(EINVAL);
945  }
946 
947  // do not mess up sliceDir if we have a "trailing" 0-size slice
948  if (srcSliceH == 0)
949  return 0;
950 
951  if (c->gamma_flag && c->cascaded_context[0])
952  return scale_gamma(c, srcSlice, srcStride, srcSliceY, srcSliceH,
953  dstSlice, dstStride, dstSliceY, dstSliceH);
954 
955  if (c->cascaded_context[0] && srcSliceY == 0 && srcSliceH == c->cascaded_context[0]->srcH)
956  return scale_cascaded(c, srcSlice, srcStride, srcSliceY, srcSliceH,
957  dstSlice, dstStride, dstSliceY, dstSliceH);
958 
959  if (!srcSliceY && (c->flags & SWS_BITEXACT) && c->dither == SWS_DITHER_ED && c->dither_error[0])
960  for (i = 0; i < 4; i++)
961  memset(c->dither_error[i], 0, sizeof(c->dither_error[0][0]) * (c->dstW+2));
962 
963  if (usePal(c->srcFormat))
964  ff_update_palette(c, (const uint32_t *)srcSlice[1]);
965 
966  memcpy(src2, srcSlice, sizeof(src2));
967  memcpy(dst2, dstSlice, sizeof(dst2));
968  memcpy(srcStride2, srcStride, sizeof(srcStride2));
969  memcpy(dstStride2, dstStride, sizeof(dstStride2));
970 
971  if (frame_start && !scale_dst) {
972  if (srcSliceY != 0 && srcSliceY + srcSliceH != c->srcH) {
973  av_log(c, AV_LOG_ERROR, "Slices start in the middle!\n");
974  return AVERROR(EINVAL);
975  }
976 
977  c->sliceDir = (srcSliceY == 0) ? 1 : -1;
978  } else if (scale_dst)
979  c->sliceDir = 1;
980 
981  if (c->src0Alpha && !c->dst0Alpha && isALPHA(c->dstFormat)) {
982  uint8_t *base;
983  int x,y;
984 
985  av_fast_malloc(&c->rgb0_scratch, &c->rgb0_scratch_allocated,
986  FFABS(srcStride[0]) * srcSliceH + 32);
987  if (!c->rgb0_scratch)
988  return AVERROR(ENOMEM);
989 
990  base = srcStride[0] < 0 ? c->rgb0_scratch - srcStride[0] * (srcSliceH-1) :
991  c->rgb0_scratch;
992  for (y=0; y<srcSliceH; y++){
993  memcpy(base + srcStride[0]*y, src2[0] + srcStride[0]*y, 4*c->srcW);
994  for (x=c->src0Alpha-1; x<4*c->srcW; x+=4) {
995  base[ srcStride[0]*y + x] = 0xFF;
996  }
997  }
998  src2[0] = base;
999  }
1000 
1001  if (c->srcXYZ && !(c->dstXYZ && c->srcW==c->dstW && c->srcH==c->dstH)) {
1002  uint8_t *base;
1003 
1004  av_fast_malloc(&c->xyz_scratch, &c->xyz_scratch_allocated,
1005  FFABS(srcStride[0]) * srcSliceH + 32);
1006  if (!c->xyz_scratch)
1007  return AVERROR(ENOMEM);
1008 
1009  base = srcStride[0] < 0 ? c->xyz_scratch - srcStride[0] * (srcSliceH-1) :
1010  c->xyz_scratch;
1011 
1012  ff_xyz12Torgb48(c, base, srcStride[0], src2[0], srcStride[0], c->srcW, srcSliceH);
1013  src2[0] = base;
1014  }
1015 
1016  if (c->sliceDir != 1) {
1017  // slices go from bottom to top => we flip the image internally
1018  for (i=0; i<4; i++) {
1019  srcStride2[i] *= -1;
1020  dstStride2[i] *= -1;
1021  }
1022 
1023  src2[0] += (srcSliceH - 1) * srcStride[0];
1024  if (!usePal(c->srcFormat))
1025  src2[1] += ((srcSliceH >> c->chrSrcVSubSample) - 1) * srcStride[1];
1026  src2[2] += ((srcSliceH >> c->chrSrcVSubSample) - 1) * srcStride[2];
1027  src2[3] += (srcSliceH - 1) * srcStride[3];
1028  dst2[0] += ( c->dstH - 1) * dstStride[0];
1029  dst2[1] += ((c->dstH >> c->chrDstVSubSample) - 1) * dstStride[1];
1030  dst2[2] += ((c->dstH >> c->chrDstVSubSample) - 1) * dstStride[2];
1031  dst2[3] += ( c->dstH - 1) * dstStride[3];
1032 
1033  srcSliceY_internal = c->srcH-srcSliceY-srcSliceH;
1034  }
1035  reset_ptr(src2, c->srcFormat);
1036  reset_ptr((void*)dst2, c->dstFormat);
1037 
1038  if (c->convert_unscaled) {
1039  int offset = srcSliceY_internal;
1040  int slice_h = srcSliceH;
1041 
1042  // for dst slice scaling, offset the pointers to match the unscaled API
1043  if (scale_dst) {
1044  av_assert0(offset == 0);
1045  for (i = 0; i < 4 && src2[i]; i++) {
1046  if (!src2[i] || (i > 0 && usePal(c->srcFormat)))
1047  break;
1048  src2[i] += (dstSliceY >> ((i == 1 || i == 2) ? c->chrSrcVSubSample : 0)) * srcStride2[i];
1049  }
1050 
1051  for (i = 0; i < 4 && dst2[i]; i++) {
1052  if (!dst2[i] || (i > 0 && usePal(c->dstFormat)))
1053  break;
1054  dst2[i] -= (dstSliceY >> ((i == 1 || i == 2) ? c->chrDstVSubSample : 0)) * dstStride2[i];
1055  }
1056  offset = dstSliceY;
1057  slice_h = dstSliceH;
1058  }
1059 
1060  ret = c->convert_unscaled(c, src2, srcStride2, offset, slice_h,
1061  dst2, dstStride2);
1062  if (scale_dst)
1063  dst2[0] += dstSliceY * dstStride2[0];
1064  } else {
1065  ret = ff_swscale(c, src2, srcStride2, srcSliceY_internal, srcSliceH,
1066  dst2, dstStride2, dstSliceY, dstSliceH);
1067  }
1068 
1069  if (c->dstXYZ && !(c->srcXYZ && c->srcW==c->dstW && c->srcH==c->dstH)) {
1070  uint8_t *dst;
1071 
1072  if (scale_dst) {
1073  dst = dst2[0];
1074  } else {
1075  int dstY = c->dstY ? c->dstY : srcSliceY + srcSliceH;
1076 
1077  av_assert0(dstY >= ret);
1078  av_assert0(ret >= 0);
1079  av_assert0(c->dstH >= dstY);
1080  dst = dst2[0] + (dstY - ret) * dstStride2[0];
1081  }
1082 
1083  /* replace on the same data */
1084  ff_rgb48Toxyz12(c, dst, dstStride2[0], dst, dstStride2[0], c->dstW, ret);
1085  }
1086 
1087  /* reset slice direction at end of frame */
1088  if ((srcSliceY_internal + srcSliceH == c->srcH) || scale_dst)
1089  c->sliceDir = 0;
1090 
1091  return ret;
1092 }
1093 
1095 {
1096  av_frame_unref(c->frame_src);
1097  av_frame_unref(c->frame_dst);
1098  c->src_ranges.nb_ranges = 0;
1099 }
1100 
1102 {
1103  int ret, allocated = 0;
1104 
1105  ret = av_frame_ref(c->frame_src, src);
1106  if (ret < 0)
1107  return ret;
1108 
1109  if (!dst->buf[0]) {
1110  dst->width = c->dstW;
1111  dst->height = c->dstH;
1112  dst->format = c->dstFormat;
1113 
1114  ret = av_frame_get_buffer(dst, 0);
1115  if (ret < 0)
1116  return ret;
1117  allocated = 1;
1118  }
1119 
1120  ret = av_frame_ref(c->frame_dst, dst);
1121  if (ret < 0) {
1122  if (allocated)
1124 
1125  return ret;
1126  }
1127 
1128  return 0;
1129 }
1130 
1131 int sws_send_slice(struct SwsContext *c, unsigned int slice_start,
1132  unsigned int slice_height)
1133 {
1134  int ret;
1135 
1136  ret = ff_range_add(&c->src_ranges, slice_start, slice_height);
1137  if (ret < 0)
1138  return ret;
1139 
1140  return 0;
1141 }
1142 
1143 unsigned int sws_receive_slice_alignment(const struct SwsContext *c)
1144 {
1145  if (c->slice_ctx)
1146  return c->slice_ctx[0]->dst_slice_align;
1147 
1148  return c->dst_slice_align;
1149 }
1150 
1151 int sws_receive_slice(struct SwsContext *c, unsigned int slice_start,
1152  unsigned int slice_height)
1153 {
1154  unsigned int align = sws_receive_slice_alignment(c);
1155  uint8_t *dst[4];
1156 
1157  /* wait until complete input has been received */
1158  if (!(c->src_ranges.nb_ranges == 1 &&
1159  c->src_ranges.ranges[0].start == 0 &&
1160  c->src_ranges.ranges[0].len == c->srcH))
1161  return AVERROR(EAGAIN);
1162 
1163  if ((slice_start > 0 || slice_height < c->dstH) &&
1164  (slice_start % align || slice_height % align)) {
1166  "Incorrectly aligned output: %u/%u not multiples of %u\n",
1167  slice_start, slice_height, align);
1168  return AVERROR(EINVAL);
1169  }
1170 
1171  if (c->slicethread) {
1172  int nb_jobs = c->slice_ctx[0]->dither == SWS_DITHER_ED ? 1 : c->nb_slice_ctx;
1173  int ret = 0;
1174 
1175  c->dst_slice_start = slice_start;
1176  c->dst_slice_height = slice_height;
1177 
1178  avpriv_slicethread_execute(c->slicethread, nb_jobs, 0);
1179 
1180  for (int i = 0; i < c->nb_slice_ctx; i++) {
1181  if (c->slice_err[i] < 0) {
1182  ret = c->slice_err[i];
1183  break;
1184  }
1185  }
1186 
1187  memset(c->slice_err, 0, c->nb_slice_ctx * sizeof(*c->slice_err));
1188 
1189  return ret;
1190  }
1191 
1192  for (int i = 0; i < FF_ARRAY_ELEMS(dst); i++) {
1193  ptrdiff_t offset = c->frame_dst->linesize[i] * (ptrdiff_t)(slice_start >> c->chrDstVSubSample);
1194  dst[i] = FF_PTR_ADD(c->frame_dst->data[i], offset);
1195  }
1196 
1197  return scale_internal(c, (const uint8_t * const *)c->frame_src->data,
1198  c->frame_src->linesize, 0, c->srcH,
1199  dst, c->frame_dst->linesize, slice_start, slice_height);
1200 }
1201 
1203 {
1204  int ret;
1205 
1206  ret = sws_frame_start(c, dst, src);
1207  if (ret < 0)
1208  return ret;
1209 
1210  ret = sws_send_slice(c, 0, src->height);
1211  if (ret >= 0)
1212  ret = sws_receive_slice(c, 0, dst->height);
1213 
1214  sws_frame_end(c);
1215 
1216  return ret;
1217 }
1218 
1219 /**
1220  * swscale wrapper, so we don't need to export the SwsContext.
1221  * Assumes planar YUV to be in YUV order instead of YVU.
1222  */
1224  const uint8_t * const srcSlice[],
1225  const int srcStride[], int srcSliceY,
1226  int srcSliceH, uint8_t *const dst[],
1227  const int dstStride[])
1228 {
1229  if (c->nb_slice_ctx)
1230  c = c->slice_ctx[0];
1231 
1232  return scale_internal(c, srcSlice, srcStride, srcSliceY, srcSliceH,
1233  dst, dstStride, 0, c->dstH);
1234 }
1235 
1236 void ff_sws_slice_worker(void *priv, int jobnr, int threadnr,
1237  int nb_jobs, int nb_threads)
1238 {
1239  SwsContext *parent = priv;
1240  SwsContext *c = parent->slice_ctx[threadnr];
1241 
1242  const int slice_height = FFALIGN(FFMAX((parent->dst_slice_height + nb_jobs - 1) / nb_jobs, 1),
1243  c->dst_slice_align);
1244  const int slice_start = jobnr * slice_height;
1245  const int slice_end = FFMIN((jobnr + 1) * slice_height, parent->dst_slice_height);
1246  int err = 0;
1247 
1248  if (slice_end > slice_start) {
1249  uint8_t *dst[4] = { NULL };
1250 
1251  for (int i = 0; i < FF_ARRAY_ELEMS(dst) && parent->frame_dst->data[i]; i++) {
1252  const int vshift = (i == 1 || i == 2) ? c->chrDstVSubSample : 0;
1253  const ptrdiff_t offset = parent->frame_dst->linesize[i] *
1254  (ptrdiff_t)((slice_start + parent->dst_slice_start) >> vshift);
1255 
1256  dst[i] = parent->frame_dst->data[i] + offset;
1257  }
1258 
1259  err = scale_internal(c, (const uint8_t * const *)parent->frame_src->data,
1260  parent->frame_src->linesize, 0, c->srcH,
1261  dst, parent->frame_dst->linesize,
1263  }
1264 
1265  parent->slice_err[threadnr] = err;
1266 }
isBayer
static av_always_inline int isBayer(enum AVPixelFormat pix_fmt)
Definition: swscale_internal.h:836
yuv2packed2_fn
void(* yuv2packed2_fn)(struct SwsContext *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:221
_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:115
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
yuv2packed1_fn
void(* yuv2packed1_fn)(struct SwsContext *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:188
AVPixelFormat
AVPixelFormat
Pixel format.
Definition: pixfmt.h:71
SwsPlane::sliceH
int sliceH
number of lines
Definition: swscale_internal.h:1085
hScale16To19_c
static void hScale16To19_c(SwsContext *c, int16_t *_dst, int dstW, const uint8_t *_src, const int16_t *filter, const int32_t *filterPos, int filterSize)
Definition: swscale.c:65
isPacked
static av_always_inline int isPacked(enum AVPixelFormat pix_fmt)
Definition: swscale_internal.h:881
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:462
u
#define u(width, name, range_min, range_max)
Definition: cbs_h2645.c:251
av_pix_fmt_desc_get
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition: pixdesc.c:3025
av_clip_uintp2
#define av_clip_uintp2
Definition: common.h:124
ff_hyscale_fast_c
void ff_hyscale_fast_c(SwsContext *c, int16_t *dst, int dstWidth, const uint8_t *src, int srcW, int xInc)
Definition: hscale_fast_bilinear.c:23
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:1103
avpriv_slicethread_execute
void avpriv_slicethread_execute(AVSliceThread *ctx, int nb_jobs, int execute_main)
Execute slice threading.
Definition: slicethread.c:271
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:389
pixdesc.h
w
uint8_t w
Definition: llviddspenc.c:38
hScale8To15_c
static void hScale8To15_c(SwsContext *c, int16_t *dst, int dstW, const uint8_t *src, const int16_t *filter, const int32_t *filterPos, int filterSize)
Definition: swscale.c:124
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:1110
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
ff_update_palette
void ff_update_palette(SwsContext *c, const uint32_t *pal)
Definition: swscale.c:766
isGray
#define isGray(x)
Definition: swscale.c:42
AV_PIX_FMT_RGB32_1
#define AV_PIX_FMT_RGB32_1
Definition: pixfmt.h:461
base
uint8_t base
Definition: vp3data.h:128
filter
void(* filter)(uint8_t *src, int stride, int qscale)
Definition: h263dsp.c:29
AV_PIX_FMT_BGR24
@ AV_PIX_FMT_BGR24
packed RGB 8:8:8, 24bpp, BGRBGR...
Definition: pixfmt.h:76
sws_scale
int attribute_align_arg sws_scale(struct SwsContext *c, 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:1223
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
scale_internal
static int scale_internal(SwsContext *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:900
cpu_flags
static atomic_int cpu_flags
Definition: cpu.c:56
sws_send_slice
int sws_send_slice(struct SwsContext *c, 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:1131
scale_cascaded
static int scale_cascaded(SwsContext *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:881
_src
uint8_t ptrdiff_t const uint8_t * _src
Definition: dsp.h:52
AVFrame::data
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:410
sws_receive_slice
int sws_receive_slice(struct SwsContext *c, 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:1151
SWS_FAST_BILINEAR
#define SWS_FAST_BILINEAR
Definition: swscale.h:65
is16BPS
static av_always_inline int is16BPS(enum AVPixelFormat pix_fmt)
Definition: swscale_internal.h:721
ff_sws_init_swscale_aarch64
av_cold void ff_sws_init_swscale_aarch64(SwsContext *c)
Definition: swscale.c:241
SWS_BITEXACT
#define SWS_BITEXACT
Definition: swscale.h:115
slice_end
static int slice_end(AVCodecContext *avctx, AVFrame *pict, int *got_output)
Handle slice ends.
Definition: mpeg12dec.c:1719
yuv2anyX_fn
void(* yuv2anyX_fn)(struct SwsContext *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:287
frame_start
static void frame_start(MpegEncContext *s)
Definition: mpegvideo_enc.c:1778
hScale8To19_c
static void hScale8To19_c(SwsContext *c, int16_t *_dst, int dstW, const uint8_t *src, const int16_t *filter, const int32_t *filterPos, int filterSize)
Definition: swscale.c:140
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:735
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
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
SwsContext::dst_slice_height
int dst_slice_height
Definition: swscale_internal.h:339
ff_sws_init_swscale_loongarch
av_cold void ff_sws_init_swscale_loongarch(SwsContext *c)
Definition: swscale_init_loongarch.c:61
sws_init_swscale
static av_cold void sws_init_swscale(SwsContext *c)
Definition: swscale.c:567
SWS_DITHER_ED
@ SWS_DITHER_ED
Definition: swscale_internal.h:73
emms_c
#define emms_c()
Definition: emms.h:63
intreadwrite.h
GU
#define GU
sws_frame_start
int sws_frame_start(struct SwsContext *c, AVFrame *dst, const AVFrame *src)
Initialize the scaling process for a given pair of source/destination frames.
Definition: swscale.c:1101
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(SwsContext *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:1097
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
scale_gamma
static int scale_gamma(SwsContext *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:847
lumRangeFromJpeg_c
static void lumRangeFromJpeg_c(int16_t *dst, int width)
Definition: swscale.c:184
ff_init_vscale_pfn
void ff_init_vscale_pfn(SwsContext *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
AV_PIX_FMT_BGR32_1
#define AV_PIX_FMT_BGR32_1
Definition: pixfmt.h:463
FFABS
#define FFABS(a)
Absolute value, Note, INT_MIN / INT64_MIN result in undefined behavior as they are not representable ...
Definition: common.h:74
SwsContext::dst_slice_start
int dst_slice_start
Definition: swscale_internal.h:338
ff_sws_init_range_convert
av_cold void ff_sws_init_range_convert(SwsContext *c)
Definition: swscale.c:542
SwsContext::slice_err
int * slice_err
Definition: swscale_internal.h:334
AV_PIX_FMT_GRAY8A
@ AV_PIX_FMT_GRAY8A
alias for AV_PIX_FMT_YA8
Definition: pixfmt.h:143
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:1083
ff_sws_init_swscale_x86
av_cold void ff_sws_init_swscale_x86(SwsContext *c)
Definition: swscale.c:487
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
AV_PIX_FMT_GRAY8
@ AV_PIX_FMT_GRAY8
Y , 8bpp.
Definition: pixfmt.h:81
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
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:2572
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
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:1236
isBE
static av_always_inline int isBE(enum AVPixelFormat pix_fmt)
Definition: swscale_internal.h:742
AV_PIX_FMT_RGB24
@ AV_PIX_FMT_RGB24
packed RGB 8:8:8, 24bpp, RGBRGB...
Definition: pixfmt.h:75
ff_sws_init_scale
void ff_sws_init_scale(SwsContext *c)
Definition: swscale.c:600
ff_swscale
int ff_swscale(SwsContext *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
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:1043
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:912
BV
#define BV
cpu.h
isAnyRGB
static av_always_inline int isAnyRGB(enum AVPixelFormat pix_fmt)
Definition: swscale_internal.h:850
for
for(k=2;k<=8;++k)
Definition: h264pred_template.c:425
hScale16To15_c
static void hScale16To15_c(SwsContext *c, int16_t *dst, int dstW, const uint8_t *_src, const int16_t *filter, const int32_t *filterPos, int filterSize)
Definition: swscale.c:95
SwsContext::slice_ctx
struct SwsContext ** slice_ctx
Definition: swscale_internal.h:333
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:728
AV_WL16
#define AV_WL16(p, v)
Definition: intreadwrite.h:408
AV_PIX_FMT_RGB32
#define AV_PIX_FMT_RGB32
Definition: pixfmt.h:460
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_hcscale_fast_c
void ff_hcscale_fast_c(SwsContext *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
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:1057
GY
#define GY
emms.h
SwsContext::frame_src
AVFrame * frame_src
Definition: swscale_internal.h:369
sws_scale_frame
int sws_scale_frame(struct SwsContext *c, AVFrame *dst, const AVFrame *src)
Scale source data from src and write the output to dst.
Definition: swscale.c:1202
ff_sws_init_swscale_riscv
av_cold void ff_sws_init_swscale_riscv(SwsContext *c)
Definition: swscale.c:68
av_assert2
#define av_assert2(cond)
assert() equivalent, that does lie in speed critical code.
Definition: avassert.h:67
ff_sws_init_input_funcs
void ff_sws_init_input_funcs(SwsContext *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)
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:256
src2
const pixel * src2
Definition: h264pred_template.c:422
common.h
sws_receive_slice_alignment
unsigned int sws_receive_slice_alignment(const struct SwsContext *c)
Get the alignment required for slices.
Definition: swscale.c:1143
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:631
av_always_inline
#define av_always_inline
Definition: attributes.h:49
swscale_internal.h
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:151
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
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:1095
slice_start
static int slice_start(SliceContext *sc, VVCContext *s, VVCFrameContext *fc, const CodedBitstreamUnit *unit, const int is_first_slice)
Definition: dec.c:737
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
ret
ret
Definition: filter_design.txt:187
__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_pb_64
static const uint8_t sws_pb_64[8]
Definition: swscale.c:50
sws_frame_end
void sws_frame_end(struct SwsContext *c)
Finish the scaling process for a pair of source/destination frames previously submitted with sws_fram...
Definition: swscale.c:1094
ff_sws_init_swscale_ppc
av_cold void ff_sws_init_swscale_ppc(SwsContext *c)
Definition: swscale_altivec.c:232
ff_rgb48Toxyz12
void ff_rgb48Toxyz12(const SwsContext *c, uint8_t *dst, int dst_stride, const uint8_t *src, int src_stride, int w, int h)
Definition: swscale.c:707
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:131
ff_sws_init_output_funcs
void ff_sws_init_output_funcs(SwsContext *c, yuv2planar1_fn *yuv2plane1, yuv2planarX_fn *yuv2planeX, yuv2interleavedX_fn *yuv2nv12cX, yuv2packed1_fn *yuv2packed1, yuv2packed2_fn *yuv2packed2, yuv2packedX_fn *yuv2packedX, yuv2anyX_fn *yuv2anyX)
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:619
yuv2packedX_fn
void(* yuv2packedX_fn)(struct SwsContext *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:253
SwsContext::frame_dst
AVFrame * frame_dst
Definition: swscale_internal.h:370
ff_xyz12Torgb48
void ff_xyz12Torgb48(const SwsContext *c, uint8_t *dst, int dst_stride, const uint8_t *src, int src_stride, int w, int h)
Definition: swscale.c:648
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
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:82
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:1084
AVPixFmtDescriptor
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
Definition: pixdesc.h:69
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
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
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
h
h
Definition: vp9dsp_template.c:2070
ff_updateMMXDitherTables
void ff_updateMMXDitherTables(SwsContext *c, int dstY)
isPlanar
static av_always_inline int isPlanar(enum AVPixelFormat pix_fmt)
Definition: swscale_internal.h:890
width
#define width
Definition: dsp.h:85
SwsContext
Definition: swscale_internal.h:324
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