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