History

avfilter/scale_npp: add scale2ref_npp filter

Roman Arzumanyan committed 5 years ago

Commit 08a50191 parent 82e32516 files · +620 −40Browse files

Showing the changes to libavfilter (4 of 6 files). Show all

Unified · Split

4 files
  1. libavfilter/Makefile +1 −0
  2. libavfilter/allfilters.c +1 −0
  3. libavfilter/version.h +1 −1
  4. libavfilter/vf_scale_npp.c +505 −39
libavfilter/Makefile+1−0
@@ -415,6 +415,7 @@ OBJS-$(CONFIG_SCALE_QSV_FILTER) += vf_scale_qsv.o · 414 unmodified lines
415OBJS-$(CONFIG_SCALE_VAAPI_FILTER) += vf_scale_vaapi.o scale_eval.o vaapi_vpp.o415OBJS-$(CONFIG_SCALE_VAAPI_FILTER) += vf_scale_vaapi.o scale_eval.o vaapi_vpp.o
416OBJS-$(CONFIG_SCALE_VULKAN_FILTER) += vf_scale_vulkan.o vulkan.o416OBJS-$(CONFIG_SCALE_VULKAN_FILTER) += vf_scale_vulkan.o vulkan.o
417OBJS-$(CONFIG_SCALE2REF_FILTER) += vf_scale.o scale_eval.o417OBJS-$(CONFIG_SCALE2REF_FILTER) += vf_scale.o scale_eval.o
418OBJS-$(CONFIG_SCALE2REF_NPP_FILTER) += vf_scale_npp.o scale_eval.o
418OBJS-$(CONFIG_SCDET_FILTER) += vf_scdet.o419OBJS-$(CONFIG_SCDET_FILTER) += vf_scdet.o
419OBJS-$(CONFIG_SCHARR_FILTER) += vf_convolution.o420OBJS-$(CONFIG_SCHARR_FILTER) += vf_convolution.o
420OBJS-$(CONFIG_SCROLL_FILTER) += vf_scroll.o421OBJS-$(CONFIG_SCROLL_FILTER) += vf_scroll.o
libavfilter/allfilters.c+1−0
@@ -396,6 +396,7 @@ extern const AVFilter ff_vf_scale_qsv; · 395 unmodified lines
396extern const AVFilter ff_vf_scale_vaapi;396extern const AVFilter ff_vf_scale_vaapi;
397extern const AVFilter ff_vf_scale_vulkan;397extern const AVFilter ff_vf_scale_vulkan;
398extern const AVFilter ff_vf_scale2ref;398extern const AVFilter ff_vf_scale2ref;
399extern const AVFilter ff_vf_scale2ref_npp;
399extern const AVFilter ff_vf_scdet;400extern const AVFilter ff_vf_scdet;
400extern const AVFilter ff_vf_scharr;401extern const AVFilter ff_vf_scharr;
401extern const AVFilter ff_vf_scroll;402extern const AVFilter ff_vf_scroll;
libavfilter/version.h+1−1
@@ -31,7 +31,7 @@ · 30 unmodified lines
31 31
32#define LIBAVFILTER_VERSION_MAJOR 832#define LIBAVFILTER_VERSION_MAJOR 8
33#define LIBAVFILTER_VERSION_MINOR 1633#define LIBAVFILTER_VERSION_MINOR 16
34#define LIBAVFILTER_VERSION_MICRO 10034#define LIBAVFILTER_VERSION_MICRO 101
35 35
36 36
37#define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \37#define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \
libavfilter/vf_scale_npp.c+505−39
@@ -25,13 +25,13 @@ · 24 unmodified lines
25#include <stdio.h>25#include <stdio.h>
26#include <string.h>26#include <string.h>
27 27
28#include "libavutil/avstring.h"
29#include "libavutil/common.h"
30#include "libavutil/hwcontext.h"28#include "libavutil/hwcontext.h"
31#include "libavutil/hwcontext_cuda_internal.h"29#include "libavutil/hwcontext_cuda_internal.h"
32#include "libavutil/cuda_check.h"30#include "libavutil/cuda_check.h"
33#include "libavutil/internal.h"31#include "libavutil/internal.h"
34#include "libavutil/opt.h"32#include "libavutil/opt.h"
33#include "libavutil/parseutils.h"
34#include "libavutil/eval.h"
35#include "libavutil/pixdesc.h"35#include "libavutil/pixdesc.h"
36 36
37#include "avfilter.h"37#include "avfilter.h"
@@ -44,6 +44,7 @@ · 6 unmodified lines
44 44
45static const enum AVPixelFormat supported_formats[] = {45static const enum AVPixelFormat supported_formats[] = {
46 AV_PIX_FMT_YUV420P,46 AV_PIX_FMT_YUV420P,
47 AV_PIX_FMT_YUVA420P,
47 AV_PIX_FMT_NV12,48 AV_PIX_FMT_NV12,
48 AV_PIX_FMT_YUV444P,49 AV_PIX_FMT_YUV444P,
49};50};
@@ -67,12 +68,62 @@ typedef struct NPPScaleStageContext { · 17 unmodified lines
67 struct {68 struct {
68 int width;69 int width;
69 int height;70 int height;
70 } planes_in[3], planes_out[3];71 } planes_in[4], planes_out[4];
71 72
72 AVBufferRef *frames_ctx;73 AVBufferRef *frames_ctx;
73 AVFrame *frame;74 AVFrame *frame;
74} NPPScaleStageContext;75} NPPScaleStageContext;
75 76
77static const char *const var_names[] = {
78 "in_w", "iw",
79 "in_h", "ih",
80 "out_w", "ow",
81 "out_h", "oh",
82 "a",
83 "sar",
84 "dar",
85 "n",
86 "t",
87 "pos",
88 "main_w",
89 "main_h",
90 "main_a",
91 "main_sar",
92 "main_dar", "mdar",
93 "main_n",
94 "main_t",
95 "main_pos",
96 NULL
97};
98
99enum var_name {
100 VAR_IN_W, VAR_IW,
101 VAR_IN_H, VAR_IH,
102 VAR_OUT_W, VAR_OW,
103 VAR_OUT_H, VAR_OH,
104 VAR_A,
105 VAR_SAR,
106 VAR_DAR,
107 VAR_N,
108 VAR_T,
109 VAR_POS,
110 VAR_S2R_MAIN_W,
111 VAR_S2R_MAIN_H,
112 VAR_S2R_MAIN_A,
113 VAR_S2R_MAIN_SAR,
114 VAR_S2R_MAIN_DAR, VAR_S2R_MDAR,
115 VAR_S2R_MAIN_N,
116 VAR_S2R_MAIN_T,
117 VAR_S2R_MAIN_POS,
118 VARS_NB
119};
120
121enum EvalMode {
122 EVAL_MODE_INIT,
123 EVAL_MODE_FRAME,
124 EVAL_MODE_NB
125};
126
76typedef struct NPPScaleContext {127typedef struct NPPScaleContext {
77 const AVClass *class;128 const AVClass *class;
78 129
@@ -102,35 +153,269 @@ typedef struct NPPScaleContext { · 23 unmodified lines
102 int force_divisible_by;153 int force_divisible_by;
103 154
104 int interp_algo;155 int interp_algo;
156
157 char* size_str;
158
159 AVExpr* w_pexpr;
160 AVExpr* h_pexpr;
161
162 double var_values[VARS_NB];
163
164 int eval_mode;
105} NPPScaleContext;165} NPPScaleContext;
106 166
107static int nppscale_init(AVFilterContext *ctx)167const AVFilter ff_vf_scale2ref_npp;
168
169static int config_props(AVFilterLink *outlink);
170
171static int check_exprs(AVFilterContext* ctx)
108{172{
109 NPPScaleContext *s = ctx->priv;173 NPPScaleContext* scale = ctx->priv;
110 int i;174 unsigned vars_w[VARS_NB] = {0}, vars_h[VARS_NB] = {0};
175
176 if (!scale->w_pexpr && !scale->h_pexpr)
177 return AVERROR(EINVAL);
178
179 if (scale->w_pexpr)
180 av_expr_count_vars(scale->w_pexpr, vars_w, VARS_NB);
181 if (scale->h_pexpr)
182 av_expr_count_vars(scale->h_pexpr, vars_h, VARS_NB);
183
184 if (vars_w[VAR_OUT_W] || vars_w[VAR_OW]) {
185 av_log(ctx, AV_LOG_ERROR, "Width expression cannot be self-referencing: '%s'.\n", scale->w_expr);
186 return AVERROR(EINVAL);
187 }
188
189 if (vars_h[VAR_OUT_H] || vars_h[VAR_OH]) {
190 av_log(ctx, AV_LOG_ERROR, "Height expression cannot be self-referencing: '%s'.\n", scale->h_expr);
191 return AVERROR(EINVAL);
192 }
193
194 if ((vars_w[VAR_OUT_H] || vars_w[VAR_OH]) &&
195 (vars_h[VAR_OUT_W] || vars_h[VAR_OW])) {
196 av_log(ctx, AV_LOG_WARNING, "Circular references detected for width '%s' and height '%s' - possibly invalid.\n", scale->w_expr, scale->h_expr);
197 }
198
199 if (ctx->filter != &ff_vf_scale2ref_npp &&
200 (vars_w[VAR_S2R_MAIN_W] || vars_h[VAR_S2R_MAIN_W] ||
201 vars_w[VAR_S2R_MAIN_H] || vars_h[VAR_S2R_MAIN_H] ||
202 vars_w[VAR_S2R_MAIN_A] || vars_h[VAR_S2R_MAIN_A] ||
203 vars_w[VAR_S2R_MAIN_SAR] || vars_h[VAR_S2R_MAIN_SAR] ||
204 vars_w[VAR_S2R_MAIN_DAR] || vars_h[VAR_S2R_MAIN_DAR] ||
205 vars_w[VAR_S2R_MDAR] || vars_h[VAR_S2R_MDAR] ||
206 vars_w[VAR_S2R_MAIN_N] || vars_h[VAR_S2R_MAIN_N] ||
207 vars_w[VAR_S2R_MAIN_T] || vars_h[VAR_S2R_MAIN_T] ||
208 vars_w[VAR_S2R_MAIN_POS] || vars_h[VAR_S2R_MAIN_POS])) {
209 av_log(ctx, AV_LOG_ERROR, "Expressions with scale2ref_npp variables are not valid in scale_npp filter.\n");
210 return AVERROR(EINVAL);
211 }
212
213 if (scale->eval_mode == EVAL_MODE_INIT &&
214 (vars_w[VAR_N] || vars_h[VAR_N] ||
215 vars_w[VAR_T] || vars_h[VAR_T] ||
216 vars_w[VAR_POS] || vars_h[VAR_POS] ||
217 vars_w[VAR_S2R_MAIN_N] || vars_h[VAR_S2R_MAIN_N] ||
218 vars_w[VAR_S2R_MAIN_T] || vars_h[VAR_S2R_MAIN_T] ||
219 vars_w[VAR_S2R_MAIN_POS] || vars_h[VAR_S2R_MAIN_POS]) ) {
220 av_log(ctx, AV_LOG_ERROR, "Expressions with frame variables 'n', 't', 'pos' are not valid in init eval_mode.\n");
221 return AVERROR(EINVAL);
222 }
223
224 return 0;
225}
226
227static int nppscale_parse_expr(AVFilterContext* ctx, char* str_expr,
228 AVExpr** pexpr_ptr, const char* var,
229 const char* args)
230{
231 NPPScaleContext* scale = ctx->priv;
232 int ret, is_inited = 0;
233 char* old_str_expr = NULL;
234 AVExpr* old_pexpr = NULL;
235
236 if (str_expr) {
237 old_str_expr = av_strdup(str_expr);
238 if (!old_str_expr)
239 return AVERROR(ENOMEM);
240 av_opt_set(scale, var, args, 0);
241 }
242
243 if (*pexpr_ptr) {
244 old_pexpr = *pexpr_ptr;
245 *pexpr_ptr = NULL;
246 is_inited = 1;
247 }
248
249 ret = av_expr_parse(pexpr_ptr, args, var_names, NULL, NULL, NULL, NULL, 0,
250 ctx);
251 if (ret < 0) {
252 av_log(ctx, AV_LOG_ERROR, "Cannot parse expression for %s: '%s'\n", var,
253 args);
254 goto revert;
255 }
256
257 ret = check_exprs(ctx);
258 if (ret < 0)
259 goto revert;
260
261 if (is_inited && (ret = config_props(ctx->outputs[0])) < 0)
262 goto revert;
263
264 av_expr_free(old_pexpr);
265 old_pexpr = NULL;
266 av_freep(&old_str_expr);
267
268 return 0;
269
270revert:
271 av_expr_free(*pexpr_ptr);
272 *pexpr_ptr = NULL;
273 if (old_str_expr) {
274 av_opt_set(scale, var, old_str_expr, 0);
275 av_free(old_str_expr);
276 }
277 if (old_pexpr)
278 *pexpr_ptr = old_pexpr;
279
280 return ret;
281}
282
283static av_cold int nppscale_init(AVFilterContext* ctx)
284{
285 NPPScaleContext* scale = ctx->priv;
286 int i, ret;
111 287
112 if (!strcmp(s->format_str, "same")) {288 if (!strcmp(scale->format_str, "same")) {
113 s->format = AV_PIX_FMT_NONE;289 scale->format = AV_PIX_FMT_NONE;
114 } else {290 } else {
115 s->format = av_get_pix_fmt(s->format_str);291 scale->format = av_get_pix_fmt(scale->format_str);
116 if (s->format == AV_PIX_FMT_NONE) {292 if (scale->format == AV_PIX_FMT_NONE) {
117 av_log(ctx, AV_LOG_ERROR, "Unrecognized pixel format: %s\n", s->format_str);293 av_log(ctx, AV_LOG_ERROR, "Unrecognized pixel format: %s\n", scale->format_str);
118 return AVERROR(EINVAL);294 return AVERROR(EINVAL);
119 }295 }
120 }296 }
121 297
122 for (i = 0; i < FF_ARRAY_ELEMS(s->stages); i++) {298 if (scale->size_str && (scale->w_expr || scale->h_expr)) {
123 s->stages[i].frame = av_frame_alloc();299 av_log(ctx, AV_LOG_ERROR,
124 if (!s->stages[i].frame)300 "Size and width/height exprs cannot be set at the same time.\n");
301 return AVERROR(EINVAL);
302 }
303
304 if (scale->w_expr && !scale->h_expr)
305 FFSWAP(char*, scale->w_expr, scale->size_str);
306
307 if (scale->size_str) {
308 char buf[32];
309 ret = av_parse_video_size(&scale->w, &scale->h, scale->size_str);
310 if (0 > ret) {
311 av_log(ctx, AV_LOG_ERROR, "Invalid size '%s'\n", scale->size_str);
312 return ret;
313 }
314
315 snprintf(buf, sizeof(buf) - 1, "%d", scale->w);
316 ret = av_opt_set(scale, "w", buf, 0);
317 if (ret < 0)
318 return ret;
319
320 snprintf(buf, sizeof(buf) - 1, "%d", scale->h);
321 ret = av_opt_set(scale, "h", buf, 0);
322 if (ret < 0)
323 return ret;
324 }
325
326 if (!scale->w_expr) {
327 ret = av_opt_set(scale, "w", "iw", 0);
328 if (ret < 0)
329 return ret;
330 }
331
332 if (!scale->h_expr) {
333 ret = av_opt_set(scale, "h", "ih", 0);
334 if (ret < 0)
335 return ret;
336 }
337
338 ret = nppscale_parse_expr(ctx, NULL, &scale->w_pexpr, "width", scale->w_expr);
339 if (ret < 0)
340 return ret;
341
342 ret = nppscale_parse_expr(ctx, NULL, &scale->h_pexpr, "height", scale->h_expr);
343 if (ret < 0)
344 return ret;
345
346 for (i = 0; i < FF_ARRAY_ELEMS(scale->stages); i++) {
347 scale->stages[i].frame = av_frame_alloc();
348 if (!scale->stages[i].frame)
125 return AVERROR(ENOMEM);349 return AVERROR(ENOMEM);
126 }350 }
127 s->tmp_frame = av_frame_alloc();351 scale->tmp_frame = av_frame_alloc();
128 if (!s->tmp_frame)352 if (!scale->tmp_frame)
129 return AVERROR(ENOMEM);353 return AVERROR(ENOMEM);
130 354
131 return 0;355 return 0;
132}356}
133 357
358static int nppscale_eval_dimensions(AVFilterContext* ctx)
359{
360 NPPScaleContext* scale = ctx->priv;
361 const char scale2ref = ctx->filter == &ff_vf_scale2ref_npp;
362 const AVFilterLink* inlink = ctx->inputs[scale2ref ? 1 : 0];
363 char* expr;
364 int eval_w, eval_h;
365 int ret;
366 double res;
367
368 scale->var_values[VAR_IN_W] = scale->var_values[VAR_IW] = inlink->w;
369 scale->var_values[VAR_IN_H] = scale->var_values[VAR_IH] = inlink->h;
370 scale->var_values[VAR_OUT_W] = scale->var_values[VAR_OW] = NAN;
371 scale->var_values[VAR_OUT_H] = scale->var_values[VAR_OH] = NAN;
372 scale->var_values[VAR_A] = (double)inlink->w / inlink->h;
373 scale->var_values[VAR_SAR] = inlink->sample_aspect_ratio.num ?
374 (double)inlink->sample_aspect_ratio.num / inlink->sample_aspect_ratio.den : 1;
375 scale->var_values[VAR_DAR] = scale->var_values[VAR_A] * scale->var_values[VAR_SAR];
376
377 if (scale2ref) {
378 const AVFilterLink* main_link = ctx->inputs[0];
379
380 scale->var_values[VAR_S2R_MAIN_W] = main_link->w;
381 scale->var_values[VAR_S2R_MAIN_H] = main_link->h;
382 scale->var_values[VAR_S2R_MAIN_A] = (double)main_link->w / main_link->h;
383 scale->var_values[VAR_S2R_MAIN_SAR] = main_link->sample_aspect_ratio.num ?
384 (double)main_link->sample_aspect_ratio.num / main_link->sample_aspect_ratio.den : 1;
385 scale->var_values[VAR_S2R_MAIN_DAR] = scale->var_values[VAR_S2R_MDAR] =
386 scale->var_values[VAR_S2R_MAIN_A] * scale->var_values[VAR_S2R_MAIN_SAR];
387 }
388
389 res = av_expr_eval(scale->w_pexpr, scale->var_values, NULL);
390 eval_w = scale->var_values[VAR_OUT_W] = scale->var_values[VAR_OW] = (int)res == 0 ? inlink->w : (int)res;
391
392 res = av_expr_eval(scale->h_pexpr, scale->var_values, NULL);
393 if (isnan(res)) {
394 expr = scale->h_expr;
395 ret = AVERROR(EINVAL);
396 goto fail;
397 }
398 eval_h = scale->var_values[VAR_OUT_H] = scale->var_values[VAR_OH] = (int)res == 0 ? inlink->h : (int)res;
399
400 res = av_expr_eval(scale->w_pexpr, scale->var_values, NULL);
401 if (isnan(res)) {
402 expr = scale->w_expr;
403 ret = AVERROR(EINVAL);
404 goto fail;
405 }
406 eval_w = scale->var_values[VAR_OUT_W] = scale->var_values[VAR_OW] = (int)res == 0 ? inlink->w : (int)res;
407
408 scale->w = eval_w;
409 scale->h = eval_h;
410
411 return 0;
412
413fail:
414 av_log(ctx, AV_LOG_ERROR, "Error when evaluating the expression '%s'.\n",
415 expr);
416 return ret;
417}
418
134static void nppscale_uninit(AVFilterContext *ctx)419static void nppscale_uninit(AVFilterContext *ctx)
135{420{
136 NPPScaleContext *s = ctx->priv;421 NPPScaleContext *s = ctx->priv;
@@ -141,6 +426,10 @@ static void nppscale_uninit(AVFilterContext *ctx) · 4 unmodified lines
141 av_buffer_unref(&s->stages[i].frames_ctx);426 av_buffer_unref(&s->stages[i].frames_ctx);
142 }427 }
143 av_frame_free(&s->tmp_frame);428 av_frame_free(&s->tmp_frame);
429
430 av_expr_free(s->w_pexpr);
431 av_expr_free(s->h_pexpr);
432 s->w_pexpr = s->h_pexpr = NULL;
144}433}
145 434
146static int init_stage(NPPScaleStageContext *stage, AVBufferRef *device_ctx)435static int init_stage(NPPScaleStageContext *stage, AVBufferRef *device_ctx)
@@ -164,6 +453,13 @@ static int init_stage(NPPScaleStageContext *stage, AVBufferRef *device_ctx) · 17 unmodified lines
164 stage->planes_out[i].height = stage->planes_out[0].height >> out_sh;453 stage->planes_out[i].height = stage->planes_out[0].height >> out_sh;
165 }454 }
166 455
456 if (AV_PIX_FMT_YUVA420P == stage->in_fmt) {
457 stage->planes_in[3].width = stage->planes_in[0].width;
458 stage->planes_in[3].height = stage->planes_in[0].height;
459 stage->planes_out[3].width = stage->planes_out[0].width;
460 stage->planes_out[3].height = stage->planes_out[0].height;
461 }
462
167 out_ref = av_hwframe_ctx_alloc(device_ctx);463 out_ref = av_hwframe_ctx_alloc(device_ctx);
168 if (!out_ref)464 if (!out_ref)
169 return AVERROR(ENOMEM);465 return AVERROR(ENOMEM);
@@ -326,31 +622,32 @@ static int init_processing_chain(AVFilterContext *ctx, int in_width, int in_heig · 156 unmodified lines
326 return 0;622 return 0;
327}623}
328 624
329static int nppscale_config_props(AVFilterLink *outlink)625static int config_props(AVFilterLink *outlink)
330{626{
331 AVFilterContext *ctx = outlink->src;627 AVFilterContext *ctx = outlink->src;
332 AVFilterLink *inlink = outlink->src->inputs[0];628 AVFilterLink *inlink0 = outlink->src->inputs[0];
629 AVFilterLink *inlink = ctx->filter == &ff_vf_scale2ref_npp ?
630 outlink->src->inputs[1] :
631 outlink->src->inputs[0];
333 NPPScaleContext *s = ctx->priv;632 NPPScaleContext *s = ctx->priv;
334 int w, h;
335 int ret;633 int ret;
336 634
337 if ((ret = ff_scale_eval_dimensions(s,635 if ((ret = nppscale_eval_dimensions(ctx)) < 0)
338 s->w_expr, s->h_expr,
339 inlink, outlink,
340 &w, &h)) < 0)
341 goto fail;636 goto fail;
342 637
343 ff_scale_adjust_dimensions(inlink, &w, &h,638 ff_scale_adjust_dimensions(inlink, &s->w, &s->h,
344 s->force_original_aspect_ratio, s->force_divisible_by);639 s->force_original_aspect_ratio,
640 s->force_divisible_by);
345 641
346 if (((int64_t)h * inlink->w) > INT_MAX ||642 if (s->w > INT_MAX || s->h > INT_MAX ||
347 ((int64_t)w * inlink->h) > INT_MAX)643 (s->h * inlink->w) > INT_MAX ||
644 (s->w * inlink->h) > INT_MAX)
348 av_log(ctx, AV_LOG_ERROR, "Rescaled value for width or height is too big.\n");645 av_log(ctx, AV_LOG_ERROR, "Rescaled value for width or height is too big.\n");
349 646
350 outlink->w = w;647 outlink->w = s->w;
351 outlink->h = h;648 outlink->h = s->h;
352 649
353 ret = init_processing_chain(ctx, inlink->w, inlink->h, w, h);650 ret = init_processing_chain(ctx, inlink0->w, inlink0->h, outlink->w, outlink->h);
354 if (ret < 0)651 if (ret < 0)
355 return ret;652 return ret;
356 653
@@ -370,6 +667,22 @@ fail: · 13 unmodified lines
370 return ret;667 return ret;
371}668}
372 669
670static int config_props_ref(AVFilterLink *outlink)
671{
672 AVFilterLink *inlink = outlink->src->inputs[1];
673 AVFilterContext *ctx = outlink->src;
674
675 outlink->w = inlink->w;
676 outlink->h = inlink->h;
677 outlink->sample_aspect_ratio = inlink->sample_aspect_ratio;
678 outlink->time_base = inlink->time_base;
679 outlink->frame_rate = inlink->frame_rate;
680
681 ctx->outputs[1]->hw_frames_ctx = av_buffer_ref(ctx->inputs[1]->hw_frames_ctx);
682
683 return 0;
684}
685
373static int nppscale_deinterleave(AVFilterContext *ctx, NPPScaleStageContext *stage,686static int nppscale_deinterleave(AVFilterContext *ctx, NPPScaleStageContext *stage,
374 AVFrame *out, AVFrame *in)687 AVFrame *out, AVFrame *in)
375{688{
@@ -454,12 +767,71 @@ static int (*const nppscale_process[])(AVFilterContext *ctx, NPPScaleStageContex · 78 unmodified lines
454 [STAGE_INTERLEAVE] = nppscale_interleave,767 [STAGE_INTERLEAVE] = nppscale_interleave,
455};768};
456 769
457static int nppscale_scale(AVFilterContext *ctx, AVFrame *out, AVFrame *in)770static int nppscale_scale(AVFilterLink *link, AVFrame *out, AVFrame *in)
458{771{
772 AVFilterContext *ctx = link->dst;
459 NPPScaleContext *s = ctx->priv;773 NPPScaleContext *s = ctx->priv;
774 AVFilterLink *outlink = ctx->outputs[0];
460 AVFrame *src = in;775 AVFrame *src = in;
776 char buf[32];
461 int i, ret, last_stage = -1;777 int i, ret, last_stage = -1;
778 int frame_changed;
779
780 frame_changed = in->width != link->w ||
781 in->height != link->h ||
782 in->format != link->format ||
783 in->sample_aspect_ratio.den != link->sample_aspect_ratio.den ||
784 in->sample_aspect_ratio.num != link->sample_aspect_ratio.num;
785
786 if (s->eval_mode == EVAL_MODE_FRAME || frame_changed) {
787 unsigned vars_w[VARS_NB] = { 0 }, vars_h[VARS_NB] = { 0 };
788
789 av_expr_count_vars(s->w_pexpr, vars_w, VARS_NB);
790 av_expr_count_vars(s->h_pexpr, vars_h, VARS_NB);
791
792 if (s->eval_mode == EVAL_MODE_FRAME && !frame_changed && ctx->filter != &ff_vf_scale2ref_npp &&
793 !(vars_w[VAR_N] || vars_w[VAR_T] || vars_w[VAR_POS]) &&
794 !(vars_h[VAR_N] || vars_h[VAR_T] || vars_h[VAR_POS]) &&
795 s->w && s->h)
796 goto scale;
797
798 if (s->eval_mode == EVAL_MODE_INIT) {
799 snprintf(buf, sizeof(buf)-1, "%d", outlink->w);
800 av_opt_set(s, "w", buf, 0);
801 snprintf(buf, sizeof(buf)-1, "%d", outlink->h);
802 av_opt_set(s, "h", buf, 0);
803
804 ret = nppscale_parse_expr(ctx, NULL, &s->w_pexpr, "width", s->w_expr);
805 if (ret < 0)
806 return ret;
807
808 ret = nppscale_parse_expr(ctx, NULL, &s->h_pexpr, "height", s->h_expr);
809 if (ret < 0)
810 return ret;
811 }
812
813 if (ctx->filter == &ff_vf_scale2ref_npp) {
814 s->var_values[VAR_S2R_MAIN_N] = link->frame_count_out;
815 s->var_values[VAR_S2R_MAIN_T] = TS2T(in->pts, link->time_base);
816 s->var_values[VAR_S2R_MAIN_POS] = in->pkt_pos == -1 ? NAN : in->pkt_pos;
817 } else {
818 s->var_values[VAR_N] = link->frame_count_out;
819 s->var_values[VAR_T] = TS2T(in->pts, link->time_base);
820 s->var_values[VAR_POS] = in->pkt_pos == -1 ? NAN : in->pkt_pos;
821 }
822
823 link->format = in->format;
824 link->w = in->width;
825 link->h = in->height;
826
827 link->sample_aspect_ratio.den = in->sample_aspect_ratio.den;
828 link->sample_aspect_ratio.num = in->sample_aspect_ratio.num;
462 829
830 if ((ret = config_props(outlink)) < 0)
831 return ret;
832 }
833
834scale:
463 for (i = 0; i < FF_ARRAY_ELEMS(s->stages); i++) {835 for (i = 0; i < FF_ARRAY_ELEMS(s->stages); i++) {
464 if (!s->stages[i].stage_needed)836 if (!s->stages[i].stage_needed)
465 continue;837 continue;
@@ -516,7 +888,7 @@ static int nppscale_filter_frame(AVFilterLink *link, AVFrame *in) · 50 unmodified lines
516 if (ret < 0)888 if (ret < 0)
517 goto fail;889 goto fail;
518 890
519 ret = nppscale_scale(ctx, out, in);891 ret = nppscale_scale(link, out, in);
520 892
521 CHECK_CU(device_hwctx->internal->cuda_dl->cuCtxPopCurrent(&dummy));893 CHECK_CU(device_hwctx->internal->cuda_dl->cuCtxPopCurrent(&dummy));
522 if (ret < 0)894 if (ret < 0)
@@ -535,12 +907,54 @@ fail: · 12 unmodified lines
535 return ret;907 return ret;
536}908}
537 909
910static int nppscale_filter_frame_ref(AVFilterLink *link, AVFrame *in)
911{
912 NPPScaleContext *scale = link->dst->priv;
913 AVFilterLink *outlink = link->dst->outputs[1];
914 int frame_changed;
915
916 frame_changed = in->width != link->w ||
917 in->height != link->h ||
918 in->format != link->format ||
919 in->sample_aspect_ratio.den != link->sample_aspect_ratio.den ||
920 in->sample_aspect_ratio.num != link->sample_aspect_ratio.num;
921
922 if (frame_changed) {
923 link->format = in->format;
924 link->w = in->width;
925 link->h = in->height;
926 link->sample_aspect_ratio.num = in->sample_aspect_ratio.num;
927 link->sample_aspect_ratio.den = in->sample_aspect_ratio.den;
928
929 config_props_ref(outlink);
930 }
931
932 if (scale->eval_mode == EVAL_MODE_FRAME) {
933 scale->var_values[VAR_N] = link->frame_count_out;
934 scale->var_values[VAR_T] = TS2T(in->pts, link->time_base);
935 scale->var_values[VAR_POS] = in->pkt_pos == -1 ? NAN : in->pkt_pos;
936 }
937
938 return ff_filter_frame(outlink, in);
939}
940
941static int request_frame(AVFilterLink *outlink)
942{
943 return ff_request_frame(outlink->src->inputs[0]);
944}
945
946static int request_frame_ref(AVFilterLink *outlink)
947{
948 return ff_request_frame(outlink->src->inputs[1]);
949}
950
538#define OFFSET(x) offsetof(NPPScaleContext, x)951#define OFFSET(x) offsetof(NPPScaleContext, x)
539#define FLAGS (AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM)952#define FLAGS (AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM)
540static const AVOption options[] = {953static const AVOption options[] = {
541 { "w", "Output video width", OFFSET(w_expr), AV_OPT_TYPE_STRING, { .str = "iw" }, .flags = FLAGS },954 { "w", "Output video width", OFFSET(w_expr), AV_OPT_TYPE_STRING, .flags = FLAGS },
542 { "h", "Output video height", OFFSET(h_expr), AV_OPT_TYPE_STRING, { .str = "ih" }, .flags = FLAGS },955 { "h", "Output video height", OFFSET(h_expr), AV_OPT_TYPE_STRING, .flags = FLAGS },
543 { "format", "Output pixel format", OFFSET(format_str), AV_OPT_TYPE_STRING, { .str = "same" }, .flags = FLAGS },956 { "format", "Output pixel format", OFFSET(format_str), AV_OPT_TYPE_STRING, { .str = "same" }, .flags = FLAGS },
957 { "s", "Output video size", OFFSET(size_str), AV_OPT_TYPE_STRING, { .str = NULL }, .flags = FLAGS },
544 958
545 { "interp_algo", "Interpolation algorithm used for resizing", OFFSET(interp_algo), AV_OPT_TYPE_INT, { .i64 = NPPI_INTER_CUBIC }, 0, INT_MAX, FLAGS, "interp_algo" },959 { "interp_algo", "Interpolation algorithm used for resizing", OFFSET(interp_algo), AV_OPT_TYPE_INT, { .i64 = NPPI_INTER_CUBIC }, 0, INT_MAX, FLAGS, "interp_algo" },
546 { "nn", "nearest neighbour", 0, AV_OPT_TYPE_CONST, { .i64 = NPPI_INTER_NN }, 0, 0, FLAGS, "interp_algo" },960 { "nn", "nearest neighbour", 0, AV_OPT_TYPE_CONST, { .i64 = NPPI_INTER_NN }, 0, 0, FLAGS, "interp_algo" },
@@ -551,11 +965,14 @@ static const AVOption options[] = { · 4 unmodified lines
551 { "cubic2p_b05c03", "2-parameter cubic (B=1/2, C=3/10)", 0, AV_OPT_TYPE_CONST, { .i64 = NPPI_INTER_CUBIC2P_B05C03 }, 0, 0, FLAGS, "interp_algo" },965 { "cubic2p_b05c03", "2-parameter cubic (B=1/2, C=3/10)", 0, AV_OPT_TYPE_CONST, { .i64 = NPPI_INTER_CUBIC2P_B05C03 }, 0, 0, FLAGS, "interp_algo" },
552 { "super", "supersampling", 0, AV_OPT_TYPE_CONST, { .i64 = NPPI_INTER_SUPER }, 0, 0, FLAGS, "interp_algo" },966 { "super", "supersampling", 0, AV_OPT_TYPE_CONST, { .i64 = NPPI_INTER_SUPER }, 0, 0, FLAGS, "interp_algo" },
553 { "lanczos", "Lanczos", 0, AV_OPT_TYPE_CONST, { .i64 = NPPI_INTER_LANCZOS }, 0, 0, FLAGS, "interp_algo" },967 { "lanczos", "Lanczos", 0, AV_OPT_TYPE_CONST, { .i64 = NPPI_INTER_LANCZOS }, 0, 0, FLAGS, "interp_algo" },
554 { "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, 2, FLAGS, "force_oar" },968 { "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, 2, FLAGS, "force_oar" },
555 { "disable", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = 0 }, 0, 0, FLAGS, "force_oar" },969 { "disable", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = 0 }, 0, 0, FLAGS, "force_oar" },
556 { "decrease", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = 1 }, 0, 0, FLAGS, "force_oar" },970 { "decrease", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = 1 }, 0, 0, FLAGS, "force_oar" },
557 { "increase", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = 2 }, 0, 0, FLAGS, "force_oar" },971 { "increase", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = 2 }, 0, 0, FLAGS, "force_oar" },
558 { "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, FLAGS },972 { "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, FLAGS },
973 { "eval", "specify when to evaluate expressions", OFFSET(eval_mode), AV_OPT_TYPE_INT, { .i64 = EVAL_MODE_INIT }, 0, EVAL_MODE_NB-1, FLAGS, "eval" },
974 { "init", "eval expressions once during initialization", 0, AV_OPT_TYPE_CONST, { .i64 = EVAL_MODE_INIT }, 0, 0, FLAGS, "eval" },
975 { "frame", "eval expressions during initialization and per-frame", 0, AV_OPT_TYPE_CONST, { .i64 = EVAL_MODE_FRAME }, 0, 0, FLAGS, "eval" },
559 { NULL },976 { NULL },
560};977};
561 978
@@ -564,6 +981,7 @@ static const AVClass nppscale_class = { · 2 unmodified lines
564 .item_name = av_default_item_name,981 .item_name = av_default_item_name,
565 .option = options,982 .option = options,
566 .version = LIBAVUTIL_VERSION_INT,983 .version = LIBAVUTIL_VERSION_INT,
984 .category = AV_CLASS_CATEGORY_FILTER,
567};985};
568 986
569static const AVFilterPad nppscale_inputs[] = {987static const AVFilterPad nppscale_inputs[] = {
@@ -571,15 +989,15 @@ static const AVFilterPad nppscale_inputs[] = { · 1 unmodified line
571 .name = "default",989 .name = "default",
572 .type = AVMEDIA_TYPE_VIDEO,990 .type = AVMEDIA_TYPE_VIDEO,
573 .filter_frame = nppscale_filter_frame,991 .filter_frame = nppscale_filter_frame,
574 },992 }
575};993};
576 994
577static const AVFilterPad nppscale_outputs[] = {995static const AVFilterPad nppscale_outputs[] = {
578 {996 {
579 .name = "default",997 .name = "default",
580 .type = AVMEDIA_TYPE_VIDEO,998 .type = AVMEDIA_TYPE_VIDEO,
581 .config_props = nppscale_config_props,999 .config_props = config_props,
582 },1000 }
583};1001};
584 1002
585const AVFilter ff_vf_scale_npp = {1003const AVFilter ff_vf_scale_npp = {
@@ -600,3 +1018,51 @@ const AVFilter ff_vf_scale_npp = { · 14 unmodified lines
600 1018
601 .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE,1019 .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE,
602};1020};
1021
1022static const AVFilterPad nppscale2ref_inputs[] = {
1023 {
1024 .name = "default",
1025 .type = AVMEDIA_TYPE_VIDEO,
1026 .filter_frame = nppscale_filter_frame,
1027 },
1028 {
1029 .name = "ref",
1030 .type = AVMEDIA_TYPE_VIDEO,
1031 .filter_frame = nppscale_filter_frame_ref,
1032 }
1033};
1034
1035static const AVFilterPad nppscale2ref_outputs[] = {
1036 {
1037 .name = "default",
1038 .type = AVMEDIA_TYPE_VIDEO,
1039 .config_props = config_props,
1040 .request_frame= request_frame,
1041 },
1042 {
1043 .name = "ref",
1044 .type = AVMEDIA_TYPE_VIDEO,
1045 .config_props = config_props_ref,
1046 .request_frame= request_frame_ref,
1047 }
1048};
1049
1050const AVFilter ff_vf_scale2ref_npp = {
1051 .name = "scale2ref_npp",
1052 .description = NULL_IF_CONFIG_SMALL("NVIDIA Performance Primitives video "
1053 "scaling and format conversion to the "
1054 "given reference."),
1055
1056 .init = nppscale_init,
1057 .uninit = nppscale_uninit,
1058
1059 .priv_size = sizeof(NPPScaleContext),
1060 .priv_class = &nppscale_class,
1061
1062 FILTER_INPUTS(nppscale2ref_inputs),
1063 FILTER_OUTPUTS(nppscale2ref_outputs),
1064
1065 FILTER_SINGLE_PIXFMT(AV_PIX_FMT_CUDA),
1066
1067 .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE,
1068};

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t