FFmpeg
vf_libplacebo.c
Go to the documentation of this file.
1 /*
2  * This file is part of FFmpeg.
3  *
4  * FFmpeg is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * FFmpeg is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with FFmpeg; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17  */
18 
19 #include <math.h>
20 
21 #include "libavutil/avassert.h"
22 #include "libavutil/avstring.h"
23 #include "libavutil/eval.h"
24 #include "libavutil/fifo.h"
25 #include "libavutil/file.h"
26 #include "libavutil/frame.h"
27 #include "libavutil/mem.h"
28 #include "libavutil/opt.h"
29 #include "libavutil/parseutils.h"
30 #include "formats.h"
31 #include "filters.h"
32 #include "video.h"
33 #include "vulkan_filter.h"
34 #include "scale_eval.h"
35 
36 #include <libplacebo/options.h>
37 #include <libplacebo/renderer.h>
38 #include <libplacebo/utils/libav.h>
39 #include <libplacebo/utils/frame_queue.h>
40 #include <libplacebo/vulkan.h>
41 
42 enum {
56 };
57 
58 enum {
69 };
70 
71 static const char *const var_names[] = {
72  "in_idx", "idx",///< index of input
73  "in_w", "iw", ///< width of the input video frame
74  "in_h", "ih", ///< height of the input video frame
75  "out_w", "ow", ///< width of the output video frame
76  "out_h", "oh", ///< height of the output video frame
77  "crop_w", "cw", ///< evaluated input crop width
78  "crop_h", "ch", ///< evaluated input crop height
79  "pos_w", "pw", ///< evaluated output placement width
80  "pos_h", "ph", ///< evaluated output placement height
81  "a", ///< iw/ih
82  "sar", ///< input pixel aspect ratio
83  "dar", ///< output pixel aspect ratio
84  "hsub", ///< input horizontal subsampling factor
85  "vsub", ///< input vertical subsampling factor
86  "ohsub", ///< output horizontal subsampling factor
87  "ovsub", ///< output vertical subsampling factor
88  "in_t", "t", ///< input frame pts
89  "out_t", "ot", ///< output frame pts
90  "n", ///< number of frame
91  NULL,
92 };
93 
94 enum var_name {
115 };
116 
117 /* per-input dynamic filter state */
118 typedef struct LibplaceboInput {
119  int idx;
120  pl_renderer renderer;
121  pl_queue queue;
122  enum pl_queue_status qstatus;
123  struct pl_frame_mix mix; ///< temporary storage
124  AVFifo *out_pts; ///< timestamps of wanted output frames
126  int status;
128 
129 enum fit_mode {
136 };
137 
138 enum fit_sense {
142 };
143 
144 typedef struct LibplaceboContext {
145  /* lavfi vulkan*/
147 
148  /* libplacebo */
149  pl_log log;
150  pl_vulkan vulkan;
151  pl_gpu gpu;
152  pl_tex tex[4];
153  struct pl_custom_lut *lut;
154 
155  /* dedicated renderer for linear output composition */
156  pl_renderer linear_rr;
157  pl_tex linear_tex;
158 
159  /* input state */
163 
164  /* settings */
167  uint8_t fillcolor[4];
169  char *w_expr;
170  char *h_expr;
171  char *fps_string;
172  AVRational fps; ///< parsed FPS, or 0/0 for "none"
177  // Parsed expressions for input/output crop
183  /* enum pl_lut_type */
184  int lut_type;
189  int fit_mode;
198  int rotation;
201 
202  pl_cache cache;
205 
207 
208  /* pl_render_params */
209  pl_options opts;
210  char *upscaler;
211  char *downscaler;
212  char *frame_mixer;
213  float antiringing;
214  int sigmoid;
215  int skip_aa;
220 
221  /* pl_deinterlace_params */
225 
226  /* pl_deband_params */
227  int deband;
232 
233  /* pl_color_adjustment */
234  float brightness;
235  float contrast;
236  float saturation;
237  float hue;
238  float gamma;
239  float temperature;
240 
241  /* pl_peak_detect_params */
243  float smoothing;
244  float scene_low;
245  float scene_high;
246  float percentile;
247 
248  /* pl_color_map_params */
256 
257  /* pl_dither_params */
261 
262  /* pl_cone_params */
263  int cones;
264  float cone_str;
265 
266  /* custom shaders */
267  char *shader_path;
268  void *shader_bin;
270  const struct pl_hook *hooks[2];
273 
274 static inline enum pl_log_level get_log_level(void)
275 {
276  int av_lev = av_log_get_level();
277  return av_lev >= AV_LOG_TRACE ? PL_LOG_TRACE :
278  av_lev >= AV_LOG_DEBUG ? PL_LOG_DEBUG :
279  av_lev >= AV_LOG_VERBOSE ? PL_LOG_INFO :
280  av_lev >= AV_LOG_WARNING ? PL_LOG_WARN :
281  av_lev >= AV_LOG_ERROR ? PL_LOG_ERR :
282  av_lev >= AV_LOG_FATAL ? PL_LOG_FATAL :
283  PL_LOG_NONE;
284 }
285 
286 static void pl_av_log(void *log_ctx, enum pl_log_level level, const char *msg)
287 {
288  int av_lev;
289 
290  switch (level) {
291  case PL_LOG_FATAL: av_lev = AV_LOG_FATAL; break;
292  case PL_LOG_ERR: av_lev = AV_LOG_ERROR; break;
293  case PL_LOG_WARN: av_lev = AV_LOG_WARNING; break;
294  case PL_LOG_INFO: av_lev = AV_LOG_VERBOSE; break;
295  case PL_LOG_DEBUG: av_lev = AV_LOG_DEBUG; break;
296  case PL_LOG_TRACE: av_lev = AV_LOG_TRACE; break;
297  default: return;
298  }
299 
300  av_log(log_ctx, av_lev, "%s\n", msg);
301 }
302 
303 static const struct pl_tone_map_function *get_tonemapping_func(int tm) {
304  switch (tm) {
305  case TONE_MAP_AUTO: return &pl_tone_map_auto;
306  case TONE_MAP_CLIP: return &pl_tone_map_clip;
307  case TONE_MAP_ST2094_40: return &pl_tone_map_st2094_40;
308  case TONE_MAP_ST2094_10: return &pl_tone_map_st2094_10;
309  case TONE_MAP_BT2390: return &pl_tone_map_bt2390;
310  case TONE_MAP_BT2446A: return &pl_tone_map_bt2446a;
311  case TONE_MAP_SPLINE: return &pl_tone_map_spline;
312  case TONE_MAP_REINHARD: return &pl_tone_map_reinhard;
313  case TONE_MAP_MOBIUS: return &pl_tone_map_mobius;
314  case TONE_MAP_HABLE: return &pl_tone_map_hable;
315  case TONE_MAP_GAMMA: return &pl_tone_map_gamma;
316  case TONE_MAP_LINEAR: return &pl_tone_map_linear;
317  default: av_assert0(0);
318  }
319 }
320 
321 static void set_gamut_mode(struct pl_color_map_params *p, int gamut_mode)
322 {
323  switch (gamut_mode) {
324  case GAMUT_MAP_CLIP: p->gamut_mapping = &pl_gamut_map_clip; return;
325  case GAMUT_MAP_PERCEPTUAL: p->gamut_mapping = &pl_gamut_map_perceptual; return;
326  case GAMUT_MAP_RELATIVE: p->gamut_mapping = &pl_gamut_map_relative; return;
327  case GAMUT_MAP_SATURATION: p->gamut_mapping = &pl_gamut_map_saturation; return;
328  case GAMUT_MAP_ABSOLUTE: p->gamut_mapping = &pl_gamut_map_absolute; return;
329  case GAMUT_MAP_DESATURATE: p->gamut_mapping = &pl_gamut_map_desaturate; return;
330  case GAMUT_MAP_DARKEN: p->gamut_mapping = &pl_gamut_map_darken; return;
331  case GAMUT_MAP_HIGHLIGHT: p->gamut_mapping = &pl_gamut_map_highlight; return;
332  case GAMUT_MAP_LINEAR: p->gamut_mapping = &pl_gamut_map_linear; return;
333  }
334 
335  av_assert0(0);
336 };
337 
338 static int find_scaler(AVFilterContext *avctx,
339  const struct pl_filter_config **opt,
340  const char *name, int frame_mixing)
341 {
342  const struct pl_filter_preset *preset, *presets_avail;
343  presets_avail = frame_mixing ? pl_frame_mixers : pl_scale_filters;
344 
345  if (!strcmp(name, "help")) {
346  av_log(avctx, AV_LOG_INFO, "Available scaler presets:\n");
347  for (preset = presets_avail; preset->name; preset++)
348  av_log(avctx, AV_LOG_INFO, " %s\n", preset->name);
349  return AVERROR_EXIT;
350  }
351 
352  for (preset = presets_avail; preset->name; preset++) {
353  if (!strcmp(name, preset->name)) {
354  *opt = preset->filter;
355  return 0;
356  }
357  }
358 
359  av_log(avctx, AV_LOG_ERROR, "No such scaler preset '%s'.\n", name);
360  return AVERROR(EINVAL);
361 }
362 
364 {
365  LibplaceboContext *s = avctx->priv;
366  int ret;
367  uint8_t *lutbuf;
368  size_t lutbuf_size;
369 
370  if ((ret = av_file_map(s->lut_filename, &lutbuf, &lutbuf_size, 0, s)) < 0) {
371  av_log(avctx, AV_LOG_ERROR,
372  "The LUT file '%s' could not be read: %s\n",
373  s->lut_filename, av_err2str(ret));
374  return ret;
375  }
376 
377  s->lut = pl_lut_parse_cube(s->log, lutbuf, lutbuf_size);
378  av_file_unmap(lutbuf, lutbuf_size);
379  if (!s->lut)
380  return AVERROR(EINVAL);
381  return 0;
382 }
383 
385 {
386  int err = 0;
387  LibplaceboContext *s = ctx->priv;
388  AVDictionaryEntry *e = NULL;
389  pl_options opts = s->opts;
390  int gamut_mode = s->gamut_mode;
391 
392  opts->deinterlace_params = *pl_deinterlace_params(
393  .algo = s->deinterlace,
394  .skip_spatial_check = s->skip_spatial_check,
395  );
396 
397  opts->deband_params = *pl_deband_params(
398  .iterations = s->deband_iterations,
399  .threshold = s->deband_threshold,
400  .radius = s->deband_radius,
401  .grain = s->deband_grain,
402  );
403 
404  opts->sigmoid_params = pl_sigmoid_default_params;
405 
406  opts->color_adjustment = (struct pl_color_adjustment) {
407  .brightness = s->brightness,
408  .contrast = s->contrast,
409  .saturation = s->saturation,
410  .hue = s->hue,
411  .gamma = s->gamma,
412  // libplacebo uses a normalized/relative scale for CCT
413  .temperature = (s->temperature - 6500.0) / 3500.0,
414  };
415 
416  opts->peak_detect_params = (struct pl_peak_detect_params) {
417  PL_PEAK_DETECT_DEFAULTS
418  .smoothing_period = s->smoothing,
419  .scene_threshold_low = s->scene_low,
420  .scene_threshold_high = s->scene_high,
421  .percentile = s->percentile,
422  };
423 
424  opts->color_map_params = (struct pl_color_map_params) {
425  PL_COLOR_MAP_DEFAULTS
426  .tone_mapping_function = get_tonemapping_func(s->tonemapping),
427  .tone_mapping_param = s->tonemapping_param,
428  .inverse_tone_mapping = s->inverse_tonemapping,
429  .lut_size = s->tonemapping_lut_size,
430  .contrast_recovery = s->contrast_recovery,
431  .contrast_smoothness = s->contrast_smoothness,
432  };
433 
434  set_gamut_mode(&opts->color_map_params, gamut_mode);
435 
436  opts->dither_params = *pl_dither_params(
437  .method = s->dithering,
438  .lut_size = s->dither_lut_size,
439  .temporal = s->dither_temporal,
440  );
441 
442  opts->cone_params = *pl_cone_params(
443  .cones = s->cones,
444  .strength = s->cone_str,
445  );
446 
447  opts->params = (struct pl_render_params) {
448  PL_RENDER_DEFAULTS
449  .antiringing_strength = s->antiringing,
450  .background_transparency = 1.0f - (float) s->fillcolor[3] / UINT8_MAX,
451  .background_color = {
452  (float) s->fillcolor[0] / UINT8_MAX,
453  (float) s->fillcolor[1] / UINT8_MAX,
454  (float) s->fillcolor[2] / UINT8_MAX,
455  },
456  .corner_rounding = s->corner_rounding,
457 
458  .deinterlace_params = &opts->deinterlace_params,
459  .deband_params = s->deband ? &opts->deband_params : NULL,
460  .sigmoid_params = s->sigmoid ? &opts->sigmoid_params : NULL,
461  .color_adjustment = &opts->color_adjustment,
462  .peak_detect_params = s->peakdetect ? &opts->peak_detect_params : NULL,
463  .color_map_params = &opts->color_map_params,
464  .dither_params = s->dithering >= 0 ? &opts->dither_params : NULL,
465  .cone_params = s->cones ? &opts->cone_params : NULL,
466 
467  .hooks = s->hooks,
468  .num_hooks = s->num_hooks,
469 
470  .skip_anti_aliasing = s->skip_aa,
471  .disable_linear_scaling = s->disable_linear,
472  .disable_builtin_scalers = s->disable_builtin,
473  .force_dither = s->force_dither,
474  .disable_fbos = s->disable_fbos,
475  };
476 
477  RET(find_scaler(ctx, &opts->params.upscaler, s->upscaler, 0));
478  RET(find_scaler(ctx, &opts->params.downscaler, s->downscaler, 0));
479  RET(find_scaler(ctx, &opts->params.frame_mixer, s->frame_mixer, 1));
480 
481  while ((e = av_dict_get(s->extra_opts, "", e, AV_DICT_IGNORE_SUFFIX))) {
482  if (!pl_options_set_str(s->opts, e->key, e->value)) {
483  err = AVERROR(EINVAL);
484  goto fail;
485  }
486  }
487 
488  return 0;
489 
490 fail:
491  return err;
492 }
493 
494 static int parse_shader(AVFilterContext *avctx, const void *shader, size_t len)
495 {
496  LibplaceboContext *s = avctx->priv;
497  const struct pl_hook *hook;
498 
499  hook = pl_mpv_user_shader_parse(s->gpu, shader, len);
500  if (!hook) {
501  av_log(avctx, AV_LOG_ERROR, "Failed parsing custom shader!\n");
502  return AVERROR(EINVAL);
503  }
504 
505  s->hooks[s->num_hooks++] = hook;
506  return update_settings(avctx);
507 }
508 
509 static void libplacebo_uninit(AVFilterContext *avctx);
511 static int init_vulkan(AVFilterContext *avctx, const AVVulkanDeviceContext *hwctx);
512 
514 {
515  int err = 0;
516  LibplaceboContext *s = avctx->priv;
517 
518  if (s->normalize_sar && s->fit_mode != FIT_FILL) {
519  av_log(avctx, AV_LOG_WARNING, "normalize_sar has no effect when using "
520  "a fit mode other than 'fill'\n");
521  }
522 
523  /* Create libplacebo log context */
524  s->log = pl_log_create(PL_API_VER, pl_log_params(
525  .log_level = get_log_level(),
526  .log_cb = pl_av_log,
527  .log_priv = s,
528  ));
529 
530  if (!s->log)
531  return AVERROR(ENOMEM);
532 
533  s->opts = pl_options_alloc(s->log);
534  if (!s->opts) {
535  libplacebo_uninit(avctx);
536  return AVERROR(ENOMEM);
537  }
538 
539  if (s->shader_cache && s->shader_cache[0]) {
540  s->cache = pl_cache_create(pl_cache_params(
541  .log = s->log,
542  .get = pl_cache_get_file,
543  .set = pl_cache_set_file,
544  .priv = s->shader_cache,
545  ));
546  if (!s->cache) {
547  libplacebo_uninit(avctx);
548  return AVERROR(ENOMEM);
549  }
550  }
551 
552  if (s->out_format_string) {
553  s->out_format = av_get_pix_fmt(s->out_format_string);
554  if (s->out_format == AV_PIX_FMT_NONE) {
555  av_log(avctx, AV_LOG_ERROR, "Invalid output format: %s\n",
556  s->out_format_string);
557  libplacebo_uninit(avctx);
558  return AVERROR(EINVAL);
559  }
560  } else {
561  s->out_format = AV_PIX_FMT_NONE;
562  }
563 
564  for (int i = 0; i < s->nb_inputs; i++) {
565  AVFilterPad pad = {
566  .name = av_asprintf("input%d", i),
567  .type = AVMEDIA_TYPE_VIDEO,
568  .config_props = &libplacebo_config_input,
569  };
570  if (!pad.name)
571  return AVERROR(ENOMEM);
572  RET(ff_append_inpad_free_name(avctx, &pad));
573  }
574 
575  RET(update_settings(avctx));
576  RET(av_expr_parse(&s->crop_x_pexpr, s->crop_x_expr, var_names,
577  NULL, NULL, NULL, NULL, 0, s));
578  RET(av_expr_parse(&s->crop_y_pexpr, s->crop_y_expr, var_names,
579  NULL, NULL, NULL, NULL, 0, s));
580  RET(av_expr_parse(&s->crop_w_pexpr, s->crop_w_expr, var_names,
581  NULL, NULL, NULL, NULL, 0, s));
582  RET(av_expr_parse(&s->crop_h_pexpr, s->crop_h_expr, var_names,
583  NULL, NULL, NULL, NULL, 0, s));
584  RET(av_expr_parse(&s->pos_x_pexpr, s->pos_x_expr, var_names,
585  NULL, NULL, NULL, NULL, 0, s));
586  RET(av_expr_parse(&s->pos_y_pexpr, s->pos_y_expr, var_names,
587  NULL, NULL, NULL, NULL, 0, s));
588  RET(av_expr_parse(&s->pos_w_pexpr, s->pos_w_expr, var_names,
589  NULL, NULL, NULL, NULL, 0, s));
590  RET(av_expr_parse(&s->pos_h_pexpr, s->pos_h_expr, var_names,
591  NULL, NULL, NULL, NULL, 0, s));
592 
593  if (strcmp(s->fps_string, "none") != 0)
594  RET(av_parse_video_rate(&s->fps, s->fps_string));
595 
596  /* if we are told to inherit the input link's device, ignore the global
597  * hw_device_ctx even if it would be compatible. This ensure consistent
598  * behaviour when the flag is set. */
599  if (!s->inherit_device) {
600  const AVVulkanDeviceContext *vkhwctx = NULL;
601  if (avctx->hw_device_ctx) {
602  const AVHWDeviceContext *avhwctx = (void *) avctx->hw_device_ctx->data;
603  if (avhwctx->type == AV_HWDEVICE_TYPE_VULKAN)
604  vkhwctx = avhwctx->hwctx;
605  }
606  RET(init_vulkan(avctx, vkhwctx));
607  }
608 
609  return 0;
610 
611 fail:
612  return err;
613 }
614 
615 static void lock_queue(void *priv, uint32_t qf, uint32_t qidx)
616 {
617  AVHWDeviceContext *avhwctx = priv;
618  const AVVulkanDeviceContext *hwctx = avhwctx->hwctx;
619 #if FF_API_VULKAN_SYNC_QUEUES
621  hwctx->lock_queue(avhwctx, qf, qidx);
623 #endif
624 }
625 
626 static void unlock_queue(void *priv, uint32_t qf, uint32_t qidx)
627 {
628  AVHWDeviceContext *avhwctx = priv;
629  const AVVulkanDeviceContext *hwctx = avhwctx->hwctx;
630 #if FF_API_VULKAN_SYNC_QUEUES
632  hwctx->unlock_queue(avhwctx, qf, qidx);
634 #endif
635 }
636 
637 static int input_init(AVFilterContext *avctx, LibplaceboInput *input, int idx)
638 {
639  LibplaceboContext *s = avctx->priv;
640 
641  input->out_pts = av_fifo_alloc2(1, sizeof(int64_t), AV_FIFO_FLAG_AUTO_GROW);
642  if (!input->out_pts)
643  return AVERROR(ENOMEM);
644  input->queue = pl_queue_create(s->gpu);
645  input->renderer = pl_renderer_create(s->log, s->gpu);
646  input->idx = idx;
647 
648  return 0;
649 }
650 
652 {
653  pl_renderer_destroy(&input->renderer);
654  pl_queue_destroy(&input->queue);
655  av_fifo_freep2(&input->out_pts);
656 }
657 
658 static int copy_pl_queue(const AVVulkanDeviceContext *hwctx,
659  const AVVulkanDeviceQueueFamily *qf,
660  struct pl_vulkan_queue *pl_qf)
661 {
662  pl_qf->index = qf->idx;
663  pl_qf->count = qf->num;
664 #if PL_API_VER >= 365
665  pl_qf->flags = hwctx->queue_flags;
666 #else
667  if (hwctx->queue_flags != 0)
668  return AVERROR(EINVAL); // prevent undefined behavior
669 #endif
670  return 0;
671 }
672 
673 static int init_vulkan(AVFilterContext *avctx, const AVVulkanDeviceContext *hwctx)
674 {
675  int err = 0;
676  LibplaceboContext *s = avctx->priv;
677  uint8_t *buf = NULL;
678  size_t buf_len;
679 
680  if (hwctx) {
681  struct pl_vulkan_import_params import_params = {
682  .instance = hwctx->inst,
683  .get_proc_addr = hwctx->get_proc_addr,
684  .phys_device = hwctx->phys_dev,
685  .device = hwctx->act_dev,
686  .extensions = hwctx->enabled_dev_extensions,
687  .num_extensions = hwctx->nb_enabled_dev_extensions,
688  .features = &hwctx->device_features,
689  .lock_queue = lock_queue,
690  .unlock_queue = unlock_queue,
691  .queue_ctx = avctx->hw_device_ctx->data,
692  .queue_graphics = { VK_QUEUE_FAMILY_IGNORED },
693  .queue_compute = { VK_QUEUE_FAMILY_IGNORED },
694  .queue_transfer = { VK_QUEUE_FAMILY_IGNORED },
695  /* This is the highest version created by hwcontext_vulkan.c */
696  .max_api_version = VK_API_VERSION_1_3,
697  };
698  for (int i = 0; i < hwctx->nb_qf; i++) {
699  const AVVulkanDeviceQueueFamily *qf = &hwctx->qf[i];
700  if (qf->flags & VK_QUEUE_GRAPHICS_BIT)
701  RET(copy_pl_queue(hwctx, qf, &import_params.queue_graphics));
702  if (qf->flags & VK_QUEUE_COMPUTE_BIT)
703  RET(copy_pl_queue(hwctx, qf, &import_params.queue_compute));
704  if (qf->flags & VK_QUEUE_TRANSFER_BIT)
705  RET(copy_pl_queue(hwctx, qf, &import_params.queue_transfer));
706  }
707 
708  /* Import libavfilter vulkan context into libplacebo */
709  s->vulkan = pl_vulkan_import(s->log, &import_params);
710  s->have_hwdevice = 1;
711  } else {
712  s->vulkan = pl_vulkan_create(s->log, pl_vulkan_params(
713  .queue_count = 0, /* enable all queues for parallelization */
714  ));
715  }
716 
717  if (!s->vulkan) {
718  av_log(avctx, AV_LOG_ERROR, "Failed %s Vulkan device!\n",
719  hwctx ? "importing" : "creating");
720  err = AVERROR_EXTERNAL;
721  goto fail;
722  }
723 
724  s->gpu = s->vulkan->gpu;
725  pl_gpu_set_cache(s->gpu, s->cache);
726 
727  /* Parse the user shaders, if requested */
728  if (s->shader_bin_len)
729  RET(parse_shader(avctx, s->shader_bin, s->shader_bin_len));
730 
731  if (s->shader_path && s->shader_path[0]) {
732  RET(av_file_map(s->shader_path, &buf, &buf_len, 0, s));
733  RET(parse_shader(avctx, buf, buf_len));
734  }
735 
736  if (s->lut_filename)
737  RET(parse_custom_lut(avctx));
738 
739  /* Initialize inputs */
740  s->inputs = av_calloc(s->nb_inputs, sizeof(*s->inputs));
741  if (!s->inputs)
742  return AVERROR(ENOMEM);
743  for (int i = 0; i < s->nb_inputs; i++)
744  RET(input_init(avctx, &s->inputs[i], i));
745  s->nb_active = s->nb_inputs;
746  s->linear_rr = pl_renderer_create(s->log, s->gpu);
747 
748  /* fall through */
749 fail:
750  if (buf)
751  av_file_unmap(buf, buf_len);
752  return err;
753 }
754 
756 {
757  LibplaceboContext *s = avctx->priv;
758 
759  for (int i = 0; i < FF_ARRAY_ELEMS(s->tex); i++)
760  pl_tex_destroy(s->gpu, &s->tex[i]);
761  for (int i = 0; i < s->num_hooks; i++)
762  pl_mpv_user_shader_destroy(&s->hooks[i]);
763  if (s->inputs) {
764  for (int i = 0; i < s->nb_inputs; i++)
765  input_uninit(&s->inputs[i]);
766  av_freep(&s->inputs);
767  }
768 
769  pl_lut_free(&s->lut);
770  pl_cache_destroy(&s->cache);
771  pl_renderer_destroy(&s->linear_rr);
772  pl_tex_destroy(s->gpu, &s->linear_tex);
773  pl_options_free(&s->opts);
774  pl_vulkan_destroy(&s->vulkan);
775  pl_log_destroy(&s->log);
776  ff_vk_uninit(&s->vkctx);
777  s->gpu = NULL;
778 
779  av_expr_free(s->crop_x_pexpr);
780  av_expr_free(s->crop_y_pexpr);
781  av_expr_free(s->crop_w_pexpr);
782  av_expr_free(s->crop_h_pexpr);
783  av_expr_free(s->pos_x_pexpr);
784  av_expr_free(s->pos_y_pexpr);
785  av_expr_free(s->pos_w_pexpr);
786  av_expr_free(s->pos_h_pexpr);
787 }
788 
789 static int libplacebo_process_command(AVFilterContext *ctx, const char *cmd,
790  const char *arg, char *res, int res_len,
791  int flags)
792 {
793  int err = 0;
794  RET(ff_filter_process_command(ctx, cmd, arg, res, res_len, flags));
796  return 0;
797 
798 fail:
799  return err;
800 }
801 
802 static const AVFrame *ref_frame(const struct pl_frame_mix *mix)
803 {
804  for (int i = 0; i < mix->num_frames; i++) {
805  if (i+1 == mix->num_frames || mix->timestamps[i+1] > 0)
806  return pl_get_mapped_avframe(mix->frames[i]);
807  }
808  return NULL;
809 }
810 
811 static inline double q2d_fallback(AVRational q, const double def)
812 {
813  return (q.num && q.den) ? av_q2d(q) : def;
814 }
815 
817  struct pl_frame *target, double target_pts)
818 {
819  FilterLink *outl = ff_filter_link(ctx->outputs[0]);
820  LibplaceboContext *s = ctx->priv;
821  const AVFilterLink *outlink = ctx->outputs[0];
822  const AVFilterLink *inlink = ctx->inputs[in->idx];
823  const AVFrame *ref = ref_frame(&in->mix);
824 
825  for (int i = 0; i < in->mix.num_frames; i++) {
826  // Mutate the `pl_frame.crop` fields in-place. This is fine because we
827  // own the entire pl_queue, and hence, the pointed-at frames.
828  struct pl_frame *image = (struct pl_frame *) in->mix.frames[i];
829  const AVFrame *src = pl_get_mapped_avframe(image);
830  double image_pts = TS2T(src->pts, inlink->time_base);
831 
832  /* Update dynamic variables */
833  s->var_values[VAR_IN_IDX] = s->var_values[VAR_IDX] = in->idx;
834  s->var_values[VAR_IN_W] = s->var_values[VAR_IW] = inlink->w;
835  s->var_values[VAR_IN_H] = s->var_values[VAR_IH] = inlink->h;
836  s->var_values[VAR_A] = (double) inlink->w / inlink->h;
837  s->var_values[VAR_SAR] = q2d_fallback(inlink->sample_aspect_ratio, 1.0);
838  s->var_values[VAR_IN_T] = s->var_values[VAR_T] = image_pts;
839  s->var_values[VAR_OUT_T] = s->var_values[VAR_OT] = target_pts;
840  s->var_values[VAR_N] = outl->frame_count_out;
841 
842  /* Clear these explicitly to avoid leaking previous frames' state */
843  s->var_values[VAR_CROP_W] = s->var_values[VAR_CW] = NAN;
844  s->var_values[VAR_CROP_H] = s->var_values[VAR_CH] = NAN;
845  s->var_values[VAR_POS_W] = s->var_values[VAR_PW] = NAN;
846  s->var_values[VAR_POS_H] = s->var_values[VAR_PH] = NAN;
847 
848  /* Compute dimensions first and placement second */
849  s->var_values[VAR_CROP_W] = s->var_values[VAR_CW] =
850  av_expr_eval(s->crop_w_pexpr, s->var_values, NULL);
851  s->var_values[VAR_CROP_H] = s->var_values[VAR_CH] =
852  av_expr_eval(s->crop_h_pexpr, s->var_values, NULL);
853  s->var_values[VAR_CROP_W] = s->var_values[VAR_CW] =
854  av_expr_eval(s->crop_w_pexpr, s->var_values, NULL);
855  s->var_values[VAR_POS_W] = s->var_values[VAR_PW] =
856  av_expr_eval(s->pos_w_pexpr, s->var_values, NULL);
857  s->var_values[VAR_POS_H] = s->var_values[VAR_PH] =
858  av_expr_eval(s->pos_h_pexpr, s->var_values, NULL);
859  s->var_values[VAR_POS_W] = s->var_values[VAR_PW] =
860  av_expr_eval(s->pos_w_pexpr, s->var_values, NULL);
861 
862  image->crop.x0 = av_expr_eval(s->crop_x_pexpr, s->var_values, NULL);
863  image->crop.y0 = av_expr_eval(s->crop_y_pexpr, s->var_values, NULL);
864  image->crop.x1 = image->crop.x0 + s->var_values[VAR_CROP_W];
865  image->crop.y1 = image->crop.y0 + s->var_values[VAR_CROP_H];
866 
867  const pl_rect2df crop_orig = image->crop;
868  pl_rotation rot_total = PL_ROTATION_360 + image->rotation - target->rotation;
869  if (rot_total % PL_ROTATION_180 == PL_ROTATION_90) {
870  /* Libplacebo expects the input crop relative to the actual frame
871  * dimensions, so un-transpose them here */
872  FFSWAP(float, image->crop.x0, image->crop.y0);
873  FFSWAP(float, image->crop.x1, image->crop.y1);
874  }
875 
876  if (src == ref) {
877  /* Only update the target crop once, for the 'reference' frame */
878  target->crop.x0 = av_expr_eval(s->pos_x_pexpr, s->var_values, NULL);
879  target->crop.y0 = av_expr_eval(s->pos_y_pexpr, s->var_values, NULL);
880  target->crop.x1 = target->crop.x0 + s->var_values[VAR_POS_W];
881  target->crop.y1 = target->crop.y0 + s->var_values[VAR_POS_H];
882 
883  /* Effective visual crop */
884  double sar_in = q2d_fallback(inlink->sample_aspect_ratio, 1.0);
885  double sar_out = q2d_fallback(outlink->sample_aspect_ratio, 1.0);
886  if (rot_total % PL_ROTATION_180 == PL_ROTATION_90)
887  sar_in = 1.0 / sar_in;
888 
889  pl_rect2df fixed = crop_orig;
890  pl_rect2df_stretch(&fixed, sar_in / sar_out, 1.0);
891 
892  switch (s->fit_mode) {
893  case FIT_FILL:
894  if (s->normalize_sar)
895  pl_rect2df_aspect_copy(&target->crop, &fixed, s->pad_crop_ratio);
896  break;
897  case FIT_CONTAIN:
898  pl_rect2df_aspect_copy(&target->crop, &fixed, 0.0);
899  break;
900  case FIT_COVER:
901  pl_rect2df_aspect_copy(&target->crop, &fixed, 1.0);
902  break;
903  case FIT_NONE: {
904  const float sx = fabsf(pl_rect_w(fixed)) / pl_rect_w(target->crop);
905  const float sy = fabsf(pl_rect_h(fixed)) / pl_rect_h(target->crop);
906  pl_rect2df_stretch(&target->crop, sx, sy);
907  break;
908  }
909  case FIT_SCALE_DOWN:
910  pl_rect2df_aspect_fit(&target->crop, &fixed, 0.0);
911  }
912  }
913  }
914 }
915 
916 /* Construct and emit an output frame for a given timestamp */
918 {
919  int err = 0, ok, changed = 0;
920  LibplaceboContext *s = ctx->priv;
921  pl_options opts = s->opts;
922  AVFilterLink *outlink = ctx->outputs[0];
923  const AVPixFmtDescriptor *outdesc = av_pix_fmt_desc_get(outlink->format);
924  const double target_pts = TS2T(pts, outlink->time_base);
925  struct pl_frame target;
926  const AVFrame *ref = NULL;
927  AVFrame *out;
928 
929  /* Count the number of visible inputs, by excluding frames which are fully
930  * obscured or which have no frames in the mix */
931  int idx_start = 0, nb_visible = 0;
932  for (int i = 0; i < s->nb_inputs; i++) {
933  LibplaceboInput *in = &s->inputs[i];
934  struct pl_frame dummy;
935  if (in->qstatus != PL_QUEUE_OK || !in->mix.num_frames)
936  continue;
937  const struct pl_frame *cur = pl_frame_mix_nearest(&in->mix);
938  av_assert1(cur);
939  update_crops(ctx, in, &dummy, target_pts);
940  const int x0 = roundf(FFMIN(dummy.crop.x0, dummy.crop.x1)),
941  y0 = roundf(FFMIN(dummy.crop.y0, dummy.crop.y1)),
942  x1 = roundf(FFMAX(dummy.crop.x0, dummy.crop.x1)),
943  y1 = roundf(FFMAX(dummy.crop.y0, dummy.crop.y1));
944 
945  /* If an opaque frame covers entire the output, disregard all lower layers */
946  const bool cropped = x0 > 0 || y0 > 0 || x1 < outlink->w || y1 < outlink->h;
947  if (!cropped && cur->repr.alpha == PL_ALPHA_NONE) {
948  idx_start = i;
949  nb_visible = 0;
950  ref = NULL;
951  }
952  /* Use first visible input as overall reference */
953  if (!ref)
954  ref = ref_frame(&in->mix);
955  nb_visible++;
956  }
957 
958  out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
959  if (!out)
960  return AVERROR(ENOMEM);
961 
962  if (!ref)
963  goto props_done;
964 
966  out->width = outlink->w;
967  out->height = outlink->h;
968  out->colorspace = outlink->colorspace;
969  out->color_range = outlink->color_range;
970  out->alpha_mode = outlink->alpha_mode;
971  if (s->deinterlace)
973 
975  /* Output of dovi reshaping is always BT.2020+PQ, so infer the correct
976  * output colorspace defaults */
977  out->color_primaries = AVCOL_PRI_BT2020;
978  out->color_trc = AVCOL_TRC_SMPTE2084;
980  }
981 
982  if (s->color_trc >= 0)
983  out->color_trc = s->color_trc;
984  if (s->color_primaries >= 0)
985  out->color_primaries = s->color_primaries;
986  if (s->chroma_location >= 0)
987  out->chroma_location = s->chroma_location;
988 
989  /* Strip side data if no longer relevant */
990  if (out->width != ref->width || out->height != ref->height)
992  if (ref->color_trc != out->color_trc || ref->color_primaries != out->color_primaries)
994  av_frame_side_data_remove_by_props(&out->side_data, &out->nb_side_data, changed);
995 
996  if (s->apply_filmgrain)
998 
999  if (s->reset_sar) {
1000  out->sample_aspect_ratio = ref->sample_aspect_ratio;
1001  } else {
1002  const AVRational ar_ref = { ref->width, ref->height };
1003  const AVRational ar_out = { out->width, out->height };
1004  const AVRational stretch = av_div_q(ar_ref, ar_out);
1005  out->sample_aspect_ratio = av_mul_q(ref->sample_aspect_ratio, stretch);
1006  }
1007 
1008 props_done:
1009  out->pts = pts;
1010  if (s->fps.num)
1011  out->duration = 1;
1012 
1013  /* Map, render and unmap output frame */
1014  if (outdesc->flags & AV_PIX_FMT_FLAG_HWACCEL) {
1015  ok = pl_map_avframe_ex(s->gpu, &target, pl_avframe_params(
1016  .frame = out,
1017  .map_dovi = false,
1018  ));
1019  } else {
1020  ok = pl_frame_recreate_from_avframe(s->gpu, &target, s->tex, out);
1021  }
1022  if (!ok) {
1023  err = AVERROR_EXTERNAL;
1024  goto fail;
1025  }
1026 
1027  struct pl_frame orig_target = target;
1028  bool use_linear_compositor = false;
1029  if (s->linear_tex && target.color.transfer != PL_COLOR_TRC_LINEAR &&
1030  !s->disable_linear && nb_visible > 1) {
1031  target = (struct pl_frame) {
1032  .num_planes = 1,
1033  .planes[0] = {
1034  .components = 4,
1035  .component_mapping = {0, 1, 2, 3},
1036  .texture = s->linear_tex,
1037  },
1038  .repr = pl_color_repr_rgb,
1039  .color = orig_target.color,
1040  .rotation = orig_target.rotation,
1041  };
1042  target.repr.alpha = PL_ALPHA_PREMULTIPLIED;
1043  target.color.transfer = PL_COLOR_TRC_LINEAR;
1044  use_linear_compositor = true;
1045  }
1046 
1047  /* Draw first frame opaque, others with blending */
1048  struct pl_render_params tmp_params = opts->params;
1049  for (int i = 0; i < s->nb_inputs; i++) {
1050  LibplaceboInput *in = &s->inputs[i];
1051  if (!in->renderer)
1052  continue; /* input was already freed */
1053  FilterLink *il = ff_filter_link(ctx->inputs[i]);
1054  FilterLink *ol = ff_filter_link(outlink);
1055  int high_fps = av_cmp_q(il->frame_rate, ol->frame_rate) >= 0;
1056  if (in->qstatus != PL_QUEUE_OK || !in->mix.num_frames || i < idx_start) {
1057  pl_renderer_flush_cache(in->renderer);
1058  continue;
1059  }
1060  tmp_params.skip_caching_single_frame = high_fps;
1061  update_crops(ctx, in, &target, target_pts);
1062  pl_render_image_mix(in->renderer, &in->mix, &target, &tmp_params);
1063 
1064  /* Force straight output and set correct blend operator. This is
1065  * required to get correct blending onto YUV target buffers. */
1066  target.repr.alpha = PL_ALPHA_INDEPENDENT;
1067  tmp_params.blend_params = &pl_alpha_overlay;
1068  tmp_params.background = tmp_params.border = PL_CLEAR_SKIP;
1069  }
1070 
1071  if (use_linear_compositor) {
1072  /* Blit the linear intermediate image to the output frame */
1073  target.crop = orig_target.crop = (struct pl_rect2df) {0};
1074  target.repr.alpha = PL_ALPHA_PREMULTIPLIED;
1075  pl_render_image(s->linear_rr, &target, &orig_target, &opts->params);
1076  target = orig_target;
1077  } else if (!ref) {
1078  /* Render an empty image to clear the frame to the desired fill color */
1079  pl_render_image(s->linear_rr, NULL, &target, &opts->params);
1080  }
1081 
1082  if (outdesc->flags & AV_PIX_FMT_FLAG_HWACCEL) {
1083  pl_unmap_avframe(s->gpu, &target);
1084  } else if (!pl_download_avframe(s->gpu, &target, out)) {
1085  err = AVERROR_EXTERNAL;
1086  goto fail;
1087  }
1088  return ff_filter_frame(outlink, out);
1089 
1090 fail:
1091  av_frame_free(&out);
1092  return err;
1093 }
1094 
1095 static bool map_frame(pl_gpu gpu, pl_tex *tex,
1096  const struct pl_source_frame *src,
1097  struct pl_frame *out)
1098 {
1099  AVFrame *avframe = src->frame_data;
1100  LibplaceboContext *s = avframe->opaque;
1101  bool ok = pl_map_avframe_ex(gpu, out, pl_avframe_params(
1102  .frame = avframe,
1103  .tex = tex,
1104  .map_dovi = s->apply_dovi,
1105  ));
1106  out->lut = s->lut;
1107  out->lut_type = s->lut_type;
1108  out->rotation += s->rotation;
1109 
1110  if (!s->apply_filmgrain)
1111  out->film_grain.type = PL_FILM_GRAIN_NONE;
1112 
1113  av_frame_free(&avframe);
1114  return ok;
1115 }
1116 
1117 static void unmap_frame(pl_gpu gpu, struct pl_frame *frame,
1118  const struct pl_source_frame *src)
1119 {
1120  pl_unmap_avframe(gpu, frame);
1121 }
1122 
1123 static void discard_frame(const struct pl_source_frame *src)
1124 {
1125  AVFrame *avframe = src->frame_data;
1126  av_frame_free(&avframe);
1127 }
1128 
1130 {
1131  int ret, status;
1132  LibplaceboContext *s = ctx->priv;
1133  AVFilterLink *outlink = ctx->outputs[0];
1134  AVFilterLink *inlink = ctx->inputs[input->idx];
1135  AVFrame *in;
1136  int64_t pts;
1137 
1138  while ((ret = ff_inlink_consume_frame(inlink, &in)) > 0) {
1139  struct pl_source_frame src = {
1140  .pts = TS2T(in->pts, inlink->time_base),
1141  .duration = TS2T(in->duration, inlink->time_base),
1142  .first_field = s->deinterlace ? pl_field_from_avframe(in) : PL_FIELD_NONE,
1143  .frame_data = in,
1144  .map = map_frame,
1145  .unmap = unmap_frame,
1146  .discard = discard_frame,
1147  };
1148 
1149  in->opaque = s;
1150  pl_queue_push(input->queue, &src);
1151 
1152  if (!s->fps.num) {
1153  /* Internally queue an output frame for the same PTS */
1154  pts = av_rescale_q(in->pts, inlink->time_base, outlink->time_base);
1155  av_fifo_write(input->out_pts, &pts, 1);
1156 
1157  if (s->send_fields && src.first_field != PL_FIELD_NONE) {
1158  /* Queue the second field for interlaced content */
1159  pts += av_rescale_q(in->duration, inlink->time_base, outlink->time_base) / 2;
1160  av_fifo_write(input->out_pts, &pts, 1);
1161  }
1162  }
1163  }
1164 
1165  if (ret < 0)
1166  return ret;
1167 
1168  if (!input->status && ff_inlink_acknowledge_status(inlink, &status, &pts)) {
1169  pts = av_rescale_q_rnd(pts, inlink->time_base, outlink->time_base,
1170  AV_ROUND_UP);
1171  pl_queue_push(input->queue, NULL); /* Signal EOF to pl_queue */
1172  input->status = status;
1173  input->status_pts = pts;
1174  s->nb_active--;
1175  }
1176 
1177  return 0;
1178 }
1179 
1180 static void drain_input_pts(LibplaceboInput *in, int64_t until)
1181 {
1182  int64_t pts;
1183  while (av_fifo_peek(in->out_pts, &pts, 1, 0) >= 0 && pts <= until)
1184  av_fifo_drain2(in->out_pts, 1);
1185 }
1186 
1188 {
1189  int ret, ok = 0, retry = 0;
1190  LibplaceboContext *s = ctx->priv;
1191  AVFilterLink *outlink = ctx->outputs[0];
1192  FilterLink *outl = ff_filter_link(outlink);
1193  int64_t pts, out_pts;
1194 
1196  pl_log_level_update(s->log, get_log_level());
1197 
1198  for (int i = 0; i < s->nb_inputs; i++) {
1199  if ((ret = handle_input(ctx, &s->inputs[i])) < 0)
1200  return ret;
1201  }
1202 
1203  if (ff_outlink_frame_wanted(outlink)) {
1204  if (s->fps.num) {
1205  out_pts = outl->frame_count_out;
1206  } else {
1207  /* Determine the PTS of the next frame from any active input */
1208  out_pts = INT64_MAX;
1209  for (int i = 0; i < s->nb_inputs; i++) {
1210  LibplaceboInput *in = &s->inputs[i];
1211  if (av_fifo_peek(in->out_pts, &pts, 1, 0) >= 0) {
1212  out_pts = FFMIN(out_pts, pts);
1213  } else if (!in->status) {
1214  ff_inlink_request_frame(ctx->inputs[i]);
1215  retry = true;
1216  }
1217  }
1218 
1219  if (retry) /* some inputs are incomplete */
1220  return 0;
1221  }
1222 
1223  /* Update all input queues to the chosen out_pts */
1224  for (int i = 0; i < s->nb_inputs; i++) {
1225  LibplaceboInput *in = &s->inputs[i];
1226  FilterLink *l = ff_filter_link(outlink);
1227  if (in->status && out_pts >= in->status_pts) {
1228  /* Free up resources which will never be needed again */
1229  pl_renderer_destroy(&in->renderer);
1230  pl_queue_destroy(&in->queue);
1231  in->qstatus = PL_QUEUE_EOF;
1232  continue;
1233  }
1234 
1235  in->qstatus = pl_queue_update(in->queue, &in->mix, pl_queue_params(
1236  .pts = TS2T(out_pts, outlink->time_base),
1237  .radius = pl_frame_mix_radius(&s->opts->params),
1238  .vsync_duration = q2d_fallback(av_inv_q(l->frame_rate), 0.0),
1239  ));
1240 
1241  switch (in->qstatus) {
1242  case PL_QUEUE_MORE:
1243  ff_inlink_request_frame(ctx->inputs[i]);
1244  retry = true;
1245  break;
1246  case PL_QUEUE_OK:
1247  ok |= in->mix.num_frames > 0;
1248  break;
1249  case PL_QUEUE_ERR:
1250  return AVERROR_EXTERNAL;
1251  }
1252  }
1253 
1254  /* In constant FPS mode, we can also output an empty frame if there is
1255  * a gap in the input timeline and we still have active streams */
1256  ok |= s->fps.num && s->nb_active > 0;
1257 
1258  if (retry) {
1259  return 0;
1260  } else if (ok) {
1261  /* Got any valid frame mixes, drain PTS queue and render output */
1262  for (int i = 0; i < s->nb_inputs; i++)
1263  drain_input_pts(&s->inputs[i], out_pts);
1264  return output_frame(ctx, out_pts);
1265  } else if (s->nb_active == 0) {
1266  /* Forward most recent status */
1267  int status = s->inputs[0].status;
1268  int64_t status_pts = s->inputs[0].status_pts;
1269  for (int i = 1; i < s->nb_inputs; i++) {
1270  const LibplaceboInput *in = &s->inputs[i];
1271  if (in->status_pts > status_pts) {
1272  status = s->inputs[i].status;
1273  status_pts = s->inputs[i].status_pts;
1274  }
1275  }
1276  ff_outlink_set_status(outlink, status, status_pts);
1277  return 0;
1278  }
1279 
1280  return AVERROR_BUG;
1281  }
1282 
1283  return FFERROR_NOT_READY;
1284 }
1285 
1287  AVFilterFormatsConfig **cfg_in,
1288  AVFilterFormatsConfig **cfg_out)
1289 {
1290  int err;
1291  const LibplaceboContext *s = ctx->priv;
1292  const AVPixFmtDescriptor *desc = NULL;
1293  AVFilterFormats *infmts = NULL, *outfmts = NULL;
1294 
1295  if (!s->gpu) {
1296  /* Device deferred to config_input (inherit_device): we have no GPU yet
1297  * to enumerate software formats against, and this mode requires Vulkan
1298  * input, so advertise Vulkan only. */
1299  RET(ff_add_format(&infmts, AV_PIX_FMT_VULKAN));
1300  if (s->out_format == AV_PIX_FMT_NONE || av_vkfmt_from_pixfmt(s->out_format))
1301  RET(ff_add_format(&outfmts, AV_PIX_FMT_VULKAN));
1302  goto done;
1303  }
1304 
1305  /* List AV_PIX_FMT_VULKAN first to prefer it when possible */
1306  if (s->have_hwdevice) {
1307  RET(ff_add_format(&infmts, AV_PIX_FMT_VULKAN));
1308  if (s->out_format == AV_PIX_FMT_NONE || av_vkfmt_from_pixfmt(s->out_format))
1309  RET(ff_add_format(&outfmts, AV_PIX_FMT_VULKAN));
1310  }
1311 
1312  while ((desc = av_pix_fmt_desc_next(desc))) {
1314  if (pixfmt == AV_PIX_FMT_VULKAN)
1315  continue; /* Handled above */
1316 
1317  if (!pl_test_pixfmt(s->gpu, pixfmt))
1318  continue;
1319 
1320  RET(ff_add_format(&infmts, pixfmt));
1321 
1322  /* Filter for supported output pixel formats */
1323  if (desc->flags & AV_PIX_FMT_FLAG_BE)
1324  continue; /* BE formats are not supported by pl_download_avframe */
1325 
1326  /* Mask based on user specified format */
1327  if (pixfmt != s->out_format && s->out_format != AV_PIX_FMT_NONE)
1328  continue;
1329 
1330  if (!pl_test_pixfmt_caps(s->gpu, pixfmt, PL_FMT_CAP_RENDERABLE))
1331  continue;
1332 
1333  RET(ff_add_format(&outfmts, pixfmt));
1334  }
1335 
1336 done:
1337 
1338  if (!infmts || !outfmts) {
1339  err = AVERROR(EINVAL);
1340  goto fail;
1341  }
1342 
1343  for (int i = 0; i < s->nb_inputs; i++) {
1344  if (i > 0) {
1345  /* Duplicate the format list for each subsequent input */
1346  infmts = NULL;
1347  for (int n = 0; n < cfg_in[0]->formats->nb_formats; n++)
1348  RET(ff_add_format(&infmts, cfg_in[0]->formats->formats[n]));
1349  }
1350  RET(ff_formats_ref(infmts, &cfg_in[i]->formats));
1351  RET(ff_formats_ref(ff_all_color_spaces(), &cfg_in[i]->color_spaces));
1352  RET(ff_formats_ref(ff_all_color_ranges(), &cfg_in[i]->color_ranges));
1353  RET(ff_formats_ref(ff_all_alpha_modes(), &cfg_in[i]->alpha_modes));
1354  }
1355 
1356  RET(ff_formats_ref(outfmts, &cfg_out[0]->formats));
1357 
1358  outfmts = s->colorspace > 0 ? ff_make_formats_list_singleton(s->colorspace)
1359  : ff_all_color_spaces();
1360  RET(ff_formats_ref(outfmts, &cfg_out[0]->color_spaces));
1361 
1362  outfmts = s->color_range > 0 ? ff_make_formats_list_singleton(s->color_range)
1363  : ff_all_color_ranges();
1364  RET(ff_formats_ref(outfmts, &cfg_out[0]->color_ranges));
1365 
1366  outfmts = s->alpha_mode > 0 ? ff_make_formats_list_singleton(s->alpha_mode)
1367  : ff_all_alpha_modes();
1368  RET(ff_formats_ref(outfmts, &cfg_out[0]->alpha_modes));
1369  return 0;
1370 
1371 fail:
1372  if (infmts && !infmts->refcount)
1373  ff_formats_unref(&infmts);
1374  if (outfmts && !outfmts->refcount)
1375  ff_formats_unref(&outfmts);
1376  return err;
1377 }
1378 
1380 {
1381  AVFilterContext *avctx = inlink->dst;
1382  LibplaceboContext *s = avctx->priv;
1384 
1385  if (s->rotation % PL_ROTATION_180 == PL_ROTATION_90) {
1386  /* Swap width and height for 90 degree rotations to make the size and
1387  * scaling calculations work out correctly */
1388  FFSWAP(int, inlink->w, inlink->h);
1389  if (inlink->sample_aspect_ratio.num)
1390  inlink->sample_aspect_ratio = av_inv_q(inlink->sample_aspect_ratio);
1391  }
1392 
1393  /* Deferred Vulkan setup (inherit_device): the device was not created at
1394  * init; adopt the one the input frames live on. query_formats advertised
1395  * Vulkan only, so a non-Vulkan input here is a configuration error. */
1396  if (!s->gpu) {
1397  AVHWFramesContext *hwfc;
1398  int err;
1399  av_assert0(s->inherit_device);
1400  if (inlink->format != AV_PIX_FMT_VULKAN || !l->hw_frames_ctx) {
1401  av_log(avctx, AV_LOG_ERROR, "inherit_device requires a Vulkan "
1402  "hardware frames context on the input.\n");
1403  return AVERROR(EINVAL);
1404  }
1405  hwfc = (AVHWFramesContext *) l->hw_frames_ctx->data;
1406  av_buffer_unref(&avctx->hw_device_ctx);
1407  avctx->hw_device_ctx = av_buffer_ref(hwfc->device_ref);
1408  if (!avctx->hw_device_ctx)
1409  return AVERROR(ENOMEM);
1410  if ((err = init_vulkan(avctx, hwfc->device_ctx->hwctx)) < 0)
1411  return err;
1412  }
1413 
1414  if (inlink->format == AV_PIX_FMT_VULKAN)
1416 
1417  /* Forward this to the vkctx for format selection */
1418  s->vkctx.input_format = inlink->format;
1419 
1420  return 0;
1421 }
1422 
1424 {
1425  return av_cmp_q(a, b) < 0 ? b : a;
1426 }
1427 
1429 {
1430  int err;
1431  FilterLink *l = ff_filter_link(outlink);
1432  AVFilterContext *avctx = outlink->src;
1433  LibplaceboContext *s = avctx->priv;
1434  AVFilterLink *inlink = outlink->src->inputs[0];
1435  FilterLink *ol = ff_filter_link(outlink);
1437  const AVPixFmtDescriptor *out_desc = av_pix_fmt_desc_get(outlink->format);
1438  AVHWFramesContext *hwfc;
1439  AVVulkanFramesContext *vkfc;
1440 
1441  /* Frame dimensions */
1442  RET(ff_scale_eval_dimensions(s, s->w_expr, s->h_expr, inlink, outlink,
1443  &outlink->w, &outlink->h));
1444 
1445  s->reset_sar |= s->normalize_sar || s->nb_inputs > 1;
1446  double sar_in = q2d_fallback(inlink->sample_aspect_ratio, 1.0);
1447 
1448  int force_oar = s->force_original_aspect_ratio;
1449  if (!force_oar && s->fit_sense == FIT_CONSTRAINT) {
1450  if (s->fit_mode == FIT_CONTAIN || s->fit_mode == FIT_SCALE_DOWN) {
1451  force_oar = SCALE_FORCE_OAR_DECREASE;
1452  } else if (s->fit_mode == FIT_COVER) {
1453  force_oar = SCALE_FORCE_OAR_INCREASE;
1454  }
1455  }
1456 
1457  RET(ff_scale_adjust_dimensions(inlink, &outlink->w, &outlink->h,
1458  force_oar, s->force_divisible_by,
1459  s->reset_sar ? sar_in : 1.0));
1460 
1461  if (s->fit_mode == FIT_SCALE_DOWN && s->fit_sense == FIT_CONSTRAINT) {
1462  int w_adj = s->reset_sar ? sar_in * inlink->w : inlink->w;
1463  outlink->w = FFMIN(outlink->w, w_adj);
1464  outlink->h = FFMIN(outlink->h, inlink->h);
1465  }
1466 
1467  if (s->nb_inputs > 1 && !s->disable_fbos) {
1468  /* Create a separate renderer and composition texture */
1469  const enum pl_fmt_caps caps = PL_FMT_CAP_BLENDABLE | PL_FMT_CAP_BLITTABLE;
1470  pl_fmt fmt = pl_find_fmt(s->gpu, PL_FMT_FLOAT, 4, 16, 0, caps);
1471  bool ok = !!fmt;
1472  if (ok) {
1473  ok = pl_tex_recreate(s->gpu, &s->linear_tex, pl_tex_params(
1474  .format = fmt,
1475  .w = outlink->w,
1476  .h = outlink->h,
1477  .blit_dst = true,
1478  .renderable = true,
1479  .sampleable = true,
1480  .storable = fmt->caps & PL_FMT_CAP_STORABLE,
1481  ));
1482  }
1483 
1484  if (!ok) {
1485  av_log(avctx, AV_LOG_WARNING, "Failed to create a linear texture "
1486  "for compositing multiple inputs, falling back to non-linear "
1487  "blending.\n");
1488  }
1489  }
1490 
1491  if (s->reset_sar) {
1492  /* SAR is normalized, or we have multiple inputs, set out to 1:1 */
1493  outlink->sample_aspect_ratio = (AVRational){ 1, 1 };
1494  } else if (inlink->sample_aspect_ratio.num && s->fit_mode == FIT_FILL) {
1495  /* This is consistent with other scale_* filters, which only
1496  * set the outlink SAR to be equal to the scale SAR iff the input SAR
1497  * was set to something nonzero */
1498  const AVRational ar_in = { inlink->w, inlink->h };
1499  const AVRational ar_out = { outlink->w, outlink->h };
1500  const AVRational stretch = av_div_q(ar_in, ar_out);
1501  outlink->sample_aspect_ratio = av_mul_q(inlink->sample_aspect_ratio, stretch);
1502  } else {
1503  outlink->sample_aspect_ratio = inlink->sample_aspect_ratio;
1504  }
1505 
1506  /* Frame rate */
1507  if (s->fps.num) {
1508  ol->frame_rate = s->fps;
1509  outlink->time_base = av_inv_q(s->fps);
1510  } else {
1511  FilterLink *il = ff_filter_link(avctx->inputs[0]);
1512  ol->frame_rate = il->frame_rate;
1513  outlink->time_base = avctx->inputs[0]->time_base;
1514  for (int i = 1; i < s->nb_inputs; i++) {
1515  il = ff_filter_link(avctx->inputs[i]);
1516  ol->frame_rate = max_q(ol->frame_rate, il->frame_rate);
1517  outlink->time_base = av_gcd_q(outlink->time_base,
1518  avctx->inputs[i]->time_base,
1520  }
1521 
1522  if (s->deinterlace && s->send_fields) {
1523  const AVRational q2 = { 2, 1 };
1524  ol->frame_rate = av_mul_q(ol->frame_rate, q2);
1525  /* Ensure output frame timestamps are divisible by two */
1526  outlink->time_base = av_div_q(outlink->time_base, q2);
1527  }
1528  }
1529 
1530  /* Static variables */
1531  s->var_values[VAR_OUT_W] = s->var_values[VAR_OW] = outlink->w;
1532  s->var_values[VAR_OUT_H] = s->var_values[VAR_OH] = outlink->h;
1533  s->var_values[VAR_DAR] = q2d_fallback(outlink->sample_aspect_ratio, 1.0);
1534  s->var_values[VAR_HSUB] = 1 << desc->log2_chroma_w;
1535  s->var_values[VAR_VSUB] = 1 << desc->log2_chroma_h;
1536  s->var_values[VAR_OHSUB] = 1 << out_desc->log2_chroma_w;
1537  s->var_values[VAR_OVSUB] = 1 << out_desc->log2_chroma_h;
1538 
1539  if (outlink->format != AV_PIX_FMT_VULKAN)
1540  return 0;
1541 
1542  s->vkctx.output_width = outlink->w;
1543  s->vkctx.output_height = outlink->h;
1544  /* Default to reusing the input format */
1545  if (s->out_format == AV_PIX_FMT_NONE || s->out_format == AV_PIX_FMT_VULKAN) {
1546  s->vkctx.output_format = s->vkctx.input_format;
1547  } else {
1548  s->vkctx.output_format = s->out_format;
1549  }
1550  RET(ff_vk_filter_config_output(outlink));
1551  hwfc = (AVHWFramesContext *)l->hw_frames_ctx->data;
1552  vkfc = hwfc->hwctx;
1553  vkfc->usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
1554 
1555  return 0;
1556 
1557 fail:
1558  return err;
1559 }
1560 
1561 #define OFFSET(x) offsetof(LibplaceboContext, x)
1562 #define STATIC (AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM)
1563 #define DYNAMIC (STATIC | AV_OPT_FLAG_RUNTIME_PARAM)
1564 
1565 static const AVOption libplacebo_options[] = {
1566  { "inputs", "Number of inputs", OFFSET(nb_inputs), AV_OPT_TYPE_INT, {.i64 = 1}, 1, INT_MAX, .flags = STATIC },
1567  { "inherit_device", "Inherit the Vulkan device from the input's hardware frames context",
1568  OFFSET(inherit_device), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, .flags = STATIC },
1569  { "w", "Output video frame width", OFFSET(w_expr), AV_OPT_TYPE_STRING, {.str = "iw"}, .flags = STATIC },
1570  { "h", "Output video frame height", OFFSET(h_expr), AV_OPT_TYPE_STRING, {.str = "ih"}, .flags = STATIC },
1571  { "fps", "Output video frame rate", OFFSET(fps_string), AV_OPT_TYPE_STRING, {.str = "none"}, .flags = STATIC },
1572  { "crop_x", "Input video crop x", OFFSET(crop_x_expr), AV_OPT_TYPE_STRING, {.str = "(iw-cw)/2"}, .flags = DYNAMIC },
1573  { "crop_y", "Input video crop y", OFFSET(crop_y_expr), AV_OPT_TYPE_STRING, {.str = "(ih-ch)/2"}, .flags = DYNAMIC },
1574  { "crop_w", "Input video crop w", OFFSET(crop_w_expr), AV_OPT_TYPE_STRING, {.str = "iw"}, .flags = DYNAMIC },
1575  { "crop_h", "Input video crop h", OFFSET(crop_h_expr), AV_OPT_TYPE_STRING, {.str = "ih"}, .flags = DYNAMIC },
1576  { "pos_x", "Output video placement x", OFFSET(pos_x_expr), AV_OPT_TYPE_STRING, {.str = "(ow-pw)/2"}, .flags = DYNAMIC },
1577  { "pos_y", "Output video placement y", OFFSET(pos_y_expr), AV_OPT_TYPE_STRING, {.str = "(oh-ph)/2"}, .flags = DYNAMIC },
1578  { "pos_w", "Output video placement w", OFFSET(pos_w_expr), AV_OPT_TYPE_STRING, {.str = "ow"}, .flags = DYNAMIC },
1579  { "pos_h", "Output video placement h", OFFSET(pos_h_expr), AV_OPT_TYPE_STRING, {.str = "oh"}, .flags = DYNAMIC },
1580  { "format", "Output video format", OFFSET(out_format_string), AV_OPT_TYPE_STRING, .flags = STATIC },
1581  { "force_original_aspect_ratio", "decrease or increase w/h if necessary to keep the original AR", OFFSET(force_original_aspect_ratio), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, SCALE_FORCE_OAR_NB-1, STATIC, .unit = "force_oar" },
1582  { "disable", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = SCALE_FORCE_OAR_DISABLE }, 0, 0, STATIC, .unit = "force_oar" },
1583  { "decrease", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = SCALE_FORCE_OAR_DECREASE }, 0, 0, STATIC, .unit = "force_oar" },
1584  { "increase", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = SCALE_FORCE_OAR_INCREASE }, 0, 0, STATIC, .unit = "force_oar" },
1585  { "force_divisible_by", "enforce that the output resolution is divisible by a defined integer when force_original_aspect_ratio is used", OFFSET(force_divisible_by), AV_OPT_TYPE_INT, { .i64 = 1 }, 1, 256, STATIC },
1586  { "reset_sar", "force SAR normalization to 1:1 by adjusting pos_x/y/w/h", OFFSET(reset_sar), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, STATIC },
1587  { "normalize_sar", "like reset_sar, but pad/crop instead of stretching the video", OFFSET(normalize_sar), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, STATIC },
1588  { "pad_crop_ratio", "ratio between padding and cropping when normalizing SAR (0=pad, 1=crop)", OFFSET(pad_crop_ratio), AV_OPT_TYPE_FLOAT, {.dbl=0.0}, 0.0, 1.0, DYNAMIC },
1589  { "fit_mode", "Content fit strategy for placing input layers in the output", OFFSET(fit_mode), AV_OPT_TYPE_INT, {.i64 = FIT_FILL }, 0, FIT_MODE_NB - 1, STATIC, .unit = "fit_mode" },
1590  { "fill", "Stretch content, ignoring aspect ratio", 0, AV_OPT_TYPE_CONST, {.i64 = FIT_FILL }, 0, 0, STATIC, .unit = "fit_mode" },
1591  { "contain", "Stretch content, padding to preserve aspect", 0, AV_OPT_TYPE_CONST, {.i64 = FIT_CONTAIN }, 0, 0, STATIC, .unit = "fit_mode" },
1592  { "cover", "Stretch content, cropping to preserve aspect", 0, AV_OPT_TYPE_CONST, {.i64 = FIT_COVER }, 0, 0, STATIC, .unit = "fit_mode" },
1593  { "none", "Keep input unscaled, padding and cropping as needed", 0, AV_OPT_TYPE_CONST, {.i64 = FIT_NONE }, 0, 0, STATIC, .unit = "fit_mode" },
1594  { "place", "Keep input unscaled, padding and cropping as needed", 0, AV_OPT_TYPE_CONST, {.i64 = FIT_NONE }, 0, 0, STATIC, .unit = "fit_mode" },
1595  { "scale_down", "Downscale only if larger, padding to preserve aspect", 0, AV_OPT_TYPE_CONST, {.i64 = FIT_SCALE_DOWN }, 0, 0, STATIC, .unit = "fit_mode" },
1596  { "fit_sense", "Output size strategy (for the base layer only)", OFFSET(fit_sense), AV_OPT_TYPE_INT, {.i64 = FIT_TARGET }, 0, FIT_SENSE_NB - 1, STATIC, .unit = "fit_sense" },
1597  { "target", "Computed resolution is the exact output size", 0, AV_OPT_TYPE_CONST, {.i64 = FIT_TARGET }, 0, 0, STATIC, .unit = "fit_sense" },
1598  { "constraint", "Computed resolution constrains the output size", 0, AV_OPT_TYPE_CONST, {.i64 = FIT_CONSTRAINT }, 0, 0, STATIC, .unit = "fit_sense" },
1599  { "fillcolor", "Background fill color", OFFSET(fillcolor), AV_OPT_TYPE_COLOR, {.str = "black@0"}, .flags = DYNAMIC },
1600  { "corner_rounding", "Corner rounding radius", OFFSET(corner_rounding), AV_OPT_TYPE_FLOAT, {.dbl = 0.0}, 0.0, 1.0, .flags = DYNAMIC },
1601  { "lut", "Path to custom LUT file to apply", OFFSET(lut_filename), AV_OPT_TYPE_STRING, { .str = NULL }, .flags = STATIC },
1602  { "lut_type", "Application mode of the custom LUT", OFFSET(lut_type), AV_OPT_TYPE_INT, { .i64 = PL_LUT_UNKNOWN }, 0, PL_LUT_CONVERSION, STATIC, .unit = "lut_type" },
1603  { "auto", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = PL_LUT_UNKNOWN }, 0, 0, STATIC, .unit = "lut_type" },
1604  { "native", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = PL_LUT_NATIVE }, 0, 0, STATIC, .unit = "lut_type" },
1605  { "normalized", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = PL_LUT_NORMALIZED }, 0, 0, STATIC, .unit = "lut_type" },
1606  { "conversion", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = PL_LUT_CONVERSION }, 0, 0, STATIC, .unit = "lut_type" },
1607 
1608  { "extra_opts", "Pass extra libplacebo-specific options using a :-separated list of key=value pairs", OFFSET(extra_opts), AV_OPT_TYPE_DICT, .flags = DYNAMIC },
1609  { "shader_cache", "Set shader cache path", OFFSET(shader_cache), AV_OPT_TYPE_STRING, {.str = NULL}, .flags = STATIC },
1610 
1611  {"colorspace", "select colorspace", OFFSET(colorspace), AV_OPT_TYPE_INT, {.i64=-1}, -1, AVCOL_SPC_NB-1, DYNAMIC, .unit = "colorspace"},
1612  {"auto", "keep the same colorspace", 0, AV_OPT_TYPE_CONST, {.i64=-1}, INT_MIN, INT_MAX, STATIC, .unit = "colorspace"},
1613  {"gbr", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_SPC_RGB}, INT_MIN, INT_MAX, STATIC, .unit = "colorspace"},
1614  {"bt709", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_SPC_BT709}, INT_MIN, INT_MAX, STATIC, .unit = "colorspace"},
1615  {"unknown", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_SPC_UNSPECIFIED}, INT_MIN, INT_MAX, STATIC, .unit = "colorspace"},
1616  {"bt470bg", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_SPC_BT470BG}, INT_MIN, INT_MAX, STATIC, .unit = "colorspace"},
1617  {"smpte170m", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_SPC_SMPTE170M}, INT_MIN, INT_MAX, STATIC, .unit = "colorspace"},
1618  {"smpte240m", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_SPC_SMPTE240M}, INT_MIN, INT_MAX, STATIC, .unit = "colorspace"},
1619  {"ycgco", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_SPC_YCGCO}, INT_MIN, INT_MAX, STATIC, .unit = "colorspace"},
1620  {"bt2020nc", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_SPC_BT2020_NCL}, INT_MIN, INT_MAX, STATIC, .unit = "colorspace"},
1621  {"bt2020c", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_SPC_BT2020_CL}, INT_MIN, INT_MAX, STATIC, .unit = "colorspace"},
1622  {"ictcp", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_SPC_ICTCP}, INT_MIN, INT_MAX, STATIC, .unit = "colorspace"},
1623 
1624  {"range", "select color range", OFFSET(color_range), AV_OPT_TYPE_INT, {.i64=-1}, -1, AVCOL_RANGE_NB-1, DYNAMIC, .unit = "range"},
1625  {"auto", "keep the same color range", 0, AV_OPT_TYPE_CONST, {.i64=-1}, 0, 0, STATIC, .unit = "range"},
1626  {"unspecified", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_RANGE_UNSPECIFIED}, 0, 0, STATIC, .unit = "range"},
1627  {"unknown", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_RANGE_UNSPECIFIED}, 0, 0, STATIC, .unit = "range"},
1628  {"limited", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_RANGE_MPEG}, 0, 0, STATIC, .unit = "range"},
1629  {"tv", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_RANGE_MPEG}, 0, 0, STATIC, .unit = "range"},
1630  {"mpeg", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_RANGE_MPEG}, 0, 0, STATIC, .unit = "range"},
1631  {"full", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_RANGE_JPEG}, 0, 0, STATIC, .unit = "range"},
1632  {"pc", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_RANGE_JPEG}, 0, 0, STATIC, .unit = "range"},
1633  {"jpeg", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_RANGE_JPEG}, 0, 0, STATIC, .unit = "range"},
1634 
1635  {"color_primaries", "select color primaries", OFFSET(color_primaries), AV_OPT_TYPE_INT, {.i64=-1}, -1, AVCOL_PRI_EXT_NB-1, DYNAMIC, .unit = "color_primaries"},
1636  {"auto", "keep the same color primaries", 0, AV_OPT_TYPE_CONST, {.i64=-1}, INT_MIN, INT_MAX, STATIC, .unit = "color_primaries"},
1637  {"bt709", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_PRI_BT709}, INT_MIN, INT_MAX, STATIC, .unit = "color_primaries"},
1638  {"unknown", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_PRI_UNSPECIFIED}, INT_MIN, INT_MAX, STATIC, .unit = "color_primaries"},
1639  {"bt470m", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_PRI_BT470M}, INT_MIN, INT_MAX, STATIC, .unit = "color_primaries"},
1640  {"bt470bg", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_PRI_BT470BG}, INT_MIN, INT_MAX, STATIC, .unit = "color_primaries"},
1641  {"smpte170m", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_PRI_SMPTE170M}, INT_MIN, INT_MAX, STATIC, .unit = "color_primaries"},
1642  {"smpte240m", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_PRI_SMPTE240M}, INT_MIN, INT_MAX, STATIC, .unit = "color_primaries"},
1643  {"film", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_PRI_FILM}, INT_MIN, INT_MAX, STATIC, .unit = "color_primaries"},
1644  {"bt2020", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_PRI_BT2020}, INT_MIN, INT_MAX, STATIC, .unit = "color_primaries"},
1645  {"smpte428", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_PRI_SMPTE428}, INT_MIN, INT_MAX, STATIC, .unit = "color_primaries"},
1646  {"smpte431", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_PRI_SMPTE431}, INT_MIN, INT_MAX, STATIC, .unit = "color_primaries"},
1647  {"smpte432", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_PRI_SMPTE432}, INT_MIN, INT_MAX, STATIC, .unit = "color_primaries"},
1648  {"jedec-p22", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_PRI_JEDEC_P22}, INT_MIN, INT_MAX, STATIC, .unit = "color_primaries"},
1649  {"ebu3213", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_PRI_EBU3213}, INT_MIN, INT_MAX, STATIC, .unit = "color_primaries"},
1650  {"vgamut", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_PRI_V_GAMUT}, INT_MIN, INT_MAX, STATIC, .unit = "color_primaries"},
1651 
1652  {"color_trc", "select color transfer", OFFSET(color_trc), AV_OPT_TYPE_INT, {.i64=-1}, -1, AVCOL_TRC_EXT_NB-1, DYNAMIC, .unit = "color_trc"},
1653  {"auto", "keep the same color transfer", 0, AV_OPT_TYPE_CONST, {.i64=-1}, INT_MIN, INT_MAX, STATIC, .unit = "color_trc"},
1654  {"bt709", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_BT709}, INT_MIN, INT_MAX, STATIC, .unit = "color_trc"},
1655  {"unknown", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_UNSPECIFIED}, INT_MIN, INT_MAX, STATIC, .unit = "color_trc"},
1656  {"gamma22", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_GAMMA22}, INT_MIN, INT_MAX, STATIC, .unit = "color_trc"},
1657  {"bt470m", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_GAMMA22}, INT_MIN, INT_MAX, STATIC, .unit = "color_trc"},
1658  {"gamma28", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_GAMMA28}, INT_MIN, INT_MAX, STATIC, .unit = "color_trc"},
1659  {"bt470bg", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_GAMMA28}, INT_MIN, INT_MAX, STATIC, .unit = "color_trc"},
1660  {"smpte170m", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_SMPTE170M}, INT_MIN, INT_MAX, STATIC, .unit = "color_trc"},
1661  {"smpte240m", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_SMPTE240M}, INT_MIN, INT_MAX, STATIC, .unit = "color_trc"},
1662  {"linear", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_LINEAR}, INT_MIN, INT_MAX, STATIC, .unit = "color_trc"},
1663  {"iec61966-2-4", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_IEC61966_2_4}, INT_MIN, INT_MAX, STATIC, .unit = "color_trc"},
1664  {"bt1361e", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_BT1361_ECG}, INT_MIN, INT_MAX, STATIC, .unit = "color_trc"},
1665  {"iec61966-2-1", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_IEC61966_2_1}, INT_MIN, INT_MAX, STATIC, .unit = "color_trc"},
1666  {"bt2020-10", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_BT2020_10}, INT_MIN, INT_MAX, STATIC, .unit = "color_trc"},
1667  {"bt2020-12", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_BT2020_12}, INT_MIN, INT_MAX, STATIC, .unit = "color_trc"},
1668  {"smpte2084", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_SMPTE2084}, INT_MIN, INT_MAX, STATIC, .unit = "color_trc"},
1669  {"arib-std-b67", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_ARIB_STD_B67}, INT_MIN, INT_MAX, STATIC, .unit = "color_trc"},
1670  {"vlog", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_V_LOG}, INT_MIN, INT_MAX, STATIC, .unit = "color_trc"},
1671 
1672  {"chroma_location", "select chroma location", OFFSET(chroma_location), AV_OPT_TYPE_INT, {.i64=-1}, -1, AVCHROMA_LOC_NB-1, DYNAMIC, .unit = "chroma_location"},
1673  {"auto", "keep the same chroma location", 0, AV_OPT_TYPE_CONST, {.i64=-1}, 0, 0, STATIC, .unit = "chroma_location"},
1674  {"unspecified", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCHROMA_LOC_UNSPECIFIED}, 0, 0, STATIC, .unit = "chroma_location"},
1675  {"unknown", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCHROMA_LOC_UNSPECIFIED}, 0, 0, STATIC, .unit = "chroma_location"},
1676  {"left", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCHROMA_LOC_LEFT}, 0, 0, STATIC, .unit = "chroma_location"},
1677  {"center", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCHROMA_LOC_CENTER}, 0, 0, STATIC, .unit = "chroma_location"},
1678  {"topleft", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCHROMA_LOC_TOPLEFT}, 0, 0, STATIC, .unit = "chroma_location"},
1679  {"top", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCHROMA_LOC_TOP}, 0, 0, STATIC, .unit = "chroma_location"},
1680  {"bottomleft", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCHROMA_LOC_BOTTOMLEFT}, 0, 0, STATIC, .unit = "chroma_location"},
1681  {"bottom", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCHROMA_LOC_BOTTOM}, 0, 0, STATIC, .unit = "chroma_location"},
1682 
1683  {"rotate", "rotate the input clockwise", OFFSET(rotation), AV_OPT_TYPE_INT, {.i64=PL_ROTATION_0}, PL_ROTATION_0, PL_ROTATION_360, DYNAMIC, .unit = "rotation"},
1684  {"0", NULL, 0, AV_OPT_TYPE_CONST, {.i64=PL_ROTATION_0}, .flags = STATIC, .unit = "rotation"},
1685  {"90", NULL, 0, AV_OPT_TYPE_CONST, {.i64=PL_ROTATION_90}, .flags = STATIC, .unit = "rotation"},
1686  {"180", NULL, 0, AV_OPT_TYPE_CONST, {.i64=PL_ROTATION_180}, .flags = STATIC, .unit = "rotation"},
1687  {"270", NULL, 0, AV_OPT_TYPE_CONST, {.i64=PL_ROTATION_270}, .flags = STATIC, .unit = "rotation"},
1688  {"360", NULL, 0, AV_OPT_TYPE_CONST, {.i64=PL_ROTATION_360}, .flags = STATIC, .unit = "rotation"},
1689 
1690  {"alpha_mode", "select alpha moda", OFFSET(alpha_mode), AV_OPT_TYPE_INT, {.i64=-1}, -1, AVALPHA_MODE_NB-1, DYNAMIC, .unit = "alpha_mode"},
1691  {"auto", "keep the same alpha mode", 0, AV_OPT_TYPE_CONST, {.i64=-1}, 0, 0, DYNAMIC, .unit = "alpha_mode"},
1692  {"unspecified", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVALPHA_MODE_UNSPECIFIED}, 0, 0, DYNAMIC, .unit = "alpha_mode"},
1693  {"unknown", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVALPHA_MODE_UNSPECIFIED}, 0, 0, DYNAMIC, .unit = "alpha_mode"},
1694  {"premultiplied", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVALPHA_MODE_PREMULTIPLIED}, 0, 0, DYNAMIC, .unit = "alpha_mode"},
1695  {"straight", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVALPHA_MODE_STRAIGHT}, 0, 0, DYNAMIC, .unit = "alpha_mode"},
1696 
1697  { "upscaler", "Upscaler function", OFFSET(upscaler), AV_OPT_TYPE_STRING, {.str = "spline36"}, .flags = DYNAMIC },
1698  { "downscaler", "Downscaler function", OFFSET(downscaler), AV_OPT_TYPE_STRING, {.str = "mitchell"}, .flags = DYNAMIC },
1699  { "frame_mixer", "Frame mixing function", OFFSET(frame_mixer), AV_OPT_TYPE_STRING, {.str = "none"}, .flags = DYNAMIC },
1700  { "antiringing", "Antiringing strength (for non-EWA filters)", OFFSET(antiringing), AV_OPT_TYPE_FLOAT, {.dbl = 0.0}, 0.0, 1.0, DYNAMIC },
1701  { "sigmoid", "Enable sigmoid upscaling", OFFSET(sigmoid), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, DYNAMIC },
1702  { "apply_filmgrain", "Apply film grain metadata", OFFSET(apply_filmgrain), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, DYNAMIC },
1703  { "apply_dolbyvision", "Apply Dolby Vision metadata", OFFSET(apply_dovi), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, DYNAMIC },
1704 
1705  { "deinterlace", "Deinterlacing mode", OFFSET(deinterlace), AV_OPT_TYPE_INT, {.i64 = PL_DEINTERLACE_WEAVE}, 0, PL_DEINTERLACE_ALGORITHM_COUNT - 1, DYNAMIC, .unit = "deinterlace" },
1706  { "weave", "Weave fields together (no-op)", 0, AV_OPT_TYPE_CONST, {.i64 = PL_DEINTERLACE_WEAVE}, 0, 0, STATIC, .unit = "deinterlace" },
1707  { "bob", "Naive bob deinterlacing", 0, AV_OPT_TYPE_CONST, {.i64 = PL_DEINTERLACE_BOB}, 0, 0, STATIC, .unit = "deinterlace" },
1708  { "yadif", "Yet another deinterlacing filter", 0, AV_OPT_TYPE_CONST, {.i64 = PL_DEINTERLACE_YADIF}, 0, 0, STATIC, .unit = "deinterlace" },
1709 #if PL_API_VER >= 353
1710  { "bwdif", "Bob weaver deinterlacing filter", 0, AV_OPT_TYPE_CONST, {.i64 = PL_DEINTERLACE_BWDIF}, 0, 0, STATIC, .unit = "deinterlace" },
1711 #endif
1712  { "skip_spatial_check", "Skip yadif spatial check", OFFSET(skip_spatial_check), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, DYNAMIC },
1713  { "send_fields", "Output a frame for each field", OFFSET(send_fields), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, DYNAMIC },
1714 
1715  { "deband", "Enable debanding", OFFSET(deband), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, DYNAMIC },
1716  { "deband_iterations", "Deband iterations", OFFSET(deband_iterations), AV_OPT_TYPE_INT, {.i64 = 1}, 0, 16, DYNAMIC },
1717  { "deband_threshold", "Deband threshold", OFFSET(deband_threshold), AV_OPT_TYPE_FLOAT, {.dbl = 4.0}, 0.0, 1024.0, DYNAMIC },
1718  { "deband_radius", "Deband radius", OFFSET(deband_radius), AV_OPT_TYPE_FLOAT, {.dbl = 16.0}, 0.0, 1024.0, DYNAMIC },
1719  { "deband_grain", "Deband grain", OFFSET(deband_grain), AV_OPT_TYPE_FLOAT, {.dbl = 6.0}, 0.0, 1024.0, DYNAMIC },
1720 
1721  { "brightness", "Brightness boost", OFFSET(brightness), AV_OPT_TYPE_FLOAT, {.dbl = 0.0}, -1.0, 1.0, DYNAMIC },
1722  { "contrast", "Contrast gain", OFFSET(contrast), AV_OPT_TYPE_FLOAT, {.dbl = 1.0}, 0.0, 16.0, DYNAMIC },
1723  { "saturation", "Saturation gain", OFFSET(saturation), AV_OPT_TYPE_FLOAT, {.dbl = 1.0}, 0.0, 16.0, DYNAMIC },
1724  { "hue", "Hue shift", OFFSET(hue), AV_OPT_TYPE_FLOAT, {.dbl = 0.0}, -M_PI, M_PI, DYNAMIC },
1725  { "gamma", "Gamma adjustment", OFFSET(gamma), AV_OPT_TYPE_FLOAT, {.dbl = 1.0}, 0.0, 16.0, DYNAMIC },
1726  { "temperature", "Color temperature adjustment (kelvin)", OFFSET(temperature), AV_OPT_TYPE_FLOAT, {.dbl = 6500.0}, 1667.0, 25000.0, DYNAMIC },
1727 
1728  { "peak_detect", "Enable dynamic peak detection for HDR tone-mapping", OFFSET(peakdetect), AV_OPT_TYPE_BOOL, {.i64 = 1}, 0, 1, DYNAMIC },
1729  { "smoothing_period", "Peak detection smoothing period", OFFSET(smoothing), AV_OPT_TYPE_FLOAT, {.dbl = 20.0}, 0.0, 1000.0, DYNAMIC },
1730  { "scene_threshold_low", "Scene change low threshold", OFFSET(scene_low), AV_OPT_TYPE_FLOAT, {.dbl = 1.0}, -1.0, 100.0, DYNAMIC },
1731  { "scene_threshold_high", "Scene change high threshold", OFFSET(scene_high), AV_OPT_TYPE_FLOAT, {.dbl = 3.0}, -1.0, 100.0, DYNAMIC },
1732  { "percentile", "Peak detection percentile", OFFSET(percentile), AV_OPT_TYPE_FLOAT, {.dbl = 99.995}, 0.0, 100.0, DYNAMIC },
1733 
1734  { "gamut_mode", "Gamut-mapping mode", OFFSET(gamut_mode), AV_OPT_TYPE_INT, {.i64 = GAMUT_MAP_PERCEPTUAL}, 0, GAMUT_MAP_COUNT - 1, DYNAMIC, .unit = "gamut_mode" },
1735  { "clip", "Hard-clip (RGB per-channel)", 0, AV_OPT_TYPE_CONST, {.i64 = GAMUT_MAP_CLIP}, 0, 0, STATIC, .unit = "gamut_mode" },
1736  { "perceptual", "Colorimetric soft clipping", 0, AV_OPT_TYPE_CONST, {.i64 = GAMUT_MAP_PERCEPTUAL}, 0, 0, STATIC, .unit = "gamut_mode" },
1737  { "relative", "Relative colorimetric clipping", 0, AV_OPT_TYPE_CONST, {.i64 = GAMUT_MAP_RELATIVE}, 0, 0, STATIC, .unit = "gamut_mode" },
1738  { "saturation", "Saturation mapping (RGB -> RGB)", 0, AV_OPT_TYPE_CONST, {.i64 = GAMUT_MAP_SATURATION}, 0, 0, STATIC, .unit = "gamut_mode" },
1739  { "absolute", "Absolute colorimetric clipping", 0, AV_OPT_TYPE_CONST, {.i64 = GAMUT_MAP_ABSOLUTE}, 0, 0, STATIC, .unit = "gamut_mode" },
1740  { "desaturate", "Colorimetrically desaturate colors towards white", 0, AV_OPT_TYPE_CONST, {.i64 = GAMUT_MAP_DESATURATE}, 0, 0, STATIC, .unit = "gamut_mode" },
1741  { "darken", "Colorimetric clip with bias towards darkening image to fit gamut", 0, AV_OPT_TYPE_CONST, {.i64 = GAMUT_MAP_DARKEN}, 0, 0, STATIC, .unit = "gamut_mode" },
1742  { "warn", "Highlight out-of-gamut colors", 0, AV_OPT_TYPE_CONST, {.i64 = GAMUT_MAP_HIGHLIGHT}, 0, 0, STATIC, .unit = "gamut_mode" },
1743  { "linear", "Linearly reduce chromaticity to fit gamut", 0, AV_OPT_TYPE_CONST, {.i64 = GAMUT_MAP_LINEAR}, 0, 0, STATIC, .unit = "gamut_mode" },
1744  { "tonemapping", "Tone-mapping algorithm", OFFSET(tonemapping), AV_OPT_TYPE_INT, {.i64 = TONE_MAP_AUTO}, 0, TONE_MAP_COUNT - 1, DYNAMIC, .unit = "tonemap" },
1745  { "auto", "Automatic selection", 0, AV_OPT_TYPE_CONST, {.i64 = TONE_MAP_AUTO}, 0, 0, STATIC, .unit = "tonemap" },
1746  { "clip", "No tone mapping (clip", 0, AV_OPT_TYPE_CONST, {.i64 = TONE_MAP_CLIP}, 0, 0, STATIC, .unit = "tonemap" },
1747  { "st2094-40", "SMPTE ST 2094-40", 0, AV_OPT_TYPE_CONST, {.i64 = TONE_MAP_ST2094_40}, 0, 0, STATIC, .unit = "tonemap" },
1748  { "st2094-10", "SMPTE ST 2094-10", 0, AV_OPT_TYPE_CONST, {.i64 = TONE_MAP_ST2094_10}, 0, 0, STATIC, .unit = "tonemap" },
1749  { "bt.2390", "ITU-R BT.2390 EETF", 0, AV_OPT_TYPE_CONST, {.i64 = TONE_MAP_BT2390}, 0, 0, STATIC, .unit = "tonemap" },
1750  { "bt.2446a", "ITU-R BT.2446 Method A", 0, AV_OPT_TYPE_CONST, {.i64 = TONE_MAP_BT2446A}, 0, 0, STATIC, .unit = "tonemap" },
1751  { "spline", "Single-pivot polynomial spline", 0, AV_OPT_TYPE_CONST, {.i64 = TONE_MAP_SPLINE}, 0, 0, STATIC, .unit = "tonemap" },
1752  { "reinhard", "Reinhard", 0, AV_OPT_TYPE_CONST, {.i64 = TONE_MAP_REINHARD}, 0, 0, STATIC, .unit = "tonemap" },
1753  { "mobius", "Mobius", 0, AV_OPT_TYPE_CONST, {.i64 = TONE_MAP_MOBIUS}, 0, 0, STATIC, .unit = "tonemap" },
1754  { "hable", "Filmic tone-mapping (Hable)", 0, AV_OPT_TYPE_CONST, {.i64 = TONE_MAP_HABLE}, 0, 0, STATIC, .unit = "tonemap" },
1755  { "gamma", "Gamma function with knee", 0, AV_OPT_TYPE_CONST, {.i64 = TONE_MAP_GAMMA}, 0, 0, STATIC, .unit = "tonemap" },
1756  { "linear", "Perceptually linear stretch", 0, AV_OPT_TYPE_CONST, {.i64 = TONE_MAP_LINEAR}, 0, 0, STATIC, .unit = "tonemap" },
1757  { "tonemapping_param", "Tunable parameter for some tone-mapping functions", OFFSET(tonemapping_param), AV_OPT_TYPE_FLOAT, {.dbl = 0.0}, 0.0, 100.0, .flags = DYNAMIC },
1758  { "inverse_tonemapping", "Inverse tone mapping (range expansion)", OFFSET(inverse_tonemapping), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, DYNAMIC },
1759  { "tonemapping_lut_size", "Tone-mapping LUT size", OFFSET(tonemapping_lut_size), AV_OPT_TYPE_INT, {.i64 = 256}, 2, 1024, DYNAMIC },
1760  { "contrast_recovery", "HDR contrast recovery strength", OFFSET(contrast_recovery), AV_OPT_TYPE_FLOAT, {.dbl = 0.30}, 0.0, 3.0, DYNAMIC },
1761  { "contrast_smoothness", "HDR contrast recovery smoothness", OFFSET(contrast_smoothness), AV_OPT_TYPE_FLOAT, {.dbl = 3.50}, 1.0, 32.0, DYNAMIC },
1762 
1763  { "dithering", "Dither method to use", OFFSET(dithering), AV_OPT_TYPE_INT, {.i64 = PL_DITHER_BLUE_NOISE}, -1, PL_DITHER_METHOD_COUNT - 1, DYNAMIC, .unit = "dither" },
1764  { "none", "Disable dithering", 0, AV_OPT_TYPE_CONST, {.i64 = -1}, 0, 0, STATIC, .unit = "dither" },
1765  { "blue", "Blue noise", 0, AV_OPT_TYPE_CONST, {.i64 = PL_DITHER_BLUE_NOISE}, 0, 0, STATIC, .unit = "dither" },
1766  { "ordered", "Ordered LUT", 0, AV_OPT_TYPE_CONST, {.i64 = PL_DITHER_ORDERED_LUT}, 0, 0, STATIC, .unit = "dither" },
1767  { "ordered_fixed", "Fixed function ordered", 0, AV_OPT_TYPE_CONST, {.i64 = PL_DITHER_ORDERED_FIXED}, 0, 0, STATIC, .unit = "dither" },
1768  { "white", "White noise", 0, AV_OPT_TYPE_CONST, {.i64 = PL_DITHER_WHITE_NOISE}, 0, 0, STATIC, .unit = "dither" },
1769  { "dither_lut_size", "Dithering LUT size", OFFSET(dither_lut_size), AV_OPT_TYPE_INT, {.i64 = 6}, 1, 8, STATIC },
1770  { "dither_temporal", "Enable temporal dithering", OFFSET(dither_temporal), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, DYNAMIC },
1771 
1772  { "cones", "Colorblindness adaptation model", OFFSET(cones), AV_OPT_TYPE_FLAGS, {.i64 = 0}, 0, PL_CONE_LMS, DYNAMIC, .unit = "cone" },
1773  { "l", "L cone", 0, AV_OPT_TYPE_CONST, {.i64 = PL_CONE_L}, 0, 0, STATIC, .unit = "cone" },
1774  { "m", "M cone", 0, AV_OPT_TYPE_CONST, {.i64 = PL_CONE_M}, 0, 0, STATIC, .unit = "cone" },
1775  { "s", "S cone", 0, AV_OPT_TYPE_CONST, {.i64 = PL_CONE_S}, 0, 0, STATIC, .unit = "cone" },
1776  { "cone-strength", "Colorblindness adaptation strength", OFFSET(cone_str), AV_OPT_TYPE_FLOAT, {.dbl = 0.0}, 0.0, 10.0, DYNAMIC },
1777 
1778  { "custom_shader_path", "Path to custom user shader (mpv .hook format)", OFFSET(shader_path), AV_OPT_TYPE_STRING, .flags = STATIC },
1779  { "custom_shader_bin", "Custom user shader as binary (mpv .hook format)", OFFSET(shader_bin), AV_OPT_TYPE_BINARY, .flags = STATIC },
1780 
1781  /* Performance/quality tradeoff options */
1782  { "skip_aa", "Skip anti-aliasing", OFFSET(skip_aa), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, DYNAMIC },
1783  { "disable_linear", "Disable linear scaling", OFFSET(disable_linear), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, DYNAMIC },
1784  { "disable_builtin", "Disable built-in scalers", OFFSET(disable_builtin), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, DYNAMIC },
1785  { "force_dither", "Force dithering", OFFSET(force_dither), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, DYNAMIC },
1786  { "disable_fbos", "Force-disable FBOs", OFFSET(disable_fbos), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, DYNAMIC },
1787  { NULL },
1788 };
1789 
1790 AVFILTER_DEFINE_CLASS(libplacebo);
1791 
1793  {
1794  .name = "default",
1795  .type = AVMEDIA_TYPE_VIDEO,
1796  .config_props = &libplacebo_config_output,
1797  },
1798 };
1799 
1801  .p.name = "libplacebo",
1802  .p.description = NULL_IF_CONFIG_SMALL("Apply various GPU filters from libplacebo"),
1803  .p.priv_class = &libplacebo_class,
1805  .priv_size = sizeof(LibplaceboContext),
1806  .init = &libplacebo_init,
1812  .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE,
1813 };
formats
formats
Definition: signature.h:47
ff_get_video_buffer
AVFrame * ff_get_video_buffer(AVFilterLink *link, int w, int h)
Request a picture buffer with a specific set of permissions.
Definition: video.c:89
AVHWDeviceContext::hwctx
void * hwctx
The format-specific data, allocated and freed by libavutil along with this context.
Definition: hwcontext.h:88
AV_ROUND_UP
@ AV_ROUND_UP
Round toward +infinity.
Definition: mathematics.h:134
av_fifo_drain2
void av_fifo_drain2(AVFifo *f, size_t size)
Discard the specified amount of data from an AVFifo.
Definition: fifo.c:266
LibplaceboContext::colorspace
int colorspace
Definition: vf_libplacebo.c:193
dithering
New swscale design to change SwsGraph is what coordinates multiple passes These can include cascaded scaling error diffusion dithering
Definition: swscale-v2.txt:9
FF_ENABLE_DEPRECATION_WARNINGS
#define FF_ENABLE_DEPRECATION_WARNINGS
Definition: internal.h:67
VAR_IH
@ VAR_IH
Definition: vf_libplacebo.c:97
LibplaceboContext::out_format
enum AVPixelFormat out_format
Definition: vf_libplacebo.c:166
AVVulkanDeviceContext::phys_dev
VkPhysicalDevice phys_dev
Physical device.
Definition: hwcontext_vulkan.h:79
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
name
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 default minimum maximum flags name is the option name
Definition: writing_filters.txt:88
level
uint8_t level
Definition: svq3.c:208
AVCOL_PRI_EBU3213
@ AVCOL_PRI_EBU3213
EBU Tech. 3213-E (nothing there) / one of JEDEC P22 group phosphors.
Definition: pixfmt.h:658
GAMUT_MAP_SATURATION
@ GAMUT_MAP_SATURATION
Definition: vf_libplacebo.c:62
mix
static int mix(int c0, int c1)
Definition: 4xm.c:717
LibplaceboContext::fps_string
char * fps_string
Definition: vf_libplacebo.c:171
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
LibplaceboContext::percentile
float percentile
Definition: vf_libplacebo.c:246
LibplaceboContext::deband
int deband
Definition: vf_libplacebo.c:227
AVALPHA_MODE_STRAIGHT
@ AVALPHA_MODE_STRAIGHT
Alpha channel is independent of color values.
Definition: pixfmt.h:819
var_name
var_name
Definition: noise.c:46
SCALE_FORCE_OAR_DISABLE
@ SCALE_FORCE_OAR_DISABLE
Definition: scale_eval.h:25
AVALPHA_MODE_PREMULTIPLIED
@ AVALPHA_MODE_PREMULTIPLIED
Alpha channel is multiplied into color values.
Definition: pixfmt.h:818
LibplaceboContext::deband_iterations
int deband_iterations
Definition: vf_libplacebo.c:228
LibplaceboContext::deband_threshold
float deband_threshold
Definition: vf_libplacebo.c:229
GAMUT_MAP_HIGHLIGHT
@ GAMUT_MAP_HIGHLIGHT
Definition: vf_libplacebo.c:66
LibplaceboContext::gamut_mode
int gamut_mode
Definition: vf_libplacebo.c:249
out
static FILE * out
Definition: movenc.c:55
VAR_IN_H
@ VAR_IN_H
Definition: vf_libplacebo.c:97
LibplaceboContext::crop_y_pexpr
AVExpr * crop_y_pexpr
Definition: vf_libplacebo.c:178
av_frame_get_side_data
AVFrameSideData * av_frame_get_side_data(const AVFrame *frame, enum AVFrameSideDataType type)
Definition: frame.c:659
LibplaceboContext::linear_tex
pl_tex linear_tex
Definition: vf_libplacebo.c:157
LibplaceboContext::deinterlace
int deinterlace
Definition: vf_libplacebo.c:222
LibplaceboContext::contrast
float contrast
Definition: vf_libplacebo.c:235
ff_filter_frame
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Definition: avfilter.c:1068
AVFrame::duration
int64_t duration
Duration of the frame, in the same units as pts.
Definition: frame.h:820
av_pix_fmt_desc_get
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition: pixdesc.c:3460
VAR_OUT_T
@ VAR_OUT_T
Definition: vf_libplacebo.c:112
AVBufferRef::data
uint8_t * data
The data buffer.
Definition: buffer.h:90
RET
#define RET(x)
Definition: vulkan.h:34
FFERROR_NOT_READY
return FFERROR_NOT_READY
Definition: filter_design.txt:204
AVCOL_TRC_LINEAR
@ AVCOL_TRC_LINEAR
"Linear transfer characteristics"
Definition: pixfmt.h:681
AVCHROMA_LOC_BOTTOM
@ AVCHROMA_LOC_BOTTOM
Definition: pixfmt.h:809
av_div_q
AVRational av_div_q(AVRational b, AVRational c)
Divide one rational by another.
Definition: rational.c:88
saturation
static IPT saturation(const CmsCtx *ctx, IPT ipt)
Definition: cms.c:559
GAMUT_MAP_CLIP
@ GAMUT_MAP_CLIP
Definition: vf_libplacebo.c:59
AV_FRAME_DATA_DOVI_METADATA
@ AV_FRAME_DATA_DOVI_METADATA
Parsed Dolby Vision metadata, suitable for passing to a software implementation.
Definition: frame.h:208
AV_TIME_BASE_Q
#define AV_TIME_BASE_Q
Internal time base represented as fractional value.
Definition: avutil.h:263
int64_t
long long int64_t
Definition: coverity.c:34
TONE_MAP_ST2094_40
@ TONE_MAP_ST2094_40
Definition: vf_libplacebo.c:45
inlink
The exact code depends on how similar the blocks are and how related they are to the and needs to apply these operations to the correct inlink or outlink if there are several Macros are available to factor that when no extra processing is inlink
Definition: filter_design.txt:212
av_asprintf
char * av_asprintf(const char *fmt,...)
Definition: avstring.c:115
FF_FILTER_FLAG_HWFRAME_AWARE
#define FF_FILTER_FLAG_HWFRAME_AWARE
The filter is aware of hardware frames, and any hardware frame context should not be automatically pr...
Definition: filters.h:208
AV_FRAME_DATA_FILM_GRAIN_PARAMS
@ AV_FRAME_DATA_FILM_GRAIN_PARAMS
Film grain parameters for a frame, described by AVFilmGrainParams.
Definition: frame.h:188
VAR_OHSUB
@ VAR_OHSUB
Definition: vf_libplacebo.c:109
LibplaceboContext::apply_filmgrain
int apply_filmgrain
Definition: vf_libplacebo.c:191
find_scaler
static int find_scaler(AVFilterContext *avctx, const struct pl_filter_config **opt, const char *name, int frame_mixing)
Definition: vf_libplacebo.c:338
normalize.log
log
Definition: normalize.py:21
av_frame_free
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:64
VAR_IN_IDX
@ VAR_IN_IDX
Definition: vf_libplacebo.c:95
AVFrame::opaque
void * opaque
Frame owner's private data.
Definition: frame.h:610
update_settings
static int update_settings(AVFilterContext *ctx)
Definition: vf_libplacebo.c:384
av_fifo_peek
int av_fifo_peek(const AVFifo *f, void *buf, size_t nb_elems, size_t offset)
Read data from a FIFO without modifying FIFO state.
Definition: fifo.c:255
lock_queue
static void lock_queue(void *priv, uint32_t qf, uint32_t qidx)
Definition: vf_libplacebo.c:615
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:472
AVVulkanDeviceContext::get_proc_addr
PFN_vkGetInstanceProcAddr get_proc_addr
Pointer to a vkGetInstanceProcAddr loading function.
Definition: hwcontext_vulkan.h:69
AVFrame::pts
int64_t pts
Presentation timestamp in time_base units (time when frame should be shown to user).
Definition: frame.h:574
AVCOL_RANGE_JPEG
@ AVCOL_RANGE_JPEG
Full range content.
Definition: pixfmt.h:783
pl_av_log
static void pl_av_log(void *log_ctx, enum pl_log_level level, const char *msg)
Definition: vf_libplacebo.c:286
AVOption
AVOption.
Definition: opt.h:428
AVCOL_SPC_NB
@ AVCOL_SPC_NB
Not part of ABI.
Definition: pixfmt.h:726
b
#define b
Definition: input.c:43
AVCOL_TRC_UNSPECIFIED
@ AVCOL_TRC_UNSPECIFIED
Definition: pixfmt.h:675
LibplaceboContext
Definition: vf_libplacebo.c:144
LibplaceboInput::status
int status
Definition: vf_libplacebo.c:126
filters.h
LibplaceboContext::crop_h_pexpr
AVExpr * crop_h_pexpr
Definition: vf_libplacebo.c:178
av_pix_fmt_desc_next
const AVPixFmtDescriptor * av_pix_fmt_desc_next(const AVPixFmtDescriptor *prev)
Iterate over all pixel format descriptors known to libavutil.
Definition: pixdesc.c:3467
AVVulkanDeviceContext::inst
VkInstance inst
Vulkan instance.
Definition: hwcontext_vulkan.h:74
AV_DICT_IGNORE_SUFFIX
#define AV_DICT_IGNORE_SUFFIX
Return first entry in a dictionary whose first part corresponds to the search key,...
Definition: dict.h:75
AVCOL_PRI_JEDEC_P22
@ AVCOL_PRI_JEDEC_P22
Definition: pixfmt.h:659
AV_LOG_VERBOSE
#define AV_LOG_VERBOSE
Detailed information.
Definition: log.h:226
LibplaceboContext::tex
pl_tex tex[4]
Definition: vf_libplacebo.c:152
AVCOL_SPC_RGB
@ AVCOL_SPC_RGB
order of coefficients is actually GBR, also IEC 61966-2-1 (sRGB), YZX and ST 428-1
Definition: pixfmt.h:707
ff_scale_eval_dimensions
int ff_scale_eval_dimensions(void *log_ctx, const char *w_expr, const char *h_expr, AVFilterLink *inlink, AVFilterLink *outlink, int *ret_w, int *ret_h)
Parse and evaluate string expressions for width and height.
Definition: scale_eval.c:58
AVCOL_TRC_BT2020_12
@ AVCOL_TRC_BT2020_12
ITU-R BT2020 for 12-bit system.
Definition: pixfmt.h:688
handle_input
static int handle_input(AVFilterContext *ctx, LibplaceboInput *input)
Definition: vf_libplacebo.c:1129
AVFilterContext::hw_device_ctx
AVBufferRef * hw_device_ctx
For filters which will create hardware frames, sets the device the filter should create them in.
Definition: avfilter.h:336
ff_vk_uninit
void ff_vk_uninit(FFVulkanContext *s)
Frees main context.
Definition: vulkan.c:2704
LibplaceboContext::sigmoid
int sigmoid
Definition: vf_libplacebo.c:214
LibplaceboContext::crop_h_expr
char * crop_h_expr
Definition: vf_libplacebo.c:174
AVDictionary
Definition: dict.c:32
FFMAX
#define FFMAX(a, b)
Definition: macros.h:47
av_buffer_ref
AVBufferRef * av_buffer_ref(const AVBufferRef *buf)
Create a new reference to an AVBuffer.
Definition: buffer.c:103
map_frame
static bool map_frame(pl_gpu gpu, pl_tex *tex, const struct pl_source_frame *src, struct pl_frame *out)
Definition: vf_libplacebo.c:1095
VAR_OT
@ VAR_OT
Definition: vf_libplacebo.c:112
AVFilter::name
const char * name
Filter name.
Definition: avfilter.h:219
LibplaceboContext::chroma_location
int chroma_location
Definition: vf_libplacebo.c:197
video.h
LibplaceboContext::vkctx
FFVulkanContext vkctx
Definition: vf_libplacebo.c:146
AVCOL_SPC_BT2020_CL
@ AVCOL_SPC_BT2020_CL
ITU-R BT2020 constant luminance system.
Definition: pixfmt.h:718
ff_make_formats_list_singleton
AVFilterFormats * ff_make_formats_list_singleton(int fmt)
Equivalent to ff_make_format_list({const int[]}{ fmt, -1 })
Definition: formats.c:596
VAR_CROP_H
@ VAR_CROP_H
Definition: vf_libplacebo.c:101
dummy
static int dummy
Definition: ffplay.c:3751
AV_PIX_FMT_VULKAN
@ AV_PIX_FMT_VULKAN
Vulkan hardware images.
Definition: pixfmt.h:379
libplacebo_activate
static int libplacebo_activate(AVFilterContext *ctx)
Definition: vf_libplacebo.c:1187
roundf
static av_always_inline av_const float roundf(float x)
Definition: libm.h:453
AVVulkanDeviceContext::unlock_queue
attribute_deprecated void(* unlock_queue)(struct AVHWDeviceContext *ctx, uint32_t queue_family, uint32_t index)
Similar to lock_queue(), unlocks a queue.
Definition: hwcontext_vulkan.h:137
AV_HWDEVICE_TYPE_VULKAN
@ AV_HWDEVICE_TYPE_VULKAN
Definition: hwcontext.h:39
FIT_NONE
@ FIT_NONE
Definition: vf_libplacebo.c:133
AVFilterFormats
A list of supported formats for one end of a filter link.
Definition: formats.h:64
AV_FRAME_FLAG_TOP_FIELD_FIRST
#define AV_FRAME_FLAG_TOP_FIELD_FIRST
A flag to mark frames where the top field is displayed first if the content is interlaced.
Definition: frame.h:700
formats.h
av_expr_parse
int av_expr_parse(AVExpr **expr, const char *s, const char *const *const_names, const char *const *func1_names, double(*const *funcs1)(void *, double), const char *const *func2_names, double(*const *funcs2)(void *, double, double), int log_offset, void *log_ctx)
Parse an expression.
Definition: eval.c:735
unmap_frame
static void unmap_frame(pl_gpu gpu, struct pl_frame *frame, const struct pl_source_frame *src)
Definition: vf_libplacebo.c:1117
VAR_VSUB
@ VAR_VSUB
Definition: vf_libplacebo.c:108
libplacebo_config_output
static int libplacebo_config_output(AVFilterLink *outlink)
Definition: vf_libplacebo.c:1428
VAR_PH
@ VAR_PH
Definition: vf_libplacebo.c:103
ff_inlink_consume_frame
int ff_inlink_consume_frame(AVFilterLink *link, AVFrame **rframe)
Take a frame from the link's FIFO and update the link's stats.
Definition: avfilter.c:1519
SCALE_FORCE_OAR_INCREASE
@ SCALE_FORCE_OAR_INCREASE
Definition: scale_eval.h:27
AVCOL_SPC_BT470BG
@ AVCOL_SPC_BT470BG
also ITU-R BT601-6 625 / ITU-R BT1358 625 / ITU-R BT1700 625 PAL & SECAM / IEC 61966-2-4 xvYCC601
Definition: pixfmt.h:712
fifo.h
AV_OPT_TYPE_BINARY
@ AV_OPT_TYPE_BINARY
Underlying C type is a uint8_t* that is either NULL or points to an array allocated with the av_mallo...
Definition: opt.h:285
AVCOL_TRC_IEC61966_2_1
@ AVCOL_TRC_IEC61966_2_1
IEC 61966-2-1 (sRGB or sYCC)
Definition: pixfmt.h:686
av_file_map
int av_file_map(const char *filename, uint8_t **bufptr, size_t *size, int log_offset, void *log_ctx)
Read the file with name filename, and put its content in a newly allocated buffer or map it with mmap...
Definition: file.c:55
LibplaceboContext::pos_w_pexpr
AVExpr * pos_w_pexpr
Definition: vf_libplacebo.c:179
AVFilterContext::priv
void * priv
private data for use by the filter
Definition: avfilter.h:288
AVVulkanDeviceContext::lock_queue
attribute_deprecated void(* lock_queue)(struct AVHWDeviceContext *ctx, uint32_t queue_family, uint32_t index)
Locks a queue, preventing other threads from submitting any command buffers to this queue.
Definition: hwcontext_vulkan.h:129
LibplaceboContext::shader_bin_len
int shader_bin_len
Definition: vf_libplacebo.c:269
av_fifo_write
int av_fifo_write(AVFifo *f, const void *buf, size_t nb_elems)
Write data into a FIFO.
Definition: fifo.c:188
FIT_TARGET
@ FIT_TARGET
Definition: vf_libplacebo.c:139
vulkan_filter.h
AV_PIX_FMT_FLAG_HWACCEL
#define AV_PIX_FMT_FLAG_HWACCEL
Pixel format is an HW accelerated format.
Definition: pixdesc.h:128
AVCOL_RANGE_NB
@ AVCOL_RANGE_NB
Not part of ABI.
Definition: pixfmt.h:784
AVCOL_TRC_GAMMA28
@ AVCOL_TRC_GAMMA28
also ITU-R BT470BG
Definition: pixfmt.h:678
AVVulkanFramesContext
Allocated as AVHWFramesContext.hwctx, used to set pool-specific options.
Definition: hwcontext_vulkan.h:171
LibplaceboContext::nb_inputs
int nb_inputs
Definition: vf_libplacebo.c:161
LibplaceboContext::pos_y_expr
char * pos_y_expr
Definition: vf_libplacebo.c:175
GAMUT_MAP_LINEAR
@ GAMUT_MAP_LINEAR
Definition: vf_libplacebo.c:67
pts
static int64_t pts
Definition: transcode_aac.c:649
LibplaceboContext::crop_y_expr
char * crop_y_expr
Definition: vf_libplacebo.c:173
AVFILTER_FLAG_DYNAMIC_INPUTS
#define AVFILTER_FLAG_DYNAMIC_INPUTS
The number of the filter inputs is not determined just by AVFilter.inputs.
Definition: avfilter.h:155
TONE_MAP_SPLINE
@ TONE_MAP_SPLINE
Definition: vf_libplacebo.c:49
SCALE_FORCE_OAR_NB
@ SCALE_FORCE_OAR_NB
Definition: scale_eval.h:28
fabsf
static __device__ float fabsf(float a)
Definition: cuda_runtime.h:181
av_expr_free
void av_expr_free(AVExpr *e)
Free a parsed expression previously created with av_expr_parse().
Definition: eval.c:368
AVRational::num
int num
Numerator.
Definition: rational.h:59
LibplaceboContext::contrast_smoothness
float contrast_smoothness
Definition: vf_libplacebo.c:255
FILTER_QUERY_FUNC2
#define FILTER_QUERY_FUNC2(func)
Definition: filters.h:241
VAR_CROP_W
@ VAR_CROP_W
Definition: vf_libplacebo.c:100
AV_SIDE_DATA_PROP_SIZE_DEPENDENT
@ AV_SIDE_DATA_PROP_SIZE_DEPENDENT
Side data depends on the video dimensions.
Definition: frame.h:354
LibplaceboInput::renderer
pl_renderer renderer
Definition: vf_libplacebo.c:120
AVCOL_TRC_GAMMA22
@ AVCOL_TRC_GAMMA22
also ITU-R BT470M / ITU-R BT1700 625 PAL & SECAM
Definition: pixfmt.h:677
AVFilterPad
A filter pad used for either input or output.
Definition: filters.h:40
TONE_MAP_ST2094_10
@ TONE_MAP_ST2094_10
Definition: vf_libplacebo.c:46
LibplaceboContext::fit_mode
int fit_mode
Definition: vf_libplacebo.c:189
AVHWDeviceContext
This struct aggregates all the (hardware/vendor-specific) "high-level" state, i.e.
Definition: hwcontext.h:63
LibplaceboContext::extra_opts
AVDictionary * extra_opts
Definition: vf_libplacebo.c:200
VAR_OW
@ VAR_OW
Definition: vf_libplacebo.c:98
LibplaceboContext::antiringing
float antiringing
Definition: vf_libplacebo.c:213
preset
preset
Definition: vf_curves.c:47
avassert.h
AVVulkanDeviceQueueFamily::num
int num
Definition: hwcontext_vulkan.h:37
LibplaceboContext::pos_w_expr
char * pos_w_expr
Definition: vf_libplacebo.c:176
LibplaceboContext::disable_linear
int disable_linear
Definition: vf_libplacebo.c:216
AV_LOG_TRACE
#define AV_LOG_TRACE
Extremely verbose debugging, useful for libav* development.
Definition: log.h:236
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:210
VAR_VARS_NB
@ VAR_VARS_NB
Definition: vf_libplacebo.c:114
FF_ARRAY_ELEMS
#define FF_ARRAY_ELEMS(a)
Definition: sinewin_tablegen.c:29
LibplaceboContext::crop_x_expr
char * crop_x_expr
Definition: vf_libplacebo.c:173
FFFilter
Definition: filters.h:267
av_dict_get
AVDictionaryEntry * av_dict_get(const AVDictionary *m, const char *key, const AVDictionaryEntry *prev, int flags)
Get a dictionary entry with matching key.
Definition: dict.c:60
float
float
Definition: af_crystalizer.c:122
flags
#define flags(name, subs,...)
Definition: cbs_av1.c:504
LibplaceboContext::lut
struct pl_custom_lut * lut
Definition: vf_libplacebo.c:153
FIT_CONTAIN
@ FIT_CONTAIN
Definition: vf_libplacebo.c:131
ff_inlink_request_frame
void ff_inlink_request_frame(AVFilterLink *link)
Mark that a frame is wanted on the link.
Definition: avfilter.c:1622
ref_frame
static const AVFrame * ref_frame(const struct pl_frame_mix *mix)
Definition: vf_libplacebo.c:802
output_frame
static int output_frame(AVFilterContext *ctx, int64_t pts)
Definition: vf_libplacebo.c:917
FILTER_OUTPUTS
#define FILTER_OUTPUTS(array)
Definition: filters.h:265
AVCHROMA_LOC_TOP
@ AVCHROMA_LOC_TOP
Definition: pixfmt.h:807
LibplaceboContext::force_original_aspect_ratio
int force_original_aspect_ratio
Definition: vf_libplacebo.c:185
AVCOL_TRC_BT1361_ECG
@ AVCOL_TRC_BT1361_ECG
ITU-R BT1361 Extended Colour Gamut.
Definition: pixfmt.h:685
LibplaceboContext::force_dither
int force_dither
Definition: vf_libplacebo.c:218
LibplaceboContext::inputs
LibplaceboInput * inputs
Definition: vf_libplacebo.c:160
discard_frame
static void discard_frame(const struct pl_source_frame *src)
Definition: vf_libplacebo.c:1123
ff_filter_link
static FilterLink * ff_filter_link(AVFilterLink *link)
Definition: filters.h:199
AVCOL_SPC_SMPTE170M
@ AVCOL_SPC_SMPTE170M
also ITU-R BT601-6 525 / ITU-R BT1358 525 / ITU-R BT1700 NTSC / functionally identical to above
Definition: pixfmt.h:713
LibplaceboContext::opts
pl_options opts
Definition: vf_libplacebo.c:209
ff_formats_ref
int ff_formats_ref(AVFilterFormats *f, AVFilterFormats **ref)
Add *ref as a new reference to formats.
Definition: formats.c:756
av_q2d
static double av_q2d(AVRational a)
Convert an AVRational to a double.
Definition: rational.h:104
GAMUT_MAP_ABSOLUTE
@ GAMUT_MAP_ABSOLUTE
Definition: vf_libplacebo.c:63
ff_outlink_set_status
static void ff_outlink_set_status(AVFilterLink *link, int status, int64_t pts)
Set the status field of a link from the source filter.
Definition: filters.h:629
libplacebo_uninit
static void libplacebo_uninit(AVFilterContext *avctx)
Definition: vf_libplacebo.c:755
LibplaceboContext::frame_mixer
char * frame_mixer
Definition: vf_libplacebo.c:212
av_assert0
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:42
q2d_fallback
static double q2d_fallback(AVRational q, const double def)
Definition: vf_libplacebo.c:811
AV_LOG_DEBUG
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:231
ctx
static AVFormatContext * ctx
Definition: movenc.c:49
av_expr_eval
double av_expr_eval(AVExpr *e, const double *const_values, void *opaque)
Evaluate a previously parsed expression.
Definition: eval.c:824
LibplaceboContext::tonemapping
int tonemapping
Definition: vf_libplacebo.c:250
AVCOL_PRI_SMPTE428
@ AVCOL_PRI_SMPTE428
SMPTE ST 428-1 (CIE 1931 XYZ)
Definition: pixfmt.h:654
av_rescale_q
int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq)
Rescale a 64-bit integer by 2 rational numbers.
Definition: mathematics.c:142
AVExpr
Definition: eval.c:171
LibplaceboContext::crop_w_expr
char * crop_w_expr
Definition: vf_libplacebo.c:174
LibplaceboContext::disable_builtin
int disable_builtin
Definition: vf_libplacebo.c:217
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
LibplaceboContext::color_trc
int color_trc
Definition: vf_libplacebo.c:196
libplacebo_process_command
static int libplacebo_process_command(AVFilterContext *ctx, const char *cmd, const char *arg, char *res, int res_len, int flags)
Definition: vf_libplacebo.c:789
VAR_IN_T
@ VAR_IN_T
Definition: vf_libplacebo.c:111
ff_vf_libplacebo
const FFFilter ff_vf_libplacebo
Definition: vf_libplacebo.c:1800
LibplaceboContext::w_expr
char * w_expr
Definition: vf_libplacebo.c:169
AVCOL_PRI_SMPTE240M
@ AVCOL_PRI_SMPTE240M
identical to above, also called "SMPTE C" even though it uses D65
Definition: pixfmt.h:651
LibplaceboInput
Definition: vf_libplacebo.c:118
color_range
color_range
Definition: vf_selectivecolor.c:43
LibplaceboContext::force_divisible_by
int force_divisible_by
Definition: vf_libplacebo.c:186
AVCOL_PRI_UNSPECIFIED
@ AVCOL_PRI_UNSPECIFIED
Definition: pixfmt.h:645
NAN
#define NAN
Definition: mathematics.h:115
av_file_unmap
void av_file_unmap(uint8_t *bufptr, size_t size)
Unmap or free the buffer bufptr created by av_file_map().
Definition: file.c:142
AVCOL_PRI_BT470BG
@ AVCOL_PRI_BT470BG
also ITU-R BT601-6 625 / ITU-R BT1358 625 / ITU-R BT1700 625 PAL & SECAM
Definition: pixfmt.h:649
arg
const char * arg
Definition: jacosubdec.c:65
AVCOL_PRI_SMPTE170M
@ AVCOL_PRI_SMPTE170M
also ITU-R BT601-6 525 / ITU-R BT1358 525 / ITU-R BT1700 NTSC
Definition: pixfmt.h:650
if
if(ret)
Definition: filter_design.txt:179
av_log_get_level
int av_log_get_level(void)
Get the current log level.
Definition: log.c:472
get_tonemapping_func
static const struct pl_tone_map_function * get_tonemapping_func(int tm)
Definition: vf_libplacebo.c:303
fail
#define fail
Definition: test.h:478
VAR_IW
@ VAR_IW
Definition: vf_libplacebo.c:96
AVVulkanDeviceContext
Main Vulkan context, allocated as AVHWDeviceContext.hwctx.
Definition: hwcontext_vulkan.h:59
opts
static AVDictionary * opts
Definition: movenc.c:51
LibplaceboContext::fit_sense
int fit_sense
Definition: vf_libplacebo.c:190
VAR_PW
@ VAR_PW
Definition: vf_libplacebo.c:102
NULL
#define NULL
Definition: coverity.c:32
LibplaceboContext::dither_temporal
int dither_temporal
Definition: vf_libplacebo.c:260
av_frame_copy_props
int av_frame_copy_props(AVFrame *dst, const AVFrame *src)
Copy only "metadata" fields from src to dst.
Definition: frame.c:599
SCALE_FORCE_OAR_DECREASE
@ SCALE_FORCE_OAR_DECREASE
Definition: scale_eval.h:26
format
New swscale design to change SwsGraph is what coordinates multiple passes These can include cascaded scaling error diffusion and so on Or we could have separate passes for the vertical and horizontal scaling In between each SwsPass lies a fully allocated image buffer Graph passes may have different levels of e g we can have a single threaded error diffusion pass following a multi threaded scaling pass SwsGraph is internally recreated whenever the image format
Definition: swscale-v2.txt:14
av_buffer_unref
void av_buffer_unref(AVBufferRef **buf)
Free a given reference and automatically free the buffer if there are no more references to it.
Definition: buffer.c:139
AVVulkanDeviceContext::nb_enabled_dev_extensions
int nb_enabled_dev_extensions
Definition: hwcontext_vulkan.h:117
LibplaceboContext::skip_aa
int skip_aa
Definition: vf_libplacebo.c:215
AVCHROMA_LOC_LEFT
@ AVCHROMA_LOC_LEFT
MPEG-2/4 4:2:0, H.264 default for 4:2:0.
Definition: pixfmt.h:804
LibplaceboContext::shader_bin
void * shader_bin
Definition: vf_libplacebo.c:268
AVRational
Rational number (pair of numerator and denominator).
Definition: rational.h:58
AVCHROMA_LOC_TOPLEFT
@ AVCHROMA_LOC_TOPLEFT
ITU-R 601, SMPTE 274M 296M S314M(DV 4:1:1), mpeg2 4:2:2.
Definition: pixfmt.h:806
LibplaceboContext::cones
int cones
Definition: vf_libplacebo.c:263
AVHWFramesContext::device_ref
AVBufferRef * device_ref
A reference to the parent AVHWDeviceContext.
Definition: hwcontext.h:129
AVCOL_TRC_IEC61966_2_4
@ AVCOL_TRC_IEC61966_2_4
IEC 61966-2-4.
Definition: pixfmt.h:684
fit_mode
fit_mode
Definition: vf_libplacebo.c:129
ff_append_inpad_free_name
int ff_append_inpad_free_name(AVFilterContext *f, AVFilterPad *p)
Definition: avfilter.c:132
LibplaceboContext::brightness
float brightness
Definition: vf_libplacebo.c:234
activate
filter_frame For filters that do not use the activate() callback
AV_OPT_TYPE_COLOR
@ AV_OPT_TYPE_COLOR
Underlying C type is uint8_t[4].
Definition: opt.h:322
FIT_COVER
@ FIT_COVER
Definition: vf_libplacebo.c:132
fit_sense
fit_sense
Definition: vf_libplacebo.c:138
AV_OPT_TYPE_DICT
@ AV_OPT_TYPE_DICT
Underlying C type is AVDictionary*.
Definition: opt.h:289
AVFilterContext::inputs
AVFilterLink ** inputs
array of pointers to input links
Definition: avfilter.h:281
LibplaceboContext::gpu
pl_gpu gpu
Definition: vf_libplacebo.c:151
AVCOL_PRI_BT709
@ AVCOL_PRI_BT709
also ITU-R BT1361 / IEC 61966-2-4 / SMPTE RP 177 Annex B
Definition: pixfmt.h:644
ff_add_format
int ff_add_format(AVFilterFormats **avff, int64_t fmt)
Add fmt to the list of media formats contained in *avff.
Definition: formats.c:571
parseutils.h
VAR_OUT_W
@ VAR_OUT_W
Definition: vf_libplacebo.c:98
AVFilterFormats::nb_formats
unsigned nb_formats
number of formats
Definition: formats.h:65
AVVulkanDeviceContext::nb_qf
int nb_qf
Definition: hwcontext_vulkan.h:149
ff_vk_filter_config_output
int ff_vk_filter_config_output(AVFilterLink *outlink)
Definition: vulkan_filter.c:209
AVVulkanFramesContext::usage
VkImageUsageFlagBits usage
Defines extra usage of output frames.
Definition: hwcontext_vulkan.h:191
LibplaceboContext::fillcolor
uint8_t fillcolor[4]
Definition: vf_libplacebo.c:167
double
double
Definition: af_crystalizer.c:132
AVCOL_TRC_BT2020_10
@ AVCOL_TRC_BT2020_10
ITU-R BT2020 for 10-bit system.
Definition: pixfmt.h:687
AVCOL_SPC_YCGCO
@ AVCOL_SPC_YCGCO
used by Dirac / VC-2 and H.264 FRext, see ITU-T SG16
Definition: pixfmt.h:715
VAR_OUT_H
@ VAR_OUT_H
Definition: vf_libplacebo.c:99
input_init
static int input_init(AVFilterContext *avctx, LibplaceboInput *input, int idx)
Definition: vf_libplacebo.c:637
AVVulkanDeviceContext::qf
AVVulkanDeviceQueueFamily qf[64]
Queue families used.
Definition: hwcontext_vulkan.h:148
FFVulkanContext
Definition: vulkan.h:275
ff_all_color_spaces
AVFilterFormats * ff_all_color_spaces(void)
Construct an AVFilterFormats representing all possible color spaces.
Definition: formats.c:697
AVFilterFormats::refcount
unsigned refcount
number of references to this list
Definition: formats.h:68
AVPixFmtDescriptor::flags
uint64_t flags
Combination of AV_PIX_FMT_FLAG_...
Definition: pixdesc.h:94
ff_inlink_acknowledge_status
int ff_inlink_acknowledge_status(AVFilterLink *link, int *rstatus, int64_t *rpts)
Test and acknowledge the change of status on the link.
Definition: avfilter.c:1466
LibplaceboContext::nb_active
int nb_active
Definition: vf_libplacebo.c:162
AVCOL_RANGE_UNSPECIFIED
@ AVCOL_RANGE_UNSPECIFIED
Definition: pixfmt.h:749
parse_shader
static int parse_shader(AVFilterContext *avctx, const void *shader, size_t len)
Definition: vf_libplacebo.c:494
set_gamut_mode
static void set_gamut_mode(struct pl_color_map_params *p, int gamut_mode)
Definition: vf_libplacebo.c:321
libplacebo_config_input
static int libplacebo_config_input(AVFilterLink *inlink)
Definition: vf_libplacebo.c:1379
AVFilterFormatsConfig
Lists of formats / etc.
Definition: avfilter.h:120
VAR_CW
@ VAR_CW
Definition: vf_libplacebo.c:100
AVCOL_PRI_BT2020
@ AVCOL_PRI_BT2020
ITU-R BT2020.
Definition: pixfmt.h:653
LibplaceboInput::status_pts
int64_t status_pts
Definition: vf_libplacebo.c:125
LibplaceboContext::cone_str
float cone_str
Definition: vf_libplacebo.c:264
LibplaceboContext::reset_sar
int reset_sar
Definition: vf_libplacebo.c:187
LibplaceboContext::have_hwdevice
int have_hwdevice
Definition: vf_libplacebo.c:206
color_primaries
static const AVColorPrimariesDesc color_primaries[AVCOL_PRI_NB]
Definition: csp.c:76
init_vulkan
static int init_vulkan(AVFilterContext *avctx, const AVVulkanDeviceContext *hwctx)
Definition: vf_libplacebo.c:673
LibplaceboContext::hue
float hue
Definition: vf_libplacebo.c:237
GAMUT_MAP_COUNT
@ GAMUT_MAP_COUNT
Definition: vf_libplacebo.c:68
AVCOL_TRC_SMPTE2084
@ AVCOL_TRC_SMPTE2084
SMPTE ST 2084 for 10-, 12-, 14- and 16-bit systems.
Definition: pixfmt.h:689
TS2T
#define TS2T(ts, tb)
Definition: filters.h:483
TONE_MAP_COUNT
@ TONE_MAP_COUNT
Definition: vf_libplacebo.c:55
AVCOL_PRI_SMPTE431
@ AVCOL_PRI_SMPTE431
SMPTE ST 431-2 (2011) / DCI P3.
Definition: pixfmt.h:656
eval.h
init
int(* init)(AVBSFContext *ctx)
Definition: dts2pts.c:608
AVFifo
Definition: fifo.c:35
NULL_IF_CONFIG_SMALL
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
Definition: internal.h:88
AVCOL_TRC_SMPTE240M
@ AVCOL_TRC_SMPTE240M
Definition: pixfmt.h:680
AVCOL_PRI_FILM
@ AVCOL_PRI_FILM
colour filters using Illuminant C
Definition: pixfmt.h:652
process_command
static int process_command(AVFilterContext *ctx, const char *cmd, const char *args, char *res, int res_len, int flags)
Definition: af_acrusher.c:307
i
#define i(width, name, range_min, range_max)
Definition: cbs_h264.c:63
av_err2str
#define av_err2str(errnum)
Convenience macro, the return value should be used only directly in function arguments but never stan...
Definition: error.h:122
AVFILTER_DEFINE_CLASS
AVFILTER_DEFINE_CLASS(libplacebo)
LibplaceboContext::deband_grain
float deband_grain
Definition: vf_libplacebo.c:231
LibplaceboInput::mix
struct pl_frame_mix mix
temporary storage
Definition: vf_libplacebo.c:123
AVFILTER_FLAG_HWDEVICE
#define AVFILTER_FLAG_HWDEVICE
The filter can create hardware frames using AVFilterContext.hw_device_ctx.
Definition: avfilter.h:187
FIT_FILL
@ FIT_FILL
Definition: vf_libplacebo.c:130
TONE_MAP_LINEAR
@ TONE_MAP_LINEAR
Definition: vf_libplacebo.c:54
LibplaceboContext::out_format_string
char * out_format_string
Definition: vf_libplacebo.c:165
LibplaceboContext::disable_fbos
int disable_fbos
Definition: vf_libplacebo.c:219
LibplaceboContext::saturation
float saturation
Definition: vf_libplacebo.c:236
LibplaceboContext::num_hooks
int num_hooks
Definition: vf_libplacebo.c:271
AVCHROMA_LOC_UNSPECIFIED
@ AVCHROMA_LOC_UNSPECIFIED
Definition: pixfmt.h:803
AVALPHA_MODE_NB
@ AVALPHA_MODE_NB
Not part of ABI.
Definition: pixfmt.h:820
libplacebo_options
static const AVOption libplacebo_options[]
Definition: vf_libplacebo.c:1565
scale_eval.h
sigmoid
static float sigmoid(float x)
Definition: vf_dnn_detect.c:90
frame.h
TONE_MAP_BT2390
@ TONE_MAP_BT2390
Definition: vf_libplacebo.c:47
ff_filter_process_command
int ff_filter_process_command(AVFilterContext *ctx, const char *cmd, const char *arg, char *res, int res_len, int flags)
Generic processing of user supplied commands that are set in the same way as the filter options.
Definition: avfilter.c:906
av_frame_remove_side_data
void av_frame_remove_side_data(AVFrame *frame, enum AVFrameSideDataType type)
Remove and free all side data instances of the given type.
Definition: frame.c:725
TONE_MAP_AUTO
@ TONE_MAP_AUTO
Definition: vf_libplacebo.c:43
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
AVCOL_TRC_EXT_NB
@ AVCOL_TRC_EXT_NB
Not part of ABI.
Definition: pixfmt.h:699
AVVulkanDeviceQueueFamily::idx
int idx
Definition: hwcontext_vulkan.h:35
ff_all_color_ranges
AVFilterFormats * ff_all_color_ranges(void)
Construct an AVFilterFormats representing all possible color ranges.
Definition: formats.c:713
LibplaceboContext::var_values
double var_values[VAR_VARS_NB]
Definition: vf_libplacebo.c:168
AVERROR_EXTERNAL
#define AVERROR_EXTERNAL
Generic error in an external library.
Definition: error.h:59
LibplaceboContext::normalize_sar
int normalize_sar
Definition: vf_libplacebo.c:188
av_pix_fmt_desc_get_id
enum AVPixelFormat av_pix_fmt_desc_get_id(const AVPixFmtDescriptor *desc)
Definition: pixdesc.c:3479
LibplaceboContext::corner_rounding
float corner_rounding
Definition: vf_libplacebo.c:181
LibplaceboContext::alpha_mode
int alpha_mode
Definition: vf_libplacebo.c:199
LibplaceboContext::apply_dovi
int apply_dovi
Definition: vf_libplacebo.c:192
VAR_POS_H
@ VAR_POS_H
Definition: vf_libplacebo.c:103
av_frame_side_data_remove_by_props
void av_frame_side_data_remove_by_props(AVFrameSideData ***sd, int *nb_sd, int props)
Remove and free all side data instances that match any of the given side data properties.
Definition: side_data.c:123
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
LibplaceboContext::downscaler
char * downscaler
Definition: vf_libplacebo.c:211
fixed
#define fixed(width, name, value)
Definition: cbs_apv.c:75
LibplaceboContext::log
pl_log log
Definition: vf_libplacebo.c:149
LibplaceboContext::vulkan
pl_vulkan vulkan
Definition: vf_libplacebo.c:150
M_PI
#define M_PI
Definition: mathematics.h:67
LibplaceboContext::pos_h_pexpr
AVExpr * pos_h_pexpr
Definition: vf_libplacebo.c:179
AV_LOG_INFO
#define AV_LOG_INFO
Standard information.
Definition: log.h:221
AVCOL_TRC_BT709
@ AVCOL_TRC_BT709
also ITU-R BT1361
Definition: pixfmt.h:674
av_vkfmt_from_pixfmt
const VkFormat * av_vkfmt_from_pixfmt(enum AVPixelFormat p)
Returns the optimal per-plane Vulkan format for a given sw_format, one for each plane.
Definition: hwcontext_stub.c:30
AV_OPT_TYPE_FLOAT
@ AV_OPT_TYPE_FLOAT
Underlying C type is float.
Definition: opt.h:270
GAMUT_MAP_DESATURATE
@ GAMUT_MAP_DESATURATE
Definition: vf_libplacebo.c:64
AVCOL_SPC_SMPTE240M
@ AVCOL_SPC_SMPTE240M
derived from 170M primaries and D65 white point, 170M is derived from BT470 System M's primaries
Definition: pixfmt.h:714
LibplaceboContext::cache
pl_cache cache
Definition: vf_libplacebo.c:202
av_parse_video_rate
int av_parse_video_rate(AVRational *rate, const char *arg)
Parse str and store the detected values in *rate.
Definition: parseutils.c:181
get_log_level
static enum pl_log_level get_log_level(void)
Definition: vf_libplacebo.c:274
FIT_SENSE_NB
@ FIT_SENSE_NB
Definition: vf_libplacebo.c:141
ff_formats_unref
void ff_formats_unref(AVFilterFormats **ref)
If *ref is non-NULL, remove *ref as a reference to the format list it currently points to,...
Definition: formats.c:795
LibplaceboContext::pos_x_expr
char * pos_x_expr
Definition: vf_libplacebo.c:175
LibplaceboContext::upscaler
char * upscaler
Definition: vf_libplacebo.c:210
FIT_CONSTRAINT
@ FIT_CONSTRAINT
Definition: vf_libplacebo.c:140
AVCOL_SPC_BT2020_NCL
@ AVCOL_SPC_BT2020_NCL
ITU-R BT2020 non-constant luminance system.
Definition: pixfmt.h:717
av_gcd_q
AVRational av_gcd_q(AVRational a, AVRational b, int max_den, AVRational def)
Return the best rational so that a and b are multiple of it.
Definition: rational.c:188
LibplaceboContext::gamma
float gamma
Definition: vf_libplacebo.c:238
algo
Definition: dct.c:58
AV_TIME_BASE
#define AV_TIME_BASE
Internal time base represented as integer.
Definition: avutil.h:253
VAR_OVSUB
@ VAR_OVSUB
Definition: vf_libplacebo.c:110
AVCOL_PRI_V_GAMUT
@ AVCOL_PRI_V_GAMUT
Definition: pixfmt.h:664
av_assert1
#define av_assert1(cond)
assert() equivalent, that does not lie in speed critical code.
Definition: avassert.h:58
s
uint8_t s
Definition: llvidencdsp.c:39
LibplaceboInput::qstatus
enum pl_queue_status qstatus
Definition: vf_libplacebo.c:122
LibplaceboContext::tonemapping_lut_size
int tonemapping_lut_size
Definition: vf_libplacebo.c:253
GAMUT_MAP_DARKEN
@ GAMUT_MAP_DARKEN
Definition: vf_libplacebo.c:65
FFMIN
#define FFMIN(a, b)
Definition: macros.h:49
LibplaceboContext::tonemapping_param
float tonemapping_param
Definition: vf_libplacebo.c:251
AV_PIX_FMT_FLAG_BE
#define AV_PIX_FMT_FLAG_BE
Pixel format is big-endian.
Definition: pixdesc.h:116
LibplaceboContext::pos_h_expr
char * pos_h_expr
Definition: vf_libplacebo.c:176
LibplaceboContext::color_primaries
int color_primaries
Definition: vf_libplacebo.c:195
av_inv_q
static av_always_inline AVRational av_inv_q(AVRational q)
Invert a rational.
Definition: rational.h:159
TONE_MAP_BT2446A
@ TONE_MAP_BT2446A
Definition: vf_libplacebo.c:48
len
int len
Definition: vorbis_enc_data.h:426
uninit
static av_cold void uninit(AVBitStreamFilterContext *ctx)
Definition: lcevc_merge.c:135
var_names
static const char *const var_names[]
Definition: vf_libplacebo.c:71
LibplaceboContext::shader_cache
char * shader_cache
Definition: vf_libplacebo.c:203
AVFilterPad::name
const char * name
Pad name.
Definition: filters.h:46
AVCOL_SPC_UNSPECIFIED
@ AVCOL_SPC_UNSPECIFIED
Definition: pixfmt.h:709
LibplaceboContext::dithering
int dithering
Definition: vf_libplacebo.c:258
LibplaceboContext::scene_high
float scene_high
Definition: vf_libplacebo.c:245
STATIC
#define STATIC
Definition: vf_libplacebo.c:1562
drain_input_pts
static void drain_input_pts(LibplaceboInput *in, int64_t until)
Definition: vf_libplacebo.c:1180
AV_FRAME_FLAG_INTERLACED
#define AV_FRAME_FLAG_INTERLACED
A flag to mark frames whose content is interlaced.
Definition: frame.h:695
AVCOL_RANGE_MPEG
@ AVCOL_RANGE_MPEG
Narrow or limited range content.
Definition: pixfmt.h:766
av_calloc
void * av_calloc(size_t nmemb, size_t size)
Definition: mem.c:264
LibplaceboContext::skip_spatial_check
int skip_spatial_check
Definition: vf_libplacebo.c:223
AV_SIDE_DATA_PROP_COLOR_DEPENDENT
@ AV_SIDE_DATA_PROP_COLOR_DEPENDENT
Side data depends on the video color space.
Definition: frame.h:361
parse_custom_lut
static int parse_custom_lut(AVFilterContext *avctx)
Definition: vf_libplacebo.c:363
LibplaceboInput::queue
pl_queue queue
Definition: vf_libplacebo.c:121
av_cmp_q
static int av_cmp_q(AVRational a, AVRational b)
Compare two rationals.
Definition: rational.h:89
AVHWFramesContext
This struct describes a set or pool of "hardware" frames (i.e.
Definition: hwcontext.h:118
AVCOL_PRI_BT470M
@ AVCOL_PRI_BT470M
also FCC Title 47 Code of Federal Regulations 73.682 (a)(20)
Definition: pixfmt.h:647
ret
ret
Definition: filter_design.txt:187
AV_LOG_FATAL
#define AV_LOG_FATAL
Something went wrong and recovery is not possible.
Definition: log.h:204
pixfmt
enum AVPixelFormat pixfmt
Definition: kmsgrab.c:367
AVHWDeviceContext::type
enum AVHWDeviceType type
This field identifies the underlying API used for hardware access.
Definition: hwcontext.h:75
LibplaceboContext::inherit_device
int inherit_device
Definition: vf_libplacebo.c:204
FFSWAP
#define FFSWAP(type, a, b)
Definition: macros.h:52
AVALPHA_MODE_UNSPECIFIED
@ AVALPHA_MODE_UNSPECIFIED
Unknown alpha handling, or no alpha channel.
Definition: pixfmt.h:817
frame
these buffered frames must be flushed immediately if a new input produces new the filter must not call request_frame to get more It must just process the frame or queue it The task of requesting more frames is left to the filter s request_frame method or the application If a filter has several the filter must be ready for frames arriving randomly on any input any filter with several inputs will most likely require some kind of queuing mechanism It is perfectly acceptable to have a limited queue and to drop frames when the inputs are too unbalanced request_frame For filters that do not use the this method is called when a frame is wanted on an output For a it should directly call filter_frame on the corresponding output For a if there are queued frames already one of these frames should be pushed If the filter should request a frame on one of its repeatedly until at least one frame has been pushed Return or at least make progress towards producing a frame
Definition: filter_design.txt:265
LibplaceboContext::scene_low
float scene_low
Definition: vf_libplacebo.c:244
AVHWFramesContext::device_ctx
AVHWDeviceContext * device_ctx
The parent AVHWDeviceContext.
Definition: hwcontext.h:137
VAR_OH
@ VAR_OH
Definition: vf_libplacebo.c:99
AVHWFramesContext::hwctx
void * hwctx
The format-specific data, allocated and freed automatically along with this context.
Definition: hwcontext.h:153
VAR_CH
@ VAR_CH
Definition: vf_libplacebo.c:101
LibplaceboContext::linear_rr
pl_renderer linear_rr
Definition: vf_libplacebo.c:156
av_fifo_alloc2
AVFifo * av_fifo_alloc2(size_t nb_elems, size_t elem_size, unsigned int flags)
Allocate and initialize an AVFifo with a given element size.
Definition: fifo.c:47
VAR_T
@ VAR_T
Definition: vf_libplacebo.c:111
LibplaceboContext::peakdetect
int peakdetect
Definition: vf_libplacebo.c:242
av_get_pix_fmt
enum AVPixelFormat av_get_pix_fmt(const char *name)
Return the pixel format corresponding to name.
Definition: pixdesc.c:3392
LibplaceboContext::deband_radius
float deband_radius
Definition: vf_libplacebo.c:230
LibplaceboInput::idx
int idx
Definition: vf_libplacebo.c:119
AVCOL_TRC_ARIB_STD_B67
@ AVCOL_TRC_ARIB_STD_B67
ARIB STD-B67, known as "Hybrid log-gamma".
Definition: pixfmt.h:693
status
ov_status_e status
Definition: dnn_backend_openvino.c:100
LibplaceboContext::contrast_recovery
float contrast_recovery
Definition: vf_libplacebo.c:254
VAR_IN_W
@ VAR_IN_W
Definition: vf_libplacebo.c:96
AVCOL_PRI_EXT_NB
@ AVCOL_PRI_EXT_NB
Not part of ABI.
Definition: pixfmt.h:665
update_crops
static void update_crops(AVFilterContext *ctx, LibplaceboInput *in, struct pl_frame *target, double target_pts)
Definition: vf_libplacebo.c:816
libplacebo_outputs
static const AVFilterPad libplacebo_outputs[]
Definition: vf_libplacebo.c:1792
AVCHROMA_LOC_CENTER
@ AVCHROMA_LOC_CENTER
MPEG-1 4:2:0, JPEG 4:2:0, H.263 4:2:0.
Definition: pixfmt.h:805
AVRational::den
int den
Denominator.
Definition: rational.h:60
AV_PIX_FMT_NONE
@ AV_PIX_FMT_NONE
Definition: pixfmt.h:72
AV_OPT_TYPE_INT
@ AV_OPT_TYPE_INT
Underlying C type is int.
Definition: opt.h:258
VAR_HSUB
@ VAR_HSUB
Definition: vf_libplacebo.c:107
LibplaceboContext::inverse_tonemapping
int inverse_tonemapping
Definition: vf_libplacebo.c:252
ref
static int ref[MAX_W *MAX_W]
Definition: jpeg2000dwt.c:117
LibplaceboContext::rotation
int rotation
Definition: vf_libplacebo.c:198
ff_all_alpha_modes
AVFilterFormats * ff_all_alpha_modes(void)
Construct an AVFilterFormats representing all possible alpha modes.
Definition: formats.c:724
AVCOL_TRC_SMPTE170M
@ AVCOL_TRC_SMPTE170M
also ITU-R BT601-6 525 or 625 / ITU-R BT1358 525 or 625 / ITU-R BT1700 NTSC
Definition: pixfmt.h:679
Windows::Graphics::DirectX::Direct3D11::p
IDirect3DDxgiInterfaceAccess _COM_Outptr_ void ** p
Definition: vsrc_gfxcapture_winrt.hpp:53
file.h
av_mul_q
AVRational av_mul_q(AVRational b, AVRational c)
Multiply two rationals.
Definition: rational.c:80
OFFSET
#define OFFSET(x)
Definition: vf_libplacebo.c:1561
VAR_SAR
@ VAR_SAR
Definition: vf_libplacebo.c:105
LibplaceboContext::fps
AVRational fps
parsed FPS, or 0/0 for "none"
Definition: vf_libplacebo.c:172
input_uninit
static void input_uninit(LibplaceboInput *input)
Definition: vf_libplacebo.c:651
AVFilterContext
An instance of a filter.
Definition: avfilter.h:273
FIT_MODE_NB
@ FIT_MODE_NB
Definition: vf_libplacebo.c:135
FF_DISABLE_DEPRECATION_WARNINGS
#define FF_DISABLE_DEPRECATION_WARNINGS
Definition: internal.h:66
copy_pl_queue
static int copy_pl_queue(const AVVulkanDeviceContext *hwctx, const AVVulkanDeviceQueueFamily *qf, struct pl_vulkan_queue *pl_qf)
Definition: vf_libplacebo.c:658
desc
const char * desc
Definition: libsvtav1.c:83
AVVulkanDeviceContext::enabled_dev_extensions
const char *const * enabled_dev_extensions
Enabled device extensions.
Definition: hwcontext_vulkan.h:116
ff_vk_filter_config_input
int ff_vk_filter_config_input(AVFilterLink *inlink)
Definition: vulkan_filter.c:176
AVMEDIA_TYPE_VIDEO
@ AVMEDIA_TYPE_VIDEO
Definition: avutil.h:200
FFFilter::p
AVFilter p
The public AVFilter.
Definition: filters.h:271
libplacebo_query_format
static int libplacebo_query_format(const AVFilterContext *ctx, AVFilterFormatsConfig **cfg_in, AVFilterFormatsConfig **cfg_out)
Definition: vf_libplacebo.c:1286
FIT_SCALE_DOWN
@ FIT_SCALE_DOWN
Definition: vf_libplacebo.c:134
mem.h
VAR_IDX
@ VAR_IDX
Definition: vf_libplacebo.c:95
AVFilterFormatsConfig::formats
AVFilterFormats * formats
List of supported formats (pixel or sample).
Definition: avfilter.h:125
TONE_MAP_MOBIUS
@ TONE_MAP_MOBIUS
Definition: vf_libplacebo.c:51
LibplaceboInput::out_pts
AVFifo * out_pts
timestamps of wanted output frames
Definition: vf_libplacebo.c:124
LibplaceboContext::crop_w_pexpr
AVExpr * crop_w_pexpr
Definition: vf_libplacebo.c:178
AVPixFmtDescriptor
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
Definition: pixdesc.h:69
LibplaceboContext::pad_crop_ratio
float pad_crop_ratio
Definition: vf_libplacebo.c:180
AVVulkanDeviceContext::act_dev
VkDevice act_dev
Active device.
Definition: hwcontext_vulkan.h:84
w
uint8_t w
Definition: llvidencdsp.c:39
AVCOL_PRI_SMPTE432
@ AVCOL_PRI_SMPTE432
SMPTE ST 432-1 (2010) / P3 D65 / Display P3.
Definition: pixfmt.h:657
AVCOL_TRC_V_LOG
@ AVCOL_TRC_V_LOG
Definition: pixfmt.h:698
TONE_MAP_REINHARD
@ TONE_MAP_REINHARD
Definition: vf_libplacebo.c:50
AVDictionaryEntry
Definition: dict.h:90
AV_OPT_TYPE_BOOL
@ AV_OPT_TYPE_BOOL
Underlying C type is int.
Definition: opt.h:326
FF_FILTER_FORWARD_STATUS_BACK_ALL
#define FF_FILTER_FORWARD_STATUS_BACK_ALL(outlink, filter)
Forward the status on an output link to all input links.
Definition: filters.h:652
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:35
VAR_POS_W
@ VAR_POS_W
Definition: vf_libplacebo.c:102
max_q
static AVRational max_q(AVRational a, AVRational b)
Definition: vf_libplacebo.c:1423
LibplaceboContext::smoothing
float smoothing
Definition: vf_libplacebo.c:243
TONE_MAP_GAMMA
@ TONE_MAP_GAMMA
Definition: vf_libplacebo.c:53
AV_OPT_TYPE_FLAGS
@ AV_OPT_TYPE_FLAGS
Underlying C type is unsigned int.
Definition: opt.h:254
AVERROR_BUG
#define AVERROR_BUG
Internal bug, also see AVERROR_BUG2.
Definition: error.h:52
AVCHROMA_LOC_NB
@ AVCHROMA_LOC_NB
Not part of ABI.
Definition: pixfmt.h:810
DYNAMIC
#define DYNAMIC
Definition: vf_libplacebo.c:1563
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
GAMUT_MAP_PERCEPTUAL
@ GAMUT_MAP_PERCEPTUAL
Definition: vf_libplacebo.c:60
AVVulkanDeviceQueueFamily
Definition: hwcontext_vulkan.h:33
VAR_N
@ VAR_N
Definition: vf_libplacebo.c:113
av_fifo_freep2
void av_fifo_freep2(AVFifo **f)
Free an AVFifo and reset pointer to NULL.
Definition: fifo.c:286
LibplaceboContext::shader_path
char * shader_path
Definition: vf_libplacebo.c:267
VAR_A
@ VAR_A
Definition: vf_libplacebo.c:104
LibplaceboContext::crop_x_pexpr
AVExpr * crop_x_pexpr
Definition: vf_libplacebo.c:178
AVERROR_EXIT
#define AVERROR_EXIT
Immediate exit was requested; the called function should not be restarted.
Definition: error.h:58
ff_outlink_frame_wanted
the definition of that something depends on the semantic of the filter The callback must examine the status of the filter s links and proceed accordingly The status of output links is stored in the status_in and status_out fields and tested by the ff_outlink_frame_wanted() function. If this function returns true
AVVulkanDeviceContext::device_features
VkPhysicalDeviceFeatures2 device_features
This structure should be set to the set of features that present and enabled during device creation.
Definition: hwcontext_vulkan.h:92
TONE_MAP_HABLE
@ TONE_MAP_HABLE
Definition: vf_libplacebo.c:52
LibplaceboContext::color_range
int color_range
Definition: vf_libplacebo.c:194
LibplaceboContext::temperature
float temperature
Definition: vf_libplacebo.c:239
avstring.h
AV_OPT_TYPE_STRING
@ AV_OPT_TYPE_STRING
Underlying C type is a uint8_t* that is either NULL or points to a C string allocated with the av_mal...
Definition: opt.h:275
LibplaceboContext::dither_lut_size
int dither_lut_size
Definition: vf_libplacebo.c:259
LibplaceboContext::pos_x_pexpr
AVExpr * pos_x_pexpr
Definition: vf_libplacebo.c:179
GAMUT_MAP_RELATIVE
@ GAMUT_MAP_RELATIVE
Definition: vf_libplacebo.c:61
libplacebo_init
static int libplacebo_init(AVFilterContext *avctx)
Definition: vf_libplacebo.c:513
AVCOL_SPC_BT709
@ AVCOL_SPC_BT709
also ITU-R BT1361 / IEC 61966-2-4 xvYCC709 / derived in SMPTE RP 177 Annex B
Definition: pixfmt.h:708
LibplaceboContext::h_expr
char * h_expr
Definition: vf_libplacebo.c:170
VAR_DAR
@ VAR_DAR
Definition: vf_libplacebo.c:106
AVCOL_SPC_ICTCP
@ AVCOL_SPC_ICTCP
ITU-R BT.2100-0, ICtCp.
Definition: pixfmt.h:722
AVVulkanDeviceQueueFamily::flags
VkQueueFlagBits flags
Definition: hwcontext_vulkan.h:41
LibplaceboContext::hooks
const struct pl_hook * hooks[2]
Definition: vf_libplacebo.c:270
AV_OPT_TYPE_CONST
@ AV_OPT_TYPE_CONST
Special option type for declaring named constants.
Definition: opt.h:298
AVVulkanDeviceContext::queue_flags
VkDeviceQueueCreateFlags queue_flags
Definition: hwcontext_vulkan.h:152
LibplaceboContext::lut_type
int lut_type
Definition: vf_libplacebo.c:184
AVCHROMA_LOC_BOTTOMLEFT
@ AVCHROMA_LOC_BOTTOMLEFT
Definition: pixfmt.h:808
ff_scale_adjust_dimensions
int ff_scale_adjust_dimensions(AVFilterLink *inlink, int *ret_w, int *ret_h, int force_original_aspect_ratio, int force_divisible_by, double w_adj)
Transform evaluated width and height obtained from ff_scale_eval_dimensions into actual target width ...
Definition: scale_eval.c:123
av_rescale_q_rnd
int64_t av_rescale_q_rnd(int64_t a, AVRational bq, AVRational cq, enum AVRounding rnd)
Rescale a 64-bit integer by 2 rational numbers with specified rounding.
Definition: mathematics.c:134
LibplaceboContext::lut_filename
char * lut_filename
Definition: vf_libplacebo.c:182
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
LibplaceboContext::pos_y_pexpr
AVExpr * pos_y_pexpr
Definition: vf_libplacebo.c:179
src
#define src
Definition: vp8dsp.c:248
AV_FIFO_FLAG_AUTO_GROW
#define AV_FIFO_FLAG_AUTO_GROW
Automatically resize the FIFO on writes, so that the data fits.
Definition: fifo.h:63
unlock_queue
static void unlock_queue(void *priv, uint32_t qf, uint32_t qidx)
Definition: vf_libplacebo.c:626
log_cb
static void log_cb(cmsContext ctx, cmsUInt32Number error, const char *str)
Definition: fflcms2.c:24
LibplaceboContext::send_fields
int send_fields
Definition: vf_libplacebo.c:224
TONE_MAP_CLIP
@ TONE_MAP_CLIP
Definition: vf_libplacebo.c:44