From b1ebe93eb202aa436a7c9edc6d4ea973ff7b49fd Mon Sep 17 00:00:00 2001 From: Yinhang Liu Date: Mon, 20 Mar 2023 20:41:29 +0800 Subject: [PATCH] msdkvpp: Add function to dynamically create sink caps and src caps We need to create the sink caps and src caps dynamically for different platforms. By default, the vpp init function create static pad template and the compatibility and flexibility of the platform are too poor. Part-of: --- .../gst-plugins-bad/sys/msdk/gstmsdkcaps.c | 344 ++++++++++++++++++ .../gst-plugins-bad/sys/msdk/gstmsdkcaps.h | 4 + 2 files changed, 348 insertions(+) diff --git a/subprojects/gst-plugins-bad/sys/msdk/gstmsdkcaps.c b/subprojects/gst-plugins-bad/sys/msdk/gstmsdkcaps.c index a3bf7494de..cd675a3cce 100644 --- a/subprojects/gst-plugins-bad/sys/msdk/gstmsdkcaps.c +++ b/subprojects/gst-plugins-bad/sys/msdk/gstmsdkcaps.c @@ -38,6 +38,8 @@ #define ENC_IOPATTERN MFX_IOPATTERN_IN_VIDEO_MEMORY #define DEC_IOPATTERN MFX_IOPATTERN_OUT_VIDEO_MEMORY +#define VPP_IOPATTERN \ + MFX_IOPATTERN_IN_VIDEO_MEMORY | MFX_IOPATTERN_OUT_VIDEO_MEMORY #ifdef _WIN32 /* fix "unreferenced local variable" for windows */ @@ -1149,6 +1151,259 @@ failed: return FALSE; } +static void +_vpp_init_param (mfxVideoParam * param, + GstVideoFormat infmt, GstVideoFormat outfmt) +{ + g_return_if_fail (param != NULL); + + memset (param, 0, sizeof (mfxVideoParam)); + param->IOPattern = VPP_IOPATTERN; + param->vpp.In.Width = default_width; + param->vpp.In.Height = default_height; + param->vpp.In.CropW = param->mfx.FrameInfo.Width; + param->vpp.In.CropH = param->mfx.FrameInfo.Height; + param->vpp.In.PicStruct = MFX_PICSTRUCT_PROGRESSIVE; + param->vpp.In.FrameRateExtN = 30; + param->vpp.In.FrameRateExtD = 1; + param->vpp.In.AspectRatioW = 1; + param->vpp.In.AspectRatioH = 1; + + param->vpp.Out = param->vpp.In; + + _fill_mfxframeinfo (infmt, ¶m->vpp.In); + _fill_mfxframeinfo (outfmt, ¶m->vpp.Out); +} + +static inline gboolean +_vpp_is_param_supported (mfxSession * session, + mfxVideoParam * in, mfxVideoParam * out) +{ + mfxStatus status = MFXVideoVPP_Query (*session, in, out); + if (status == MFX_ERR_NONE) + return TRUE; + + return FALSE; +} + +static gboolean +_vpp_are_formats_supported (mfxSession * session, + GstVideoFormat infmt, GstVideoFormat outfmt, + mfxVideoParam * in, mfxVideoParam * out) +{ + if (!_fill_mfxframeinfo (infmt, &in->vpp.In)) + return FALSE; + + if (!_fill_mfxframeinfo (outfmt, &in->vpp.Out)) + return FALSE; + + if (!_vpp_is_param_supported (session, in, out)) + return FALSE; + + return TRUE; +} + +static gboolean +_vpp_get_supported_formats (mfxSession * session, + GValue * supported_in_fmts, GValue * supported_out_fmts) +{ + guint size; + const GValue *gfmt; + GValue fmts = G_VALUE_INIT; + GstVideoFormat infmt = DEFAULT_VIDEO_FORMAT; + GstVideoFormat outfmt = DEFAULT_VIDEO_FORMAT; + gboolean infmt_in_list, outfmt_in_list; + mfxVideoParam in, out; + + _vpp_init_param (&in, infmt, outfmt); + out = in; + + g_value_init (&fmts, GST_TYPE_LIST); + gst_msdk_get_video_format_list (&fmts); + + size = gst_value_list_get_size (&fmts); + for (guint i = 0; i < size; i++) { + gfmt = gst_value_list_get_value (&fmts, i); + infmt = g_value_get_uint (gfmt); + + for (guint j = 0; j < size; j++) { + gfmt = gst_value_list_get_value (&fmts, j); + outfmt = g_value_get_uint (gfmt); + + infmt_in_list = _format_in_list (infmt, supported_in_fmts); + outfmt_in_list = _format_in_list (outfmt, supported_out_fmts); + if (infmt_in_list && outfmt_in_list) + continue; + + if (!_vpp_are_formats_supported (session, infmt, outfmt, &in, &out)) + continue; + + if (!infmt_in_list) + _list_append_string (supported_in_fmts, + gst_video_format_to_string (infmt)); + + if (!outfmt_in_list) + _list_append_string (supported_out_fmts, + gst_video_format_to_string (outfmt)); + } + } + + g_value_unset (&fmts); + + if (gst_value_list_get_size (supported_in_fmts) == 0 || + gst_value_list_get_size (supported_out_fmts) == 0) + return FALSE; + + return TRUE; +} + +static gboolean +_vpp_get_desc_image_range (mfxVPPDescription * vpp_desc, + GstVideoFormat format, mfxRange32U * width, mfxRange32U * height) +{ + mfxU32 infmt = gst_msdk_get_mfx_fourcc_from_format (format); + + for (guint f = 0; f < vpp_desc->NumFilters; f++) { + for (guint i = 0; i < vpp_desc->NumFilters; i++) { + if (vpp_desc->Filters[f].MemDesc->Formats[i].InFormat != infmt) + continue; + + *width = vpp_desc->Filters[f].MemDesc->Width; + *height = vpp_desc->Filters[f].MemDesc->Height; + return TRUE; + } + } + + return FALSE; +} + +static gboolean +_vpp_get_resolution_range (mfxSession * session, + mfxVPPDescription * vpp_desc, ResolutionRange * res_range) +{ + mfxVideoParam in, out; + mfxRange32U width, height; + ResolutionRange res = { default_width, default_width, + default_height, default_height + }; + + g_return_val_if_fail (res_range != NULL, FALSE); + + if (!_vpp_get_desc_image_range (vpp_desc, + DEFAULT_VIDEO_FORMAT, &width, &height)) + return FALSE; + + _vpp_init_param (&in, DEFAULT_VIDEO_FORMAT, DEFAULT_VIDEO_FORMAT); + out = in; + + IsParamSupportedFunc func = _vpp_is_param_supported; + if (!_get_min_width (session, &in, &out, func, &width, &res.min_width) || + !_get_max_width (session, &in, &out, func, &width, &res.max_width) || + !_get_min_height (session, &in, &out, func, &height, &res.min_height) || + !_get_max_height (session, &in, &out, func, &height, &res.max_height)) + return FALSE; + + GST_DEBUG ("Got VPP supported resolution range " + "width: [%d, %d], height: [%d, %d]", + res.min_width, res.max_width, res.min_height, res.max_height); + + res_range->min_width = res.min_width; + res_range->max_width = res.max_width; + res_range->min_height = res.min_height; + res_range->max_height = res.max_height; + + return TRUE; +} + +static GstCaps * +_vpp_create_caps (GstMsdkContext * context, + GValue * supported_fmts, ResolutionRange * res) +{ + GstCaps *caps, *dma_caps; + + caps = gst_caps_from_string ("video/x-raw"); + gst_caps_set_value (caps, "format", supported_fmts); + +#ifndef _WIN32 + dma_caps = gst_caps_from_string ("video/x-raw(memory:DMABuf)"); + gst_caps_set_value (dma_caps, "format", supported_fmts); + gst_caps_append (caps, dma_caps); + + gst_caps_append (caps, + gst_caps_from_string ("video/x-raw(memory:VAMemory), " + "format=(string){ NV12, VUYA, P010_10LE }")); +#else + VAR_UNUSED (dma_caps); + gst_caps_append (caps, + gst_caps_from_string ("video/x-raw(memory:D3D11Memory), " + "format=(string){ NV12, VUYA, P010_10LE }")); +#endif + + gst_caps_set_simple (caps, + "width", GST_TYPE_INT_RANGE, res->min_width, res->max_width, + "height", GST_TYPE_INT_RANGE, res->min_height, res->max_height, NULL); + + gst_msdkcaps_set_strings (caps, "memory:SystemMemory", + "interlace-mode", "progressive, interleaved, mixed"); + + GST_DEBUG ("Create VPP caps %" GST_PTR_FORMAT, caps); + + return caps; +} + +gboolean +gst_msdkcaps_vpp_create_caps (GstMsdkContext * context, + gpointer vpp_description, GstCaps ** sink_caps, GstCaps ** src_caps) +{ + mfxVPPDescription *vpp_desc; + GstCaps *in_caps = NULL, *out_caps = NULL; + GValue supported_in_fmts = G_VALUE_INIT; + GValue supported_out_fmts = G_VALUE_INIT; + ResolutionRange res_range = { 1, G_MAXUINT16, 1, G_MAXUINT16 }; + mfxSession session; + + g_return_val_if_fail (context, FALSE); + g_return_val_if_fail (vpp_description, FALSE); + + session = gst_msdk_context_get_session (context); + vpp_desc = (mfxVPPDescription *) vpp_description; + + g_value_init (&supported_in_fmts, GST_TYPE_LIST); + g_value_init (&supported_out_fmts, GST_TYPE_LIST); + + if (!_vpp_get_supported_formats (&session, + &supported_in_fmts, &supported_out_fmts)) + goto failed; + + if (!_vpp_get_resolution_range (&session, vpp_desc, &res_range)) + goto failed; + + in_caps = _vpp_create_caps (context, &supported_in_fmts, &res_range); + g_value_unset (&supported_in_fmts); + if (!in_caps) + goto failed; + + out_caps = _vpp_create_caps (context, &supported_out_fmts, &res_range); + g_value_unset (&supported_out_fmts); + if (!out_caps) + goto failed; + + *sink_caps = in_caps; + *src_caps = out_caps; + + return TRUE; + +failed: + GST_WARNING ("Failed to create caps for VPP"); + + g_value_unset (&supported_in_fmts); + g_value_unset (&supported_out_fmts); + if (in_caps) + gst_caps_unref (in_caps); + + return FALSE; +} + #else static gboolean @@ -1453,6 +1708,95 @@ failed: return FALSE; } +static const char * +_vpp_get_raw_formats (GstPadDirection direction) +{ + switch (direction) { + case GST_PAD_SINK: + return "NV12, YV12, I420, YUY2, UYVY, VUYA, BGRA, BGRx, P010_10LE, " + "RGB16, Y410, Y210, P012_LE, Y212_LE, Y412_LE"; + case GST_PAD_SRC: + return "NV12, BGRA, YUY2, UYVY, VUYA, BGRx, P010_10LE, BGR10A2_LE, " + "YV12, Y410, Y210, RGBP, BGRP, P012_LE, Y212_LE, Y412_LE"; + default: + GST_WARNING ("Unsupported VPP direction"); + break; + } + + return NULL; +} + +#ifndef _WIN32 +static const char * +_vpp_get_dma_formats (GstPadDirection direction) +{ + switch (direction) { + case GST_PAD_SINK: + return "NV12, BGRA, YUY2, UYVY, VUYA, P010_10LE, RGB16, Y410, Y210, " + "P012_LE, Y212_LE, Y412_LE"; + case GST_PAD_SRC: + return "NV12, BGRA, YUY2, UYVY, VUYA, BGRx, P010_10LE, BGR10A2_LE, " + "YV12, Y410, Y210, RGBP, BGRP, P012_LE, Y212_LE, Y412_LE"; + default: + GST_WARNING ("Unsupported VPP direction"); + break; + } + + return NULL; +} +#endif + +static GstCaps * +_vpp_create_caps (GstMsdkContext * context, GstPadDirection direction) +{ + GstCaps *caps = NULL, *dma_caps = NULL; + gchar *caps_str; + + caps_str = g_strdup_printf ("video/x-raw, format=(string){ %s }", + _vpp_get_raw_formats (direction)); + caps = gst_caps_from_string (caps_str); + g_free (caps_str); + +#ifndef _WIN32 + caps_str = + g_strdup_printf ("video/x-raw(memory:DMABuf), format=(string){ %s }", + _vpp_get_dma_formats (direction)); + dma_caps = gst_caps_from_string (caps_str); + g_free (caps_str); + gst_caps_append (caps, dma_caps); + + gst_caps_append (caps, gst_caps_from_string ("video/x-raw(memory:VAMemory), " + "format=(string){ NV12, VUYA, P010_10LE }")); +#else + VAR_UNUSED (dma_caps); + VAR_UNUSED (caps_str); + + gst_caps_append (caps, + gst_caps_from_string ("video/x-raw(memory:D3D11Memory), " + "format=(string){ NV12, VUYA, P010_10LE }")); +#endif + + gst_caps_set_simple (caps, + "width", GST_TYPE_INT_RANGE, 1, G_MAXINT, + "height", GST_TYPE_INT_RANGE, 1, G_MAXINT, + "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL); + + gst_msdkcaps_set_strings (caps, "memory:SystemMemory", + "interlace-mode", "progressive, interleaved, mixed"); + + return caps; +} + +gboolean +gst_msdkcaps_vpp_create_caps (GstMsdkContext * context, + gpointer vpp_description, GstCaps ** sink_caps, GstCaps ** src_caps) +{ + *sink_caps = _vpp_create_caps (context, GST_PAD_SINK); + *src_caps = _vpp_create_caps (context, GST_PAD_SRC); + + return TRUE; +} + #endif static void diff --git a/subprojects/gst-plugins-bad/sys/msdk/gstmsdkcaps.h b/subprojects/gst-plugins-bad/sys/msdk/gstmsdkcaps.h index edc58441fd..5155c40a88 100644 --- a/subprojects/gst-plugins-bad/sys/msdk/gstmsdkcaps.h +++ b/subprojects/gst-plugins-bad/sys/msdk/gstmsdkcaps.h @@ -53,6 +53,10 @@ gst_msdkcaps_dec_create_caps (GstMsdkContext * context, gpointer dec_description, guint codec_id, GstCaps ** sink_caps, GstCaps ** src_caps); +gboolean +gst_msdkcaps_vpp_create_caps (GstMsdkContext * context, + gpointer vpp_description, GstCaps ** sink_caps, GstCaps ** src_caps); + void gst_msdkcaps_pad_template_init (GstElementClass * klass, GstCaps * sink_caps, GstCaps * src_caps,