Skip to content

Commit 7c7f4e5

Browse files
ntocmassiot
authored andcommitted
upipe_ffmt: add support for filters options
1 parent a0ff584 commit 7c7f4e5

File tree

1 file changed

+243
-41
lines changed

1 file changed

+243
-41
lines changed

lib/upipe-filters/upipe_filter_format.c

Lines changed: 243 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,16 @@ struct upipe_ffmt {
127127

128128
/** swscale flags */
129129
int sws_flags;
130+
/** deinterlace_vaapi mode option */
131+
const char *deinterlace_vaapi_mode;
132+
/** scale_vaapi mode option */
133+
const char *scale_vaapi_mode;
134+
/** vpp_qsv deinterlace option */
135+
const char *vpp_qsv_deinterlace;
136+
/** vpp_qsv scale_mode option */
137+
const char *vpp_qsv_scale_mode;
138+
/** ni_quadra_scale filterblit option */
139+
const char *ni_quadra_scale_filterblit;
130140

131141
/** avfilter hw config type */
132142
char *hw_type;
@@ -208,6 +218,11 @@ static struct upipe *upipe_ffmt_alloc(struct upipe_mgr *mgr,
208218
upipe_ffmt->flow_def_wanted = flow_def;
209219
upipe_ffmt->flow_def_requested = NULL;
210220
upipe_ffmt->sws_flags = 0;
221+
upipe_ffmt->deinterlace_vaapi_mode = NULL;
222+
upipe_ffmt->scale_vaapi_mode = NULL;
223+
upipe_ffmt->vpp_qsv_deinterlace = NULL;
224+
upipe_ffmt->vpp_qsv_scale_mode = NULL;
225+
upipe_ffmt->ni_quadra_scale_filterblit = NULL;
211226
upipe_ffmt->hw_type = NULL;
212227
upipe_ffmt->hw_device = NULL;
213228
upipe_throw_ready(upipe);
@@ -376,16 +391,30 @@ static int upipe_ffmt_check_flow_format(struct upipe *upipe,
376391
bool pic_vaapi_out = !strcmp(surface_type_out, "av.vaapi");
377392
bool pic_qsv_in = !strcmp(surface_type_in, "av.qsv");
378393
bool pic_qsv_out = !strcmp(surface_type_out, "av.qsv");
379-
bool hw_in = pic_vaapi_in || pic_qsv_in;
380-
bool hw_out = pic_vaapi_out || pic_qsv_out;
394+
bool pic_quadra_in = !strcmp(surface_type_in, "av.ni_quadra");
395+
bool pic_quadra_out = !strcmp(surface_type_out, "av.ni_quadra");
396+
bool hw_in = pic_vaapi_in || pic_qsv_in || pic_quadra_in;
397+
bool hw_out = pic_vaapi_out || pic_qsv_out || pic_quadra_out;
381398
bool hw = hw_in || hw_out;
399+
int bit_depth_in = 0;
400+
int bit_depth_out = 0;
401+
uref_pic_flow_get_bit_depth(flow_def, &bit_depth_in);
402+
uref_pic_flow_get_bit_depth(flow_def_dup, &bit_depth_out);
382403
bool need_hw_transfer = (hw_in && !hw_out) || (!hw_in && hw_out);
383404
bool need_derive = pic_vaapi_in && pic_qsv_out;
405+
bool need_tonemap = ubase_check(uref_pic_flow_check_hdr10(flow_def)) &&
406+
ubase_check(uref_pic_flow_check_sdr(flow_def_dup));
384407
bool need_avfilter = ffmt_mgr->avfilter_mgr && hw &&
385408
(need_deint || need_scale || need_format || need_hw_transfer ||
386409
need_derive || need_range);
387410

388411
if (need_avfilter) {
412+
const char *range_in =
413+
ubase_check(uref_pic_flow_get_full_range(flow_def)) ?
414+
"full" : "limited";
415+
const char *range_out =
416+
ubase_check(uref_pic_flow_get_full_range(flow_def_dup)) ?
417+
"full" : "limited";
389418
if (need_format) {
390419
const char *pix_fmt_in = "unknown";
391420
const char *pix_fmt_out = "unknown";
@@ -414,18 +443,15 @@ static int upipe_ffmt_check_flow_format(struct upipe *upipe,
414443
" → %" PRIu64 "x%" PRIu64,
415444
hsize_in, vsize_in, hsize_out, vsize_out);
416445
}
417-
if (need_range) {
418-
const char *from =
419-
ubase_check(uref_pic_flow_get_full_range(flow_def)) ?
420-
"full" : "limited";
421-
const char *to =
422-
ubase_check(uref_pic_flow_get_full_range(flow_def_dup)) ?
423-
"full" : "limited";
446+
if (need_range)
424447
upipe_notice_va(upipe, "need range conversion %s → %s",
425-
from, to);
426-
}
448+
range_in, range_out);
427449
if (need_derive)
428450
upipe_notice(upipe, "need hw surface mapping vaapi → qsv");
451+
if (need_deint)
452+
upipe_notice(upipe, "need deinterlace");
453+
if (need_tonemap)
454+
upipe_notice(upipe, "need tonemap hdr10 → sdr");
429455

430456
uint64_t hsize = 0, vsize = 0;
431457
uref_pic_flow_get_hsize(flow_def_dup, &hsize);
@@ -438,43 +464,160 @@ static int upipe_ffmt_check_flow_format(struct upipe *upipe,
438464
upipe_avfilt_mgr_get_pixfmt_name(ffmt_mgr->avfilter_mgr,
439465
flow_def_dup, &pix_fmt_sw, true);
440466

467+
int val;
468+
469+
const char *color_matrix = NULL;
470+
UBASE_RETURN(uref_pic_flow_get_matrix_coefficients_val(
471+
flow_def_dup, &val))
472+
if (val != 2)
473+
UBASE_RETURN(upipe_avfilt_mgr_get_color_space_name(
474+
ffmt_mgr->avfilter_mgr, val, &color_matrix))
475+
476+
const char *color_primaries = NULL;
477+
UBASE_RETURN(uref_pic_flow_get_colour_primaries_val(
478+
flow_def_dup, &val))
479+
if (val != 2)
480+
UBASE_RETURN(upipe_avfilt_mgr_get_color_primaries_name(
481+
ffmt_mgr->avfilter_mgr, val, &color_primaries))
482+
483+
const char *color_transfer = NULL;
484+
UBASE_RETURN(uref_pic_flow_get_transfer_characteristics_val(
485+
flow_def_dup, &val))
486+
if (val != 2)
487+
UBASE_RETURN(upipe_avfilt_mgr_get_color_transfer_name(
488+
ffmt_mgr->avfilter_mgr, val, &color_transfer))
489+
490+
bool in_10bit = bit_depth_in == 10;
491+
bool out_10bit = bit_depth_out == 10;
492+
const char *pix_fmt_semiplanar_in = in_10bit ? "p010le" : "nv12";
493+
const char *pix_fmt_semiplanar_out = out_10bit ? "p010le" : "nv12";
494+
441495
char filters[512];
442496
int pos = 0;
443-
444-
#define str_cat(fmt, ...) pos += sprintf(filters + pos, fmt, ##__VA_ARGS__)
445-
446-
if (!hw_in)
447-
str_cat("scale,format=nv12,hwupload,");
448-
if (need_deint)
449-
str_cat("deinterlace_vaapi=auto=1,");
450-
if (need_scale || need_format || need_range) {
451-
str_cat("scale_vaapi=");
452-
if (need_scale)
453-
str_cat("w=%"PRIu64":h=%"PRIu64, hsize, vsize);
454-
if (need_format) {
455-
if (need_scale)
456-
str_cat(":");
457-
str_cat("format=%s", pix_fmt_sw);
497+
int opt;
498+
499+
#define add_filter(Name) \
500+
pos += (opt = 0, snprintf(filters + pos, sizeof(filters) - pos, \
501+
"%s%s", pos ? "," : "", Name))
502+
503+
#define add_option(Fmt, ...) \
504+
pos += snprintf(filters + pos, sizeof(filters) - pos, \
505+
"%s" Fmt, opt++ ? ":" : "=", ##__VA_ARGS__)
506+
507+
if (!hw_in) {
508+
if (pic_quadra_out) {
509+
if (need_deint) {
510+
add_filter("yadif");
511+
add_option("deint=interlaced");
512+
}
513+
} else {
514+
add_filter("scale");
515+
add_option("interl=-1");
516+
add_filter("format");
517+
add_option("%s", pix_fmt_semiplanar_in);
518+
}
519+
add_filter("hwupload");
520+
}
521+
if (pic_qsv_in || pic_qsv_out) {
522+
if (pic_vaapi_in) {
523+
add_filter("hwmap");
524+
add_option("derive_device=qsv");
525+
add_filter("format");
526+
add_option("qsv");
527+
}
528+
add_filter("vpp_qsv");
529+
if (need_deint)
530+
add_option("deinterlace=%s",
531+
upipe_ffmt->vpp_qsv_deinterlace ?: "advanced");
532+
if (need_scale) {
533+
add_option("width=%"PRIu64, hsize);
534+
add_option("height=%"PRIu64, vsize);
535+
}
536+
add_option("scale_mode=%s",
537+
upipe_ffmt->vpp_qsv_scale_mode ?: "hq");
538+
if (need_format)
539+
add_option("format=%s", pix_fmt_sw);
540+
if (need_range)
541+
add_option("out_range=%s", range_out);
542+
if (color_matrix)
543+
add_option("out_color_matrix=%s", color_matrix);
544+
if (color_primaries)
545+
add_option("out_color_primaries=%s", color_primaries);
546+
if (color_transfer)
547+
add_option("out_color_transfer=%s", color_transfer);
548+
add_option("tonemap=%d", need_tonemap ? 1 : 0);
549+
add_option("async_depth=0");
550+
} else {
551+
if (need_deint && !pic_quadra_out) {
552+
add_filter("deinterlace_vaapi");
553+
add_option("auto=1");
554+
if (upipe_ffmt->deinterlace_vaapi_mode)
555+
add_option("mode=%s",
556+
upipe_ffmt->deinterlace_vaapi_mode);
458557
}
459-
if (need_range) {
460-
if (need_scale || need_format)
461-
str_cat(":");
462-
str_cat("out_range=%s",
463-
ubase_check(uref_pic_flow_get_full_range(flow_def_dup)) ?
464-
"full" : "limited");
558+
if (need_scale || need_format || need_range) {
559+
if (pic_quadra_out) {
560+
add_filter("ni_quadra_scale");
561+
if (need_scale)
562+
add_option("size=%"PRIu64"x%"PRIu64, hsize, vsize);
563+
if (upipe_ffmt->ni_quadra_scale_filterblit)
564+
add_option("filterblit=%s",
565+
upipe_ffmt->ni_quadra_scale_filterblit);
566+
else
567+
add_option("autoselect=1");
568+
} else {
569+
add_filter("scale_vaapi");
570+
add_option("mode=%s",
571+
upipe_ffmt->scale_vaapi_mode ?: "hq");
572+
if (need_scale) {
573+
add_option("w=%"PRIu64, hsize);
574+
add_option("h=%"PRIu64, vsize);
575+
}
576+
if (need_range)
577+
add_option("out_range=%s", range_out);
578+
if (color_primaries)
579+
add_option("out_color_primaries=%s",
580+
color_primaries);
581+
if (color_transfer)
582+
add_option("out_color_transfer=%s",
583+
color_transfer);
584+
}
585+
if (color_matrix)
586+
add_option("out_color_matrix=%s", color_matrix);
587+
if (need_format)
588+
add_option("format=%s", pix_fmt_sw);
589+
}
590+
if (need_tonemap && (pic_vaapi_in || pic_vaapi_out)) {
591+
add_filter("tonemap_vaapi");
592+
add_option("format=%s", pix_fmt_sw);
593+
if (color_matrix)
594+
add_option("matrix=%s", color_matrix);
595+
if (color_primaries)
596+
add_option("primaries=%s", color_primaries);
597+
if (color_transfer)
598+
add_option("transfer=%s", color_transfer);
465599
}
466-
str_cat(",");
467600
}
468601
if (!hw_out) {
469-
str_cat("hwmap=mode=read+direct,format=nv12,");
470-
if (pix_fmt != NULL && strcmp(pix_fmt, "nv12"))
471-
str_cat("scale,format=%s,", pix_fmt);
472-
} else if (pic_qsv_out && (need_deint || need_scale || pic_vaapi_in))
473-
str_cat("hwmap=derive_device=qsv,format=qsv");
474-
#undef str_cat
602+
add_filter("hwmap");
603+
add_option("mode=read+direct");
604+
add_filter("format");
605+
add_option("%s", pix_fmt_semiplanar_out);
606+
if (pix_fmt != NULL && strcmp(pix_fmt, pix_fmt_semiplanar_out)) {
607+
add_filter("scale");
608+
add_option("interl=-1");
609+
add_filter("format");
610+
add_option("%s", pix_fmt);
611+
}
612+
}
475613

476-
if (filters[pos - 1] == ',')
477-
filters[pos - 1] = '\0';
614+
#undef add_filter
615+
#undef add_option
616+
617+
if (pos >= sizeof(filters)) {
618+
upipe_err(upipe, "filtergraph too long");
619+
return UBASE_ERR_INVALID;
620+
}
478621

479622
struct upipe *avfilt = upipe_void_alloc(
480623
ffmt_mgr->avfilter_mgr,
@@ -627,6 +770,60 @@ static int upipe_ffmt_check_flow_format(struct upipe *upipe,
627770
return err;
628771
}
629772

773+
/** @internal @This sets the filters options.
774+
*
775+
* @param upipe description structure of the pipe
776+
* @param option option name (filter name/option)
777+
* @param value value or NULL to use the default value
778+
* @return an error code
779+
*/
780+
static int upipe_ffmt_set_option(struct upipe *upipe,
781+
const char *option,
782+
const char *value)
783+
{
784+
struct upipe_ffmt *upipe_ffmt = upipe_ffmt_from_upipe(upipe);
785+
786+
if (!strcmp(option, "deinterlace_vaapi/mode"))
787+
// default bob weave motion_adaptive motion_compensated
788+
upipe_ffmt->deinterlace_vaapi_mode = value;
789+
else if (!strcmp(option, "scale_vaapi/mode"))
790+
// default fast hq nl_anamorphic
791+
upipe_ffmt->scale_vaapi_mode = value;
792+
else if (!strcmp(option, "vpp_qsv/deinterlace"))
793+
// bob advanced
794+
upipe_ffmt->vpp_qsv_deinterlace = value;
795+
else if (!strcmp(option, "vpp_qsv/scale_mode"))
796+
// auto low_power hq compute vd ve
797+
upipe_ffmt->vpp_qsv_scale_mode = value;
798+
else if (!strcmp(option, "ni_quadra_scale/filterblit"))
799+
// 0 1 2
800+
upipe_ffmt->ni_quadra_scale_filterblit = value;
801+
else if (!strcmp(option, "deinterlace-preset")) {
802+
if (!strcmp(value, "fast")) {
803+
upipe_ffmt->deinterlace_vaapi_mode = "bob";
804+
upipe_ffmt->vpp_qsv_deinterlace = "bob";
805+
} else if (!strcmp(value, "hq")) {
806+
upipe_ffmt->deinterlace_vaapi_mode = "motion_compensated";
807+
upipe_ffmt->vpp_qsv_deinterlace = "advanced";
808+
} else
809+
return UBASE_ERR_INVALID;
810+
} else if (!strcmp(option, "scale-preset")) {
811+
if (!strcmp(value, "fast")) {
812+
upipe_ffmt->scale_vaapi_mode = "fast";
813+
upipe_ffmt->vpp_qsv_scale_mode = "low_power";
814+
upipe_ffmt->ni_quadra_scale_filterblit = "0";
815+
} else if (!strcmp(value, "hq")) {
816+
upipe_ffmt->scale_vaapi_mode = "hq";
817+
upipe_ffmt->vpp_qsv_scale_mode = "hq";
818+
upipe_ffmt->ni_quadra_scale_filterblit = NULL;
819+
} else
820+
return UBASE_ERR_INVALID;
821+
} else
822+
return UBASE_ERR_INVALID;
823+
824+
return UBASE_ERR_NONE;
825+
}
826+
630827
/** @internal @This sets the input flow definition.
631828
*
632829
* @param upipe description structure of the pipe
@@ -784,6 +981,11 @@ static int upipe_ffmt_control(struct upipe *upipe, int command, va_list args)
784981
break;
785982
}
786983

984+
case UPIPE_SET_OPTION: {
985+
const char *option = va_arg(args, const char *);
986+
const char *value = va_arg(args, const char *);
987+
return upipe_ffmt_set_option(upipe, option, value);
988+
}
787989
case UPIPE_SET_FLOW_DEF: {
788990
struct uref *flow_def = va_arg(args, struct uref *);
789991
return upipe_ffmt_set_flow_def(upipe, flow_def);

0 commit comments

Comments
 (0)