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 static int swscale(SwsContext *c, const uint8_t *src[],
237  int srcStride[], int srcSliceY, int srcSliceH,
238  uint8_t *dst[], int dstStride[],
239  int dstSliceY, int dstSliceH)
240 {
241  const int scale_dst = dstSliceY > 0 || dstSliceH < c->dstH;
242 
243  /* load a few things into local vars to make the code more readable?
244  * and faster */
245  const int dstW = c->dstW;
246  int dstH = c->dstH;
247 
248  const enum AVPixelFormat dstFormat = c->dstFormat;
249  const int flags = c->flags;
250  int32_t *vLumFilterPos = c->vLumFilterPos;
251  int32_t *vChrFilterPos = c->vChrFilterPos;
252 
253  const int vLumFilterSize = c->vLumFilterSize;
254  const int vChrFilterSize = c->vChrFilterSize;
255 
256  yuv2planar1_fn yuv2plane1 = c->yuv2plane1;
257  yuv2planarX_fn yuv2planeX = c->yuv2planeX;
258  yuv2interleavedX_fn yuv2nv12cX = c->yuv2nv12cX;
259  yuv2packed1_fn yuv2packed1 = c->yuv2packed1;
260  yuv2packed2_fn yuv2packed2 = c->yuv2packed2;
261  yuv2packedX_fn yuv2packedX = c->yuv2packedX;
262  yuv2anyX_fn yuv2anyX = c->yuv2anyX;
263  const int chrSrcSliceY = srcSliceY >> c->chrSrcVSubSample;
264  const int chrSrcSliceH = AV_CEIL_RSHIFT(srcSliceH, c->chrSrcVSubSample);
265  int should_dither = isNBPS(c->srcFormat) ||
266  is16BPS(c->srcFormat);
267  int lastDstY;
268 
269  /* vars which will change and which we need to store back in the context */
270  int dstY = c->dstY;
271  int lastInLumBuf = c->lastInLumBuf;
272  int lastInChrBuf = c->lastInChrBuf;
273 
274  int lumStart = 0;
275  int lumEnd = c->descIndex[0];
276  int chrStart = lumEnd;
277  int chrEnd = c->descIndex[1];
278  int vStart = chrEnd;
279  int vEnd = c->numDesc;
280  SwsSlice *src_slice = &c->slice[lumStart];
281  SwsSlice *hout_slice = &c->slice[c->numSlice-2];
282  SwsSlice *vout_slice = &c->slice[c->numSlice-1];
283  SwsFilterDescriptor *desc = c->desc;
284 
285  int needAlpha = c->needAlpha;
286 
287  int hasLumHoles = 1;
288  int hasChrHoles = 1;
289 
290  if (isPacked(c->srcFormat)) {
291  src[1] =
292  src[2] =
293  src[3] = src[0];
294  srcStride[1] =
295  srcStride[2] =
296  srcStride[3] = srcStride[0];
297  }
298  srcStride[1] *= 1 << c->vChrDrop;
299  srcStride[2] *= 1 << c->vChrDrop;
300 
301  DEBUG_BUFFERS("swscale() %p[%d] %p[%d] %p[%d] %p[%d] -> %p[%d] %p[%d] %p[%d] %p[%d]\n",
302  src[0], srcStride[0], src[1], srcStride[1],
303  src[2], srcStride[2], src[3], srcStride[3],
304  dst[0], dstStride[0], dst[1], dstStride[1],
305  dst[2], dstStride[2], dst[3], dstStride[3]);
306  DEBUG_BUFFERS("srcSliceY: %d srcSliceH: %d dstY: %d dstH: %d\n",
307  srcSliceY, srcSliceH, dstY, dstH);
308  DEBUG_BUFFERS("vLumFilterSize: %d vChrFilterSize: %d\n",
309  vLumFilterSize, vChrFilterSize);
310 
311  if (dstStride[0]&15 || dstStride[1]&15 ||
312  dstStride[2]&15 || dstStride[3]&15) {
313  SwsContext *const ctx = c->parent ? c->parent : c;
314  if (flags & SWS_PRINT_INFO &&
315  !atomic_exchange_explicit(&ctx->stride_unaligned_warned, 1, memory_order_relaxed)) {
317  "Warning: dstStride is not aligned!\n"
318  " ->cannot do aligned memory accesses anymore\n");
319  }
320  }
321 
322 #if ARCH_X86
323  if ( (uintptr_t)dst[0]&15 || (uintptr_t)dst[1]&15 || (uintptr_t)dst[2]&15
324  || (uintptr_t)src[0]&15 || (uintptr_t)src[1]&15 || (uintptr_t)src[2]&15
325  || dstStride[0]&15 || dstStride[1]&15 || dstStride[2]&15 || dstStride[3]&15
326  || srcStride[0]&15 || srcStride[1]&15 || srcStride[2]&15 || srcStride[3]&15
327  ) {
328  SwsContext *const ctx = c->parent ? c->parent : c;
329  int cpu_flags = av_get_cpu_flags();
330  if (flags & SWS_PRINT_INFO && HAVE_MMXEXT && (cpu_flags & AV_CPU_FLAG_SSE2) &&
331  !atomic_exchange_explicit(&ctx->stride_unaligned_warned,1, memory_order_relaxed)) {
332  av_log(c, AV_LOG_WARNING, "Warning: data is not aligned! This can lead to a speed loss\n");
333  }
334  }
335 #endif
336 
337  if (scale_dst) {
338  dstY = dstSliceY;
339  dstH = dstY + dstSliceH;
340  lastInLumBuf = -1;
341  lastInChrBuf = -1;
342  } else if (srcSliceY == 0) {
343  /* Note the user might start scaling the picture in the middle so this
344  * will not get executed. This is not really intended but works
345  * currently, so people might do it. */
346  dstY = 0;
347  lastInLumBuf = -1;
348  lastInChrBuf = -1;
349  }
350 
351  if (!should_dither) {
352  c->chrDither8 = c->lumDither8 = sws_pb_64;
353  }
354  lastDstY = dstY;
355 
356  ff_init_vscale_pfn(c, yuv2plane1, yuv2planeX, yuv2nv12cX,
357  yuv2packed1, yuv2packed2, yuv2packedX, yuv2anyX, c->use_mmx_vfilter);
358 
359  ff_init_slice_from_src(src_slice, (uint8_t**)src, srcStride, c->srcW,
360  srcSliceY, srcSliceH, chrSrcSliceY, chrSrcSliceH, 1);
361 
362  ff_init_slice_from_src(vout_slice, (uint8_t**)dst, dstStride, c->dstW,
363  dstY, dstSliceH, dstY >> c->chrDstVSubSample,
364  AV_CEIL_RSHIFT(dstSliceH, c->chrDstVSubSample), scale_dst);
365  if (srcSliceY == 0) {
366  hout_slice->plane[0].sliceY = lastInLumBuf + 1;
367  hout_slice->plane[1].sliceY = lastInChrBuf + 1;
368  hout_slice->plane[2].sliceY = lastInChrBuf + 1;
369  hout_slice->plane[3].sliceY = lastInLumBuf + 1;
370 
371  hout_slice->plane[0].sliceH =
372  hout_slice->plane[1].sliceH =
373  hout_slice->plane[2].sliceH =
374  hout_slice->plane[3].sliceH = 0;
375  hout_slice->width = dstW;
376  }
377 
378  for (; dstY < dstH; dstY++) {
379  const int chrDstY = dstY >> c->chrDstVSubSample;
380  int use_mmx_vfilter= c->use_mmx_vfilter;
381 
382  // First line needed as input
383  const int firstLumSrcY = FFMAX(1 - vLumFilterSize, vLumFilterPos[dstY]);
384  const int firstLumSrcY2 = FFMAX(1 - vLumFilterSize, vLumFilterPos[FFMIN(dstY | ((1 << c->chrDstVSubSample) - 1), c->dstH - 1)]);
385  // First line needed as input
386  const int firstChrSrcY = FFMAX(1 - vChrFilterSize, vChrFilterPos[chrDstY]);
387 
388  // Last line needed as input
389  int lastLumSrcY = FFMIN(c->srcH, firstLumSrcY + vLumFilterSize) - 1;
390  int lastLumSrcY2 = FFMIN(c->srcH, firstLumSrcY2 + vLumFilterSize) - 1;
391  int lastChrSrcY = FFMIN(c->chrSrcH, firstChrSrcY + vChrFilterSize) - 1;
392  int enough_lines;
393 
394  int i;
395  int posY, cPosY, firstPosY, lastPosY, firstCPosY, lastCPosY;
396 
397  // handle holes (FAST_BILINEAR & weird filters)
398  if (firstLumSrcY > lastInLumBuf) {
399 
400  hasLumHoles = lastInLumBuf != firstLumSrcY - 1;
401  if (hasLumHoles) {
402  hout_slice->plane[0].sliceY = firstLumSrcY;
403  hout_slice->plane[3].sliceY = firstLumSrcY;
404  hout_slice->plane[0].sliceH =
405  hout_slice->plane[3].sliceH = 0;
406  }
407 
408  lastInLumBuf = firstLumSrcY - 1;
409  }
410  if (firstChrSrcY > lastInChrBuf) {
411 
412  hasChrHoles = lastInChrBuf != firstChrSrcY - 1;
413  if (hasChrHoles) {
414  hout_slice->plane[1].sliceY = firstChrSrcY;
415  hout_slice->plane[2].sliceY = firstChrSrcY;
416  hout_slice->plane[1].sliceH =
417  hout_slice->plane[2].sliceH = 0;
418  }
419 
420  lastInChrBuf = firstChrSrcY - 1;
421  }
422 
423  DEBUG_BUFFERS("dstY: %d\n", dstY);
424  DEBUG_BUFFERS("\tfirstLumSrcY: %d lastLumSrcY: %d lastInLumBuf: %d\n",
425  firstLumSrcY, lastLumSrcY, lastInLumBuf);
426  DEBUG_BUFFERS("\tfirstChrSrcY: %d lastChrSrcY: %d lastInChrBuf: %d\n",
427  firstChrSrcY, lastChrSrcY, lastInChrBuf);
428 
429  // Do we have enough lines in this slice to output the dstY line
430  enough_lines = lastLumSrcY2 < srcSliceY + srcSliceH &&
431  lastChrSrcY < AV_CEIL_RSHIFT(srcSliceY + srcSliceH, c->chrSrcVSubSample);
432 
433  if (!enough_lines) {
434  lastLumSrcY = srcSliceY + srcSliceH - 1;
435  lastChrSrcY = chrSrcSliceY + chrSrcSliceH - 1;
436  DEBUG_BUFFERS("buffering slice: lastLumSrcY %d lastChrSrcY %d\n",
437  lastLumSrcY, lastChrSrcY);
438  }
439 
440  av_assert0((lastLumSrcY - firstLumSrcY + 1) <= hout_slice->plane[0].available_lines);
441  av_assert0((lastChrSrcY - firstChrSrcY + 1) <= hout_slice->plane[1].available_lines);
442 
443 
444  posY = hout_slice->plane[0].sliceY + hout_slice->plane[0].sliceH;
445  if (posY <= lastLumSrcY && !hasLumHoles) {
446  firstPosY = FFMAX(firstLumSrcY, posY);
447  lastPosY = FFMIN(firstLumSrcY + hout_slice->plane[0].available_lines - 1, srcSliceY + srcSliceH - 1);
448  } else {
449  firstPosY = posY;
450  lastPosY = lastLumSrcY;
451  }
452 
453  cPosY = hout_slice->plane[1].sliceY + hout_slice->plane[1].sliceH;
454  if (cPosY <= lastChrSrcY && !hasChrHoles) {
455  firstCPosY = FFMAX(firstChrSrcY, cPosY);
456  lastCPosY = FFMIN(firstChrSrcY + hout_slice->plane[1].available_lines - 1, AV_CEIL_RSHIFT(srcSliceY + srcSliceH, c->chrSrcVSubSample) - 1);
457  } else {
458  firstCPosY = cPosY;
459  lastCPosY = lastChrSrcY;
460  }
461 
462  ff_rotate_slice(hout_slice, lastPosY, lastCPosY);
463 
464  if (posY < lastLumSrcY + 1) {
465  for (i = lumStart; i < lumEnd; ++i)
466  desc[i].process(c, &desc[i], firstPosY, lastPosY - firstPosY + 1);
467  }
468 
469  lastInLumBuf = lastLumSrcY;
470 
471  if (cPosY < lastChrSrcY + 1) {
472  for (i = chrStart; i < chrEnd; ++i)
473  desc[i].process(c, &desc[i], firstCPosY, lastCPosY - firstCPosY + 1);
474  }
475 
476  lastInChrBuf = lastChrSrcY;
477 
478  if (!enough_lines)
479  break; // we can't output a dstY line so let's try with the next slice
480 
481 #if HAVE_MMX_INLINE
483 #endif
484  if (should_dither) {
485  c->chrDither8 = ff_dither_8x8_128[chrDstY & 7];
486  c->lumDither8 = ff_dither_8x8_128[dstY & 7];
487  }
488  if (dstY >= c->dstH - 2) {
489  /* hmm looks like we can't use MMX here without overwriting
490  * this array's tail */
491  ff_sws_init_output_funcs(c, &yuv2plane1, &yuv2planeX, &yuv2nv12cX,
492  &yuv2packed1, &yuv2packed2, &yuv2packedX, &yuv2anyX);
493  use_mmx_vfilter= 0;
494  ff_init_vscale_pfn(c, yuv2plane1, yuv2planeX, yuv2nv12cX,
495  yuv2packed1, yuv2packed2, yuv2packedX, yuv2anyX, use_mmx_vfilter);
496  }
497 
498  for (i = vStart; i < vEnd; ++i)
499  desc[i].process(c, &desc[i], dstY, 1);
500  }
501  if (isPlanar(dstFormat) && isALPHA(dstFormat) && !needAlpha) {
502  int offset = lastDstY - dstSliceY;
503  int length = dstW;
504  int height = dstY - lastDstY;
505 
506  if (is16BPS(dstFormat) || isNBPS(dstFormat)) {
507  const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(dstFormat);
508  fillPlane16(dst[3], dstStride[3], length, height, offset,
509  1, desc->comp[3].depth,
510  isBE(dstFormat));
511  } else if (is32BPS(dstFormat)) {
512  const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(dstFormat);
513  fillPlane32(dst[3], dstStride[3], length, height, offset,
514  1, desc->comp[3].depth,
515  isBE(dstFormat), desc->flags & AV_PIX_FMT_FLAG_FLOAT);
516  } else
517  fillPlane(dst[3], dstStride[3], length, height, offset, 255);
518  }
519 
520 #if HAVE_MMXEXT_INLINE
522  __asm__ volatile ("sfence" ::: "memory");
523 #endif
524  emms_c();
525 
526  /* store changed local vars back in the context */
527  c->dstY = dstY;
528  c->lastInLumBuf = lastInLumBuf;
529  c->lastInChrBuf = lastInChrBuf;
530 
531  return dstY - lastDstY;
532 }
533 
535 {
536  c->lumConvertRange = NULL;
537  c->chrConvertRange = NULL;
538  if (c->srcRange != c->dstRange && !isAnyRGB(c->dstFormat)) {
539  if (c->dstBpc <= 14) {
540  if (c->srcRange) {
541  c->lumConvertRange = lumRangeFromJpeg_c;
542  c->chrConvertRange = chrRangeFromJpeg_c;
543  } else {
544  c->lumConvertRange = lumRangeToJpeg_c;
545  c->chrConvertRange = chrRangeToJpeg_c;
546  }
547  } else {
548  if (c->srcRange) {
549  c->lumConvertRange = lumRangeFromJpeg16_c;
550  c->chrConvertRange = chrRangeFromJpeg16_c;
551  } else {
552  c->lumConvertRange = lumRangeToJpeg16_c;
553  c->chrConvertRange = chrRangeToJpeg16_c;
554  }
555  }
556  }
557 }
558 
560 {
561  enum AVPixelFormat srcFormat = c->srcFormat;
562 
563  ff_sws_init_output_funcs(c, &c->yuv2plane1, &c->yuv2planeX,
564  &c->yuv2nv12cX, &c->yuv2packed1,
565  &c->yuv2packed2, &c->yuv2packedX, &c->yuv2anyX);
566 
568 
569  if (c->srcBpc == 8) {
570  if (c->dstBpc <= 14) {
571  c->hyScale = c->hcScale = hScale8To15_c;
572  if (c->flags & SWS_FAST_BILINEAR) {
573  c->hyscale_fast = ff_hyscale_fast_c;
574  c->hcscale_fast = ff_hcscale_fast_c;
575  }
576  } else {
577  c->hyScale = c->hcScale = hScale8To19_c;
578  }
579  } else {
580  c->hyScale = c->hcScale = c->dstBpc > 14 ? hScale16To19_c
581  : hScale16To15_c;
582  }
583 
585 
586  if (!(isGray(srcFormat) || isGray(c->dstFormat) ||
587  srcFormat == AV_PIX_FMT_MONOBLACK || srcFormat == AV_PIX_FMT_MONOWHITE))
588  c->needs_hcscale = 1;
589 }
590 
592 {
594 
595 #if ARCH_PPC
597 #elif ARCH_X86
599 #elif ARCH_AARCH64
601 #elif ARCH_ARM
603 #elif ARCH_LOONGARCH64
605 #elif ARCH_RISCV
607 #endif
608 }
609 
610 static void reset_ptr(const uint8_t *src[], enum AVPixelFormat format)
611 {
612  if (!isALPHA(format))
613  src[3] = NULL;
614  if (!isPlanar(format)) {
615  src[3] = src[2] = NULL;
616 
617  if (!usePal(format))
618  src[1] = NULL;
619  }
620 }
621 
622 static int check_image_pointers(const uint8_t * const data[4], enum AVPixelFormat pix_fmt,
623  const int linesizes[4])
624 {
626  int i;
627 
628  av_assert2(desc);
629 
630  for (i = 0; i < 4; i++) {
631  int plane = desc->comp[i].plane;
632  if (!data[plane] || !linesizes[plane])
633  return 0;
634  }
635 
636  return 1;
637 }
638 
639 static void xyz12Torgb48(struct SwsContext *c, uint16_t *dst,
640  const uint16_t *src, int stride, int h)
641 {
642  int xp,yp;
643  const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->srcFormat);
644 
645  for (yp=0; yp<h; yp++) {
646  for (xp=0; xp+2<stride; xp+=3) {
647  int x, y, z, r, g, b;
648 
649  if (desc->flags & AV_PIX_FMT_FLAG_BE) {
650  x = AV_RB16(src + xp + 0);
651  y = AV_RB16(src + xp + 1);
652  z = AV_RB16(src + xp + 2);
653  } else {
654  x = AV_RL16(src + xp + 0);
655  y = AV_RL16(src + xp + 1);
656  z = AV_RL16(src + xp + 2);
657  }
658 
659  x = c->xyzgamma[x>>4];
660  y = c->xyzgamma[y>>4];
661  z = c->xyzgamma[z>>4];
662 
663  // convert from XYZlinear to sRGBlinear
664  r = c->xyz2rgb_matrix[0][0] * x +
665  c->xyz2rgb_matrix[0][1] * y +
666  c->xyz2rgb_matrix[0][2] * z >> 12;
667  g = c->xyz2rgb_matrix[1][0] * x +
668  c->xyz2rgb_matrix[1][1] * y +
669  c->xyz2rgb_matrix[1][2] * z >> 12;
670  b = c->xyz2rgb_matrix[2][0] * x +
671  c->xyz2rgb_matrix[2][1] * y +
672  c->xyz2rgb_matrix[2][2] * z >> 12;
673 
674  // limit values to 12-bit depth
675  r = av_clip_uintp2(r, 12);
676  g = av_clip_uintp2(g, 12);
677  b = av_clip_uintp2(b, 12);
678 
679  // convert from sRGBlinear to RGB and scale from 12bit to 16bit
680  if (desc->flags & AV_PIX_FMT_FLAG_BE) {
681  AV_WB16(dst + xp + 0, c->rgbgamma[r] << 4);
682  AV_WB16(dst + xp + 1, c->rgbgamma[g] << 4);
683  AV_WB16(dst + xp + 2, c->rgbgamma[b] << 4);
684  } else {
685  AV_WL16(dst + xp + 0, c->rgbgamma[r] << 4);
686  AV_WL16(dst + xp + 1, c->rgbgamma[g] << 4);
687  AV_WL16(dst + xp + 2, c->rgbgamma[b] << 4);
688  }
689  }
690  src += stride;
691  dst += stride;
692  }
693 }
694 
695 static void rgb48Toxyz12(struct SwsContext *c, uint16_t *dst,
696  const uint16_t *src, int stride, int h)
697 {
698  int xp,yp;
699  const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->dstFormat);
700 
701  for (yp=0; yp<h; yp++) {
702  for (xp=0; xp+2<stride; xp+=3) {
703  int x, y, z, r, g, b;
704 
705  if (desc->flags & AV_PIX_FMT_FLAG_BE) {
706  r = AV_RB16(src + xp + 0);
707  g = AV_RB16(src + xp + 1);
708  b = AV_RB16(src + xp + 2);
709  } else {
710  r = AV_RL16(src + xp + 0);
711  g = AV_RL16(src + xp + 1);
712  b = AV_RL16(src + xp + 2);
713  }
714 
715  r = c->rgbgammainv[r>>4];
716  g = c->rgbgammainv[g>>4];
717  b = c->rgbgammainv[b>>4];
718 
719  // convert from sRGBlinear to XYZlinear
720  x = c->rgb2xyz_matrix[0][0] * r +
721  c->rgb2xyz_matrix[0][1] * g +
722  c->rgb2xyz_matrix[0][2] * b >> 12;
723  y = c->rgb2xyz_matrix[1][0] * r +
724  c->rgb2xyz_matrix[1][1] * g +
725  c->rgb2xyz_matrix[1][2] * b >> 12;
726  z = c->rgb2xyz_matrix[2][0] * r +
727  c->rgb2xyz_matrix[2][1] * g +
728  c->rgb2xyz_matrix[2][2] * b >> 12;
729 
730  // limit values to 12-bit depth
731  x = av_clip_uintp2(x, 12);
732  y = av_clip_uintp2(y, 12);
733  z = av_clip_uintp2(z, 12);
734 
735  // convert from XYZlinear to X'Y'Z' and scale from 12bit to 16bit
736  if (desc->flags & AV_PIX_FMT_FLAG_BE) {
737  AV_WB16(dst + xp + 0, c->xyzgammainv[x] << 4);
738  AV_WB16(dst + xp + 1, c->xyzgammainv[y] << 4);
739  AV_WB16(dst + xp + 2, c->xyzgammainv[z] << 4);
740  } else {
741  AV_WL16(dst + xp + 0, c->xyzgammainv[x] << 4);
742  AV_WL16(dst + xp + 1, c->xyzgammainv[y] << 4);
743  AV_WL16(dst + xp + 2, c->xyzgammainv[z] << 4);
744  }
745  }
746  src += stride;
747  dst += stride;
748  }
749 }
750 
751 static void update_palette(SwsContext *c, const uint32_t *pal)
752 {
753  for (int i = 0; i < 256; i++) {
754  int r, g, b, y, u, v, a = 0xff;
755  if (c->srcFormat == AV_PIX_FMT_PAL8) {
756  uint32_t p = pal[i];
757  a = (p >> 24) & 0xFF;
758  r = (p >> 16) & 0xFF;
759  g = (p >> 8) & 0xFF;
760  b = p & 0xFF;
761  } else if (c->srcFormat == AV_PIX_FMT_RGB8) {
762  r = ( i >> 5 ) * 36;
763  g = ((i >> 2) & 7) * 36;
764  b = ( i & 3) * 85;
765  } else if (c->srcFormat == AV_PIX_FMT_BGR8) {
766  b = ( i >> 6 ) * 85;
767  g = ((i >> 3) & 7) * 36;
768  r = ( i & 7) * 36;
769  } else if (c->srcFormat == AV_PIX_FMT_RGB4_BYTE) {
770  r = ( i >> 3 ) * 255;
771  g = ((i >> 1) & 3) * 85;
772  b = ( i & 1) * 255;
773  } else if (c->srcFormat == AV_PIX_FMT_GRAY8 || c->srcFormat == AV_PIX_FMT_GRAY8A) {
774  r = g = b = i;
775  } else {
776  av_assert1(c->srcFormat == AV_PIX_FMT_BGR4_BYTE);
777  b = ( i >> 3 ) * 255;
778  g = ((i >> 1) & 3) * 85;
779  r = ( i & 1) * 255;
780  }
781 #define RGB2YUV_SHIFT 15
782 #define BY ( (int) (0.114 * 219 / 255 * (1 << RGB2YUV_SHIFT) + 0.5))
783 #define BV (-(int) (0.081 * 224 / 255 * (1 << RGB2YUV_SHIFT) + 0.5))
784 #define BU ( (int) (0.500 * 224 / 255 * (1 << RGB2YUV_SHIFT) + 0.5))
785 #define GY ( (int) (0.587 * 219 / 255 * (1 << RGB2YUV_SHIFT) + 0.5))
786 #define GV (-(int) (0.419 * 224 / 255 * (1 << RGB2YUV_SHIFT) + 0.5))
787 #define GU (-(int) (0.331 * 224 / 255 * (1 << RGB2YUV_SHIFT) + 0.5))
788 #define RY ( (int) (0.299 * 219 / 255 * (1 << RGB2YUV_SHIFT) + 0.5))
789 #define RV ( (int) (0.500 * 224 / 255 * (1 << RGB2YUV_SHIFT) + 0.5))
790 #define RU (-(int) (0.169 * 224 / 255 * (1 << RGB2YUV_SHIFT) + 0.5))
791 
792  y = av_clip_uint8((RY * r + GY * g + BY * b + ( 33 << (RGB2YUV_SHIFT - 1))) >> RGB2YUV_SHIFT);
793  u = av_clip_uint8((RU * r + GU * g + BU * b + (257 << (RGB2YUV_SHIFT - 1))) >> RGB2YUV_SHIFT);
794  v = av_clip_uint8((RV * r + GV * g + BV * b + (257 << (RGB2YUV_SHIFT - 1))) >> RGB2YUV_SHIFT);
795  c->pal_yuv[i]= y + (u<<8) + (v<<16) + ((unsigned)a<<24);
796 
797  switch (c->dstFormat) {
798  case AV_PIX_FMT_BGR32:
799 #if !HAVE_BIGENDIAN
800  case AV_PIX_FMT_RGB24:
801 #endif
802  c->pal_rgb[i]= r + (g<<8) + (b<<16) + ((unsigned)a<<24);
803  break;
804  case AV_PIX_FMT_BGR32_1:
805 #if HAVE_BIGENDIAN
806  case AV_PIX_FMT_BGR24:
807 #endif
808  c->pal_rgb[i]= a + (r<<8) + (g<<16) + ((unsigned)b<<24);
809  break;
810  case AV_PIX_FMT_RGB32_1:
811 #if HAVE_BIGENDIAN
812  case AV_PIX_FMT_RGB24:
813 #endif
814  c->pal_rgb[i]= a + (b<<8) + (g<<16) + ((unsigned)r<<24);
815  break;
816  case AV_PIX_FMT_RGB32:
817 #if !HAVE_BIGENDIAN
818  case AV_PIX_FMT_BGR24:
819 #endif
820  default:
821  c->pal_rgb[i]= b + (g<<8) + (r<<16) + ((unsigned)a<<24);
822  }
823  }
824 }
825 
826 static int scale_internal(SwsContext *c,
827  const uint8_t * const srcSlice[], const int srcStride[],
828  int srcSliceY, int srcSliceH,
829  uint8_t *const dstSlice[], const int dstStride[],
830  int dstSliceY, int dstSliceH);
831 
833  const uint8_t * const srcSlice[], const int srcStride[],
834  int srcSliceY, int srcSliceH,
835  uint8_t * const dstSlice[], const int dstStride[],
836  int dstSliceY, int dstSliceH)
837 {
838  int ret = scale_internal(c->cascaded_context[0],
839  srcSlice, srcStride, srcSliceY, srcSliceH,
840  c->cascaded_tmp, c->cascaded_tmpStride, 0, c->srcH);
841 
842  if (ret < 0)
843  return ret;
844 
845  if (c->cascaded_context[2])
846  ret = scale_internal(c->cascaded_context[1], (const uint8_t * const *)c->cascaded_tmp,
847  c->cascaded_tmpStride, srcSliceY, srcSliceH,
848  c->cascaded1_tmp, c->cascaded1_tmpStride, 0, c->dstH);
849  else
850  ret = scale_internal(c->cascaded_context[1], (const uint8_t * const *)c->cascaded_tmp,
851  c->cascaded_tmpStride, srcSliceY, srcSliceH,
852  dstSlice, dstStride, dstSliceY, dstSliceH);
853 
854  if (ret < 0)
855  return ret;
856 
857  if (c->cascaded_context[2]) {
858  ret = scale_internal(c->cascaded_context[2], (const uint8_t * const *)c->cascaded1_tmp,
859  c->cascaded1_tmpStride, c->cascaded_context[1]->dstY - ret,
860  c->cascaded_context[1]->dstY,
861  dstSlice, dstStride, dstSliceY, dstSliceH);
862  }
863  return ret;
864 }
865 
867  const uint8_t * const srcSlice[], const int srcStride[],
868  int srcSliceY, int srcSliceH,
869  uint8_t * const dstSlice[], const int dstStride[],
870  int dstSliceY, int dstSliceH)
871 {
872  int ret = scale_internal(c->cascaded_context[0],
873  srcSlice, srcStride, srcSliceY, srcSliceH,
874  c->cascaded_tmp, c->cascaded_tmpStride,
875  0, c->cascaded_context[0]->dstH);
876  if (ret < 0)
877  return ret;
878  ret = scale_internal(c->cascaded_context[1],
879  (const uint8_t * const * )c->cascaded_tmp, c->cascaded_tmpStride,
880  0, c->cascaded_context[0]->dstH,
881  dstSlice, dstStride, dstSliceY, dstSliceH);
882  return ret;
883 }
884 
886  const uint8_t * const srcSlice[], const int srcStride[],
887  int srcSliceY, int srcSliceH,
888  uint8_t *const dstSlice[], const int dstStride[],
889  int dstSliceY, int dstSliceH)
890 {
891  const int scale_dst = dstSliceY > 0 || dstSliceH < c->dstH;
892  const int frame_start = scale_dst || !c->sliceDir;
893  int i, ret;
894  const uint8_t *src2[4];
895  uint8_t *dst2[4];
896  int macro_height_src = isBayer(c->srcFormat) ? 2 : (1 << c->chrSrcVSubSample);
897  int macro_height_dst = isBayer(c->dstFormat) ? 2 : (1 << c->chrDstVSubSample);
898  // copy strides, so they can safely be modified
899  int srcStride2[4];
900  int dstStride2[4];
901  int srcSliceY_internal = srcSliceY;
902 
903  if (!srcStride || !dstStride || !dstSlice || !srcSlice) {
904  av_log(c, AV_LOG_ERROR, "One of the input parameters to sws_scale() is NULL, please check the calling code\n");
905  return AVERROR(EINVAL);
906  }
907 
908  if ((srcSliceY & (macro_height_src - 1)) ||
909  ((srcSliceH & (macro_height_src - 1)) && srcSliceY + srcSliceH != c->srcH) ||
910  srcSliceY + srcSliceH > c->srcH ||
911  (isBayer(c->srcFormat) && srcSliceH <= 1)) {
912  av_log(c, AV_LOG_ERROR, "Slice parameters %d, %d are invalid\n", srcSliceY, srcSliceH);
913  return AVERROR(EINVAL);
914  }
915 
916  if ((dstSliceY & (macro_height_dst - 1)) ||
917  ((dstSliceH & (macro_height_dst - 1)) && dstSliceY + dstSliceH != c->dstH) ||
918  dstSliceY + dstSliceH > c->dstH) {
919  av_log(c, AV_LOG_ERROR, "Slice parameters %d, %d are invalid\n", dstSliceY, dstSliceH);
920  return AVERROR(EINVAL);
921  }
922 
923  if (!check_image_pointers(srcSlice, c->srcFormat, srcStride)) {
924  av_log(c, AV_LOG_ERROR, "bad src image pointers\n");
925  return AVERROR(EINVAL);
926  }
927  if (!check_image_pointers((const uint8_t* const*)dstSlice, c->dstFormat, dstStride)) {
928  av_log(c, AV_LOG_ERROR, "bad dst image pointers\n");
929  return AVERROR(EINVAL);
930  }
931 
932  // do not mess up sliceDir if we have a "trailing" 0-size slice
933  if (srcSliceH == 0)
934  return 0;
935 
936  if (c->gamma_flag && c->cascaded_context[0])
937  return scale_gamma(c, srcSlice, srcStride, srcSliceY, srcSliceH,
938  dstSlice, dstStride, dstSliceY, dstSliceH);
939 
940  if (c->cascaded_context[0] && srcSliceY == 0 && srcSliceH == c->cascaded_context[0]->srcH)
941  return scale_cascaded(c, srcSlice, srcStride, srcSliceY, srcSliceH,
942  dstSlice, dstStride, dstSliceY, dstSliceH);
943 
944  if (!srcSliceY && (c->flags & SWS_BITEXACT) && c->dither == SWS_DITHER_ED && c->dither_error[0])
945  for (i = 0; i < 4; i++)
946  memset(c->dither_error[i], 0, sizeof(c->dither_error[0][0]) * (c->dstW+2));
947 
948  if (usePal(c->srcFormat))
949  update_palette(c, (const uint32_t *)srcSlice[1]);
950 
951  memcpy(src2, srcSlice, sizeof(src2));
952  memcpy(dst2, dstSlice, sizeof(dst2));
953  memcpy(srcStride2, srcStride, sizeof(srcStride2));
954  memcpy(dstStride2, dstStride, sizeof(dstStride2));
955 
956  if (frame_start && !scale_dst) {
957  if (srcSliceY != 0 && srcSliceY + srcSliceH != c->srcH) {
958  av_log(c, AV_LOG_ERROR, "Slices start in the middle!\n");
959  return AVERROR(EINVAL);
960  }
961 
962  c->sliceDir = (srcSliceY == 0) ? 1 : -1;
963  } else if (scale_dst)
964  c->sliceDir = 1;
965 
966  if (c->src0Alpha && !c->dst0Alpha && isALPHA(c->dstFormat)) {
967  uint8_t *base;
968  int x,y;
969 
970  av_fast_malloc(&c->rgb0_scratch, &c->rgb0_scratch_allocated,
971  FFABS(srcStride[0]) * srcSliceH + 32);
972  if (!c->rgb0_scratch)
973  return AVERROR(ENOMEM);
974 
975  base = srcStride[0] < 0 ? c->rgb0_scratch - srcStride[0] * (srcSliceH-1) :
976  c->rgb0_scratch;
977  for (y=0; y<srcSliceH; y++){
978  memcpy(base + srcStride[0]*y, src2[0] + srcStride[0]*y, 4*c->srcW);
979  for (x=c->src0Alpha-1; x<4*c->srcW; x+=4) {
980  base[ srcStride[0]*y + x] = 0xFF;
981  }
982  }
983  src2[0] = base;
984  }
985 
986  if (c->srcXYZ && !(c->dstXYZ && c->srcW==c->dstW && c->srcH==c->dstH)) {
987  uint8_t *base;
988 
989  av_fast_malloc(&c->xyz_scratch, &c->xyz_scratch_allocated,
990  FFABS(srcStride[0]) * srcSliceH + 32);
991  if (!c->xyz_scratch)
992  return AVERROR(ENOMEM);
993 
994  base = srcStride[0] < 0 ? c->xyz_scratch - srcStride[0] * (srcSliceH-1) :
995  c->xyz_scratch;
996 
997  xyz12Torgb48(c, (uint16_t*)base, (const uint16_t*)src2[0], srcStride[0]/2, srcSliceH);
998  src2[0] = base;
999  }
1000 
1001  if (c->sliceDir != 1) {
1002  // slices go from bottom to top => we flip the image internally
1003  for (i=0; i<4; i++) {
1004  srcStride2[i] *= -1;
1005  dstStride2[i] *= -1;
1006  }
1007 
1008  src2[0] += (srcSliceH - 1) * srcStride[0];
1009  if (!usePal(c->srcFormat))
1010  src2[1] += ((srcSliceH >> c->chrSrcVSubSample) - 1) * srcStride[1];
1011  src2[2] += ((srcSliceH >> c->chrSrcVSubSample) - 1) * srcStride[2];
1012  src2[3] += (srcSliceH - 1) * srcStride[3];
1013  dst2[0] += ( c->dstH - 1) * dstStride[0];
1014  dst2[1] += ((c->dstH >> c->chrDstVSubSample) - 1) * dstStride[1];
1015  dst2[2] += ((c->dstH >> c->chrDstVSubSample) - 1) * dstStride[2];
1016  dst2[3] += ( c->dstH - 1) * dstStride[3];
1017 
1018  srcSliceY_internal = c->srcH-srcSliceY-srcSliceH;
1019  }
1020  reset_ptr(src2, c->srcFormat);
1021  reset_ptr((void*)dst2, c->dstFormat);
1022 
1023  if (c->convert_unscaled) {
1024  int offset = srcSliceY_internal;
1025  int slice_h = srcSliceH;
1026 
1027  // for dst slice scaling, offset the pointers to match the unscaled API
1028  if (scale_dst) {
1029  av_assert0(offset == 0);
1030  for (i = 0; i < 4 && src2[i]; i++) {
1031  if (!src2[i] || (i > 0 && usePal(c->srcFormat)))
1032  break;
1033  src2[i] += (dstSliceY >> ((i == 1 || i == 2) ? c->chrSrcVSubSample : 0)) * srcStride2[i];
1034  }
1035 
1036  for (i = 0; i < 4 && dst2[i]; i++) {
1037  if (!dst2[i] || (i > 0 && usePal(c->dstFormat)))
1038  break;
1039  dst2[i] -= (dstSliceY >> ((i == 1 || i == 2) ? c->chrDstVSubSample : 0)) * dstStride2[i];
1040  }
1041  offset = dstSliceY;
1042  slice_h = dstSliceH;
1043  }
1044 
1045  ret = c->convert_unscaled(c, src2, srcStride2, offset, slice_h,
1046  dst2, dstStride2);
1047  if (scale_dst)
1048  dst2[0] += dstSliceY * dstStride2[0];
1049  } else {
1050  ret = swscale(c, src2, srcStride2, srcSliceY_internal, srcSliceH,
1051  dst2, dstStride2, dstSliceY, dstSliceH);
1052  }
1053 
1054  if (c->dstXYZ && !(c->srcXYZ && c->srcW==c->dstW && c->srcH==c->dstH)) {
1055  uint16_t *dst16;
1056 
1057  if (scale_dst) {
1058  dst16 = (uint16_t *)dst2[0];
1059  } else {
1060  int dstY = c->dstY ? c->dstY : srcSliceY + srcSliceH;
1061 
1062  av_assert0(dstY >= ret);
1063  av_assert0(ret >= 0);
1064  av_assert0(c->dstH >= dstY);
1065  dst16 = (uint16_t*)(dst2[0] + (dstY - ret) * dstStride2[0]);
1066  }
1067 
1068  /* replace on the same data */
1069  rgb48Toxyz12(c, dst16, dst16, dstStride2[0]/2, ret);
1070  }
1071 
1072  /* reset slice direction at end of frame */
1073  if ((srcSliceY_internal + srcSliceH == c->srcH) || scale_dst)
1074  c->sliceDir = 0;
1075 
1076  return ret;
1077 }
1078 
1080 {
1081  av_frame_unref(c->frame_src);
1082  av_frame_unref(c->frame_dst);
1083  c->src_ranges.nb_ranges = 0;
1084 }
1085 
1087 {
1088  int ret, allocated = 0;
1089 
1090  ret = av_frame_ref(c->frame_src, src);
1091  if (ret < 0)
1092  return ret;
1093 
1094  if (!dst->buf[0]) {
1095  dst->width = c->dstW;
1096  dst->height = c->dstH;
1097  dst->format = c->dstFormat;
1098 
1099  ret = av_frame_get_buffer(dst, 0);
1100  if (ret < 0)
1101  return ret;
1102  allocated = 1;
1103  }
1104 
1105  ret = av_frame_ref(c->frame_dst, dst);
1106  if (ret < 0) {
1107  if (allocated)
1109 
1110  return ret;
1111  }
1112 
1113  return 0;
1114 }
1115 
1116 int sws_send_slice(struct SwsContext *c, unsigned int slice_start,
1117  unsigned int slice_height)
1118 {
1119  int ret;
1120 
1121  ret = ff_range_add(&c->src_ranges, slice_start, slice_height);
1122  if (ret < 0)
1123  return ret;
1124 
1125  return 0;
1126 }
1127 
1128 unsigned int sws_receive_slice_alignment(const struct SwsContext *c)
1129 {
1130  if (c->slice_ctx)
1131  return c->slice_ctx[0]->dst_slice_align;
1132 
1133  return c->dst_slice_align;
1134 }
1135 
1136 int sws_receive_slice(struct SwsContext *c, unsigned int slice_start,
1137  unsigned int slice_height)
1138 {
1139  unsigned int align = sws_receive_slice_alignment(c);
1140  uint8_t *dst[4];
1141 
1142  /* wait until complete input has been received */
1143  if (!(c->src_ranges.nb_ranges == 1 &&
1144  c->src_ranges.ranges[0].start == 0 &&
1145  c->src_ranges.ranges[0].len == c->srcH))
1146  return AVERROR(EAGAIN);
1147 
1148  if ((slice_start > 0 || slice_height < c->dstH) &&
1149  (slice_start % align || slice_height % align)) {
1151  "Incorrectly aligned output: %u/%u not multiples of %u\n",
1152  slice_start, slice_height, align);
1153  return AVERROR(EINVAL);
1154  }
1155 
1156  if (c->slicethread) {
1157  int nb_jobs = c->slice_ctx[0]->dither == SWS_DITHER_ED ? 1 : c->nb_slice_ctx;
1158  int ret = 0;
1159 
1160  c->dst_slice_start = slice_start;
1161  c->dst_slice_height = slice_height;
1162 
1163  avpriv_slicethread_execute(c->slicethread, nb_jobs, 0);
1164 
1165  for (int i = 0; i < c->nb_slice_ctx; i++) {
1166  if (c->slice_err[i] < 0) {
1167  ret = c->slice_err[i];
1168  break;
1169  }
1170  }
1171 
1172  memset(c->slice_err, 0, c->nb_slice_ctx * sizeof(*c->slice_err));
1173 
1174  return ret;
1175  }
1176 
1177  for (int i = 0; i < FF_ARRAY_ELEMS(dst); i++) {
1178  ptrdiff_t offset = c->frame_dst->linesize[i] * (ptrdiff_t)(slice_start >> c->chrDstVSubSample);
1179  dst[i] = FF_PTR_ADD(c->frame_dst->data[i], offset);
1180  }
1181 
1182  return scale_internal(c, (const uint8_t * const *)c->frame_src->data,
1183  c->frame_src->linesize, 0, c->srcH,
1184  dst, c->frame_dst->linesize, slice_start, slice_height);
1185 }
1186 
1188 {
1189  int ret;
1190 
1191  ret = sws_frame_start(c, dst, src);
1192  if (ret < 0)
1193  return ret;
1194 
1195  ret = sws_send_slice(c, 0, src->height);
1196  if (ret >= 0)
1197  ret = sws_receive_slice(c, 0, dst->height);
1198 
1199  sws_frame_end(c);
1200 
1201  return ret;
1202 }
1203 
1204 /**
1205  * swscale wrapper, so we don't need to export the SwsContext.
1206  * Assumes planar YUV to be in YUV order instead of YVU.
1207  */
1209  const uint8_t * const srcSlice[],
1210  const int srcStride[], int srcSliceY,
1211  int srcSliceH, uint8_t *const dst[],
1212  const int dstStride[])
1213 {
1214  if (c->nb_slice_ctx)
1215  c = c->slice_ctx[0];
1216 
1217  return scale_internal(c, srcSlice, srcStride, srcSliceY, srcSliceH,
1218  dst, dstStride, 0, c->dstH);
1219 }
1220 
1221 void ff_sws_slice_worker(void *priv, int jobnr, int threadnr,
1222  int nb_jobs, int nb_threads)
1223 {
1224  SwsContext *parent = priv;
1225  SwsContext *c = parent->slice_ctx[threadnr];
1226 
1227  const int slice_height = FFALIGN(FFMAX((parent->dst_slice_height + nb_jobs - 1) / nb_jobs, 1),
1228  c->dst_slice_align);
1229  const int slice_start = jobnr * slice_height;
1230  const int slice_end = FFMIN((jobnr + 1) * slice_height, parent->dst_slice_height);
1231  int err = 0;
1232 
1233  if (slice_end > slice_start) {
1234  uint8_t *dst[4] = { NULL };
1235 
1236  for (int i = 0; i < FF_ARRAY_ELEMS(dst) && parent->frame_dst->data[i]; i++) {
1237  const int vshift = (i == 1 || i == 2) ? c->chrDstVSubSample : 0;
1238  const ptrdiff_t offset = parent->frame_dst->linesize[i] *
1239  (ptrdiff_t)((slice_start + parent->dst_slice_start) >> vshift);
1240 
1241  dst[i] = parent->frame_dst->data[i] + offset;
1242  }
1243 
1244  err = scale_internal(c, (const uint8_t * const *)parent->frame_src->data,
1245  parent->frame_src->linesize, 0, c->srcH,
1246  dst, parent->frame_dst->linesize,
1248  }
1249 
1250  parent->slice_err[threadnr] = err;
1251 }
isBayer
static av_always_inline int isBayer(enum AVPixelFormat pix_fmt)
Definition: swscale_internal.h:821
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:186
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:1058
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:866
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:291
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:453
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:2965
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:1076
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:380
pixdesc.h
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
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:1083
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
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:1208
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:885
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:1116
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:866
_src
uint8_t ptrdiff_t const uint8_t * _src
Definition: dsp.h:52
xyz12Torgb48
static void xyz12Torgb48(struct SwsContext *c, uint16_t *dst, const uint16_t *src, int stride, int h)
Definition: swscale.c:639
AVFrame::data
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:401
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:1136
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:706
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:720
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: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:61
sws_init_swscale
static av_cold void sws_init_swscale(SwsContext *c)
Definition: swscale.c:559
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:1086
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:1070
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:832
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:454
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:313
ff_sws_init_range_convert
av_cold void ff_sws_init_range_convert(SwsContext *c)
Definition: swscale.c:534
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: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:1056
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:2568
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:1221
isBE
static av_always_inline int isBE(enum AVPixelFormat pix_fmt)
Definition: swscale_internal.h:727
update_palette
static void update_palette(SwsContext *c, const uint32_t *pal)
Definition: swscale.c:751
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:591
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:387
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:1016
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:897
BV
#define BV
cpu.h
isAnyRGB
static av_always_inline int isAnyRGB(enum AVPixelFormat pix_fmt)
Definition: swscale_internal.h:835
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:308
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:713
AV_WL16
#define AV_WL16(p, v)
Definition: intreadwrite.h:408
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:1030
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:1187
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
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:1128
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:622
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:609
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:1068
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 *src[4], 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:1079
ff_sws_init_swscale_ppc
av_cold void ff_sws_init_swscale_ppc(SwsContext *c)
Definition: swscale_altivec.c:232
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:610
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:236
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:1057
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:425
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:875
width
#define width
Definition: dsp.h:85
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:695
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