FFmpeg
graph.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2024 Niklas Haas
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 "libavutil/avassert.h"
22 #include "libavutil/error.h"
23 #include "libavutil/imgutils.h"
24 #include "libavutil/macros.h"
25 #include "libavutil/mem.h"
26 #include "libavutil/opt.h"
27 #include "libavutil/pixdesc.h"
28 #include "libavutil/slicethread.h"
29 
30 #include "libswscale/swscale.h"
31 #include "libswscale/format.h"
32 
33 #include "cms.h"
34 #include "lut3d.h"
35 #include "swscale_internal.h"
36 #include "graph.h"
37 #include "ops.h"
38 
39 static int pass_alloc_output(SwsPass *pass)
40 {
41  if (!pass || pass->output.fmt != AV_PIX_FMT_NONE)
42  return 0;
43  pass->output.fmt = pass->format;
44  return av_image_alloc(pass->output.data, pass->output.linesize, pass->width,
45  pass->num_slices * pass->slice_h, pass->format, 64);
46 }
47 
49  int width, int height, SwsPass *input,
50  int align, void *priv, sws_filter_run_t run)
51 {
52  int ret;
53  SwsPass *pass = av_mallocz(sizeof(*pass));
54  if (!pass)
55  return NULL;
56 
57  pass->graph = graph;
58  pass->run = run;
59  pass->priv = priv;
60  pass->format = fmt;
61  pass->width = width;
62  pass->height = height;
63  pass->input = input;
64  pass->output.fmt = AV_PIX_FMT_NONE;
65 
67  if (ret < 0) {
68  av_free(pass);
69  return NULL;
70  }
71 
72  if (!align) {
73  pass->slice_h = pass->height;
74  pass->num_slices = 1;
75  } else {
76  pass->slice_h = (pass->height + graph->num_threads - 1) / graph->num_threads;
77  pass->slice_h = FFALIGN(pass->slice_h, align);
78  pass->num_slices = (pass->height + pass->slice_h - 1) / pass->slice_h;
79  }
80 
81  ret = av_dynarray_add_nofree(&graph->passes, &graph->num_passes, pass);
82  if (ret < 0)
83  av_freep(&pass);
84  return pass;
85 }
86 
87 /* Wrapper around ff_sws_graph_add_pass() that chains a pass "in-place" */
88 static int pass_append(SwsGraph *graph, enum AVPixelFormat fmt, int w, int h,
89  SwsPass **pass, int align, void *priv, sws_filter_run_t run)
90 {
91  SwsPass *new = ff_sws_graph_add_pass(graph, fmt, w, h, *pass, align, priv, run);
92  if (!new)
93  return AVERROR(ENOMEM);
94  *pass = new;
95  return 0;
96 }
97 
98 static void run_copy(const SwsImg *out_base, const SwsImg *in_base,
99  int y, int h, const SwsPass *pass)
100 {
101  SwsImg in = ff_sws_img_shift(in_base, y);
102  SwsImg out = ff_sws_img_shift(out_base, y);
103 
104  for (int i = 0; i < FF_ARRAY_ELEMS(out.data) && out.data[i]; i++) {
105  const int lines = h >> ff_fmt_vshift(in.fmt, i);
106  av_assert1(in.data[i]);
107 
108  if (in.linesize[i] == out.linesize[i]) {
109  memcpy(out.data[i], in.data[i], lines * out.linesize[i]);
110  } else {
111  const int linesize = FFMIN(out.linesize[i], in.linesize[i]);
112  for (int j = 0; j < lines; j++) {
113  memcpy(out.data[i], in.data[i], linesize);
114  in.data[i] += in.linesize[i];
115  out.data[i] += out.linesize[i];
116  }
117  }
118  }
119 }
120 
121 static void run_rgb0(const SwsImg *out, const SwsImg *in, int y, int h,
122  const SwsPass *pass)
123 {
124  SwsInternal *c = pass->priv;
125  const int x0 = c->src0Alpha - 1;
126  const int w4 = 4 * pass->width;
127  const int src_stride = in->linesize[0];
128  const int dst_stride = out->linesize[0];
129  const uint8_t *src = in->data[0] + y * src_stride;
130  uint8_t *dst = out->data[0] + y * dst_stride;
131 
132  for (int y = 0; y < h; y++) {
133  memcpy(dst, src, w4 * sizeof(*dst));
134  for (int x = x0; x < w4; x += 4)
135  dst[x] = 0xFF;
136 
137  src += src_stride;
138  dst += dst_stride;
139  }
140 }
141 
142 static void run_xyz2rgb(const SwsImg *out, const SwsImg *in, int y, int h,
143  const SwsPass *pass)
144 {
145  ff_xyz12Torgb48(pass->priv, out->data[0] + y * out->linesize[0], out->linesize[0],
146  in->data[0] + y * in->linesize[0], in->linesize[0],
147  pass->width, h);
148 }
149 
150 static void run_rgb2xyz(const SwsImg *out, const SwsImg *in, int y, int h,
151  const SwsPass *pass)
152 {
153  ff_rgb48Toxyz12(pass->priv, out->data[0] + y * out->linesize[0], out->linesize[0],
154  in->data[0] + y * in->linesize[0], in->linesize[0],
155  pass->width, h);
156 }
157 
158 /***********************************************************************
159  * Internal ff_swscale() wrapper. This reuses the legacy scaling API. *
160  * This is considered fully deprecated, and will be replaced by a full *
161  * reimplementation ASAP. *
162  ***********************************************************************/
163 
164 static void free_legacy_swscale(void *priv)
165 {
166  SwsContext *sws = priv;
168 }
169 
170 static void setup_legacy_swscale(const SwsImg *out, const SwsImg *in,
171  const SwsPass *pass)
172 {
173  const SwsGraph *graph = pass->graph;
174  const SwsImg *in_orig = &graph->exec.input;
175  SwsContext *sws = pass->priv;
177  if (sws->flags & SWS_BITEXACT && sws->dither == SWS_DITHER_ED && c->dither_error[0]) {
178  for (int i = 0; i < 4; i++)
179  memset(c->dither_error[i], 0, sizeof(c->dither_error[0][0]) * (sws->dst_w + 2));
180  }
181 
182  if (usePal(sws->src_format))
183  ff_update_palette(c, (const uint32_t *) in_orig->data[1]);
184 }
185 
186 static inline SwsContext *slice_ctx(const SwsPass *pass, int y)
187 {
188  SwsContext *sws = pass->priv;
189  SwsInternal *parent = sws_internal(sws);
190  if (pass->num_slices == 1)
191  return sws;
192 
193  av_assert1(parent->nb_slice_ctx == pass->num_slices);
194  sws = parent->slice_ctx[y / pass->slice_h];
195 
196  if (usePal(sws->src_format)) {
197  SwsInternal *sub = sws_internal(sws);
198  memcpy(sub->pal_yuv, parent->pal_yuv, sizeof(sub->pal_yuv));
199  memcpy(sub->pal_rgb, parent->pal_rgb, sizeof(sub->pal_rgb));
200  }
201 
202  return sws;
203 }
204 
205 static void run_legacy_unscaled(const SwsImg *out, const SwsImg *in_base,
206  int y, int h, const SwsPass *pass)
207 {
208  SwsContext *sws = slice_ctx(pass, y);
210  const SwsImg in = ff_sws_img_shift(in_base, y);
211 
212  c->convert_unscaled(c, (const uint8_t *const *) in.data, in.linesize, y, h,
213  out->data, out->linesize);
214 }
215 
216 static void run_legacy_swscale(const SwsImg *out_base, const SwsImg *in,
217  int y, int h, const SwsPass *pass)
218 {
219  SwsContext *sws = slice_ctx(pass, y);
221  const SwsImg out = ff_sws_img_shift(out_base, y);
222 
223  ff_swscale(c, (const uint8_t *const *) in->data, in->linesize, 0,
224  sws->src_h, out.data, out.linesize, y, h);
225 }
226 
227 static void get_chroma_pos(SwsGraph *graph, int *h_chr_pos, int *v_chr_pos,
228  const SwsFormat *fmt)
229 {
230  enum AVChromaLocation chroma_loc = fmt->loc;
231  const int sub_x = fmt->desc->log2_chroma_w;
232  const int sub_y = fmt->desc->log2_chroma_h;
233  int x_pos, y_pos;
234 
235  /* Explicitly default to center siting for compatibility with swscale */
236  if (chroma_loc == AVCHROMA_LOC_UNSPECIFIED) {
237  chroma_loc = AVCHROMA_LOC_CENTER;
238  graph->incomplete |= sub_x || sub_y;
239  }
240 
241  /* av_chroma_location_enum_to_pos() always gives us values in the range from
242  * 0 to 256, but we need to adjust this to the true value range of the
243  * subsampling grid, which may be larger for h/v_sub > 1 */
244  av_chroma_location_enum_to_pos(&x_pos, &y_pos, chroma_loc);
245  x_pos *= (1 << sub_x) - 1;
246  y_pos *= (1 << sub_y) - 1;
247 
248  /* Fix vertical chroma position for interlaced frames */
249  if (sub_y && fmt->interlaced) {
250  /* When vertically subsampling, chroma samples are effectively only
251  * placed next to even rows. To access them from the odd field, we need
252  * to account for this shift by offsetting the distance of one luma row.
253  *
254  * For 4x vertical subsampling (v_sub == 2), they are only placed
255  * next to every *other* even row, so we need to shift by three luma
256  * rows to get to the chroma sample. */
257  if (graph->field == FIELD_BOTTOM)
258  y_pos += (256 << sub_y) - 256;
259 
260  /* Luma row distance is doubled for fields, so halve offsets */
261  y_pos >>= 1;
262  }
263 
264  /* Explicitly strip chroma offsets when not subsampling, because it
265  * interferes with the operation of flags like SWS_FULL_CHR_H_INP */
266  *h_chr_pos = sub_x ? x_pos : -513;
267  *v_chr_pos = sub_y ? y_pos : -513;
268 }
269 
270 static void legacy_chr_pos(SwsGraph *graph, int *chr_pos, int override, int *warned)
271 {
272  if (override == -513 || override == *chr_pos)
273  return;
274 
275  if (!*warned) {
277  "Setting chroma position directly is deprecated, make sure "
278  "the frame is tagged with the correct chroma location.\n");
279  *warned = 1;
280  }
281 
282  *chr_pos = override;
283 }
284 
285 /* Takes over ownership of `sws` */
288 {
290  const int src_w = sws->src_w, src_h = sws->src_h;
291  const int dst_w = sws->dst_w, dst_h = sws->dst_h;
292  const int unscaled = src_w == dst_w && src_h == dst_h;
293  int align = c->dst_slice_align;
294  SwsPass *pass = NULL;
295  int ret;
296 
297  if (c->cascaded_context[0]) {
298  const int num_cascaded = c->cascaded_context[2] ? 3 : 2;
299  for (int i = 0; i < num_cascaded; i++) {
300  const int is_last = i + 1 == num_cascaded;
301 
302  /* Steal cascaded context, so we can manage its lifetime independently */
303  SwsContext *sub = c->cascaded_context[i];
304  c->cascaded_context[i] = NULL;
305 
306  ret = init_legacy_subpass(graph, sub, input, is_last ? output : &input);
307  if (ret < 0)
308  break;
309  }
310 
312  return ret;
313  }
314 
315  if (sws->dither == SWS_DITHER_ED && !c->convert_unscaled)
316  align = 0; /* disable slice threading */
317 
318  if (c->src0Alpha && !c->dst0Alpha && isALPHA(sws->dst_format)) {
319  ret = pass_append(graph, AV_PIX_FMT_RGBA, src_w, src_h, &input, 1, c, run_rgb0);
320  if (ret < 0) {
322  return ret;
323  }
324  }
325 
326  if (c->srcXYZ && !(c->dstXYZ && unscaled)) {
327  ret = pass_append(graph, AV_PIX_FMT_RGB48, src_w, src_h, &input, 1, c, run_xyz2rgb);
328  if (ret < 0) {
330  return ret;
331  }
332  }
333 
334  pass = ff_sws_graph_add_pass(graph, sws->dst_format, dst_w, dst_h, input, align, sws,
335  c->convert_unscaled ? run_legacy_unscaled : run_legacy_swscale);
336  if (!pass) {
338  return AVERROR(ENOMEM);
339  }
340  pass->setup = setup_legacy_swscale;
341  pass->free = free_legacy_swscale;
342 
343  /**
344  * For slice threading, we need to create sub contexts, similar to how
345  * swscale normally handles it internally. The most important difference
346  * is that we handle cascaded contexts before threaded contexts; whereas
347  * context_init_threaded() does it the other way around.
348  */
349 
350  if (pass->num_slices > 1) {
351  c->slice_ctx = av_calloc(pass->num_slices, sizeof(*c->slice_ctx));
352  if (!c->slice_ctx)
353  return AVERROR(ENOMEM);
354 
355  for (int i = 0; i < pass->num_slices; i++) {
356  SwsContext *slice;
357  SwsInternal *c2;
358  slice = c->slice_ctx[i] = sws_alloc_context();
359  if (!slice)
360  return AVERROR(ENOMEM);
361  c->nb_slice_ctx++;
362 
363  c2 = sws_internal(slice);
364  c2->parent = sws;
365 
366  ret = av_opt_copy(slice, sws);
367  if (ret < 0)
368  return ret;
369 
371  if (ret < 0)
372  return ret;
373 
374  sws_setColorspaceDetails(slice, c->srcColorspaceTable,
375  slice->src_range, c->dstColorspaceTable,
376  slice->dst_range, c->brightness, c->contrast,
377  c->saturation);
378 
379  for (int i = 0; i < FF_ARRAY_ELEMS(c->srcColorspaceTable); i++) {
380  c2->srcColorspaceTable[i] = c->srcColorspaceTable[i];
381  c2->dstColorspaceTable[i] = c->dstColorspaceTable[i];
382  }
383  }
384  }
385 
386  if (c->dstXYZ && !(c->srcXYZ && unscaled)) {
387  ret = pass_append(graph, AV_PIX_FMT_RGB48, dst_w, dst_h, &pass, 1, c, run_rgb2xyz);
388  if (ret < 0)
389  return ret;
390  }
391 
392  *output = pass;
393  return 0;
394 }
395 
398 {
399  int ret, warned = 0;
400  SwsContext *const ctx = graph->ctx;
402  if (!sws)
403  return AVERROR(ENOMEM);
404 
405  sws->flags = ctx->flags;
406  sws->dither = ctx->dither;
407  sws->alpha_blend = ctx->alpha_blend;
408  sws->gamma_flag = ctx->gamma_flag;
409 
410  sws->src_w = src.width;
411  sws->src_h = src.height;
412  sws->src_format = src.format;
413  sws->src_range = src.range == AVCOL_RANGE_JPEG;
414 
415  sws->dst_w = dst.width;
416  sws->dst_h = dst.height;
417  sws->dst_format = dst.format;
418  sws->dst_range = dst.range == AVCOL_RANGE_JPEG;
421 
422  graph->incomplete |= src.range == AVCOL_RANGE_UNSPECIFIED;
423  graph->incomplete |= dst.range == AVCOL_RANGE_UNSPECIFIED;
424 
425  /* Allow overriding chroma position with the legacy API */
426  legacy_chr_pos(graph, &sws->src_h_chr_pos, ctx->src_h_chr_pos, &warned);
427  legacy_chr_pos(graph, &sws->src_v_chr_pos, ctx->src_v_chr_pos, &warned);
428  legacy_chr_pos(graph, &sws->dst_h_chr_pos, ctx->dst_h_chr_pos, &warned);
429  legacy_chr_pos(graph, &sws->dst_v_chr_pos, ctx->dst_v_chr_pos, &warned);
430 
431  sws->scaler_params[0] = ctx->scaler_params[0];
432  sws->scaler_params[1] = ctx->scaler_params[1];
433 
435  if (ret < 0) {
437  return ret;
438  }
439 
440  /* Set correct color matrices */
441  {
442  int in_full, out_full, brightness, contrast, saturation;
443  const int *inv_table, *table;
444  sws_getColorspaceDetails(sws, (int **)&inv_table, &in_full,
445  (int **)&table, &out_full,
446  &brightness, &contrast, &saturation);
447 
448  inv_table = sws_getCoefficients(src.csp);
450 
451  graph->incomplete |= src.csp != dst.csp &&
452  (src.csp == AVCOL_SPC_UNSPECIFIED ||
453  dst.csp == AVCOL_SPC_UNSPECIFIED);
454 
455  sws_setColorspaceDetails(sws, inv_table, in_full, table, out_full,
456  brightness, contrast, saturation);
457  }
458 
459  return init_legacy_subpass(graph, sws, input, output);
460 }
461 
462 /*********************
463  * Format conversion *
464  *********************/
465 
466 #if CONFIG_UNSTABLE
467 static int add_convert_pass(SwsGraph *graph, SwsFormat src, SwsFormat dst,
469 {
471 
472  SwsContext *ctx = graph->ctx;
473  SwsOpList *ops = NULL;
474  int ret = AVERROR(ENOTSUP);
475 
476  /* Mark the entire new ops infrastructure as experimental for now */
477  if (!(ctx->flags & SWS_UNSTABLE))
478  goto fail;
479 
480  /* The new format conversion layer cannot scale for now */
481  if (src.width != dst.width || src.height != dst.height ||
482  src.desc->log2_chroma_h || src.desc->log2_chroma_w ||
483  dst.desc->log2_chroma_h || dst.desc->log2_chroma_w)
484  goto fail;
485 
486  /* The new code does not yet support alpha blending */
487  if (src.desc->flags & AV_PIX_FMT_FLAG_ALPHA &&
488  ctx->alpha_blend != SWS_ALPHA_BLEND_NONE)
489  goto fail;
490 
491  ops = ff_sws_op_list_alloc();
492  if (!ops)
493  return AVERROR(ENOMEM);
494  ops->src = src;
495  ops->dst = dst;
496 
497  ret = ff_sws_decode_pixfmt(ops, src.format);
498  if (ret < 0)
499  goto fail;
500  ret = ff_sws_decode_colors(ctx, type, ops, src, &graph->incomplete);
501  if (ret < 0)
502  goto fail;
503  ret = ff_sws_encode_colors(ctx, type, ops, dst, &graph->incomplete);
504  if (ret < 0)
505  goto fail;
506  ret = ff_sws_encode_pixfmt(ops, dst.format);
507  if (ret < 0)
508  goto fail;
509 
510  av_log(ctx, AV_LOG_VERBOSE, "Conversion pass for %s -> %s:\n",
512 
513  av_log(ctx, AV_LOG_DEBUG, "Unoptimized operation list:\n");
515  av_log(ctx, AV_LOG_DEBUG, "Optimized operation list:\n");
516 
518  if (ops->num_ops == 0) {
519  av_log(ctx, AV_LOG_VERBOSE, " optimized into memcpy\n");
520  ff_sws_op_list_free(&ops);
521  *output = input;
522  return 0;
523  }
524 
526 
527  ret = ff_sws_compile_pass(graph, ops, 0, dst, input, output);
528  if (ret < 0)
529  goto fail;
530 
531  ret = 0;
532  /* fall through */
533 
534 fail:
535  ff_sws_op_list_free(&ops);
536  if (ret == AVERROR(ENOTSUP))
537  return add_legacy_sws_pass(graph, src, dst, input, output);
538  return ret;
539 }
540 #else
541 #define add_convert_pass add_legacy_sws_pass
542 #endif
543 
544 
545 /**************************
546  * Gamut and tone mapping *
547  **************************/
548 
549 static void free_lut3d(void *priv)
550 {
551  SwsLut3D *lut = priv;
552  ff_sws_lut3d_free(&lut);
553 }
554 
555 static void setup_lut3d(const SwsImg *out, const SwsImg *in, const SwsPass *pass)
556 {
557  SwsLut3D *lut = pass->priv;
558 
559  /* Update dynamic frame metadata from the original source frame */
560  ff_sws_lut3d_update(lut, &pass->graph->src.color);
561 }
562 
563 static void run_lut3d(const SwsImg *out_base, const SwsImg *in_base,
564  int y, int h, const SwsPass *pass)
565 {
566  SwsLut3D *lut = pass->priv;
567  const SwsImg in = ff_sws_img_shift(in_base, y);
568  const SwsImg out = ff_sws_img_shift(out_base, y);
569 
570  ff_sws_lut3d_apply(lut, in.data[0], in.linesize[0], out.data[0],
571  out.linesize[0], pass->width, h);
572 }
573 
576 {
577  enum AVPixelFormat fmt_in, fmt_out;
578  SwsColorMap map = {0};
579  SwsLut3D *lut;
580  SwsPass *pass;
581  int ret;
582 
583  /**
584  * Grayspace does not really have primaries, so just force the use of
585  * the equivalent other primary set to avoid a conversion. Technically,
586  * this does affect the weights used for the Grayscale conversion, but
587  * in practise, that should give the expected results more often than not.
588  */
589  if (isGray(dst.format)) {
590  dst.color = src.color;
591  } else if (isGray(src.format)) {
592  src.color = dst.color;
593  }
594 
595  /* Fully infer color spaces before color mapping logic */
596  graph->incomplete |= ff_infer_colors(&src.color, &dst.color);
597 
598  map.intent = graph->ctx->intent;
599  map.src = src.color;
600  map.dst = dst.color;
601 
603  return 0;
604 
605  lut = ff_sws_lut3d_alloc();
606  if (!lut)
607  return AVERROR(ENOMEM);
608 
609  fmt_in = ff_sws_lut3d_pick_pixfmt(src, 0);
610  fmt_out = ff_sws_lut3d_pick_pixfmt(dst, 1);
611  if (fmt_in != src.format) {
612  SwsFormat tmp = src;
613  tmp.format = fmt_in;
614  ret = add_convert_pass(graph, src, tmp, input, &input);
615  if (ret < 0)
616  return ret;
617  }
618 
619  ret = ff_sws_lut3d_generate(lut, fmt_in, fmt_out, &map);
620  if (ret < 0) {
621  ff_sws_lut3d_free(&lut);
622  return ret;
623  }
624 
625  pass = ff_sws_graph_add_pass(graph, fmt_out, src.width, src.height,
626  input, 1, lut, run_lut3d);
627  if (!pass) {
628  ff_sws_lut3d_free(&lut);
629  return AVERROR(ENOMEM);
630  }
631  pass->setup = setup_lut3d;
632  pass->free = free_lut3d;
633 
634  *output = pass;
635  return 0;
636 }
637 
638 /***************************************
639  * Main filter graph construction code *
640  ***************************************/
641 
642 static int init_passes(SwsGraph *graph)
643 {
644  SwsFormat src = graph->src;
645  SwsFormat dst = graph->dst;
646  SwsPass *pass = NULL; /* read from main input image */
647  int ret;
648 
649  ret = adapt_colors(graph, src, dst, pass, &pass);
650  if (ret < 0)
651  return ret;
652  src.format = pass ? pass->format : src.format;
653  src.color = dst.color;
654 
655  if (!ff_fmt_equal(&src, &dst)) {
656  ret = add_convert_pass(graph, src, dst, pass, &pass);
657  if (ret < 0)
658  return ret;
659  }
660 
661  if (!pass) {
662  /* No passes were added, so no operations were necessary */
663  graph->noop = 1;
664 
665  /* Add threaded memcpy pass */
666  pass = ff_sws_graph_add_pass(graph, dst.format, dst.width, dst.height,
667  pass, 1, NULL, run_copy);
668  if (!pass)
669  return AVERROR(ENOMEM);
670  }
671 
672  return 0;
673 }
674 
675 static void sws_graph_worker(void *priv, int jobnr, int threadnr, int nb_jobs,
676  int nb_threads)
677 {
678  SwsGraph *graph = priv;
679  const SwsPass *pass = graph->exec.pass;
680  const SwsImg *input = pass->input ? &pass->input->output : &graph->exec.input;
681  const SwsImg *output = pass->output.fmt != AV_PIX_FMT_NONE ? &pass->output : &graph->exec.output;
682  const int slice_y = jobnr * pass->slice_h;
683  const int slice_h = FFMIN(pass->slice_h, pass->height - slice_y);
684 
685  pass->run(output, input, slice_y, slice_h, pass);
686 }
687 
689  int field, SwsGraph **out_graph)
690 {
691  int ret;
692  SwsGraph *graph = av_mallocz(sizeof(*graph));
693  if (!graph)
694  return AVERROR(ENOMEM);
695 
696  graph->ctx = ctx;
697  graph->src = *src;
698  graph->dst = *dst;
699  graph->field = field;
700  graph->opts_copy = *ctx;
701 
702  graph->exec.input.fmt = src->format;
703  graph->exec.output.fmt = dst->format;
704 
705  ret = avpriv_slicethread_create(&graph->slicethread, (void *) graph,
706  sws_graph_worker, NULL, ctx->threads);
707  if (ret == AVERROR(ENOSYS))
708  graph->num_threads = 1;
709  else if (ret < 0)
710  goto error;
711  else
712  graph->num_threads = ret;
713 
714  ret = init_passes(graph);
715  if (ret < 0)
716  goto error;
717 
718  *out_graph = graph;
719  return 0;
720 
721 error:
722  ff_sws_graph_free(&graph);
723  return ret;
724 }
725 
727 {
728  SwsGraph *graph = *pgraph;
729  if (!graph)
730  return;
731 
733 
734  for (int i = 0; i < graph->num_passes; i++) {
735  SwsPass *pass = graph->passes[i];
736  if (pass->free)
737  pass->free(pass->priv);
738  if (pass->output.fmt != AV_PIX_FMT_NONE)
739  av_free(pass->output.data[0]);
740  av_free(pass);
741  }
742  av_free(graph->passes);
743 
744  av_free(graph);
745  *pgraph = NULL;
746 }
747 
748 /* Tests only options relevant to SwsGraph */
749 static int opts_equal(const SwsContext *c1, const SwsContext *c2)
750 {
751  return c1->flags == c2->flags &&
752  c1->threads == c2->threads &&
753  c1->dither == c2->dither &&
754  c1->alpha_blend == c2->alpha_blend &&
755  c1->gamma_flag == c2->gamma_flag &&
756  c1->src_h_chr_pos == c2->src_h_chr_pos &&
757  c1->src_v_chr_pos == c2->src_v_chr_pos &&
758  c1->dst_h_chr_pos == c2->dst_h_chr_pos &&
759  c1->dst_v_chr_pos == c2->dst_v_chr_pos &&
760  c1->intent == c2->intent &&
761  !memcmp(c1->scaler_params, c2->scaler_params, sizeof(c1->scaler_params));
762 
763 }
764 
766  int field, SwsGraph **out_graph)
767 {
768  SwsGraph *graph = *out_graph;
769  if (graph && ff_fmt_equal(&graph->src, src) &&
770  ff_fmt_equal(&graph->dst, dst) &&
771  opts_equal(ctx, &graph->opts_copy))
772  {
773  ff_sws_graph_update_metadata(graph, &src->color);
774  return 0;
775  }
776 
777  ff_sws_graph_free(out_graph);
778  return ff_sws_graph_create(ctx, dst, src, field, out_graph);
779 }
780 
782 {
783  if (!color)
784  return;
785 
787 }
788 
789 void ff_sws_graph_run(SwsGraph *graph, uint8_t *const out_data[4],
790  const int out_linesize[4],
791  const uint8_t *const in_data[4],
792  const int in_linesize[4])
793 {
794  SwsImg *out = &graph->exec.output;
795  SwsImg *in = &graph->exec.input;
796  memcpy(out->data, out_data, sizeof(out->data));
797  memcpy(out->linesize, out_linesize, sizeof(out->linesize));
798  memcpy(in->data, in_data, sizeof(in->data));
799  memcpy(in->linesize, in_linesize, sizeof(in->linesize));
800 
801  for (int i = 0; i < graph->num_passes; i++) {
802  const SwsPass *pass = graph->passes[i];
803  graph->exec.pass = pass;
804  if (pass->setup) {
805  pass->setup(pass->output.fmt != AV_PIX_FMT_NONE ? &pass->output : out,
806  pass->input ? &pass->input->output : in, pass);
807  }
809  }
810 }
error
static void error(const char *err)
Definition: target_bsf_fuzzer.c:32
sws_setColorspaceDetails
int sws_setColorspaceDetails(SwsContext *c, const int inv_table[4], int srcRange, const int table[4], int dstRange, int brightness, int contrast, int saturation)
Definition: utils.c:835
ff_sws_op_list_free
void ff_sws_op_list_free(SwsOpList **p_ops)
Definition: ops.c:245
AV_LOG_WARNING
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:216
AVPixelFormat
AVPixelFormat
Pixel format.
Definition: pixfmt.h:71
SwsGraph::slicethread
AVSliceThread * slicethread
Definition: graph.h:110
SwsGraph::ctx
SwsContext * ctx
Definition: graph.h:109
SwsPass
Represents a single filter pass in the scaling graph.
Definition: graph.h:68
ff_sws_op_list_alloc
SwsOpList * ff_sws_op_list_alloc(void)
Definition: ops.c:234
SwsGraph::pass
const SwsPass * pass
Definition: graph.h:133
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
opt.h
SwsGraph::passes
SwsPass ** passes
Sorted sequence of filter passes to apply.
Definition: graph.h:116
adapt_colors
static int adapt_colors(SwsGraph *graph, SwsFormat src, SwsFormat dst, SwsPass *input, SwsPass **output)
Definition: graph.c:574
out
FILE * out
Definition: movenc.c:55
color
Definition: vf_paletteuse.c:513
init_passes
static int init_passes(SwsGraph *graph)
Definition: graph.c:642
ff_rgb48Toxyz12
void ff_rgb48Toxyz12(const SwsInternal *c, uint8_t *dst, int dst_stride, const uint8_t *src, int src_stride, int w, int h)
Definition: swscale.c:798
SwsPass::output
SwsImg output
Filter output buffer.
Definition: graph.h:91
SwsFormat::interlaced
int interlaced
Definition: format.h:79
SwsContext::src_w
int src_w
Deprecated frame property overrides, for the legacy API only.
Definition: swscale.h:235
ff_sws_graph_reinit
int ff_sws_graph_reinit(SwsContext *ctx, const SwsFormat *dst, const SwsFormat *src, int field, SwsGraph **out_graph)
Wrapper around ff_sws_graph_create() that reuses the existing graph if the format is compatible.
Definition: graph.c:765
SwsPass::format
enum AVPixelFormat format
Definition: graph.h:77
saturation
static IPT saturation(const CmsCtx *ctx, IPT ipt)
Definition: cms.c:559
output
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 output
Definition: filter_design.txt:226
sws_filter_run_t
void(* sws_filter_run_t)(const SwsImg *out, const SwsImg *in, int y, int h, const SwsPass *pass)
Output h lines of filtered data.
Definition: graph.h:60
SwsGraph::src
SwsFormat src
Currently active format and processing parameters.
Definition: graph.h:128
avpriv_slicethread_execute
void avpriv_slicethread_execute(AVSliceThread *ctx, int nb_jobs, int execute_main)
Execute slice threading.
Definition: slicethread.c:271
pixdesc.h
ops.h
w
uint8_t w
Definition: llviddspenc.c:38
AVCOL_RANGE_JPEG
@ AVCOL_RANGE_JPEG
Full range content.
Definition: pixfmt.h:767
isGray
static av_always_inline int isGray(enum AVPixelFormat pix_fmt)
Definition: swscale_internal.h:787
SWS_BITEXACT
@ SWS_BITEXACT
Definition: swscale.h:156
table
static const uint16_t table[]
Definition: prosumer.c:203
SwsContext::flags
unsigned flags
Bitmask of SWS_*.
Definition: swscale.h:202
AV_LOG_VERBOSE
#define AV_LOG_VERBOSE
Detailed information.
Definition: log.h:226
ff_sws_lut3d_pick_pixfmt
enum AVPixelFormat ff_sws_lut3d_pick_pixfmt(SwsFormat fmt, int output)
Pick the best compatible pixfmt for a given SwsFormat.
Definition: lut3d.c:52
SwsPass::free
void(* free)(void *priv)
Optional private state and associated free() function.
Definition: graph.h:101
c1
static const uint64_t c1
Definition: murmur3.c:52
SwsImg
Represents a view into a single field of frame data.
Definition: graph.h:33
format.h
SWS_ALPHA_BLEND_NONE
@ SWS_ALPHA_BLEND_NONE
Definition: swscale.h:88
ff_sws_init_single_context
int ff_sws_init_single_context(SwsContext *sws, SwsFilter *srcFilter, SwsFilter *dstFilter)
Definition: utils.c:1107
SwsColorMap
Definition: cms.h:60
SwsPixelType
SwsPixelType
Copyright (C) 2025 Niklas Haas.
Definition: ops.h:30
SwsPass::width
int width
Definition: graph.h:78
ff_color_update_dynamic
static void ff_color_update_dynamic(SwsColor *dst, const SwsColor *src)
Definition: format.h:70
init_legacy_subpass
static int init_legacy_subpass(SwsGraph *graph, SwsContext *sws, SwsPass *input, SwsPass **output)
Definition: graph.c:286
SWS_PIXEL_F32
@ SWS_PIXEL_F32
Definition: ops.h:35
avpriv_slicethread_create
int avpriv_slicethread_create(AVSliceThread **pctx, void *priv, void(*worker_func)(void *priv, int jobnr, int threadnr, int nb_jobs, int nb_threads), void(*main_func)(void *priv), int nb_threads)
Create slice threading context.
Definition: slicethread.c:262
macros.h
pass_append
static int pass_append(SwsGraph *graph, enum AVPixelFormat fmt, int w, int h, SwsPass **pass, int align, void *priv, sws_filter_run_t run)
Definition: graph.c:88
fail
#define fail()
Definition: checkasm.h:204
SwsOpList::num_ops
int num_ops
Definition: ops.h:211
SwsContext::src_v_chr_pos
int src_v_chr_pos
Source vertical chroma position in luma grid / 256.
Definition: swscale.h:241
slice_ctx
static SwsContext * slice_ctx(const SwsPass *pass, int y)
Definition: graph.c:186
sws_init_context
av_warn_unused_result int sws_init_context(SwsContext *sws_context, SwsFilter *srcFilter, SwsFilter *dstFilter)
Initialize the swscaler context sws_context.
Definition: utils.c:1879
SwsGraph::opts_copy
SwsContext opts_copy
Cached copy of the public options that were used to construct this SwsGraph.
Definition: graph.h:123
type
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 type
Definition: writing_filters.txt:86
ff_sws_graph_create
int ff_sws_graph_create(SwsContext *ctx, const SwsFormat *dst, const SwsFormat *src, int field, SwsGraph **out_graph)
Allocate and initialize the filter graph.
Definition: graph.c:688
avassert.h
ff_sws_graph_run
void ff_sws_graph_run(SwsGraph *graph, uint8_t *const out_data[4], const int out_linesize[4], const uint8_t *const in_data[4], const int in_linesize[4])
Dispatch the filter graph on a single field.
Definition: graph.c:789
SwsInternal::pal_rgb
uint32_t pal_rgb[256]
Definition: swscale_internal.h:383
FF_ARRAY_ELEMS
#define FF_ARRAY_ELEMS(a)
Definition: sinewin_tablegen.c:29
legacy_chr_pos
static void legacy_chr_pos(SwsGraph *graph, int *chr_pos, int override, int *warned)
Definition: graph.c:270
SwsContext::dither
SwsDither dither
Dither mode.
Definition: swscale.h:217
SwsPass::priv
void * priv
Definition: graph.h:102
SwsInternal::nb_slice_ctx
int nb_slice_ctx
Definition: swscale_internal.h:327
SwsInternal::slice_ctx
SwsContext ** slice_ctx
Definition: swscale_internal.h:325
ff_sws_encode_colors
int ff_sws_encode_colors(SwsContext *ctx, SwsPixelType type, SwsOpList *ops, const SwsFormat fmt, bool *incomplete)
av_chroma_location_enum_to_pos
int av_chroma_location_enum_to_pos(int *xpos, int *ypos, enum AVChromaLocation pos)
Converts AVChromaLocation to swscale x/y chroma position.
Definition: pixdesc.c:3865
ff_update_palette
void ff_update_palette(SwsInternal *c, const uint32_t *pal)
Definition: swscale.c:857
AVFormatContext::flags
int flags
Flags modifying the (de)muxer behaviour.
Definition: avformat.h:1415
ff_sws_lut3d_alloc
SwsLut3D * ff_sws_lut3d_alloc(void)
Definition: lut3d.c:32
SwsPass::setup
void(* setup)(const SwsImg *out, const SwsImg *in, const SwsPass *pass)
Called once from the main thread before running the filter.
Definition: graph.h:96
SwsContext::intent
int intent
Desired ICC intent for color space conversions.
Definition: swscale.h:249
AV_LOG_DEBUG
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:231
SwsGraph::num_passes
int num_passes
Definition: graph.h:117
AV_PIX_FMT_FLAG_ALPHA
#define AV_PIX_FMT_FLAG_ALPHA
The pixel format has an alpha channel.
Definition: pixdesc.h:147
ctx
AVFormatContext * ctx
Definition: movenc.c:49
ff_sws_lut3d_update
void ff_sws_lut3d_update(SwsLut3D *lut3d, const SwsColor *new_src)
Update the tone mapping state.
Definition: lut3d.c:239
field
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 field
Definition: writing_filters.txt:78
AVPixFmtDescriptor::log2_chroma_w
uint8_t log2_chroma_w
Amount to shift the luma width right to find the chroma width.
Definition: pixdesc.h:80
ff_xyz12Torgb48
void ff_xyz12Torgb48(const SwsInternal *c, uint8_t *dst, int dst_stride, const uint8_t *src, int src_stride, int w, int h)
Definition: swscale.c:739
tmp
static uint8_t tmp[40]
Definition: aes_ctr.c:52
AV_PIX_FMT_RGBA
@ AV_PIX_FMT_RGBA
packed RGBA 8:8:8:8, 32bpp, RGBARGBA...
Definition: pixfmt.h:100
FIELD_BOTTOM
@ FIELD_BOTTOM
Definition: format.h:57
SwsGraph::field
int field
Definition: graph.h:129
ff_sws_graph_add_pass
SwsPass * ff_sws_graph_add_pass(SwsGraph *graph, enum AVPixelFormat fmt, int width, int height, SwsPass *input, int align, void *priv, sws_filter_run_t run)
Allocate and add a new pass to the filter graph.
Definition: graph.c:48
ff_sws_lut3d_free
void ff_sws_lut3d_free(SwsLut3D **plut3d)
Definition: lut3d.c:42
NULL
#define NULL
Definition: coverity.c:32
run
uint8_t run
Definition: svq3.c:207
SwsContext::gamma_flag
int gamma_flag
Use gamma correct scaling.
Definition: swscale.h:227
run_xyz2rgb
static void run_xyz2rgb(const SwsImg *out, const SwsImg *in, int y, int h, const SwsPass *pass)
Definition: graph.c:142
ff_infer_colors
bool ff_infer_colors(SwsColor *src, SwsColor *dst)
Definition: format.c:508
SwsGraph::input
SwsImg input
Definition: graph.h:134
ff_sws_lut3d_generate
int ff_sws_lut3d_generate(SwsLut3D *lut3d, enum AVPixelFormat fmt_in, enum AVPixelFormat fmt_out, const SwsColorMap *map)
Recalculate the (static) 3DLUT state with new settings.
Definition: lut3d.c:211
SwsContext::src_range
int src_range
Source is full range.
Definition: swscale.h:239
SwsPass::graph
const SwsGraph * graph
Definition: graph.h:69
AVCOL_RANGE_UNSPECIFIED
@ AVCOL_RANGE_UNSPECIFIED
Definition: pixfmt.h:733
SwsContext::dst_h_chr_pos
int dst_h_chr_pos
Destination horizontal chroma position.
Definition: swscale.h:244
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
run_legacy_swscale
static void run_legacy_swscale(const SwsImg *out_base, const SwsImg *in, int y, int h, const SwsPass *pass)
Definition: graph.c:216
error.h
av_opt_copy
int av_opt_copy(void *dst, const void *src)
Copy options from src object into dest object.
Definition: opt.c:2151
av_image_alloc
int av_image_alloc(uint8_t *pointers[4], int linesizes[4], int w, int h, enum AVPixelFormat pix_fmt, int align)
Allocate an image with size w and h and pixel format pix_fmt, and fill pointers and linesizes accordi...
Definition: imgutils.c:218
ff_sws_graph_free
void ff_sws_graph_free(SwsGraph **pgraph)
Uninitialize any state associate with this filter graph and free it.
Definition: graph.c:726
SwsPass::height
int height
Definition: graph.h:78
SwsImg::linesize
int linesize[4]
Definition: graph.h:36
add_legacy_sws_pass
static int add_legacy_sws_pass(SwsGraph *graph, SwsFormat src, SwsFormat dst, SwsPass *input, SwsPass **output)
Definition: graph.c:396
lut3d.h
free_lut3d
static void free_lut3d(void *priv)
Definition: graph.c:549
height
#define height
Definition: dsp.h:89
sws_alloc_context
SwsContext * sws_alloc_context(void)
Allocate an empty SwsContext and set its fields to default values.
Definition: utils.c:1018
dst
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
Definition: dsp.h:87
usePal
static av_always_inline int usePal(enum AVPixelFormat pix_fmt)
Definition: swscale_internal.h:918
setup_lut3d
static void setup_lut3d(const SwsImg *out, const SwsImg *in, const SwsPass *pass)
Definition: graph.c:555
ff_sws_lut3d_apply
void ff_sws_lut3d_apply(const SwsLut3D *lut3d, const uint8_t *in, int in_stride, uint8_t *out, int out_stride, int w, int h)
Applies a color transformation to a plane.
Definition: lut3d.c:250
AV_PIX_FMT_RGB48
#define AV_PIX_FMT_RGB48
Definition: pixfmt.h:525
SwsGraph::exec
struct SwsGraph::@514 exec
Temporary execution state inside ff_sws_graph_run.
SwsContext::alpha_blend
SwsAlphaBlend alpha_blend
Alpha blending mode.
Definition: swscale.h:222
SwsOpList::src
SwsFormat src
Definition: ops.h:214
SwsContext::src_h
int src_h
Width and height of the source frame.
Definition: swscale.h:235
SwsGraph::output
SwsImg output
Definition: graph.h:135
AVCHROMA_LOC_UNSPECIFIED
@ AVCHROMA_LOC_UNSPECIFIED
Definition: pixfmt.h:787
SwsFormat
Definition: format.h:77
sws_getColorspaceDetails
int sws_getColorspaceDetails(SwsContext *c, int **inv_table, int *srcRange, int **table, int *dstRange, int *brightness, int *contrast, int *saturation)
Definition: utils.c:993
align
static const uint8_t *BS_FUNC() align(BSCTX *bc)
Skip bits to a byte boundary.
Definition: bitstream_template.h:419
SwsFormat::loc
enum AVChromaLocation loc
Definition: format.h:83
SwsColor
Definition: format.h:60
SwsContext::dst_format
int dst_format
Destination pixel format.
Definition: swscale.h:238
input
and forward the test the status of outputs and forward it to the corresponding return FFERROR_NOT_READY If the filters stores internally one or a few frame for some input
Definition: filter_design.txt:172
slicethread.h
AVChromaLocation
AVChromaLocation
Location of chroma samples.
Definition: pixfmt.h:786
ff_sws_op_list_optimize
int ff_sws_op_list_optimize(SwsOpList *ops)
Fuse compatible and eliminate redundant operations, as well as replacing some operations with more ef...
Definition: ops_optimizer.c:412
sws
static SwsContext * sws[3]
Definition: swscale.c:73
free_legacy_swscale
static void free_legacy_swscale(void *priv)
Definition: graph.c:164
SwsLut3D
Definition: lut3d.h:50
SwsGraph::dst
SwsFormat dst
Definition: graph.h:128
ff_fmt_vshift
static av_always_inline av_const int ff_fmt_vshift(enum AVPixelFormat fmt, int plane)
Definition: graph.h:39
SwsPass::slice_h
int slice_h
Definition: graph.h:79
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:256
SwsGraph::num_threads
int num_threads
Definition: graph.h:111
opts_equal
static int opts_equal(const SwsContext *c1, const SwsContext *c2)
Definition: graph.c:749
run_rgb0
static void run_rgb0(const SwsImg *out, const SwsImg *in, int y, int h, const SwsPass *pass)
Definition: graph.c:121
SwsFormat::desc
const AVPixFmtDescriptor * desc
Definition: format.h:84
av_assert1
#define av_assert1(cond)
assert() equivalent, that does not lie in speed critical code.
Definition: avassert.h:57
run_rgb2xyz
static void run_rgb2xyz(const SwsImg *out, const SwsImg *in, int y, int h, const SwsPass *pass)
Definition: graph.c:150
swscale_internal.h
graph.h
FFMIN
#define FFMIN(a, b)
Definition: macros.h:49
av_mallocz
void * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
Definition: mem.c:256
SwsContext::dst_h
int dst_h
Width and height of the destination frame.
Definition: swscale.h:236
run_copy
static void run_copy(const SwsImg *out_base, const SwsImg *in_base, int y, int h, const SwsPass *pass)
Definition: graph.c:98
AVCOL_SPC_UNSPECIFIED
@ AVCOL_SPC_UNSPECIFIED
Definition: pixfmt.h:693
ff_sws_img_shift
static av_const SwsImg ff_sws_img_shift(const SwsImg *base, const int y)
Definition: graph.h:45
ff_sws_decode_pixfmt
int ff_sws_decode_pixfmt(SwsOpList *ops, enum AVPixelFormat fmt)
Append a set of operations for decoding/encoding raw pixels.
av_calloc
void * av_calloc(size_t nmemb, size_t size)
Definition: mem.c:264
get_chroma_pos
static void get_chroma_pos(SwsGraph *graph, int *h_chr_pos, int *v_chr_pos, const SwsFormat *fmt)
Definition: graph.c:227
SWS_DITHER_ED
@ SWS_DITHER_ED
Definition: swscale.h:83
SwsInternal
Definition: swscale_internal.h:317
ret
ret
Definition: filter_design.txt:187
SwsOpList::dst
SwsFormat dst
Definition: ops.h:214
ff_fmt_equal
static int ff_fmt_equal(const SwsFormat *fmt1, const SwsFormat *fmt2)
Definition: format.h:129
ff_sws_decode_colors
int ff_sws_decode_colors(SwsContext *ctx, SwsPixelType type, SwsOpList *ops, const SwsFormat fmt, bool *incomplete)
Append a set of operations for transforming decoded pixel values to/from normalized RGB in the specif...
SwsGraph::noop
bool noop
Definition: graph.h:113
av_dynarray_add_nofree
int av_dynarray_add_nofree(void *tab_ptr, int *nb_ptr, void *elem)
Add an element to a dynamic array.
Definition: mem.c:315
c2
static const uint64_t c2
Definition: murmur3.c:53
ff_sws_compile_pass
int ff_sws_compile_pass(SwsGraph *graph, SwsOpList *ops, int flags, SwsFormat dst, SwsPass *input, SwsPass **output)
Resolves an operation list to a graph pass.
SwsContext::scaler_params
double scaler_params[2]
Extra parameters for fine-tuning certain scalers.
Definition: swscale.h:207
AVCHROMA_LOC_CENTER
@ AVCHROMA_LOC_CENTER
MPEG-1 4:2:0, JPEG 4:2:0, H.263 4:2:0.
Definition: pixfmt.h:789
AV_PIX_FMT_NONE
@ AV_PIX_FMT_NONE
Definition: pixfmt.h:72
SwsFormat::color
SwsColor color
Definition: format.h:85
ff_sws_color_map_noop
bool ff_sws_color_map_noop(const SwsColorMap *map)
Returns true if the given color map is a semantic no-op - that is, the overall RGB end to end transfo...
Definition: cms.c:34
setup_legacy_swscale
static void setup_legacy_swscale(const SwsImg *out, const SwsImg *in, const SwsPass *pass)
Definition: graph.c:170
ff_swscale
int ff_swscale(SwsInternal *c, const uint8_t *const src[], const int srcStride[], int srcSliceY, int srcSliceH, uint8_t *const dst[], const int dstStride[], int dstSliceY, int dstSliceH)
Definition: swscale.c:259
cms.h
add_convert_pass
#define add_convert_pass
Definition: graph.c:541
SwsInternal::pal_yuv
uint32_t pal_yuv[256]
Definition: swscale_internal.h:382
SwsGraph::incomplete
bool incomplete
Definition: graph.h:112
mem.h
sws_getCoefficients
const int * sws_getCoefficients(int colorspace)
Return a pointer to yuv<->rgb coefficients for the given colorspace suitable for sws_setColorspaceDet...
Definition: yuv2rgb.c:61
SwsContext::dst_w
int dst_w
Definition: swscale.h:236
SwsGraph
Filter graph, which represents a 'baked' pixel format conversion.
Definition: graph.h:108
SwsContext::src_format
int src_format
Source pixel format.
Definition: swscale.h:237
map
const VDPAUPixFmtMap * map
Definition: hwcontext_vdpau.c:71
SwsImg::fmt
enum AVPixelFormat fmt
Definition: graph.h:34
av_free
#define av_free(p)
Definition: tableprint_vlc.h:34
FFALIGN
#define FFALIGN(x, a)
Definition: macros.h:78
SwsContext::dst_range
int dst_range
Destination is full range.
Definition: swscale.h:240
pass_alloc_output
static int pass_alloc_output(SwsPass *pass)
Definition: graph.c:39
run_legacy_unscaled
static void run_legacy_unscaled(const SwsImg *out, const SwsImg *in_base, int y, int h, const SwsPass *pass)
Definition: graph.c:205
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:35
SwsPass::run
sws_filter_run_t run
Filter main execution function.
Definition: graph.h:76
sws_free_context
void sws_free_context(SwsContext **ctx)
Free the context and everything associated with it, and write NULL to the provided pointer.
Definition: utils.c:2326
imgutils.h
ff_sws_op_list_print
void ff_sws_op_list_print(void *log, int lev, const SwsOpList *ops)
Print out the contents of an operation list.
Definition: ops.c:411
avpriv_slicethread_free
void avpriv_slicethread_free(AVSliceThread **pctx)
Destroy slice threading context.
Definition: slicethread.c:276
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
SwsContext::src_h_chr_pos
int src_h_chr_pos
Source horizontal chroma position.
Definition: swscale.h:242
sws_internal
static SwsInternal * sws_internal(const SwsContext *sws)
Definition: swscale_internal.h:74
SwsPass::input
const SwsPass * input
Filter input.
Definition: graph.h:86
h
h
Definition: vp9dsp_template.c:2070
SwsPass::num_slices
int num_slices
Definition: graph.h:80
width
#define width
Definition: dsp.h:89
SwsOpList
Helper struct for representing a list of operations.
Definition: ops.h:209
run_lut3d
static void run_lut3d(const SwsImg *out_base, const SwsImg *in_base, int y, int h, const SwsPass *pass)
Definition: graph.c:563
SwsContext::dst_v_chr_pos
int dst_v_chr_pos
Destination vertical chroma position.
Definition: swscale.h:243
SwsContext
Main external API structure.
Definition: swscale.h:189
sws_graph_worker
static void sws_graph_worker(void *priv, int jobnr, int threadnr, int nb_jobs, int nb_threads)
Definition: graph.c:675
ff_sws_graph_update_metadata
void ff_sws_graph_update_metadata(SwsGraph *graph, const SwsColor *color)
Update dynamic per-frame HDR metadata without requiring a full reinit.
Definition: graph.c:781
SWS_UNSTABLE
@ SWS_UNSTABLE
Allow using experimental new code paths.
Definition: swscale.h:163
AVPixFmtDescriptor::log2_chroma_h
uint8_t log2_chroma_h
Amount to shift the luma height right to find the chroma height.
Definition: pixdesc.h:89
src
#define src
Definition: vp8dsp.c:248
swscale.h
SwsImg::data
uint8_t * data[4]
Definition: graph.h:35
ff_sws_encode_pixfmt
int ff_sws_encode_pixfmt(SwsOpList *ops, enum AVPixelFormat fmt)
av_get_pix_fmt_name
const char * av_get_pix_fmt_name(enum AVPixelFormat pix_fmt)
Return the short name for a pixel format, NULL in case pix_fmt is unknown.
Definition: pixdesc.c:3367
isALPHA
static av_always_inline int isALPHA(enum AVPixelFormat pix_fmt)
Definition: swscale_internal.h:878