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 <inttypes.h>
22 #include <math.h>
23 #include <stdio.h>
24 #include <string.h>
25 
26 #include "libavutil/avassert.h"
27 #include "libavutil/avutil.h"
28 #include "libavutil/bswap.h"
29 #include "libavutil/cpu.h"
30 #include "libavutil/imgutils.h"
31 #include "libavutil/intreadwrite.h"
32 #include "libavutil/mathematics.h"
33 #include "libavutil/mem_internal.h"
34 #include "libavutil/pixdesc.h"
35 #include "config.h"
36 #include "rgb2rgb.h"
37 #include "swscale_internal.h"
38 #include "swscale.h"
39 
40 DECLARE_ALIGNED(8, const uint8_t, ff_dither_8x8_128)[9][8] = {
41  { 36, 68, 60, 92, 34, 66, 58, 90, },
42  { 100, 4, 124, 28, 98, 2, 122, 26, },
43  { 52, 84, 44, 76, 50, 82, 42, 74, },
44  { 116, 20, 108, 12, 114, 18, 106, 10, },
45  { 32, 64, 56, 88, 38, 70, 62, 94, },
46  { 96, 0, 120, 24, 102, 6, 126, 30, },
47  { 48, 80, 40, 72, 54, 86, 46, 78, },
48  { 112, 16, 104, 8, 118, 22, 110, 14, },
49  { 36, 68, 60, 92, 34, 66, 58, 90, },
50 };
51 
52 DECLARE_ALIGNED(8, static const uint8_t, sws_pb_64)[8] = {
53  64, 64, 64, 64, 64, 64, 64, 64
54 };
55 
56 static av_always_inline void fillPlane(uint8_t *plane, int stride, int width,
57  int height, int y, uint8_t val)
58 {
59  int i;
60  uint8_t *ptr = plane + stride * y;
61  for (i = 0; i < height; i++) {
62  memset(ptr, val, width);
63  ptr += stride;
64  }
65 }
66 
67 static void hScale16To19_c(SwsContext *c, int16_t *_dst, int dstW,
68  const uint8_t *_src, const int16_t *filter,
69  const int32_t *filterPos, int filterSize)
70 {
71  const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->srcFormat);
72  int i;
73  int32_t *dst = (int32_t *) _dst;
74  const uint16_t *src = (const uint16_t *) _src;
75  int bits = desc->comp[0].depth - 1;
76  int sh = bits - 4;
77 
78  if ((isAnyRGB(c->srcFormat) || c->srcFormat==AV_PIX_FMT_PAL8) && desc->comp[0].depth<16) {
79  sh = 9;
80  } else if (desc->flags & AV_PIX_FMT_FLAG_FLOAT) { /* float input are process like uint 16bpc */
81  sh = 16 - 1 - 4;
82  }
83 
84  for (i = 0; i < dstW; i++) {
85  int j;
86  int srcPos = filterPos[i];
87  int val = 0;
88 
89  for (j = 0; j < filterSize; j++) {
90  val += src[srcPos + j] * filter[filterSize * i + j];
91  }
92  // filter=14 bit, input=16 bit, output=30 bit, >> 11 makes 19 bit
93  dst[i] = FFMIN(val >> sh, (1 << 19) - 1);
94  }
95 }
96 
97 static void hScale16To15_c(SwsContext *c, int16_t *dst, int dstW,
98  const uint8_t *_src, const int16_t *filter,
99  const int32_t *filterPos, int filterSize)
100 {
101  const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->srcFormat);
102  int i;
103  const uint16_t *src = (const uint16_t *) _src;
104  int sh = desc->comp[0].depth - 1;
105 
106  if (sh<15) {
107  sh = isAnyRGB(c->srcFormat) || c->srcFormat==AV_PIX_FMT_PAL8 ? 13 : (desc->comp[0].depth - 1);
108  } else if (desc->flags & AV_PIX_FMT_FLAG_FLOAT) { /* float input are process like uint 16bpc */
109  sh = 16 - 1;
110  }
111 
112  for (i = 0; i < dstW; i++) {
113  int j;
114  int srcPos = filterPos[i];
115  int val = 0;
116 
117  for (j = 0; j < filterSize; j++) {
118  val += src[srcPos + j] * filter[filterSize * i + j];
119  }
120  // filter=14 bit, input=16 bit, output=30 bit, >> 15 makes 15 bit
121  dst[i] = FFMIN(val >> sh, (1 << 15) - 1);
122  }
123 }
124 
125 // bilinear / bicubic scaling
126 static void hScale8To15_c(SwsContext *c, int16_t *dst, int dstW,
127  const uint8_t *src, const int16_t *filter,
128  const int32_t *filterPos, int filterSize)
129 {
130  int i;
131  for (i = 0; i < dstW; i++) {
132  int j;
133  int srcPos = filterPos[i];
134  int val = 0;
135  for (j = 0; j < filterSize; j++) {
136  val += ((int)src[srcPos + j]) * filter[filterSize * i + j];
137  }
138  dst[i] = FFMIN(val >> 7, (1 << 15) - 1); // the cubic equation does overflow ...
139  }
140 }
141 
142 static void hScale8To19_c(SwsContext *c, int16_t *_dst, int dstW,
143  const uint8_t *src, const int16_t *filter,
144  const int32_t *filterPos, int filterSize)
145 {
146  int i;
147  int32_t *dst = (int32_t *) _dst;
148  for (i = 0; i < dstW; i++) {
149  int j;
150  int srcPos = filterPos[i];
151  int val = 0;
152  for (j = 0; j < filterSize; j++) {
153  val += ((int)src[srcPos + j]) * filter[filterSize * i + j];
154  }
155  dst[i] = FFMIN(val >> 3, (1 << 19) - 1); // the cubic equation does overflow ...
156  }
157 }
158 
159 // FIXME all pal and rgb srcFormats could do this conversion as well
160 // FIXME all scalers more complex than bilinear could do half of this transform
161 static void chrRangeToJpeg_c(int16_t *dstU, int16_t *dstV, int width)
162 {
163  int i;
164  for (i = 0; i < width; i++) {
165  dstU[i] = (FFMIN(dstU[i], 30775) * 4663 - 9289992) >> 12; // -264
166  dstV[i] = (FFMIN(dstV[i], 30775) * 4663 - 9289992) >> 12; // -264
167  }
168 }
169 
170 static void chrRangeFromJpeg_c(int16_t *dstU, int16_t *dstV, int width)
171 {
172  int i;
173  for (i = 0; i < width; i++) {
174  dstU[i] = (dstU[i] * 1799 + 4081085) >> 11; // 1469
175  dstV[i] = (dstV[i] * 1799 + 4081085) >> 11; // 1469
176  }
177 }
178 
179 static void lumRangeToJpeg_c(int16_t *dst, int width)
180 {
181  int i;
182  for (i = 0; i < width; i++)
183  dst[i] = (FFMIN(dst[i], 30189) * 19077 - 39057361) >> 14;
184 }
185 
186 static void lumRangeFromJpeg_c(int16_t *dst, int width)
187 {
188  int i;
189  for (i = 0; i < width; i++)
190  dst[i] = (dst[i] * 14071 + 33561947) >> 14;
191 }
192 
193 static void chrRangeToJpeg16_c(int16_t *_dstU, int16_t *_dstV, int width)
194 {
195  int i;
196  int32_t *dstU = (int32_t *) _dstU;
197  int32_t *dstV = (int32_t *) _dstV;
198  for (i = 0; i < width; i++) {
199  dstU[i] = (FFMIN(dstU[i], 30775 << 4) * 4663 - (9289992 << 4)) >> 12; // -264
200  dstV[i] = (FFMIN(dstV[i], 30775 << 4) * 4663 - (9289992 << 4)) >> 12; // -264
201  }
202 }
203 
204 static void chrRangeFromJpeg16_c(int16_t *_dstU, int16_t *_dstV, int width)
205 {
206  int i;
207  int32_t *dstU = (int32_t *) _dstU;
208  int32_t *dstV = (int32_t *) _dstV;
209  for (i = 0; i < width; i++) {
210  dstU[i] = (dstU[i] * 1799 + (4081085 << 4)) >> 11; // 1469
211  dstV[i] = (dstV[i] * 1799 + (4081085 << 4)) >> 11; // 1469
212  }
213 }
214 
215 static void lumRangeToJpeg16_c(int16_t *_dst, int width)
216 {
217  int i;
218  int32_t *dst = (int32_t *) _dst;
219  for (i = 0; i < width; i++) {
220  dst[i] = ((int)(FFMIN(dst[i], 30189 << 4) * 4769U - (39057361 << 2))) >> 12;
221  }
222 }
223 
224 static void lumRangeFromJpeg16_c(int16_t *_dst, int width)
225 {
226  int i;
227  int32_t *dst = (int32_t *) _dst;
228  for (i = 0; i < width; i++)
229  dst[i] = (dst[i]*(14071/4) + (33561947<<4)/4)>>12;
230 }
231 
232 
233 #define DEBUG_SWSCALE_BUFFERS 0
234 #define DEBUG_BUFFERS(...) \
235  if (DEBUG_SWSCALE_BUFFERS) \
236  av_log(c, AV_LOG_DEBUG, __VA_ARGS__)
237 
238 static int swscale(SwsContext *c, const uint8_t *src[],
239  int srcStride[], int srcSliceY, int srcSliceH,
240  uint8_t *dst[], int dstStride[],
241  int dstSliceY, int dstSliceH)
242 {
243  const int scale_dst = dstSliceY > 0 || dstSliceH < c->dstH;
244 
245  /* load a few things into local vars to make the code more readable?
246  * and faster */
247  const int dstW = c->dstW;
248  int dstH = c->dstH;
249 
250  const enum AVPixelFormat dstFormat = c->dstFormat;
251  const int flags = c->flags;
252  int32_t *vLumFilterPos = c->vLumFilterPos;
253  int32_t *vChrFilterPos = c->vChrFilterPos;
254 
255  const int vLumFilterSize = c->vLumFilterSize;
256  const int vChrFilterSize = c->vChrFilterSize;
257 
258  yuv2planar1_fn yuv2plane1 = c->yuv2plane1;
259  yuv2planarX_fn yuv2planeX = c->yuv2planeX;
260  yuv2interleavedX_fn yuv2nv12cX = c->yuv2nv12cX;
261  yuv2packed1_fn yuv2packed1 = c->yuv2packed1;
262  yuv2packed2_fn yuv2packed2 = c->yuv2packed2;
263  yuv2packedX_fn yuv2packedX = c->yuv2packedX;
264  yuv2anyX_fn yuv2anyX = c->yuv2anyX;
265  const int chrSrcSliceY = srcSliceY >> c->chrSrcVSubSample;
266  const int chrSrcSliceH = AV_CEIL_RSHIFT(srcSliceH, c->chrSrcVSubSample);
267  int should_dither = isNBPS(c->srcFormat) ||
268  is16BPS(c->srcFormat);
269  int lastDstY;
270 
271  /* vars which will change and which we need to store back in the context */
272  int dstY = c->dstY;
273  int lastInLumBuf = c->lastInLumBuf;
274  int lastInChrBuf = c->lastInChrBuf;
275 
276  int lumStart = 0;
277  int lumEnd = c->descIndex[0];
278  int chrStart = lumEnd;
279  int chrEnd = c->descIndex[1];
280  int vStart = chrEnd;
281  int vEnd = c->numDesc;
282  SwsSlice *src_slice = &c->slice[lumStart];
283  SwsSlice *hout_slice = &c->slice[c->numSlice-2];
284  SwsSlice *vout_slice = &c->slice[c->numSlice-1];
285  SwsFilterDescriptor *desc = c->desc;
286 
287  int needAlpha = c->needAlpha;
288 
289  int hasLumHoles = 1;
290  int hasChrHoles = 1;
291 
292  if (isPacked(c->srcFormat)) {
293  src[1] =
294  src[2] =
295  src[3] = src[0];
296  srcStride[1] =
297  srcStride[2] =
298  srcStride[3] = srcStride[0];
299  }
300  srcStride[1] *= 1 << c->vChrDrop;
301  srcStride[2] *= 1 << c->vChrDrop;
302 
303  DEBUG_BUFFERS("swscale() %p[%d] %p[%d] %p[%d] %p[%d] -> %p[%d] %p[%d] %p[%d] %p[%d]\n",
304  src[0], srcStride[0], src[1], srcStride[1],
305  src[2], srcStride[2], src[3], srcStride[3],
306  dst[0], dstStride[0], dst[1], dstStride[1],
307  dst[2], dstStride[2], dst[3], dstStride[3]);
308  DEBUG_BUFFERS("srcSliceY: %d srcSliceH: %d dstY: %d dstH: %d\n",
309  srcSliceY, srcSliceH, dstY, dstH);
310  DEBUG_BUFFERS("vLumFilterSize: %d vChrFilterSize: %d\n",
311  vLumFilterSize, vChrFilterSize);
312 
313  if (dstStride[0]&15 || dstStride[1]&15 ||
314  dstStride[2]&15 || dstStride[3]&15) {
315  SwsContext *const ctx = c->parent ? c->parent : c;
316  if (flags & SWS_PRINT_INFO &&
317  !atomic_exchange_explicit(&ctx->stride_unaligned_warned, 1, memory_order_relaxed)) {
319  "Warning: dstStride is not aligned!\n"
320  " ->cannot do aligned memory accesses anymore\n");
321  }
322  }
323 
324 #if ARCH_X86
325  if ( (uintptr_t)dst[0]&15 || (uintptr_t)dst[1]&15 || (uintptr_t)dst[2]&15
326  || (uintptr_t)src[0]&15 || (uintptr_t)src[1]&15 || (uintptr_t)src[2]&15
327  || dstStride[0]&15 || dstStride[1]&15 || dstStride[2]&15 || dstStride[3]&15
328  || srcStride[0]&15 || srcStride[1]&15 || srcStride[2]&15 || srcStride[3]&15
329  ) {
330  SwsContext *const ctx = c->parent ? c->parent : c;
331  int cpu_flags = av_get_cpu_flags();
332  if (flags & SWS_PRINT_INFO && HAVE_MMXEXT && (cpu_flags & AV_CPU_FLAG_SSE2) &&
333  !atomic_exchange_explicit(&ctx->stride_unaligned_warned,1, memory_order_relaxed)) {
334  av_log(c, AV_LOG_WARNING, "Warning: data is not aligned! This can lead to a speed loss\n");
335  }
336  }
337 #endif
338 
339  if (scale_dst) {
340  dstY = dstSliceY;
341  dstH = dstY + dstSliceH;
342  lastInLumBuf = -1;
343  lastInChrBuf = -1;
344  } else if (srcSliceY == 0) {
345  /* Note the user might start scaling the picture in the middle so this
346  * will not get executed. This is not really intended but works
347  * currently, so people might do it. */
348  dstY = 0;
349  lastInLumBuf = -1;
350  lastInChrBuf = -1;
351  }
352 
353  if (!should_dither) {
354  c->chrDither8 = c->lumDither8 = sws_pb_64;
355  }
356  lastDstY = dstY;
357 
358  ff_init_vscale_pfn(c, yuv2plane1, yuv2planeX, yuv2nv12cX,
359  yuv2packed1, yuv2packed2, yuv2packedX, yuv2anyX, c->use_mmx_vfilter);
360 
361  ff_init_slice_from_src(src_slice, (uint8_t**)src, srcStride, c->srcW,
362  srcSliceY, srcSliceH, chrSrcSliceY, chrSrcSliceH, 1);
363 
364  ff_init_slice_from_src(vout_slice, (uint8_t**)dst, dstStride, c->dstW,
365  dstY, dstSliceH, dstY >> c->chrDstVSubSample,
366  AV_CEIL_RSHIFT(dstSliceH, c->chrDstVSubSample), scale_dst);
367  if (srcSliceY == 0) {
368  hout_slice->plane[0].sliceY = lastInLumBuf + 1;
369  hout_slice->plane[1].sliceY = lastInChrBuf + 1;
370  hout_slice->plane[2].sliceY = lastInChrBuf + 1;
371  hout_slice->plane[3].sliceY = lastInLumBuf + 1;
372 
373  hout_slice->plane[0].sliceH =
374  hout_slice->plane[1].sliceH =
375  hout_slice->plane[2].sliceH =
376  hout_slice->plane[3].sliceH = 0;
377  hout_slice->width = dstW;
378  }
379 
380  for (; dstY < dstH; dstY++) {
381  const int chrDstY = dstY >> c->chrDstVSubSample;
382  int use_mmx_vfilter= c->use_mmx_vfilter;
383 
384  // First line needed as input
385  const int firstLumSrcY = FFMAX(1 - vLumFilterSize, vLumFilterPos[dstY]);
386  const int firstLumSrcY2 = FFMAX(1 - vLumFilterSize, vLumFilterPos[FFMIN(dstY | ((1 << c->chrDstVSubSample) - 1), c->dstH - 1)]);
387  // First line needed as input
388  const int firstChrSrcY = FFMAX(1 - vChrFilterSize, vChrFilterPos[chrDstY]);
389 
390  // Last line needed as input
391  int lastLumSrcY = FFMIN(c->srcH, firstLumSrcY + vLumFilterSize) - 1;
392  int lastLumSrcY2 = FFMIN(c->srcH, firstLumSrcY2 + vLumFilterSize) - 1;
393  int lastChrSrcY = FFMIN(c->chrSrcH, firstChrSrcY + vChrFilterSize) - 1;
394  int enough_lines;
395 
396  int i;
397  int posY, cPosY, firstPosY, lastPosY, firstCPosY, lastCPosY;
398 
399  // handle holes (FAST_BILINEAR & weird filters)
400  if (firstLumSrcY > lastInLumBuf) {
401 
402  hasLumHoles = lastInLumBuf != firstLumSrcY - 1;
403  if (hasLumHoles) {
404  hout_slice->plane[0].sliceY = firstLumSrcY;
405  hout_slice->plane[3].sliceY = firstLumSrcY;
406  hout_slice->plane[0].sliceH =
407  hout_slice->plane[3].sliceH = 0;
408  }
409 
410  lastInLumBuf = firstLumSrcY - 1;
411  }
412  if (firstChrSrcY > lastInChrBuf) {
413 
414  hasChrHoles = lastInChrBuf != firstChrSrcY - 1;
415  if (hasChrHoles) {
416  hout_slice->plane[1].sliceY = firstChrSrcY;
417  hout_slice->plane[2].sliceY = firstChrSrcY;
418  hout_slice->plane[1].sliceH =
419  hout_slice->plane[2].sliceH = 0;
420  }
421 
422  lastInChrBuf = firstChrSrcY - 1;
423  }
424 
425  DEBUG_BUFFERS("dstY: %d\n", dstY);
426  DEBUG_BUFFERS("\tfirstLumSrcY: %d lastLumSrcY: %d lastInLumBuf: %d\n",
427  firstLumSrcY, lastLumSrcY, lastInLumBuf);
428  DEBUG_BUFFERS("\tfirstChrSrcY: %d lastChrSrcY: %d lastInChrBuf: %d\n",
429  firstChrSrcY, lastChrSrcY, lastInChrBuf);
430 
431  // Do we have enough lines in this slice to output the dstY line
432  enough_lines = lastLumSrcY2 < srcSliceY + srcSliceH &&
433  lastChrSrcY < AV_CEIL_RSHIFT(srcSliceY + srcSliceH, c->chrSrcVSubSample);
434 
435  if (!enough_lines) {
436  lastLumSrcY = srcSliceY + srcSliceH - 1;
437  lastChrSrcY = chrSrcSliceY + chrSrcSliceH - 1;
438  DEBUG_BUFFERS("buffering slice: lastLumSrcY %d lastChrSrcY %d\n",
439  lastLumSrcY, lastChrSrcY);
440  }
441 
442  av_assert0((lastLumSrcY - firstLumSrcY + 1) <= hout_slice->plane[0].available_lines);
443  av_assert0((lastChrSrcY - firstChrSrcY + 1) <= hout_slice->plane[1].available_lines);
444 
445 
446  posY = hout_slice->plane[0].sliceY + hout_slice->plane[0].sliceH;
447  if (posY <= lastLumSrcY && !hasLumHoles) {
448  firstPosY = FFMAX(firstLumSrcY, posY);
449  lastPosY = FFMIN(firstLumSrcY + hout_slice->plane[0].available_lines - 1, srcSliceY + srcSliceH - 1);
450  } else {
451  firstPosY = posY;
452  lastPosY = lastLumSrcY;
453  }
454 
455  cPosY = hout_slice->plane[1].sliceY + hout_slice->plane[1].sliceH;
456  if (cPosY <= lastChrSrcY && !hasChrHoles) {
457  firstCPosY = FFMAX(firstChrSrcY, cPosY);
458  lastCPosY = FFMIN(firstChrSrcY + hout_slice->plane[1].available_lines - 1, AV_CEIL_RSHIFT(srcSliceY + srcSliceH, c->chrSrcVSubSample) - 1);
459  } else {
460  firstCPosY = cPosY;
461  lastCPosY = lastChrSrcY;
462  }
463 
464  ff_rotate_slice(hout_slice, lastPosY, lastCPosY);
465 
466  if (posY < lastLumSrcY + 1) {
467  for (i = lumStart; i < lumEnd; ++i)
468  desc[i].process(c, &desc[i], firstPosY, lastPosY - firstPosY + 1);
469  }
470 
471  lastInLumBuf = lastLumSrcY;
472 
473  if (cPosY < lastChrSrcY + 1) {
474  for (i = chrStart; i < chrEnd; ++i)
475  desc[i].process(c, &desc[i], firstCPosY, lastCPosY - firstCPosY + 1);
476  }
477 
478  lastInChrBuf = lastChrSrcY;
479 
480  if (!enough_lines)
481  break; // we can't output a dstY line so let's try with the next slice
482 
483 #if HAVE_MMX_INLINE
485 #endif
486  if (should_dither) {
487  c->chrDither8 = ff_dither_8x8_128[chrDstY & 7];
488  c->lumDither8 = ff_dither_8x8_128[dstY & 7];
489  }
490  if (dstY >= c->dstH - 2) {
491  /* hmm looks like we can't use MMX here without overwriting
492  * this array's tail */
493  ff_sws_init_output_funcs(c, &yuv2plane1, &yuv2planeX, &yuv2nv12cX,
494  &yuv2packed1, &yuv2packed2, &yuv2packedX, &yuv2anyX);
495  use_mmx_vfilter= 0;
496  ff_init_vscale_pfn(c, yuv2plane1, yuv2planeX, yuv2nv12cX,
497  yuv2packed1, yuv2packed2, yuv2packedX, yuv2anyX, use_mmx_vfilter);
498  }
499 
500  for (i = vStart; i < vEnd; ++i)
501  desc[i].process(c, &desc[i], dstY, 1);
502  }
503  if (isPlanar(dstFormat) && isALPHA(dstFormat) && !needAlpha) {
504  int offset = lastDstY - dstSliceY;
505  int length = dstW;
506  int height = dstY - lastDstY;
507 
508  if (is16BPS(dstFormat) || isNBPS(dstFormat)) {
509  const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(dstFormat);
510  fillPlane16(dst[3], dstStride[3], length, height, offset,
511  1, desc->comp[3].depth,
512  isBE(dstFormat));
513  } else if (is32BPS(dstFormat)) {
514  const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(dstFormat);
515  fillPlane32(dst[3], dstStride[3], length, height, offset,
516  1, desc->comp[3].depth,
517  isBE(dstFormat), desc->flags & AV_PIX_FMT_FLAG_FLOAT);
518  } else
519  fillPlane(dst[3], dstStride[3], length, height, offset, 255);
520  }
521 
522 #if HAVE_MMXEXT_INLINE
524  __asm__ volatile ("sfence" ::: "memory");
525 #endif
526  emms_c();
527 
528  /* store changed local vars back in the context */
529  c->dstY = dstY;
530  c->lastInLumBuf = lastInLumBuf;
531  c->lastInChrBuf = lastInChrBuf;
532 
533  return dstY - lastDstY;
534 }
535 
537 {
538  c->lumConvertRange = NULL;
539  c->chrConvertRange = NULL;
540  if (c->srcRange != c->dstRange && !isAnyRGB(c->dstFormat)) {
541  if (c->dstBpc <= 14) {
542  if (c->srcRange) {
543  c->lumConvertRange = lumRangeFromJpeg_c;
544  c->chrConvertRange = chrRangeFromJpeg_c;
545  } else {
546  c->lumConvertRange = lumRangeToJpeg_c;
547  c->chrConvertRange = chrRangeToJpeg_c;
548  }
549  } else {
550  if (c->srcRange) {
551  c->lumConvertRange = lumRangeFromJpeg16_c;
552  c->chrConvertRange = chrRangeFromJpeg16_c;
553  } else {
554  c->lumConvertRange = lumRangeToJpeg16_c;
555  c->chrConvertRange = chrRangeToJpeg16_c;
556  }
557  }
558  }
559 }
560 
562 {
563  enum AVPixelFormat srcFormat = c->srcFormat;
564 
565  ff_sws_init_output_funcs(c, &c->yuv2plane1, &c->yuv2planeX,
566  &c->yuv2nv12cX, &c->yuv2packed1,
567  &c->yuv2packed2, &c->yuv2packedX, &c->yuv2anyX);
568 
570 
571  if (c->srcBpc == 8) {
572  if (c->dstBpc <= 14) {
573  c->hyScale = c->hcScale = hScale8To15_c;
574  if (c->flags & SWS_FAST_BILINEAR) {
575  c->hyscale_fast = ff_hyscale_fast_c;
576  c->hcscale_fast = ff_hcscale_fast_c;
577  }
578  } else {
579  c->hyScale = c->hcScale = hScale8To19_c;
580  }
581  } else {
582  c->hyScale = c->hcScale = c->dstBpc > 14 ? hScale16To19_c
583  : hScale16To15_c;
584  }
585 
587 
588  if (!(isGray(srcFormat) || isGray(c->dstFormat) ||
589  srcFormat == AV_PIX_FMT_MONOBLACK || srcFormat == AV_PIX_FMT_MONOWHITE))
590  c->needs_hcscale = 1;
591 }
592 
594 {
596 
597  if (ARCH_PPC)
599  if (ARCH_X86)
601  if (ARCH_AARCH64)
603  if (ARCH_ARM)
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) {
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  */
1204 int attribute_align_arg sws_scale(struct SwsContext *c,
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:811
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:222
stride
int stride
Definition: mace.c:144
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:116
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:189
AVPixelFormat
AVPixelFormat
Pixel format.
Definition: pixfmt.h:64
SwsPlane::sliceH
int sliceH
number of lines
Definition: swscale_internal.h:1060
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:67
isPacked
static av_always_inline int isPacked(enum AVPixelFormat pix_fmt)
Definition: swscale_internal.h:849
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:243
chrRangeFromJpeg16_c
static void chrRangeFromJpeg16_c(int16_t *_dstU, int16_t *_dstV, int width)
Definition: swscale.c:204
AV_PIX_FMT_BGR32
#define AV_PIX_FMT_BGR32
Definition: pixfmt.h:379
u
#define u(width, name, range_min, range_max)
Definition: cbs_h2645.c:264
av_pix_fmt_desc_get
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition: pixdesc.c:2660
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:1078
avpriv_slicethread_execute
void avpriv_slicethread_execute(AVSliceThread *ctx, int nb_jobs, int execute_main)
Execute slice threading.
Definition: slicethread.c:246
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:317
pixdesc.h
AVFrame::width
int width
Definition: frame.h:389
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:126
GV
#define GV
ff_sws_init_input_funcs
void ff_sws_init_input_funcs(SwsContext *c)
b
#define b
Definition: input.c:40
SwsFilterDescriptor
Struct which holds all necessary data for processing a slice.
Definition: swscale_internal.h:1085
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:143
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:378
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
mathematics.h
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:98
DEBUG_BUFFERS
#define DEBUG_BUFFERS(...)
Definition: swscale.c:234
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:513
cpu_flags
static atomic_int cpu_flags
Definition: cpu.c:50
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:338
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:59
is16BPS
static av_always_inline int is16BPS(enum AVPixelFormat pix_fmt)
Definition: swscale_internal.h:696
ff_sws_init_swscale_aarch64
av_cold void ff_sws_init_swscale_aarch64(SwsContext *c)
Definition: swscale.c:33
SWS_BITEXACT
#define SWS_BITEXACT
Definition: swscale.h:85
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:288
U
#define U(x)
Definition: vp56_arith.h:37
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:142
val
static double val(void *priv, double ch)
Definition: aeval.c:76
isNBPS
static av_always_inline int isNBPS(enum AVPixelFormat pix_fmt)
Definition: swscale_internal.h:710
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:1641
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:315
sws_init_swscale
static av_cold void sws_init_swscale(SwsContext *c)
Definition: swscale.c:561
SWS_DITHER_ED
@ SWS_DITHER_ED
Definition: swscale_internal.h:74
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
g
const char * g
Definition: vf_curves.c:117
SwsSlice::width
int width
Slice line width.
Definition: swscale_internal.h:1072
slice_end
static int slice_end(AVCodecContext *avctx, AVFrame *pict)
Handle slice ends.
Definition: mpeg12dec.c:2042
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:829
lumRangeFromJpeg_c
static void lumRangeFromJpeg_c(int16_t *dst, int width)
Definition: swscale.c:186
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:380
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:314
ff_sws_init_range_convert
av_cold void ff_sws_init_range_convert(SwsContext *c)
Definition: swscale.c:536
SwsContext::slice_err
int * slice_err
Definition: swscale_internal.h:310
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:56
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:1058
ff_sws_init_swscale_x86
av_cold void ff_sws_init_swscale_x86(SwsContext *c)
Definition: swscale.c:358
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
src
#define src
Definition: vp8dsp.c:255
FF_PTR_ADD
#define FF_PTR_ADD(ptr, off)
Definition: internal.h:100
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
for
for(j=16;j >0;--j)
Definition: h264pred_template.c:469
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:2519
chrRangeToJpeg_c
static void chrRangeToJpeg_c(int16_t *dstU, int16_t *dstV, int width)
Definition: swscale.c:161
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:717
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:593
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:325
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:1004
usePal
static av_always_inline int usePal(enum AVPixelFormat pix_fmt)
Definition: swscale_internal.h:880
BV
#define BV
cpu.h
isAnyRGB
static av_always_inline int isAnyRGB(enum AVPixelFormat pix_fmt)
Definition: swscale_internal.h:825
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:97
SwsContext::slice_ctx
struct SwsContext ** slice_ctx
Definition: swscale_internal.h:309
srcSliceH
return srcSliceH
Definition: yuv2rgb_template.c:87
format
ofilter format
Definition: ffmpeg_filter.c:172
chrRangeToJpeg16_c
static void chrRangeToJpeg16_c(int16_t *_dstU, int16_t *_dstV, int width)
Definition: swscale.c:193
AVFrame::format
int format
format of the frame, -1 if unknown or unset Values correspond to enum AVPixelFormat for video frames,...
Definition: frame.h:404
RGB2YUV_SHIFT
#define RGB2YUV_SHIFT
is32BPS
static av_always_inline int is32BPS(enum AVPixelFormat pix_fmt)
Definition: swscale_internal.h:703
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:377
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:1025
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:345
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:64
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:271
sws_receive_slice_alignment
unsigned int sws_receive_slice_alignment(const struct SwsContext *c)
Definition: swscale.c:1124
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: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:152
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:435
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:1070
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
ff_sws_init_output_funcs
av_cold 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)
Definition: output.c:2587
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:52
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
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:132
AVFrame::height
int height
Definition: frame.h:389
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:254
SwsContext::frame_dst
AVFrame * frame_dst
Definition: swscale_internal.h:346
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:238
ff_dither_8x8_128
const uint8_t ff_dither_8x8_128[9][8]
Definition: swscale.c:40
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:179
BU
#define BU
lumRangeFromJpeg16_c
static void lumRangeFromJpeg16_c(int16_t *_dst, int width)
Definition: swscale.c:224
desc
const char * desc
Definition: libsvtav1.c:79
SWS_PRINT_INFO
#define SWS_PRINT_INFO
Definition: swscale.h:76
avutil.h
lumRangeToJpeg16_c
static void lumRangeToJpeg16_c(int16_t *_dst, int width)
Definition: swscale.c:215
SwsPlane::sliceY
int sliceY
index of first line
Definition: swscale_internal.h:1059
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:170
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:560
int32_t
int32_t
Definition: audioconvert.c:56
imgutils.h
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:362
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:28
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:858
int
int
Definition: ffmpeg_filter.c:153
SwsContext
Definition: swscale_internal.h:300
rgb48Toxyz12
static void rgb48Toxyz12(struct SwsContext *c, uint16_t *dst, const uint16_t *src, int stride, int h)
Definition: swscale.c:692
rgb2rgb.h
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