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