27#include "config_components.h"
42#if CONFIG_LIBVMAF_CUDA_FILTER
43#include <libvmaf_cuda.h>
64#if CONFIG_LIBVMAF_CUDA_FILTER
65 VmafCudaState *cu_state;
69#define OFFSET(x) offsetof(LIBVMAFContext, x)
70#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
74 {
"log_fmt",
"Set the format of the log (csv, json, xml, or sub).",
OFFSET(log_fmt),
AV_OPT_TYPE_STRING, {.str=
"xml"}, 0, 1,
FLAGS},
76 {
"n_threads",
"Set number of threads to be used when computing vmaf.",
OFFSET(n_threads),
AV_OPT_TYPE_INT, {.i64=0}, 0, UINT_MAX,
FLAGS},
77 {
"n_subsample",
"Set interval for frame subsampling used when computing vmaf.",
OFFSET(n_subsample),
AV_OPT_TYPE_INT, {.i64=1}, 1, UINT_MAX,
FLAGS},
92 return VMAF_PIX_FMT_YUV420P;
97 return VMAF_PIX_FMT_YUV422P;
102 return VMAF_PIX_FMT_YUV444P;
104 return VMAF_PIX_FMT_UNKNOWN;
110 const int bytes_per_value = bpc > 8 ? 2 : 1;
116 for (
unsigned i = 0;
i < 3;
i++) {
117 uint8_t *src_data =
src->data[
i];
118 uint8_t *dst_data =
dst->data[
i];
119 for (
unsigned j = 0; j <
dst->h[
i]; j++) {
120 memcpy(dst_data, src_data, bytes_per_value *
dst->w[
i]);
121 src_data +=
src->linesize[
i];
122 dst_data +=
dst->stride[
i];
133 VmafPicture pic_ref, pic_dist;
140 if (
ctx->is_disabled || !
ref)
145 "frames use different color ranges (%s != %s)\n",
159 vmaf_picture_unref(&pic_ref);
163 err = vmaf_read_pictures(
s->vmaf, &pic_ref, &pic_dist,
s->frame_cnt++);
175 char *str_copy =
NULL;
176 char *saveptr =
NULL;
184 for (
char *p = str; *p; p++) {
198 for (
unsigned i = 0;
i < cnt2;
i++) {
212 for (
unsigned i = 0;
i < *cnt;
i++) {
237 "could not parse feature config: %s\n",
s->feature_cfg);
241 for (
unsigned i = 0;
i < dict_cnt;
i++) {
242 char *feature_name =
NULL;
243 VmafFeatureDictionary *feature_opts_dict =
NULL;
247 if (!strcmp(e->
key,
"name")) {
248 feature_name = e->
value;
252 err = vmaf_feature_dictionary_set(&feature_opts_dict, e->
key,
256 "could not set feature option: %s.%s=%s\n",
262 err = vmaf_use_feature(
s->vmaf, feature_name, feature_opts_dict);
265 "problem during vmaf_use_feature: %s\n", feature_name);
271 for (
unsigned i = 0;
i < dict_cnt;
i++) {
286 if (!
s->model_cfg)
return 0;
292 "could not parse model config: %s\n",
s->model_cfg);
296 s->model_cnt = dict_cnt;
301 for (
unsigned i = 0;
i < dict_cnt;
i++) {
302 VmafModelConfig model_cfg = { 0 };
308 if (!strcmp(e->
key,
"disable_clip")) {
309 model_cfg.flags |= !strcmp(e->
value,
"true") ?
310 VMAF_MODEL_FLAG_DISABLE_CLIP : 0;
314 if (!strcmp(e->
key,
"enable_transform")) {
315 model_cfg.flags |= !strcmp(e->
value,
"true") ?
316 VMAF_MODEL_FLAG_ENABLE_TRANSFORM : 0;
320 if (!strcmp(e->
key,
"name")) {
321 model_cfg.name = e->
value;
325 if (!strcmp(e->
key,
"version")) {
330 if (!strcmp(e->
key,
"path")) {
337 err = vmaf_model_load(&
s->model[
i], &model_cfg,
version);
340 "could not load libvmaf model with version: %s\n",
346 if (path && !
s->model[
i]) {
347 err = vmaf_model_load_from_path(&
s->model[
i], &model_cfg, path);
350 "could not load libvmaf model with path: %s\n",
358 "could not load libvmaf model with config: %s\n",
364 VmafFeatureDictionary *feature_opts_dict =
NULL;
365 char *feature_opt =
NULL;
367 char *feature_name =
av_strtok(e->
key,
".", &feature_opt);
371 err = vmaf_feature_dictionary_set(&feature_opts_dict,
372 feature_opt, e->
value);
375 "could not set feature option: %s.%s=%s\n",
376 feature_name, feature_opt, e->
value);
381 err = vmaf_model_feature_overload(
s->model[
i], feature_name,
385 "could not overload feature: %s\n", feature_name);
392 for (
unsigned i = 0;
i <
s->model_cnt;
i++) {
393 err = vmaf_use_features_from_model(
s->vmaf,
s->model[
i]);
396 "problem during vmaf_use_features_from_model\n");
403 for (
unsigned i = 0;
i < dict_cnt;
i++) {
415 return VMAF_LOG_LEVEL_NONE;
417 return VMAF_LOG_LEVEL_ERROR;
419 return VMAF_LOG_LEVEL_WARNING;
421 return VMAF_LOG_LEVEL_INFO;
423 return VMAF_LOG_LEVEL_DEBUG;
425 return VMAF_LOG_LEVEL_INFO;
434 VmafConfiguration
cfg = {
436 .n_subsample =
s->n_subsample,
437 .n_threads =
s->n_threads,
440 err = vmaf_init(&
s->vmaf,
cfg);
471 if (
ctx->inputs[0]->w !=
ctx->inputs[1]->w) {
476 if (
ctx->inputs[0]->h !=
ctx->inputs[1]->h) {
481 if (
ctx->inputs[0]->format !=
ctx->inputs[1]->format) {
490 s->bpc =
desc->comp[0].depth;
507 outlink->
w = mainlink->
w;
508 outlink->
h = mainlink->
h;
527 if (!strcmp(log_fmt,
"xml"))
528 return VMAF_OUTPUT_FORMAT_XML;
529 if (!strcmp(log_fmt,
"json"))
530 return VMAF_OUTPUT_FORMAT_JSON;
531 if (!strcmp(log_fmt,
"csv"))
532 return VMAF_OUTPUT_FORMAT_CSV;
533 if (!strcmp(log_fmt,
"sub"))
534 return VMAF_OUTPUT_FORMAT_SUB;
537 return VMAF_OUTPUT_FORMAT_XML;
543 if (!strcmp(pool_method,
"min"))
544 return VMAF_POOL_METHOD_MIN;
545 if (!strcmp(pool_method,
"mean"))
546 return VMAF_POOL_METHOD_MEAN;
547 if (!strcmp(pool_method,
"harmonic_mean"))
548 return VMAF_POOL_METHOD_HARMONIC_MEAN;
551 return VMAF_POOL_METHOD_MEAN;
564 err = vmaf_read_pictures(
s->vmaf,
NULL,
NULL, 0);
567 "problem flushing libvmaf context.\n");
570 for (
unsigned i = 0;
i <
s->model_cnt;
i++) {
573 &vmaf_score, 0,
s->frame_cnt - 1);
576 "problem getting pooled vmaf score.\n");
583 if (
s->log_path && !err)
589 for (
unsigned i = 0;
i <
s->model_cnt;
i++) {
591 vmaf_model_destroy(
s->model[
i]);
623 .p.priv_class = &libvmaf_class,
624 .preinit = libvmaf_framesync_preinit,
634#if CONFIG_LIBVMAF_CUDA_FILTER
659 CUcontext cu_ctx = device_hwctx->
cuda_ctx;
662 VmafConfiguration
cfg = {
664 .n_subsample =
s->n_subsample,
665 .n_threads =
s->n_threads,
668 VmafCudaPictureConfiguration cuda_pic_cfg = {
670 .bpc =
desc->comp[0].depth,
675 .pic_prealloc_method = VMAF_CUDA_PICTURE_PREALLOCATION_METHOD_DEVICE,
678 VmafCudaConfiguration cuda_cfg = {
684 "Unsupported input format: %s\n",
desc->name);
688 err = vmaf_init(&
s->vmaf,
cfg);
692 err = vmaf_cuda_state_init(&
s->cu_state, cuda_cfg);
696 err = vmaf_cuda_import_state(
s->vmaf,
s->cu_state);
700 err = vmaf_cuda_preallocate_pictures(
s->vmaf, cuda_pic_cfg);
715static int copy_picture_data_cuda(VmafContext* vmaf,
724 .srcMemoryType = CU_MEMORYTYPE_DEVICE,
725 .dstMemoryType = CU_MEMORYTYPE_DEVICE,
728 int err = vmaf_cuda_fetch_preallocated_picture(vmaf,
dst);
732 err = cu->cuCtxPushCurrent(device_hwctx->
cuda_ctx);
737 m.srcDevice = (CUdeviceptr)
src->data[
i];
738 m.srcPitch =
src->linesize[
i];
739 m.dstDevice = (CUdeviceptr)
dst->data[
i];
740 m.dstPitch =
dst->stride[
i];
741 m.WidthInBytes =
dst->w[
i] * ((
dst->bpc + 7) / 8);
742 m.Height =
dst->h[
i];
744 err = cu->cuMemcpy2D(&m);
750 err = cu->cuCtxPopCurrent(
NULL);
765 VmafPicture pic_ref, pic_dist;
773 if (
ctx->is_disabled || !
ref)
776 err = copy_picture_data_cuda(
s->vmaf, device_hwctx,
ref, &pic_ref,
777 frames_ctx->sw_format);
783 err = copy_picture_data_cuda(
s->vmaf, device_hwctx, dist, &pic_dist,
784 frames_ctx->sw_format);
790 err = vmaf_read_pictures(
s->vmaf, &pic_ref, &pic_dist,
s->frame_cnt++);
802 s->fs.on_event = do_vmaf_cuda;
810 .config_props = config_props_cuda,
815 .p.name =
"libvmaf_cuda",
817 .p.priv_class = &libvmaf_class,
818 .preinit = libvmaf_framesync_preinit,
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
const FFFilter ff_vf_libvmaf
const FFFilter ff_vf_libvmaf_cuda
static AVFormatContext * ctx
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Main libavfilter public API header.
#define i(width, name, range_min, range_max)
#define fs(width, name, subs,...)
static enum AVPixelFormat pix_fmt
int(* init)(AVBSFContext *ctx)
static CheckasmConfig cfg
int ff_framesync_configure(FFFrameSync *fs)
Configure a frame sync structure.
int ff_framesync_dualinput_get(FFFrameSync *fs, AVFrame **f0, AVFrame **f1)
int ff_framesync_activate(FFFrameSync *fs)
Examine the frames in the filter's input and try to produce output.
int ff_framesync_init_dualinput(FFFrameSync *fs, AVFilterContext *parent)
Initialize a frame sync structure for dualinput.
void ff_framesync_uninit(FFFrameSync *fs)
Free all memory currently allocated.
#define FRAMESYNC_DEFINE_CLASS(name, context, field)
@ AV_OPT_TYPE_INT
Underlying C type is int.
@ 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...
void av_dict_free(AVDictionary **pm)
Free all the memory allocated for an AVDictionary struct and all keys and values.
const AVDictionaryEntry * av_dict_iterate(const AVDictionary *m, const AVDictionaryEntry *prev)
Iterate over a dictionary.
int av_dict_parse_string(AVDictionary **pm, const char *str, const char *key_val_sep, const char *pairs_sep, int flags)
Parse the key/value pairs list and add the parsed entries to a dictionary.
#define AVERROR_EXTERNAL
Generic error in an external library.
#define AV_LOG_QUIET
Print no output.
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
#define AV_LOG_WARNING
Something somehow does not look correct.
#define AV_LOG_INFO
Standard information.
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
int av_log_get_level(void)
Get the current log level.
char * av_strtok(char *s, const char *delim, char **saveptr)
Split the string into several tokens which can be accessed by successive calls to av_strtok().
FFmpeg internal API for CUDA.
static av_cold void uninit(AVBitStreamFilterContext *ctx)
static int activate(AVBitStreamFilterContext *ctx)
static int config_output(AVBitStreamFilterLink *outlink)
#define FILTER_INPUTS(array)
#define FILTER_OUTPUTS(array)
#define FF_FILTER_FLAG_HWFRAME_AWARE
The filter is aware of hardware frames, and any hardware frame context should not be automatically pr...
#define FILTER_PIXFMTS_ARRAY(array)
static FilterLink * ff_filter_link(AVFilterLink *link)
#define FILTER_SINGLE_PIXFMT(pix_fmt_)
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
static enum AVPixelFormat pix_fmts[]
void * av_calloc(size_t nmemb, size_t size)
Memory handling functions.
const char * av_color_range_name(enum AVColorRange range)
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
AVPixelFormat
Pixel format.
@ AV_PIX_FMT_YUV420P
planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
@ AV_PIX_FMT_YUV422P
planar YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)
@ AV_PIX_FMT_CUDA
HW acceleration through CUDA.
@ AV_PIX_FMT_YUV420P10LE
planar YUV 4:2:0, 15bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian
@ AV_PIX_FMT_YUV422P16LE
planar YUV 4:2:2, 32bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian
@ AV_PIX_FMT_YUV422P12LE
planar YUV 4:2:2,24bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian
@ AV_PIX_FMT_YUV444P
planar YUV 4:4:4, 24bpp, (1 Cr & Cb sample per 1x1 Y samples)
@ AV_PIX_FMT_YUV420P12LE
planar YUV 4:2:0,18bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian
@ AV_PIX_FMT_YUV422P10LE
planar YUV 4:2:2, 20bpp, (1 Cr & Cb sample per 2x1 Y samples), little-endian
@ AV_PIX_FMT_YUV444P16LE
planar YUV 4:4:4, 48bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian
@ AV_PIX_FMT_YUV444P10LE
planar YUV 4:4:4, 30bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian
@ AV_PIX_FMT_YUV420P16LE
planar YUV 4:2:0, 24bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian
@ AV_PIX_FMT_YUV444P12LE
planar YUV 4:4:4,36bpp, (1 Cr & Cb sample per 1x1 Y samples), little-endian
#define AV_PIX_FMT_YUV444P16
#define FF_ARRAY_ELEMS(a)
uint8_t * data
The data buffer.
This struct is allocated as AVHWDeviceContext.hwctx.
AVCUDADeviceContextInternal * internal
Describe the class of an AVClass context structure.
A link between two filters.
int w
agreed upon image width
int h
agreed upon image height
AVFilterContext * src
source filter
AVRational time_base
Define the time base used by the PTS of the frames/samples which will pass through this link.
AVRational sample_aspect_ratio
agreed upon sample aspect ratio
AVFilterContext * dst
dest filter
int format
agreed upon media format
A filter pad used for either input or output.
This structure describes decoded (raw) audio or video data.
enum AVColorRange color_range
MPEG vs JPEG YUV range.
This struct describes a set or pool of "hardware" frames (i.e.
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
uint8_t nb_components
The number of components each pixel has, (1-4)
Link properties exposed to filter code, but not external callers.
AVRational frame_rate
Frame rate of the stream on the link, or 1/0 if unknown or variable.
AVBufferRef * hw_frames_ctx
For hwaccel pixel formats, this should be a reference to the AVHWFramesContext describing the frames.
static int ref[MAX_W *MAX_W]
static enum AVPixelFormat supported_formats[]
static int format_is_supported(enum AVPixelFormat fmt)
static int config_input_ref(AVFilterLink *inlink)
static enum VmafPoolingMethod pool_method_map(const char *pool_method)
static int copy_picture_data(AVFrame *src, VmafPicture *dst, unsigned bpc)
static const AVFilterPad libvmaf_inputs[]
static int parse_models(AVFilterContext *ctx)
static int do_vmaf(FFFrameSync *fs)
static AVDictionary ** delimited_dict_parse(char *str, unsigned *cnt)
static enum VmafPixelFormat pix_fmt_map(enum AVPixelFormat av_pix_fmt)
static int config_input_ref(AVFilterLink *inlink)
static const AVOption libvmaf_options[]
static enum VmafLogLevel log_level_map(int log_level)
static int activate(AVFilterContext *ctx)
static av_cold void uninit(AVFilterContext *ctx)
static int parse_features(AVFilterContext *ctx)
static int config_output(AVFilterLink *outlink)
static enum VmafOutputFormat log_fmt_map(const char *log_fmt)
static const AVFilterPad libvmaf_outputs[]