diff --git a/subprojects/gst-plugins-bad/sys/msdk/gstmsdkvpputil.c b/subprojects/gst-plugins-bad/sys/msdk/gstmsdkvpputil.c index 938324d51e..07cc06fe05 100644 --- a/subprojects/gst-plugins-bad/sys/msdk/gstmsdkvpputil.c +++ b/subprojects/gst-plugins-bad/sys/msdk/gstmsdkvpputil.c @@ -29,6 +29,11 @@ #include "msdk-enums.h" #include "gstmsdkcaps.h" +#ifndef _WIN32 +#include +#include +#endif + #define SWAP_GINT(a, b) do { \ const gint t = a; a = b; b = t; \ } while (0) @@ -52,6 +57,127 @@ gst_msdkvpp_is_deinterlace_enabled (GstMsdkVPP * msdkvpp, GstVideoInfo * vip) return deinterlace; } +/* This help function is to fixate output format for vpp src caps, + * when downstream element does not set a specific format, i.e. queried + * caps contains a list of formats, vpp src caps will loop the format + * list and find one format that matches the vpp sink caps format (in vinfo); + * if downstream has set a specific format, we use this format for vpp src caps. + */ +static GstCaps * +fixate_output_format (GstMsdkVPP * thiz, GstVideoInfo * vinfo, GstCaps * caps) +{ + GstVideoFormat fmt = GST_VIDEO_FORMAT_UNKNOWN; + guint i, size, fixated_idx = 0; + GstStructure *s, *out = NULL; + GstCapsFeatures *features; + GstCaps *ret; + const GValue *format; + gboolean is_dma = FALSE; + gboolean fixate = FALSE; +#ifndef _WIN32 + guint64 modifier = DRM_FORMAT_MOD_INVALID; + guint32 fourcc; +#endif + + if (!caps) + return NULL; + size = gst_caps_get_size (caps); + + for (i = 0; i < size; i++) { + s = gst_caps_get_structure (caps, i); + features = gst_caps_get_features (caps, i); + + if (gst_caps_features_contains (features, GST_CAPS_FEATURE_MEMORY_DMABUF)) { + format = gst_structure_get_value (s, "drm-format"); + is_dma = TRUE; + } else { + format = gst_structure_get_value (s, "format"); + is_dma = FALSE; + } + + if (format == NULL) + continue; + + if (GST_VALUE_HOLDS_LIST (format)) { + gint j, len; + + len = gst_value_list_get_size (format); + GST_DEBUG_OBJECT (thiz, "have %d formats", len); + for (j = 0; j < len; j++) { + const GValue *val; + + val = gst_value_list_get_value (format, j); + if (G_VALUE_HOLDS_STRING (val)) { +#ifndef _WIN32 + if (is_dma) { + fourcc = gst_video_dma_drm_fourcc_from_string + (g_value_get_string (val), &modifier); + fmt = gst_va_video_format_from_drm_fourcc (fourcc); + } else { + fmt = gst_video_format_from_string (g_value_get_string (val)); + } +#else + fmt = gst_video_format_from_string (g_value_get_string (val)); +#endif + if (fmt == GST_VIDEO_FORMAT_UNKNOWN) + continue; + if (fmt == GST_VIDEO_INFO_FORMAT (vinfo)) { + fixate = TRUE; + fixated_idx = i; + break; + } + } + } + } else if (G_VALUE_HOLDS_STRING (format)) { +#ifndef _WIN32 + if (is_dma) { + fourcc = gst_video_dma_drm_fourcc_from_string + (g_value_get_string (format), &modifier); + fmt = gst_va_video_format_from_drm_fourcc (fourcc); + } else { + fmt = gst_video_format_from_string (g_value_get_string (format)); + } +#else + fmt = gst_video_format_from_string (g_value_get_string (format)); +#endif + if (fmt == GST_VIDEO_FORMAT_UNKNOWN) + continue; + fixate = TRUE; + break; + } + if (fixate) + break; + } + + out = gst_structure_copy (gst_caps_get_structure (caps, fixated_idx)); + features = gst_caps_features_copy (gst_caps_get_features (caps, fixated_idx)); + +#ifndef _WIN32 + if (is_dma) { + gchar *drm_fmt_name; + + g_assert (modifier != DRM_FORMAT_MOD_INVALID); + + drm_fmt_name = gst_video_dma_drm_fourcc_to_string + (gst_va_drm_fourcc_from_video_format (fmt), modifier); + + gst_structure_set (out, "drm-format", G_TYPE_STRING, drm_fmt_name, NULL); + g_free (drm_fmt_name); + } else { + gst_structure_set (out, "format", G_TYPE_STRING, + gst_video_format_to_string (fmt), NULL); + } +#else + gst_structure_set (out, "format", G_TYPE_STRING, + gst_video_format_to_string (fmt), NULL); +#endif + + ret = gst_caps_new_full (out, NULL); + gst_caps_set_features_simple (ret, features); + + return ret; +} + static gboolean fixate_output_frame_size (GstMsdkVPP * thiz, GstVideoInfo * vinfo, GstStructure * outs) @@ -529,27 +655,23 @@ static GstCaps * _get_preferred_src_caps (GstMsdkVPP * thiz, GstVideoInfo * vinfo, GstCaps * srccaps) { - GstStructure *structure; - GstCaps *outcaps; + GstStructure *structure = NULL; + GstCaps *outcaps, *fixate_caps; - structure = gst_caps_get_structure (srccaps, 0); + /* Fixate the format */ + fixate_caps = fixate_output_format (thiz, vinfo, srccaps); + if (!fixate_caps) + goto fixate_failed; + structure = gst_caps_get_structure (fixate_caps, 0); /* make a copy */ structure = gst_structure_copy (structure); + gst_caps_unref (fixate_caps); if (thiz->keep_aspect) gst_structure_set (structure, "pixel-aspect-ratio", GST_TYPE_FRACTION, 1, 1, NULL); - /* Fixate the format */ - if (gst_video_is_dma_drm_caps (srccaps) && - gst_structure_has_field (structure, "drm-format")) { - if (!gst_structure_fixate_field (structure, "drm-format")) - goto fixate_failed; - } else if (gst_structure_has_field (structure, "format")) - if (!gst_structure_fixate_field (structure, "format")) - goto fixate_failed; - /* Fixate the frame size */ if (!fixate_output_frame_size (thiz, vinfo, structure)) goto fixate_failed; @@ -577,7 +699,8 @@ _get_preferred_src_caps (GstMsdkVPP * thiz, GstVideoInfo * vinfo, fixate_failed: { GST_WARNING_OBJECT (thiz, "Could not fixate src caps"); - gst_structure_free (structure); + if (structure) + gst_structure_free (structure); return NULL; } interlace_mode_failed: