From 95707bb80d00eb40b7f6d7cf6cacb1b232a1861a Mon Sep 17 00:00:00 2001 From: He Junyan Date: Fri, 19 May 2023 19:25:15 +0800 Subject: [PATCH] glupload: add a helper function to convert drm formats into gst formats MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Víctor Manuel Jáquez Leal Part-of: --- .../gst-libs/gst/gl/gstglupload.c | 118 ++++++++++++++++++ 1 file changed, 118 insertions(+) diff --git a/subprojects/gst-plugins-base/gst-libs/gst/gl/gstglupload.c b/subprojects/gst-plugins-base/gst-libs/gst/gl/gstglupload.c index a45ef76009..6eac9bf669 100644 --- a/subprojects/gst-plugins-base/gst-libs/gst/gl/gstglupload.c +++ b/subprojects/gst-plugins-base/gst-libs/gst/gl/gstglupload.c @@ -737,6 +737,124 @@ _dma_buf_transform_gst_formats_to_drm_formats (GstGLContext * context, return TRUE; } +static gboolean +_check_modifier (GstGLContext * context, guint32 fourcc, + guint64 modifier, gboolean include_external) +{ + const GArray *dma_modifiers; + guint i; + + /* If no context provide, no further check. */ + if (!context) + return TRUE; + + if (!gst_gl_context_egl_get_format_modifiers (context, fourcc, + &dma_modifiers)) + return FALSE; + + if (!dma_modifiers) { + /* recognize the fourcc but no modifier info, consider it as linear */ + if (modifier == DRM_FORMAT_MOD_LINEAR) + return TRUE; + + return FALSE; + } + + for (i = 0; i < dma_modifiers->len; i++) { + GstGLDmaModifier *mod = &g_array_index (dma_modifiers, GstGLDmaModifier, i); + + if (!mod->external_only || include_external) { + if (mod->modifier == modifier) + return TRUE; + } + } + + return FALSE; +} + +static GstVideoFormat +_get_video_format_from_drm_format (GstGLContext * context, + const gchar * drm_format, gboolean include_external) +{ + GstVideoFormat gst_format; + guint32 fourcc; + guint64 modifier; + + fourcc = gst_video_dma_drm_fourcc_from_string (drm_format, &modifier); + if (fourcc == DRM_FORMAT_INVALID) + return GST_VIDEO_FORMAT_UNKNOWN; + + gst_format = gst_video_dma_drm_fourcc_to_format (fourcc); + if (gst_format == GST_VIDEO_FORMAT_UNKNOWN) + return GST_VIDEO_FORMAT_UNKNOWN; + + if (!_check_modifier (context, fourcc, modifier, include_external)) + return GST_VIDEO_FORMAT_UNKNOWN; + + return gst_format; +} + +/* Given the drm formats in src GValue, collecting all the according + gst formats to dst GValue. Return FALSE if no valid drm formats found. */ +static gboolean +_dma_buf_transform_drm_formats_to_gst_formats (GstGLContext * context, + const GValue * drm_value, gboolean include_external, GValue * video_value) +{ + GstVideoFormat gst_format; + GArray *all_formats = NULL; + guint i; + + all_formats = g_array_new (FALSE, FALSE, sizeof (GstVideoFormat)); + + if (G_VALUE_HOLDS_STRING (drm_value)) { + gst_format = _get_video_format_from_drm_format (context, + g_value_get_string (drm_value), include_external); + + if (gst_format != GST_VIDEO_FORMAT_UNKNOWN) + g_array_append_val (all_formats, gst_format); + } else if (GST_VALUE_HOLDS_LIST (drm_value)) { + guint num_values = gst_value_list_get_size (drm_value); + + for (i = 0; i < num_values; i++) { + const GValue *val = gst_value_list_get_value (drm_value, i); + + gst_format = _get_video_format_from_drm_format (context, + g_value_get_string (val), include_external); + if (gst_format == GST_VIDEO_FORMAT_UNKNOWN) + continue; + + g_array_append_val (all_formats, gst_format); + } + } + + if (all_formats->len == 0) { + g_array_unref (all_formats); + return FALSE; + } + + if (all_formats->len == 1) { + g_value_init (video_value, G_TYPE_STRING); + gst_format = g_array_index (all_formats, GstVideoFormat, 0); + g_value_set_string (video_value, gst_video_format_to_string (gst_format)); + } else { + GValue item = G_VALUE_INIT; + + gst_value_list_init (video_value, all_formats->len); + + for (i = 0; i < all_formats->len; i++) { + g_value_init (&item, G_TYPE_STRING); + gst_format = g_array_index (all_formats, GstVideoFormat, i); + g_value_set_string (&item, gst_video_format_to_string (gst_format)); + gst_value_list_append_value (video_value, &item); + g_value_unset (&item); + } + } + + g_array_unref (all_formats); + + return TRUE; +} + static GstCaps * _dma_buf_upload_transform_caps (gpointer impl, GstGLContext * context, GstPadDirection direction, GstCaps * caps)