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