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_internal.h"
32 #include "libavutil/pixdesc.h"
33 #include "config.h"
34 #include "swscale_internal.h"
35 #include "swscale.h"
36 
37 DECLARE_ALIGNED(8, const uint8_t, ff_dither_8x8_128)[9][8] = {
38  { 36, 68, 60, 92, 34, 66, 58, 90, },
39  { 100, 4, 124, 28, 98, 2, 122, 26, },
40  { 52, 84, 44, 76, 50, 82, 42, 74, },
41  { 116, 20, 108, 12, 114, 18, 106, 10, },
42  { 32, 64, 56, 88, 38, 70, 62, 94, },
43  { 96, 0, 120, 24, 102, 6, 126, 30, },
44  { 48, 80, 40, 72, 54, 86, 46, 78, },
45  { 112, 16, 104, 8, 118, 22, 110, 14, },
46  { 36, 68, 60, 92, 34, 66, 58, 90, },
47 };
48 
49 DECLARE_ALIGNED(8, static const uint8_t, sws_pb_64)[8] = {
50  64, 64, 64, 64, 64, 64, 64, 64
51 };
52 
53 static av_always_inline void fillPlane(uint8_t *plane, int stride, int width,
54  int height, int y, uint8_t val)
55 {
56  int i;
57  uint8_t *ptr = plane + stride * y;
58  for (i = 0; i < height; i++) {
59  memset(ptr, val, width);
60  ptr += stride;
61  }
62 }
63 
64 static void hScale16To19_c(SwsContext *c, int16_t *_dst, int dstW,
65  const uint8_t *_src, const int16_t *filter,
66  const int32_t *filterPos, int filterSize)
67 {
68  const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->srcFormat);
69  int i;
70  int32_t *dst = (int32_t *) _dst;
71  const uint16_t *src = (const uint16_t *) _src;
72  int bits = desc->comp[0].depth - 1;
73  int sh = bits - 4;
74 
75  if ((isAnyRGB(c->srcFormat) || c->srcFormat==AV_PIX_FMT_PAL8) && desc->comp[0].depth<16) {
76  sh = 9;
77  } else if (desc->flags & AV_PIX_FMT_FLAG_FLOAT) { /* float input are process like uint 16bpc */
78  sh = 16 - 1 - 4;
79  }
80 
81  for (i = 0; i < dstW; i++) {
82  int j;
83  int srcPos = filterPos[i];
84  int val = 0;
85 
86  for (j = 0; j < filterSize; j++) {
87  val += src[srcPos + j] * filter[filterSize * i + j];
88  }
89  // filter=14 bit, input=16 bit, output=30 bit, >> 11 makes 19 bit
90  dst[i] = FFMIN(val >> sh, (1 << 19) - 1);
91  }
92 }
93 
94 static void hScale16To15_c(SwsContext *c, int16_t *dst, int dstW,
95  const uint8_t *_src, const int16_t *filter,
96  const int32_t *filterPos, int filterSize)
97 {
98  const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->srcFormat);
99  int i;
100  const uint16_t *src = (const uint16_t *) _src;
101  int sh = desc->comp[0].depth - 1;
102 
103  if (sh<15) {
104  sh = isAnyRGB(c->srcFormat) || c->srcFormat==AV_PIX_FMT_PAL8 ? 13 : (desc->comp[0].depth - 1);
105  } else if (desc->flags & AV_PIX_FMT_FLAG_FLOAT) { /* float input are process like uint 16bpc */
106  sh = 16 - 1;
107  }
108 
109  for (i = 0; i < dstW; i++) {
110  int j;
111  int srcPos = filterPos[i];
112  int val = 0;
113 
114  for (j = 0; j < filterSize; j++) {
115  val += src[srcPos + j] * filter[filterSize * i + j];
116  }
117  // filter=14 bit, input=16 bit, output=30 bit, >> 15 makes 15 bit
118  dst[i] = FFMIN(val >> sh, (1 << 15) - 1);
119  }
120 }
121 
122 // bilinear / bicubic scaling
123 static void hScale8To15_c(SwsContext *c, int16_t *dst, int dstW,
124  const uint8_t *src, const int16_t *filter,
125  const int32_t *filterPos, int filterSize)
126 {
127  int i;
128  for (i = 0; i < dstW; i++) {
129  int j;
130  int srcPos = filterPos[i];
131  int val = 0;
132  for (j = 0; j < filterSize; j++) {
133  val += ((int)src[srcPos + j]) * filter[filterSize * i + j];
134  }
135  dst[i] = FFMIN(val >> 7, (1 << 15) - 1); // the cubic equation does overflow ...
136  }
137 }
138 
139 static void hScale8To19_c(SwsContext *c, int16_t *_dst, int dstW,
140  const uint8_t *src, const int16_t *filter,
141  const int32_t *filterPos, int filterSize)
142 {
143  int i;
144  int32_t *dst = (int32_t *) _dst;
145  for (i = 0; i < dstW; i++) {
146  int j;
147  int srcPos = filterPos[i];
148  int val = 0;
149  for (j = 0; j < filterSize; j++) {
150  val += ((int)src[srcPos + j]) * filter[filterSize * i + j];
151  }
152  dst[i] = FFMIN(val >> 3, (1 << 19) - 1); // the cubic equation does overflow ...
153  }
154 }
155 
156 // FIXME all pal and rgb srcFormats could do this conversion as well
157 // FIXME all scalers more complex than bilinear could do half of this transform
158 static void chrRangeToJpeg_c(int16_t *dstU, int16_t *dstV, int width)
159 {
160  int i;
161  for (i = 0; i < width; i++) {
162  dstU[i] = (FFMIN(dstU[i], 30775) * 4663 - 9289992) >> 12; // -264
163  dstV[i] = (FFMIN(dstV[i], 30775) * 4663 - 9289992) >> 12; // -264
164  }
165 }
166 
167 static void chrRangeFromJpeg_c(int16_t *dstU, int16_t *dstV, int width)
168 {
169  int i;
170  for (i = 0; i < width; i++) {
171  dstU[i] = (dstU[i] * 1799 + 4081085) >> 11; // 1469
172  dstV[i] = (dstV[i] * 1799 + 4081085) >> 11; // 1469
173  }
174 }
175 
176 static void lumRangeToJpeg_c(int16_t *dst, int width)
177 {
178  int i;
179  for (i = 0; i < width; i++)
180  dst[i] = (FFMIN(dst[i], 30189) * 19077 - 39057361) >> 14;
181 }
182 
183 static void lumRangeFromJpeg_c(int16_t *dst, int width)
184 {
185  int i;
186  for (i = 0; i < width; i++)
187  dst[i] = (dst[i] * 14071 + 33561947) >> 14;
188 }
189 
190 static void chrRangeToJpeg16_c(int16_t *_dstU, int16_t *_dstV, int width)
191 {
192  int i;
193  int32_t *dstU = (int32_t *) _dstU;
194  int32_t *dstV = (int32_t *) _dstV;
195  for (i = 0; i < width; i++) {
196  dstU[i] = (FFMIN(dstU[i], 30775 << 4) * 4663 - (9289992 << 4)) >> 12; // -264
197  dstV[i] = (FFMIN(dstV[i], 30775 << 4) * 4663 - (9289992 << 4)) >> 12; // -264
198  }
199 }
200 
201 static void chrRangeFromJpeg16_c(int16_t *_dstU, int16_t *_dstV, int width)
202 {
203  int i;
204  int32_t *dstU = (int32_t *) _dstU;
205  int32_t *dstV = (int32_t *) _dstV;
206  for (i = 0; i < width; i++) {
207  dstU[i] = (dstU[i] * 1799 + (4081085 << 4)) >> 11; // 1469
208  dstV[i] = (dstV[i] * 1799 + (4081085 << 4)) >> 11; // 1469
209  }
210 }
211 
212 static void lumRangeToJpeg16_c(int16_t *_dst, int width)
213 {
214  int i;
215  int32_t *dst = (int32_t *) _dst;
216  for (i = 0; i < width; i++) {
217  dst[i] = ((int)(FFMIN(dst[i], 30189 << 4) * 4769U - (39057361 << 2))) >> 12;
218  }
219 }
220 
221 static void lumRangeFromJpeg16_c(int16_t *_dst, int width)
222 {
223  int i;
224  int32_t *dst = (int32_t *) _dst;
225  for (i = 0; i < width; i++)
226  dst[i] = (dst[i]*(14071/4) + (33561947<<4)/4)>>12;
227 }
228 
229 
230 #define DEBUG_SWSCALE_BUFFERS 0
231 #define DEBUG_BUFFERS(...) \
232  if (DEBUG_SWSCALE_BUFFERS) \
233  av_log(c, AV_LOG_DEBUG, __VA_ARGS__)
234 
235 static int swscale(SwsContext *c, const uint8_t *src[],
236  int srcStride[], int srcSliceY, int srcSliceH,
237  uint8_t *dst[], int dstStride[],
238  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  if (isPacked(c->srcFormat)) {
290  src[1] =
291  src[2] =
292  src[3] = src[0];
293  srcStride[1] =
294  srcStride[2] =
295  srcStride[3] = srcStride[0];
296  }
297  srcStride[1] *= 1 << c->vChrDrop;
298  srcStride[2] *= 1 << c->vChrDrop;
299 
300  DEBUG_BUFFERS("swscale() %p[%d] %p[%d] %p[%d] %p[%d] -> %p[%d] %p[%d] %p[%d] %p[%d]\n",
301  src[0], srcStride[0], src[1], srcStride[1],
302  src[2], srcStride[2], src[3], srcStride[3],
303  dst[0], dstStride[0], dst[1], dstStride[1],
304  dst[2], dstStride[2], dst[3], dstStride[3]);
305  DEBUG_BUFFERS("srcSliceY: %d srcSliceH: %d dstY: %d dstH: %d\n",
306  srcSliceY, srcSliceH, dstY, dstH);
307  DEBUG_BUFFERS("vLumFilterSize: %d vChrFilterSize: %d\n",
308  vLumFilterSize, vChrFilterSize);
309 
310  if (dstStride[0]&15 || dstStride[1]&15 ||
311  dstStride[2]&15 || dstStride[3]&15) {
312  SwsContext *const ctx = c->parent ? c->parent : c;
313  if (flags & SWS_PRINT_INFO &&
314  !atomic_exchange_explicit(&ctx->stride_unaligned_warned, 1, memory_order_relaxed)) {
316  "Warning: dstStride is not aligned!\n"
317  " ->cannot do aligned memory accesses anymore\n");
318  }
319  }
320 
321 #if ARCH_X86
322  if ( (uintptr_t)dst[0]&15 || (uintptr_t)dst[1]&15 || (uintptr_t)dst[2]&15
323  || (uintptr_t)src[0]&15 || (uintptr_t)src[1]&15 || (uintptr_t)src[2]&15
324  || dstStride[0]&15 || dstStride[1]&15 || dstStride[2]&15 || dstStride[3]&15
325  || srcStride[0]&15 || srcStride[1]&15 || srcStride[2]&15 || srcStride[3]&15
326  ) {
327  SwsContext *const ctx = c->parent ? c->parent : c;
328  int cpu_flags = av_get_cpu_flags();
329  if (flags & SWS_PRINT_INFO && HAVE_MMXEXT && (cpu_flags & AV_CPU_FLAG_SSE2) &&
330  !atomic_exchange_explicit(&ctx->stride_unaligned_warned,1, memory_order_relaxed)) {
331  av_log(c, AV_LOG_WARNING, "Warning: data is not aligned! This can lead to a speed loss\n");
332  }
333  }
334 #endif
335 
336  if (scale_dst) {
337  dstY = dstSliceY;
338  dstH = dstY + dstSliceH;
339  lastInLumBuf = -1;
340  lastInChrBuf = -1;
341  } else if (srcSliceY == 0) {
342  /* Note the user might start scaling the picture in the middle so this
343  * will not get executed. This is not really intended but works
344  * currently, so people might do it. */
345  dstY = 0;
346  lastInLumBuf = -1;
347  lastInChrBuf = -1;
348  }
349 
350  if (!should_dither) {
351  c->chrDither8 = c->lumDither8 = sws_pb_64;
352  }
353  lastDstY = dstY;
354 
355  ff_init_vscale_pfn(c, yuv2plane1, yuv2planeX, yuv2nv12cX,
356  yuv2packed1, yuv2packed2, yuv2packedX, yuv2anyX, c->use_mmx_vfilter);
357 
358  ff_init_slice_from_src(src_slice, (uint8_t**)src, srcStride, c->srcW,
359  srcSliceY, srcSliceH, chrSrcSliceY, chrSrcSliceH, 1);
360 
361  ff_init_slice_from_src(vout_slice, (uint8_t**)dst, dstStride, c->dstW,
362  dstY, dstSliceH, dstY >> c->chrDstVSubSample,
363  AV_CEIL_RSHIFT(dstSliceH, c->chrDstVSubSample), scale_dst);
364  if (srcSliceY == 0) {
365  hout_slice->plane[0].sliceY = lastInLumBuf + 1;
366  hout_slice->plane[1].sliceY = lastInChrBuf + 1;
367  hout_slice->plane[2].sliceY = lastInChrBuf + 1;
368  hout_slice->plane[3].sliceY = lastInLumBuf + 1;
369 
370  hout_slice->plane[0].sliceH =
371  hout_slice->plane[1].sliceH =
372  hout_slice->plane[2].sliceH =
373  hout_slice->plane[3].sliceH = 0;
374  hout_slice->width = dstW;
375  }
376 
377  for (; dstY < dstH; dstY++) {
378  const int chrDstY = dstY >> c->chrDstVSubSample;
379  int use_mmx_vfilter= c->use_mmx_vfilter;
380 
381  // First line needed as input
382  const int firstLumSrcY = FFMAX(1 - vLumFilterSize, vLumFilterPos[dstY]);
383  const int firstLumSrcY2 = FFMAX(1 - vLumFilterSize, vLumFilterPos[FFMIN(dstY | ((1 << c->chrDstVSubSample) - 1), c->dstH - 1)]);
384  // First line needed as input
385  const int firstChrSrcY = FFMAX(1 - vChrFilterSize, vChrFilterPos[chrDstY]);
386 
387  // Last line needed as input
388  int lastLumSrcY = FFMIN(c->srcH, firstLumSrcY + vLumFilterSize) - 1;
389  int lastLumSrcY2 = FFMIN(c->srcH, firstLumSrcY2 + vLumFilterSize) - 1;
390  int lastChrSrcY = FFMIN(c->chrSrcH, firstChrSrcY + vChrFilterSize) - 1;
391  int enough_lines;
392 
393  int i;
394  int posY, cPosY, firstPosY, lastPosY, firstCPosY, lastCPosY;
395 
396  // handle holes (FAST_BILINEAR & weird filters)
397  if (firstLumSrcY > lastInLumBuf) {
398 
399  hasLumHoles = lastInLumBuf != firstLumSrcY - 1;
400  if (hasLumHoles) {
401  hout_slice->plane[0].sliceY = firstLumSrcY;
402  hout_slice->plane[3].sliceY = firstLumSrcY;
403  hout_slice->plane[0].sliceH =
404  hout_slice->plane[3].sliceH = 0;
405  }
406 
407  lastInLumBuf = firstLumSrcY - 1;
408  }
409  if (firstChrSrcY > lastInChrBuf) {
410 
411  hasChrHoles = lastInChrBuf != firstChrSrcY - 1;
412  if (hasChrHoles) {
413  hout_slice->plane[1].sliceY = firstChrSrcY;
414  hout_slice->plane[2].sliceY = firstChrSrcY;
415  hout_slice->plane[1].sliceH =
416  hout_slice->plane[2].sliceH = 0;
417  }
418 
419  lastInChrBuf = firstChrSrcY - 1;
420  }
421 
422  DEBUG_BUFFERS("dstY: %d\n", dstY);
423  DEBUG_BUFFERS("\tfirstLumSrcY: %d lastLumSrcY: %d lastInLumBuf: %d\n",
424  firstLumSrcY, lastLumSrcY, lastInLumBuf);
425  DEBUG_BUFFERS("\tfirstChrSrcY: %d lastChrSrcY: %d lastInChrBuf: %d\n",
426  firstChrSrcY, lastChrSrcY, lastInChrBuf);
427 
428  // Do we have enough lines in this slice to output the dstY line
429  enough_lines = lastLumSrcY2 < srcSliceY + srcSliceH &&
430  lastChrSrcY < AV_CEIL_RSHIFT(srcSliceY + srcSliceH, c->chrSrcVSubSample);
431 
432  if (!enough_lines) {
433  lastLumSrcY = srcSliceY + srcSliceH - 1;
434  lastChrSrcY = chrSrcSliceY + chrSrcSliceH - 1;
435  DEBUG_BUFFERS("buffering slice: lastLumSrcY %d lastChrSrcY %d\n",
436  lastLumSrcY, lastChrSrcY);
437  }
438 
439  av_assert0((lastLumSrcY - firstLumSrcY + 1) <= hout_slice->plane[0].available_lines);
440  av_assert0((lastChrSrcY - firstChrSrcY + 1) <= hout_slice->plane[1].available_lines);
441 
442 
443  posY = hout_slice->plane[0].sliceY + hout_slice->plane[0].sliceH;
444  if (posY <= lastLumSrcY && !hasLumHoles) {
445  firstPosY = FFMAX(firstLumSrcY, posY);
446  lastPosY = FFMIN(firstLumSrcY + hout_slice->plane[0].available_lines - 1, srcSliceY + srcSliceH - 1);
447  } else {
448  firstPosY = posY;
449  lastPosY = lastLumSrcY;
450  }
451 
452  cPosY = hout_slice->plane[1].sliceY + hout_slice->plane[1].sliceH;
453  if (cPosY <= lastChrSrcY && !hasChrHoles) {
454  firstCPosY = FFMAX(firstChrSrcY, cPosY);
455  lastCPosY = FFMIN(firstChrSrcY + hout_slice->plane[1].available_lines - 1, AV_CEIL_RSHIFT(srcSliceY + srcSliceH, c->chrSrcVSubSample) - 1);
456  } else {
457  firstCPosY = cPosY;
458  lastCPosY = lastChrSrcY;
459  }
460 
461  ff_rotate_slice(hout_slice, lastPosY, lastCPosY);
462 
463  if (posY < lastLumSrcY + 1) {
464  for (i = lumStart; i < lumEnd; ++i)
465  desc[i].process(c, &desc[i], firstPosY, lastPosY - firstPosY + 1);
466  }
467 
468  lastInLumBuf = lastLumSrcY;
469 
470  if (cPosY < lastChrSrcY + 1) {
471  for (i = chrStart; i < chrEnd; ++i)
472  desc[i].process(c, &desc[i], firstCPosY, lastCPosY - firstCPosY + 1);
473  }
474 
475  lastInChrBuf = lastChrSrcY;
476 
477  if (!enough_lines)
478  break; // we can't output a dstY line so let's try with the next slice
479 
480 #if HAVE_MMX_INLINE
482 #endif
483  if (should_dither) {
484  c->chrDither8 = ff_dither_8x8_128[chrDstY & 7];
485  c->lumDither8 = ff_dither_8x8_128[dstY & 7];
486  }
487  if (dstY >= c->dstH - 2) {
488  /* hmm looks like we can't use MMX here without overwriting
489  * this array's tail */
490  ff_sws_init_output_funcs(c, &yuv2plane1, &yuv2planeX, &yuv2nv12cX,
491  &yuv2packed1, &yuv2packed2, &yuv2packedX, &yuv2anyX);
492  use_mmx_vfilter= 0;
493  ff_init_vscale_pfn(c, yuv2plane1, yuv2planeX, yuv2nv12cX,
494  yuv2packed1, yuv2packed2, yuv2packedX, yuv2anyX, use_mmx_vfilter);
495  }
496 
497  for (i = vStart; i < vEnd; ++i)
498  desc[i].process(c, &desc[i], dstY, 1);
499  }
500  if (isPlanar(dstFormat) && isALPHA(dstFormat) && !needAlpha) {
501  int offset = lastDstY - dstSliceY;
502  int length = dstW;
503  int height = dstY - lastDstY;
504 
505  if (is16BPS(dstFormat) || isNBPS(dstFormat)) {
506  const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(dstFormat);
507  fillPlane16(dst[3], dstStride[3], length, height, offset,
508  1, desc->comp[3].depth,
509  isBE(dstFormat));
510  } else if (is32BPS(dstFormat)) {
511  const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(dstFormat);
512  fillPlane32(dst[3], dstStride[3], length, height, offset,
513  1, desc->comp[3].depth,
514  isBE(dstFormat), desc->flags & AV_PIX_FMT_FLAG_FLOAT);
515  } else
516  fillPlane(dst[3], dstStride[3], length, height, offset, 255);
517  }
518 
519 #if HAVE_MMXEXT_INLINE
521  __asm__ volatile ("sfence" ::: "memory");
522 #endif
523  emms_c();
524 
525  /* store changed local vars back in the context */
526  c->dstY = dstY;
527  c->lastInLumBuf = lastInLumBuf;
528  c->lastInChrBuf = lastInChrBuf;
529 
530  return dstY - lastDstY;
531 }
532 
534 {
535  c->lumConvertRange = NULL;
536  c->chrConvertRange = NULL;
537  if (c->srcRange != c->dstRange && !isAnyRGB(c->dstFormat)) {
538  if (c->dstBpc <= 14) {
539  if (c->srcRange) {
540  c->lumConvertRange = lumRangeFromJpeg_c;
541  c->chrConvertRange = chrRangeFromJpeg_c;
542  } else {
543  c->lumConvertRange = lumRangeToJpeg_c;
544  c->chrConvertRange = chrRangeToJpeg_c;
545  }
546  } else {
547  if (c->srcRange) {
548  c->lumConvertRange = lumRangeFromJpeg16_c;
549  c->chrConvertRange = chrRangeFromJpeg16_c;
550  } else {
551  c->lumConvertRange = lumRangeToJpeg16_c;
552  c->chrConvertRange = chrRangeToJpeg16_c;
553  }
554  }
555  }
556 }
557 
559 {
560  enum AVPixelFormat srcFormat = c->srcFormat;
561 
562  ff_sws_init_output_funcs(c, &c->yuv2plane1, &c->yuv2planeX,
563  &c->yuv2nv12cX, &c->yuv2packed1,
564  &c->yuv2packed2, &c->yuv2packedX, &c->yuv2anyX);
565 
567 
568  if (c->srcBpc == 8) {
569  if (c->dstBpc <= 14) {
570  c->hyScale = c->hcScale = hScale8To15_c;
571  if (c->flags & SWS_FAST_BILINEAR) {
572  c->hyscale_fast = ff_hyscale_fast_c;
573  c->hcscale_fast = ff_hcscale_fast_c;
574  }
575  } else {
576  c->hyScale = c->hcScale = hScale8To19_c;
577  }
578  } else {
579  c->hyScale = c->hcScale = c->dstBpc > 14 ? hScale16To19_c
580  : hScale16To15_c;
581  }
582 
584 
585  if (!(isGray(srcFormat) || isGray(c->dstFormat) ||
586  srcFormat == AV_PIX_FMT_MONOBLACK || srcFormat == AV_PIX_FMT_MONOWHITE))
587  c->needs_hcscale = 1;
588 }
589 
591 {
593 
594 #if ARCH_PPC
596 #elif ARCH_X86
598 #elif ARCH_AARCH64
600 #elif ARCH_ARM
602 #elif ARCH_LOONGARCH64
604 #endif
605 }
606 
607 static void reset_ptr(const uint8_t *src[], enum AVPixelFormat format)
608 {
609  if (!isALPHA(format))
610  src[3] = NULL;
611  if (!isPlanar(format)) {
612  src[3] = src[2] = NULL;
613 
614  if (!usePal(format))
615  src[1] = NULL;
616  }
617 }
618 
619 static int check_image_pointers(const uint8_t * const data[4], enum AVPixelFormat pix_fmt,
620  const int linesizes[4])
621 {
623  int i;
624 
625  av_assert2(desc);
626 
627  for (i = 0; i < 4; i++) {
628  int plane = desc->comp[i].plane;
629  if (!data[plane] || !linesizes[plane])
630  return 0;
631  }
632 
633  return 1;
634 }
635 
636 static void xyz12Torgb48(struct SwsContext *c, uint16_t *dst,
637  const uint16_t *src, int stride, int h)
638 {
639  int xp,yp;
640  const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->srcFormat);
641 
642  for (yp=0; yp<h; yp++) {
643  for (xp=0; xp+2<stride; xp+=3) {
644  int x, y, z, r, g, b;
645 
646  if (desc->flags & AV_PIX_FMT_FLAG_BE) {
647  x = AV_RB16(src + xp + 0);
648  y = AV_RB16(src + xp + 1);
649  z = AV_RB16(src + xp + 2);
650  } else {
651  x = AV_RL16(src + xp + 0);
652  y = AV_RL16(src + xp + 1);
653  z = AV_RL16(src + xp + 2);
654  }
655 
656  x = c->xyzgamma[x>>4];
657  y = c->xyzgamma[y>>4];
658  z = c->xyzgamma[z>>4];
659 
660  // convert from XYZlinear to sRGBlinear
661  r = c->xyz2rgb_matrix[0][0] * x +
662  c->xyz2rgb_matrix[0][1] * y +
663  c->xyz2rgb_matrix[0][2] * z >> 12;
664  g = c->xyz2rgb_matrix[1][0] * x +
665  c->xyz2rgb_matrix[1][1] * y +
666  c->xyz2rgb_matrix[1][2] * z >> 12;
667  b = c->xyz2rgb_matrix[2][0] * x +
668  c->xyz2rgb_matrix[2][1] * y +
669  c->xyz2rgb_matrix[2][2] * z >> 12;
670 
671  // limit values to 12-bit depth
672  r = av_clip_uintp2(r, 12);
673  g = av_clip_uintp2(g, 12);
674  b = av_clip_uintp2(b, 12);
675 
676  // convert from sRGBlinear to RGB and scale from 12bit to 16bit
677  if (desc->flags & AV_PIX_FMT_FLAG_BE) {
678  AV_WB16(dst + xp + 0, c->rgbgamma[r] << 4);
679  AV_WB16(dst + xp + 1, c->rgbgamma[g] << 4);
680  AV_WB16(dst + xp + 2, c->rgbgamma[b] << 4);
681  } else {
682  AV_WL16(dst + xp + 0, c->rgbgamma[r] << 4);
683  AV_WL16(dst + xp + 1, c->rgbgamma[g] << 4);
684  AV_WL16(dst + xp + 2, c->rgbgamma[b] << 4);
685  }
686  }
687  src += stride;
688  dst += stride;
689  }
690 }
691 
692 static void rgb48Toxyz12(struct SwsContext *c, uint16_t *dst,
693  const uint16_t *src, int stride, int h)
694 {
695  int xp,yp;
696  const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->dstFormat);
697 
698  for (yp=0; yp<h; yp++) {
699  for (xp=0; xp+2<stride; xp+=3) {
700  int x, y, z, r, g, b;
701 
702  if (desc->flags & AV_PIX_FMT_FLAG_BE) {
703  r = AV_RB16(src + xp + 0);
704  g = AV_RB16(src + xp + 1);
705  b = AV_RB16(src + xp + 2);
706  } else {
707  r = AV_RL16(src + xp + 0);
708  g = AV_RL16(src + xp + 1);
709  b = AV_RL16(src + xp + 2);
710  }
711 
712  r = c->rgbgammainv[r>>4];
713  g = c->rgbgammainv[g>>4];
714  b = c->rgbgammainv[b>>4];
715 
716  // convert from sRGBlinear to XYZlinear
717  x = c->rgb2xyz_matrix[0][0] * r +
718  c->rgb2xyz_matrix[0][1] * g +
719  c->rgb2xyz_matrix[0][2] * b >> 12;
720  y = c->rgb2xyz_matrix[1][0] * r +
721  c->rgb2xyz_matrix[1][1] * g +
722  c->rgb2xyz_matrix[1][2] * b >> 12;
723  z = c->rgb2xyz_matrix[2][0] * r +
724  c->rgb2xyz_matrix[2][1] * g +
725  c->rgb2xyz_matrix[2][2] * b >> 12;
726 
727  // limit values to 12-bit depth
728  x = av_clip_uintp2(x, 12);
729  y = av_clip_uintp2(y, 12);
730  z = av_clip_uintp2(z, 12);
731 
732  // convert from XYZlinear to X'Y'Z' and scale from 12bit to 16bit
733  if (desc->flags & AV_PIX_FMT_FLAG_BE) {
734  AV_WB16(dst + xp + 0, c->xyzgammainv[x] << 4);
735  AV_WB16(dst + xp + 1, c->xyzgammainv[y] << 4);
736  AV_WB16(dst + xp + 2, c->xyzgammainv[z] << 4);
737  } else {
738  AV_WL16(dst + xp + 0, c->xyzgammainv[x] << 4);
739  AV_WL16(dst + xp + 1, c->xyzgammainv[y] << 4);
740  AV_WL16(dst + xp + 2, c->xyzgammainv[z] << 4);
741  }
742  }
743  src += stride;
744  dst += stride;
745  }
746 }
747 
748 static void update_palette(SwsContext *c, const uint32_t *pal)
749 {
750  for (int i = 0; i < 256; i++) {
751  int r, g, b, y, u, v, a = 0xff;
752  if (c->srcFormat == AV_PIX_FMT_PAL8) {
753  uint32_t p = pal[i];
754  a = (p >> 24) & 0xFF;
755  r = (p >> 16) & 0xFF;
756  g = (p >> 8) & 0xFF;
757  b = p & 0xFF;
758  } else if (c->srcFormat == AV_PIX_FMT_RGB8) {
759  r = ( i >> 5 ) * 36;
760  g = ((i >> 2) & 7) * 36;
761  b = ( i & 3) * 85;
762  } else if (c->srcFormat == AV_PIX_FMT_BGR8) {
763  b = ( i >> 6 ) * 85;
764  g = ((i >> 3) & 7) * 36;
765  r = ( i & 7) * 36;
766  } else if (c->srcFormat == AV_PIX_FMT_RGB4_BYTE) {
767  r = ( i >> 3 ) * 255;
768  g = ((i >> 1) & 3) * 85;
769  b = ( i & 1) * 255;
770  } else if (c->srcFormat == AV_PIX_FMT_GRAY8 || c->srcFormat == AV_PIX_FMT_GRAY8A) {
771  r = g = b = i;
772  } else {
773  av_assert1(c->srcFormat == AV_PIX_FMT_BGR4_BYTE);
774  b = ( i >> 3 ) * 255;
775  g = ((i >> 1) & 3) * 85;
776  r = ( i & 1) * 255;
777  }
778 #define RGB2YUV_SHIFT 15
779 #define BY ( (int) (0.114 * 219 / 255 * (1 << RGB2YUV_SHIFT) + 0.5))
780 #define BV (-(int) (0.081 * 224 / 255 * (1 << RGB2YUV_SHIFT) + 0.5))
781 #define BU ( (int) (0.500 * 224 / 255 * (1 << RGB2YUV_SHIFT) + 0.5))
782 #define GY ( (int) (0.587 * 219 / 255 * (1 << RGB2YUV_SHIFT) + 0.5))
783 #define GV (-(int) (0.419 * 224 / 255 * (1 << RGB2YUV_SHIFT) + 0.5))
784 #define GU (-(int) (0.331 * 224 / 255 * (1 << RGB2YUV_SHIFT) + 0.5))
785 #define RY ( (int) (0.299 * 219 / 255 * (1 << RGB2YUV_SHIFT) + 0.5))
786 #define RV ( (int) (0.500 * 224 / 255 * (1 << RGB2YUV_SHIFT) + 0.5))
787 #define RU (-(int) (0.169 * 224 / 255 * (1 << RGB2YUV_SHIFT) + 0.5))
788 
789  y = av_clip_uint8((RY * r + GY * g + BY * b + ( 33 << (RGB2YUV_SHIFT - 1))) >> RGB2YUV_SHIFT);
790  u = av_clip_uint8((RU * r + GU * g + BU * b + (257 << (RGB2YUV_SHIFT - 1))) >> RGB2YUV_SHIFT);
791  v = av_clip_uint8((RV * r + GV * g + BV * b + (257 << (RGB2YUV_SHIFT - 1))) >> RGB2YUV_SHIFT);
792  c->pal_yuv[i]= y + (u<<8) + (v<<16) + ((unsigned)a<<24);
793 
794  switch (c->dstFormat) {
795  case AV_PIX_FMT_BGR32:
796 #if !HAVE_BIGENDIAN
797  case AV_PIX_FMT_RGB24:
798 #endif
799  c->pal_rgb[i]= r + (g<<8) + (b<<16) + ((unsigned)a<<24);
800  break;
801  case AV_PIX_FMT_BGR32_1:
802 #if HAVE_BIGENDIAN
803  case AV_PIX_FMT_BGR24:
804 #endif
805  c->pal_rgb[i]= a + (r<<8) + (g<<16) + ((unsigned)b<<24);
806  break;
807  case AV_PIX_FMT_RGB32_1:
808 #if HAVE_BIGENDIAN
809  case AV_PIX_FMT_RGB24:
810 #endif
811  c->pal_rgb[i]= a + (b<<8) + (g<<16) + ((unsigned)r<<24);
812  break;
813  case AV_PIX_FMT_RGB32:
814 #if !HAVE_BIGENDIAN
815  case AV_PIX_FMT_BGR24:
816 #endif
817  default:
818  c->pal_rgb[i]= b + (g<<8) + (r<<16) + ((unsigned)a<<24);
819  }
820  }
821 }
822 
823 static int scale_internal(SwsContext *c,
824  const uint8_t * const srcSlice[], const int srcStride[],
825  int srcSliceY, int srcSliceH,
826  uint8_t *const dstSlice[], const int dstStride[],
827  int dstSliceY, int dstSliceH);
828 
830  const uint8_t * const srcSlice[], const int srcStride[],
831  int srcSliceY, int srcSliceH,
832  uint8_t * const dstSlice[], const int dstStride[],
833  int dstSliceY, int dstSliceH)
834 {
835  int ret = scale_internal(c->cascaded_context[0],
836  srcSlice, srcStride, srcSliceY, srcSliceH,
837  c->cascaded_tmp, c->cascaded_tmpStride, 0, c->srcH);
838 
839  if (ret < 0)
840  return ret;
841 
842  if (c->cascaded_context[2])
843  ret = scale_internal(c->cascaded_context[1], (const uint8_t * const *)c->cascaded_tmp,
844  c->cascaded_tmpStride, srcSliceY, srcSliceH,
845  c->cascaded1_tmp, c->cascaded1_tmpStride, 0, c->dstH);
846  else
847  ret = scale_internal(c->cascaded_context[1], (const uint8_t * const *)c->cascaded_tmp,
848  c->cascaded_tmpStride, srcSliceY, srcSliceH,
849  dstSlice, dstStride, dstSliceY, dstSliceH);
850 
851  if (ret < 0)
852  return ret;
853 
854  if (c->cascaded_context[2]) {
855  ret = scale_internal(c->cascaded_context[2], (const uint8_t * const *)c->cascaded1_tmp,
856  c->cascaded1_tmpStride, c->cascaded_context[1]->dstY - ret,
857  c->cascaded_context[1]->dstY,
858  dstSlice, dstStride, dstSliceY, dstSliceH);
859  }
860  return ret;
861 }
862 
864  const uint8_t * const srcSlice[], const int srcStride[],
865  int srcSliceY, int srcSliceH,
866  uint8_t * const dstSlice[], const int dstStride[],
867  int dstSliceY, int dstSliceH)
868 {
869  int ret = scale_internal(c->cascaded_context[0],
870  srcSlice, srcStride, srcSliceY, srcSliceH,
871  c->cascaded_tmp, c->cascaded_tmpStride,
872  0, c->cascaded_context[0]->dstH);
873  if (ret < 0)
874  return ret;
875  ret = scale_internal(c->cascaded_context[1],
876  (const uint8_t * const * )c->cascaded_tmp, c->cascaded_tmpStride,
877  0, c->cascaded_context[0]->dstH,
878  dstSlice, dstStride, dstSliceY, dstSliceH);
879  return ret;
880 }
881 
883  const uint8_t * const srcSlice[], const int srcStride[],
884  int srcSliceY, int srcSliceH,
885  uint8_t *const dstSlice[], const int dstStride[],
886  int dstSliceY, int dstSliceH)
887 {
888  const int scale_dst = dstSliceY > 0 || dstSliceH < c->dstH;
889  const int frame_start = scale_dst || !c->sliceDir;
890  int i, ret;
891  const uint8_t *src2[4];
892  uint8_t *dst2[4];
893  int macro_height_src = isBayer(c->srcFormat) ? 2 : (1 << c->chrSrcVSubSample);
894  int macro_height_dst = isBayer(c->dstFormat) ? 2 : (1 << c->chrDstVSubSample);
895  // copy strides, so they can safely be modified
896  int srcStride2[4];
897  int dstStride2[4];
898  int srcSliceY_internal = srcSliceY;
899 
900  if (!srcStride || !dstStride || !dstSlice || !srcSlice) {
901  av_log(c, AV_LOG_ERROR, "One of the input parameters to sws_scale() is NULL, please check the calling code\n");
902  return AVERROR(EINVAL);
903  }
904 
905  if ((srcSliceY & (macro_height_src - 1)) ||
906  ((srcSliceH & (macro_height_src - 1)) && srcSliceY + srcSliceH != c->srcH) ||
907  srcSliceY + srcSliceH > c->srcH ||
908  (isBayer(c->srcFormat) && srcSliceH <= 1)) {
909  av_log(c, AV_LOG_ERROR, "Slice parameters %d, %d are invalid\n", srcSliceY, srcSliceH);
910  return AVERROR(EINVAL);
911  }
912 
913  if ((dstSliceY & (macro_height_dst - 1)) ||
914  ((dstSliceH & (macro_height_dst - 1)) && dstSliceY + dstSliceH != c->dstH) ||
915  dstSliceY + dstSliceH > c->dstH) {
916  av_log(c, AV_LOG_ERROR, "Slice parameters %d, %d are invalid\n", dstSliceY, dstSliceH);
917  return AVERROR(EINVAL);
918  }
919 
920  if (!check_image_pointers(srcSlice, c->srcFormat, srcStride)) {
921  av_log(c, AV_LOG_ERROR, "bad src image pointers\n");
922  return AVERROR(EINVAL);
923  }
924  if (!check_image_pointers((const uint8_t* const*)dstSlice, c->dstFormat, dstStride)) {
925  av_log(c, AV_LOG_ERROR, "bad dst image pointers\n");
926  return AVERROR(EINVAL);
927  }
928 
929  // do not mess up sliceDir if we have a "trailing" 0-size slice
930  if (srcSliceH == 0)
931  return 0;
932 
933  if (c->gamma_flag && c->cascaded_context[0])
934  return scale_gamma(c, srcSlice, srcStride, srcSliceY, srcSliceH,
935  dstSlice, dstStride, dstSliceY, dstSliceH);
936 
937  if (c->cascaded_context[0] && srcSliceY == 0 && srcSliceH == c->cascaded_context[0]->srcH)
938  return scale_cascaded(c, srcSlice, srcStride, srcSliceY, srcSliceH,
939  dstSlice, dstStride, dstSliceY, dstSliceH);
940 
941  if (!srcSliceY && (c->flags & SWS_BITEXACT) && c->dither == SWS_DITHER_ED && c->dither_error[0])
942  for (i = 0; i < 4; i++)
943  memset(c->dither_error[i], 0, sizeof(c->dither_error[0][0]) * (c->dstW+2));
944 
945  if (usePal(c->srcFormat))
946  update_palette(c, (const uint32_t *)srcSlice[1]);
947 
948  memcpy(src2, srcSlice, sizeof(src2));
949  memcpy(dst2, dstSlice, sizeof(dst2));
950  memcpy(srcStride2, srcStride, sizeof(srcStride2));
951  memcpy(dstStride2, dstStride, sizeof(dstStride2));
952 
953  if (frame_start && !scale_dst) {
954  if (srcSliceY != 0 && srcSliceY + srcSliceH != c->srcH) {
955  av_log(c, AV_LOG_ERROR, "Slices start in the middle!\n");
956  return AVERROR(EINVAL);
957  }
958 
959  c->sliceDir = (srcSliceY == 0) ? 1 : -1;
960  } else if (scale_dst)
961  c->sliceDir = 1;
962 
963  if (c->src0Alpha && !c->dst0Alpha && isALPHA(c->dstFormat)) {
964  uint8_t *base;
965  int x,y;
966 
967  av_fast_malloc(&c->rgb0_scratch, &c->rgb0_scratch_allocated,
968  FFABS(srcStride[0]) * srcSliceH + 32);
969  if (!c->rgb0_scratch)
970  return AVERROR(ENOMEM);
971 
972  base = srcStride[0] < 0 ? c->rgb0_scratch - srcStride[0] * (srcSliceH-1) :
973  c->rgb0_scratch;
974  for (y=0; y<srcSliceH; y++){
975  memcpy(base + srcStride[0]*y, src2[0] + srcStride[0]*y, 4*c->srcW);
976  for (x=c->src0Alpha-1; x<4*c->srcW; x+=4) {
977  base[ srcStride[0]*y + x] = 0xFF;
978  }
979  }
980  src2[0] = base;
981  }
982 
983  if (c->srcXYZ && !(c->dstXYZ && c->srcW==c->dstW && c->srcH==c->dstH)) {
984  uint8_t *base;
985 
986  av_fast_malloc(&c->xyz_scratch, &c->xyz_scratch_allocated,
987  FFABS(srcStride[0]) * srcSliceH + 32);
988  if (!c->xyz_scratch)
989  return AVERROR(ENOMEM);
990 
991  base = srcStride[0] < 0 ? c->xyz_scratch - srcStride[0] * (srcSliceH-1) :
992  c->xyz_scratch;
993 
994  xyz12Torgb48(c, (uint16_t*)base, (const uint16_t*)src2[0], srcStride[0]/2, srcSliceH);
995  src2[0] = base;
996  }
997 
998  if (c->sliceDir != 1) {
999  // slices go from bottom to top => we flip the image internally
1000  for (i=0; i<4; i++) {
1001  srcStride2[i] *= -1;
1002  dstStride2[i] *= -1;
1003  }
1004 
1005  src2[0] += (srcSliceH - 1) * srcStride[0];
1006  if (!usePal(c->srcFormat))
1007  src2[1] += ((srcSliceH >> c->chrSrcVSubSample) - 1) * srcStride[1];
1008  src2[2] += ((srcSliceH >> c->chrSrcVSubSample) - 1) * srcStride[2];
1009  src2[3] += (srcSliceH - 1) * srcStride[3];
1010  dst2[0] += ( c->dstH - 1) * dstStride[0];
1011  dst2[1] += ((c->dstH >> c->chrDstVSubSample) - 1) * dstStride[1];
1012  dst2[2] += ((c->dstH >> c->chrDstVSubSample) - 1) * dstStride[2];
1013  dst2[3] += ( c->dstH - 1) * dstStride[3];
1014 
1015  srcSliceY_internal = c->srcH-srcSliceY-srcSliceH;
1016  }
1017  reset_ptr(src2, c->srcFormat);
1018  reset_ptr((void*)dst2, c->dstFormat);
1019 
1020  if (c->convert_unscaled) {
1021  int offset = srcSliceY_internal;
1022  int slice_h = srcSliceH;
1023 
1024  // for dst slice scaling, offset the pointers to match the unscaled API
1025  if (scale_dst) {
1026  av_assert0(offset == 0);
1027  for (i = 0; i < 4 && src2[i]; i++) {
1028  if (!src2[i] || (i > 0 && usePal(c->srcFormat)))
1029  break;
1030  src2[i] += (dstSliceY >> ((i == 1 || i == 2) ? c->chrSrcVSubSample : 0)) * srcStride2[i];
1031  }
1032 
1033  for (i = 0; i < 4 && dst2[i]; i++) {
1034  if (!dst2[i] || (i > 0 && usePal(c->dstFormat)))
1035  break;
1036  dst2[i] -= (dstSliceY >> ((i == 1 || i == 2) ? c->chrDstVSubSample : 0)) * dstStride2[i];
1037  }
1038  offset = dstSliceY;
1039  slice_h = dstSliceH;
1040  }
1041 
1042  ret = c->convert_unscaled(c, src2, srcStride2, offset, slice_h,
1043  dst2, dstStride2);
1044  if (scale_dst)
1045  dst2[0] += dstSliceY * dstStride2[0];
1046  } else {
1047  ret = swscale(c, src2, srcStride2, srcSliceY_internal, srcSliceH,
1048  dst2, dstStride2, dstSliceY, dstSliceH);
1049  }
1050 
1051  if (c->dstXYZ && !(c->srcXYZ && c->srcW==c->dstW && c->srcH==c->dstH)) {
1052  uint16_t *dst16;
1053 
1054  if (scale_dst) {
1055  dst16 = (uint16_t *)dst2[0];
1056  } else {
1057  int dstY = c->dstY ? c->dstY : srcSliceY + srcSliceH;
1058 
1059  av_assert0(dstY >= ret);
1060  av_assert0(ret >= 0);
1061  av_assert0(c->dstH >= dstY);
1062  dst16 = (uint16_t*)(dst2[0] + (dstY - ret) * dstStride2[0]);
1063  }
1064 
1065  /* replace on the same data */
1066  rgb48Toxyz12(c, dst16, dst16, dstStride2[0]/2, ret);
1067  }
1068 
1069  /* reset slice direction at end of frame */
1070  if ((srcSliceY_internal + srcSliceH == c->srcH) || scale_dst)
1071  c->sliceDir = 0;
1072 
1073  return ret;
1074 }
1075 
1077 {
1078  av_frame_unref(c->frame_src);
1079  av_frame_unref(c->frame_dst);
1080  c->src_ranges.nb_ranges = 0;
1081 }
1082 
1083 int sws_frame_start(struct SwsContext *c, AVFrame *dst, const AVFrame *src)
1084 {
1085  int ret, allocated = 0;
1086 
1087  ret = av_frame_ref(c->frame_src, src);
1088  if (ret < 0)
1089  return ret;
1090 
1091  if (!dst->buf[0]) {
1092  dst->width = c->dstW;
1093  dst->height = c->dstH;
1094  dst->format = c->dstFormat;
1095 
1096  ret = av_frame_get_buffer(dst, 0);
1097  if (ret < 0)
1098  return ret;
1099  allocated = 1;
1100  }
1101 
1102  ret = av_frame_ref(c->frame_dst, dst);
1103  if (ret < 0) {
1104  if (allocated)
1105  av_frame_unref(dst);
1106 
1107  return ret;
1108  }
1109 
1110  return 0;
1111 }
1112 
1113 int sws_send_slice(struct SwsContext *c, unsigned int slice_start,
1114  unsigned int slice_height)
1115 {
1116  int ret;
1117 
1118  ret = ff_range_add(&c->src_ranges, slice_start, slice_height);
1119  if (ret < 0)
1120  return ret;
1121 
1122  return 0;
1123 }
1124 
1125 unsigned int sws_receive_slice_alignment(const struct SwsContext *c)
1126 {
1127  if (c->slice_ctx)
1128  return c->slice_ctx[0]->dst_slice_align;
1129 
1130  return c->dst_slice_align;
1131 }
1132 
1133 int sws_receive_slice(struct SwsContext *c, unsigned int slice_start,
1134  unsigned int slice_height)
1135 {
1136  unsigned int align = sws_receive_slice_alignment(c);
1137  uint8_t *dst[4];
1138 
1139  /* wait until complete input has been received */
1140  if (!(c->src_ranges.nb_ranges == 1 &&
1141  c->src_ranges.ranges[0].start == 0 &&
1142  c->src_ranges.ranges[0].len == c->srcH))
1143  return AVERROR(EAGAIN);
1144 
1145  if ((slice_start > 0 || slice_height < c->dstH) &&
1146  (slice_start % align || slice_height % align)) {
1148  "Incorrectly aligned output: %u/%u not multiples of %u\n",
1149  slice_start, slice_height, align);
1150  return AVERROR(EINVAL);
1151  }
1152 
1153  if (c->slicethread) {
1154  int nb_jobs = c->slice_ctx[0]->dither == SWS_DITHER_ED ? 1 : c->nb_slice_ctx;
1155  int ret = 0;
1156 
1157  c->dst_slice_start = slice_start;
1158  c->dst_slice_height = slice_height;
1159 
1160  avpriv_slicethread_execute(c->slicethread, nb_jobs, 0);
1161 
1162  for (int i = 0; i < c->nb_slice_ctx; i++) {
1163  if (c->slice_err[i] < 0) {
1164  ret = c->slice_err[i];
1165  break;
1166  }
1167  }
1168 
1169  memset(c->slice_err, 0, c->nb_slice_ctx * sizeof(*c->slice_err));
1170 
1171  return ret;
1172  }
1173 
1174  for (int i = 0; i < FF_ARRAY_ELEMS(dst); i++) {
1175  ptrdiff_t offset = c->frame_dst->linesize[i] * (slice_start >> c->chrDstVSubSample);
1176  dst[i] = FF_PTR_ADD(c->frame_dst->data[i], offset);
1177  }
1178 
1179  return scale_internal(c, (const uint8_t * const *)c->frame_src->data,
1180  c->frame_src->linesize, 0, c->srcH,
1181  dst, c->frame_dst->linesize, slice_start, slice_height);
1182 }
1183 
1184 int sws_scale_frame(struct SwsContext *c, AVFrame *dst, const AVFrame *src)
1185 {
1186  int ret;
1187 
1188  ret = sws_frame_start(c, dst, src);
1189  if (ret < 0)
1190  return ret;
1191 
1192  ret = sws_send_slice(c, 0, src->height);
1193  if (ret >= 0)
1194  ret = sws_receive_slice(c, 0, dst->height);
1195 
1196  sws_frame_end(c);
1197 
1198  return ret;
1199 }
1200 
1201 /**
1202  * swscale wrapper, so we don't need to export the SwsContext.
1203  * Assumes planar YUV to be in YUV order instead of YVU.
1204  */
1206  const uint8_t * const srcSlice[],
1207  const int srcStride[], int srcSliceY,
1208  int srcSliceH, uint8_t *const dst[],
1209  const int dstStride[])
1210 {
1211  if (c->nb_slice_ctx)
1212  c = c->slice_ctx[0];
1213 
1214  return scale_internal(c, srcSlice, srcStride, srcSliceY, srcSliceH,
1215  dst, dstStride, 0, c->dstH);
1216 }
1217 
1218 void ff_sws_slice_worker(void *priv, int jobnr, int threadnr,
1219  int nb_jobs, int nb_threads)
1220 {
1221  SwsContext *parent = priv;
1222  SwsContext *c = parent->slice_ctx[threadnr];
1223 
1224  const int slice_height = FFALIGN(FFMAX((parent->dst_slice_height + nb_jobs - 1) / nb_jobs, 1),
1225  c->dst_slice_align);
1226  const int slice_start = jobnr * slice_height;
1227  const int slice_end = FFMIN((jobnr + 1) * slice_height, parent->dst_slice_height);
1228  int err = 0;
1229 
1230  if (slice_end > slice_start) {
1231  uint8_t *dst[4] = { NULL };
1232 
1233  for (int i = 0; i < FF_ARRAY_ELEMS(dst) && parent->frame_dst->data[i]; i++) {
1234  const int vshift = (i == 1 || i == 2) ? c->chrDstVSubSample : 0;
1235  const ptrdiff_t offset = parent->frame_dst->linesize[i] *
1236  ((slice_start + parent->dst_slice_start) >> vshift);
1237 
1238  dst[i] = parent->frame_dst->data[i] + offset;
1239  }
1240 
1241  err = scale_internal(c, (const uint8_t * const *)parent->frame_src->data,
1242  parent->frame_src->linesize, 0, c->srcH,
1243  dst, parent->frame_dst->linesize,
1245  }
1246 
1247  parent->slice_err[threadnr] = err;
1248 }
isBayer
static av_always_inline int isBayer(enum AVPixelFormat pix_fmt)
Definition: swscale_internal.h:818
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
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:186
process
static void process(NormalizeContext *s, AVFrame *in, AVFrame *out)
Definition: vf_normalize.c:154
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:1075
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:64
isPacked
static av_always_inline int isPacked(enum AVPixelFormat pix_fmt)
Definition: swscale_internal.h:863
r
const char * r
Definition: vf_curves.c:126
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:216
chrRangeFromJpeg16_c
static void chrRangeFromJpeg16_c(int16_t *_dstU, int16_t *_dstV, int width)
Definition: swscale.c:201
AV_PIX_FMT_BGR32
#define AV_PIX_FMT_BGR32
Definition: pixfmt.h:453
u
#define u(width, name, range_min, range_max)
Definition: cbs_h2645.c:250
av_pix_fmt_desc_get
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition: pixdesc.c:2962
av_clip_uintp2
#define av_clip_uintp2
Definition: common.h:122
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:119
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:1093
avpriv_slicethread_execute
void avpriv_slicethread_execute(AVSliceThread *ctx, int nb_jobs, int execute_main)
Execute slice threading.
Definition: slicethread.c:249
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:340
pixdesc.h
AVFrame::width
int width
Definition: frame.h:412
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:123
GV
#define GV
ff_sws_init_input_funcs
void ff_sws_init_input_funcs(SwsContext *c)
b
#define b
Definition: input.c:41
SwsFilterDescriptor
Struct which holds all necessary data for processing a slice.
Definition: swscale_internal.h:1100
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:148
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:452
base
uint8_t base
Definition: vp3data.h:128
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:1205
filter
filter_frame For filters that do not use the this method is called when a frame is pushed to the filter s input It can be called at any time except in a reentrant way If the input frame is enough to produce then the filter should push the output frames on the output link immediately As an exception to the previous rule if the input frame is enough to produce several output frames then the filter needs output only at least one per link The additional frames can be left buffered in the filter
Definition: filter_design.txt:228
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:103
DEBUG_BUFFERS
#define DEBUG_BUFFERS(...)
Definition: swscale.c:231
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:882
AVFrame::buf
AVBufferRef * buf[AV_NUM_DATA_POINTERS]
AVBuffer references backing the data for this frame.
Definition: frame.h:553
cpu_flags
static atomic_int cpu_flags
Definition: cpu.c:52
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:1113
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:863
xyz12Torgb48
static void xyz12Torgb48(struct SwsContext *c, uint16_t *dst, const uint16_t *src, int stride, int h)
Definition: swscale.c:636
AVFrame::data
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:361
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:1133
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:703
ff_sws_init_swscale_aarch64
av_cold void ff_sws_init_swscale_aarch64(SwsContext *c)
Definition: swscale.c:204
SWS_BITEXACT
#define SWS_BITEXACT
Definition: swscale.h:91
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
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:139
val
static double val(void *priv, double ch)
Definition: aeval.c:78
isNBPS
static av_always_inline int isNBPS(enum AVPixelFormat pix_fmt)
Definition: swscale_internal.h:717
RY
#define RY
slice_start
static int slice_start(SliceContext *sc, VVCContext *s, VVCFrameContext *fc, const CodedBitstreamUnit *unit, const int is_first_slice)
Definition: vvcdec.c:685
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
frame_start
static int frame_start(MpegEncContext *s)
Definition: mpegvideo_enc.c:1708
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:180
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:314
ff_sws_init_swscale_loongarch
av_cold void ff_sws_init_swscale_loongarch(SwsContext *c)
Definition: swscale_init_loongarch.c:27
sws_init_swscale
static av_cold void sws_init_swscale(SwsContext *c)
Definition: swscale.c:558
SWS_DITHER_ED
@ SWS_DITHER_ED
Definition: swscale_internal.h:73
emms_c
#define emms_c()
Definition: emms.h:63
width
#define width
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:1083
AV_CEIL_RSHIFT
#define AV_CEIL_RSHIFT(a, b)
Definition: common.h:58
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:127
pix_fmt
static enum AVPixelFormat pix_fmt
Definition: demux_decode.c:41
SwsSlice::width
int width
Slice line width.
Definition: swscale_internal.h:1087
slice_end
static int slice_end(AVCodecContext *avctx, AVFrame *pict)
Handle slice ends.
Definition: mpeg12dec.c:1717
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:48
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:829
lumRangeFromJpeg_c
static void lumRangeFromJpeg_c(int16_t *dst, int width)
Definition: swscale.c:183
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:257
AV_PIX_FMT_BGR32_1
#define AV_PIX_FMT_BGR32_1
Definition: pixfmt.h:454
FFABS
#define FFABS(a)
Absolute value, Note, INT_MIN / INT64_MIN result in undefined behavior as they are not representable ...
Definition: common.h:72
SwsContext::dst_slice_start
int dst_slice_start
Definition: swscale_internal.h:313
ff_sws_init_range_convert
av_cold void ff_sws_init_range_convert(SwsContext *c)
Definition: swscale.c:533
SwsContext::slice_err
int * slice_err
Definition: swscale_internal.h:309
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:53
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:1073
ff_sws_init_swscale_x86
av_cold void ff_sws_init_swscale_x86(SwsContext *c)
Definition: swscale.c:450
AV_WB16
#define AV_WB16(p, v)
Definition: intreadwrite.h:403
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:90
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:2561
chrRangeToJpeg_c
static void chrRangeToJpeg_c(int16_t *dstU, int16_t *dstV, int width)
Definition: swscale.c:158
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:34
ff_sws_slice_worker
void ff_sws_slice_worker(void *priv, int jobnr, int threadnr, int nb_jobs, int nb_threads)
Definition: swscale.c:1218
isBE
static av_always_inline int isBE(enum AVPixelFormat pix_fmt)
Definition: swscale_internal.h:724
update_palette
static void update_palette(SwsContext *c, const uint32_t *pal)
Definition: swscale.c:748
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:590
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:312
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:1019
usePal
static av_always_inline int usePal(enum AVPixelFormat pix_fmt)
Definition: swscale_internal.h:894
BV
#define BV
cpu.h
isAnyRGB
static av_always_inline int isAnyRGB(enum AVPixelFormat pix_fmt)
Definition: swscale_internal.h:832
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:94
SwsContext::slice_ctx
struct SwsContext ** slice_ctx
Definition: swscale_internal.h:308
srcSliceH
return srcSliceH
Definition: yuv2rgb_template.c:87
chrRangeToJpeg16_c
static void chrRangeToJpeg16_c(int16_t *_dstU, int16_t *_dstV, int width)
Definition: swscale.c:190
AVFrame::format
int format
format of the frame, -1 if unknown or unset Values correspond to enum AVPixelFormat for video frames,...
Definition: frame.h:427
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:710
AV_WL16
#define AV_WL16(p, v)
Definition: intreadwrite.h:410
height
#define height
AV_PIX_FMT_RGB32
#define AV_PIX_FMT_RGB32
Definition: pixfmt.h:451
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:1040
GY
#define GY
emms.h
SwsContext::frame_src
AVFrame * frame_src
Definition: swscale_internal.h:344
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:1184
av_assert2
#define av_assert2(cond)
assert() equivalent, that does lie in speed critical code.
Definition: avassert.h:67
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:255
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:1125
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:619
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:534
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:1085
stride
#define stride
Definition: h264pred_template.c:537
ff_init_slice_from_src
int ff_init_slice_from_src(SwsSlice *s, uint8_t *src[4], int stride[4], int srcW, int lumY, int lumH, int chrY, int chrH, int relative)
Definition: slice.c:147
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:49
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:1076
ff_sws_init_swscale_ppc
av_cold void ff_sws_init_swscale_ppc(SwsContext *c)
Definition: swscale_altivec.c:238
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)
AVFrame::height
int height
Definition: frame.h:412
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:607
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:345
atomic_exchange_explicit
#define atomic_exchange_explicit(object, desired, order)
Definition: stdatomic.h:106
swscale
static int swscale(SwsContext *c, const uint8_t *src[], int srcStride[], int srcSliceY, int srcSliceH, uint8_t *dst[], int dstStride[], int dstSliceY, int dstSliceH)
Definition: swscale.c:235
ff_dither_8x8_128
const uint8_t ff_dither_8x8_128[9][8]
Definition: swscale.c:37
AV_CPU_FLAG_MMXEXT
#define AV_CPU_FLAG_MMXEXT
SSE integer functions or AMD MMX ext.
Definition: cpu.h:30
av_clip_uint8
#define av_clip_uint8
Definition: common.h:104
RU
#define RU
lumRangeToJpeg_c
static void lumRangeToJpeg_c(int16_t *dst, int width)
Definition: swscale.c:176
BU
#define BU
lumRangeFromJpeg16_c
static void lumRangeFromJpeg16_c(int16_t *_dst, int width)
Definition: swscale.c:221
desc
const char * desc
Definition: libsvtav1.c:73
SWS_PRINT_INFO
#define SWS_PRINT_INFO
Definition: swscale.h:82
lumRangeToJpeg16_c
static void lumRangeToJpeg16_c(int16_t *_dst, int width)
Definition: swscale.c:212
SwsPlane::sliceY
int sliceY
index of first line
Definition: swscale_internal.h:1074
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:167
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:555
src
INIT_CLIP pixel * src
Definition: h264pred_template.c:418
int32_t
int32_t
Definition: audioconvert.c:56
flags
#define flags(name, subs,...)
Definition: cbs_av1.c:474
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:385
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
h
h
Definition: vp9dsp_template.c:2038
ff_updateMMXDitherTables
void ff_updateMMXDitherTables(SwsContext *c, int dstY)
isPlanar
static av_always_inline int isPlanar(enum AVPixelFormat pix_fmt)
Definition: swscale_internal.h:872
int
int
Definition: ffmpeg_filter.c:425
SwsContext
Definition: swscale_internal.h:299
rgb48Toxyz12
static void rgb48Toxyz12(struct SwsContext *c, uint16_t *dst, const uint16_t *src, int stride, int h)
Definition: swscale.c:692
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