mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-22 16:26:39 +00:00
gl: add a method to get DMA formats and modifiers
By calling the internal function gst_gl_context_egl_fetch_dma_formats() the an array of structures holding a DMA fourcc format and its modifiers (another array of structure holing modifier and if it's external only) will be stored. Users would call gst_gl_context_egl_get_format_modifiers() to get the array of modifiers of a specific DMA fourcc format. Co-authored-by: He Junyan <junyan.he@intel.com> Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4680>
This commit is contained in:
parent
4008b872bb
commit
7eed950caa
2 changed files with 274 additions and 0 deletions
|
@ -59,6 +59,19 @@
|
|||
|
||||
#define GST_CAT_DEFAULT gst_gl_context_debug
|
||||
|
||||
typedef struct _GstGLDmaFormat GstGLDmaFormat;
|
||||
|
||||
/**
|
||||
* GstGLDmaFormat: (skip)
|
||||
*
|
||||
* Opaque struct
|
||||
*/
|
||||
struct _GstGLDmaFormat
|
||||
{
|
||||
gint fourcc;
|
||||
GArray *modifiers;
|
||||
};
|
||||
|
||||
static gboolean gst_gl_context_egl_create_context (GstGLContext * context,
|
||||
GstGLAPI gl_api, GstGLContext * other_context, GError ** error);
|
||||
static void gst_gl_context_egl_destroy_context (GstGLContext * context);
|
||||
|
@ -1195,6 +1208,8 @@ gst_gl_context_egl_destroy_context (GstGLContext * context)
|
|||
gst_object_unref (window);
|
||||
}
|
||||
|
||||
g_clear_pointer (&egl->dma_formats, g_array_unref);
|
||||
|
||||
gst_gl_context_egl_activate (context, FALSE);
|
||||
|
||||
if (egl->egl_surface) {
|
||||
|
@ -1506,3 +1521,244 @@ failure:
|
|||
gst_object_unref (display_egl);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#if GST_GL_HAVE_DMABUF
|
||||
static int
|
||||
_compare_dma_formats (gconstpointer a, gconstpointer b)
|
||||
{
|
||||
return ((((GstGLDmaFormat *) a)->fourcc) - (((GstGLDmaFormat *) b)->fourcc));
|
||||
}
|
||||
|
||||
static void
|
||||
_free_dma_formats (gpointer data)
|
||||
{
|
||||
GstGLDmaFormat *format = data;
|
||||
if (format->modifiers)
|
||||
g_array_unref (format->modifiers);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_gl_context_egl_get_dma_formats: (skip)
|
||||
* @context: A #GstGLContextEGL object
|
||||
*
|
||||
* Returns: %TRUE if the array of DMABufs modifiers were fetched. Otherwise,
|
||||
* %FALSE
|
||||
*/
|
||||
static gboolean
|
||||
gst_gl_context_egl_fetch_dma_formats (GstGLContext * context)
|
||||
{
|
||||
GstGLContextEGL *egl;
|
||||
EGLDisplay egl_dpy = EGL_DEFAULT_DISPLAY;
|
||||
GstGLDisplayEGL *gl_dpy_egl;
|
||||
EGLint *formats = NULL, num_formats, mods_len = 0;
|
||||
guint i, j;
|
||||
gboolean ret;
|
||||
EGLuint64KHR *modifiers = NULL;
|
||||
EGLBoolean *ext_only = NULL;
|
||||
GArray *dma_formats;
|
||||
|
||||
EGLBoolean (*gst_eglQueryDmaBufFormatsEXT) (EGLDisplay dpy,
|
||||
EGLint max_formats, EGLint * formats, EGLint * num_formats);
|
||||
EGLBoolean (*gst_eglQueryDmaBufModifiersEXT) (EGLDisplay dpy,
|
||||
EGLint format, EGLint max_modifiers, EGLuint64KHR * modifiers,
|
||||
EGLBoolean * external_only, EGLint * num_modifiers);
|
||||
|
||||
egl = GST_GL_CONTEXT_EGL (context);
|
||||
|
||||
GST_OBJECT_LOCK (context);
|
||||
if (egl->dma_formats) {
|
||||
GST_OBJECT_UNLOCK (context);
|
||||
return TRUE;
|
||||
}
|
||||
GST_OBJECT_UNLOCK (context);
|
||||
|
||||
if (!gst_gl_context_check_feature (context,
|
||||
"EGL_EXT_image_dma_buf_import_modifiers")) {
|
||||
GST_WARNING_OBJECT (context, "\"EGL_EXT_image_dma_buf_import_modifiers\" "
|
||||
"feature is not available");
|
||||
goto failed;
|
||||
}
|
||||
|
||||
gst_eglQueryDmaBufFormatsEXT =
|
||||
gst_gl_context_get_proc_address (context, "eglQueryDmaBufFormatsEXT");
|
||||
if (!gst_eglQueryDmaBufFormatsEXT) {
|
||||
GST_ERROR_OBJECT (context, "\"eglQueryDmaBufFormatsEXT\" not exposed by the"
|
||||
" implementation as required by EGL >= 1.2");
|
||||
goto failed;
|
||||
}
|
||||
|
||||
gst_eglQueryDmaBufModifiersEXT =
|
||||
gst_gl_context_get_proc_address (context, "eglQueryDmaBufModifiersEXT");
|
||||
if (!gst_eglQueryDmaBufModifiersEXT) {
|
||||
GST_ERROR_OBJECT (context, "\"eglQueryDmaBufModifiersEXT\" not exposed by "
|
||||
"the implementation as required by EGL >= 1.2");
|
||||
goto failed;
|
||||
}
|
||||
|
||||
gl_dpy_egl = gst_gl_display_egl_from_gl_display (context->display);
|
||||
if (!gl_dpy_egl) {
|
||||
GST_WARNING_OBJECT (context,
|
||||
"Failed to retrieve GstGLDisplayEGL from %" GST_PTR_FORMAT,
|
||||
context->display);
|
||||
goto failed;
|
||||
}
|
||||
egl_dpy =
|
||||
(EGLDisplay) gst_gl_display_get_handle (GST_GL_DISPLAY (gl_dpy_egl));
|
||||
gst_object_unref (gl_dpy_egl);
|
||||
|
||||
ret = gst_eglQueryDmaBufFormatsEXT (egl_dpy, 0, NULL, &num_formats);
|
||||
if (!ret) {
|
||||
GST_WARNING_OBJECT (context, "Failed to get number of DMABuf formats: %s",
|
||||
gst_egl_get_error_string (eglGetError ()));
|
||||
goto failed;
|
||||
}
|
||||
if (num_formats == 0) {
|
||||
GST_INFO_OBJECT (context, "No DMABuf formats available");
|
||||
goto failed;
|
||||
}
|
||||
|
||||
formats = g_new (EGLint, num_formats);
|
||||
|
||||
ret = gst_eglQueryDmaBufFormatsEXT (egl_dpy, num_formats, formats,
|
||||
&num_formats);
|
||||
if (!ret) {
|
||||
GST_ERROR_OBJECT (context, "Failed to get number of DMABuf formats: %s",
|
||||
gst_egl_get_error_string (eglGetError ()));
|
||||
goto failed;
|
||||
}
|
||||
if (num_formats == 0) {
|
||||
GST_ERROR_OBJECT (context, "No DMABuf formats available");
|
||||
goto failed;
|
||||
}
|
||||
|
||||
dma_formats = g_array_sized_new (FALSE, FALSE, sizeof (GstGLDmaFormat),
|
||||
num_formats);
|
||||
g_array_set_clear_func (dma_formats, _free_dma_formats);
|
||||
|
||||
for (i = 0; i < num_formats; i++) {
|
||||
EGLint num_mods = 0;
|
||||
GstVideoFormat gst_format;
|
||||
GstGLDmaFormat dma_frmt;
|
||||
|
||||
gst_format = gst_video_dma_drm_fourcc_to_format (formats[i]);
|
||||
if (gst_format == GST_VIDEO_FORMAT_UNKNOWN)
|
||||
continue;
|
||||
|
||||
dma_frmt.fourcc = formats[i];
|
||||
dma_frmt.modifiers = NULL;
|
||||
|
||||
ret = gst_eglQueryDmaBufModifiersEXT (egl_dpy, formats[i], 0,
|
||||
NULL, NULL, &num_mods);
|
||||
if (!ret) {
|
||||
GST_WARNING_OBJECT (context, "Failed to get number of DMABuf modifiers: "
|
||||
"%s", gst_egl_get_error_string (eglGetError ()));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (num_mods > 0) {
|
||||
|
||||
if (mods_len == 0) {
|
||||
modifiers = g_new (EGLuint64KHR, num_mods);
|
||||
ext_only = g_new (EGLBoolean, num_mods);
|
||||
mods_len = num_mods;
|
||||
} else if (mods_len < num_mods) {
|
||||
modifiers = g_renew (EGLuint64KHR, modifiers, num_mods);
|
||||
ext_only = g_renew (EGLBoolean, ext_only, num_mods);
|
||||
mods_len = num_mods;
|
||||
}
|
||||
|
||||
ret = gst_eglQueryDmaBufModifiersEXT (egl_dpy, formats[i], num_mods,
|
||||
modifiers, ext_only, &num_mods);
|
||||
if (!ret) {
|
||||
GST_ERROR_OBJECT (context, "Failed to get number of DMABuf modifiers: "
|
||||
"%s", gst_egl_get_error_string (eglGetError ()));
|
||||
continue;
|
||||
}
|
||||
|
||||
dma_frmt.modifiers = g_array_sized_new (FALSE, FALSE,
|
||||
sizeof (GstGLDmaModifier), num_mods);
|
||||
dma_frmt.modifiers = g_array_set_size (dma_frmt.modifiers, num_mods);
|
||||
|
||||
for (j = 0; j < num_mods; j++) {
|
||||
GstGLDmaModifier *modifier =
|
||||
&g_array_index (dma_frmt.modifiers, GstGLDmaModifier, j);
|
||||
modifier->modifier = modifiers[j];
|
||||
modifier->external_only = ext_only[j];
|
||||
}
|
||||
}
|
||||
|
||||
g_array_append_val (dma_formats, dma_frmt);
|
||||
}
|
||||
|
||||
g_array_sort (dma_formats, _compare_dma_formats);
|
||||
|
||||
GST_OBJECT_LOCK (context);
|
||||
egl->dma_formats = dma_formats;
|
||||
GST_OBJECT_UNLOCK (context);
|
||||
|
||||
g_free (formats);
|
||||
g_free (modifiers);
|
||||
g_free (ext_only);
|
||||
|
||||
return TRUE;
|
||||
|
||||
failed:
|
||||
{
|
||||
g_free (formats);
|
||||
GST_OBJECT_UNLOCK (context);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
#endif /* GST_GL_HAVE_DMABUF */
|
||||
|
||||
/**
|
||||
* gst_gl_context_egl_get_format_modifiers: (skip)
|
||||
* @context: an EGL #GStGLContext
|
||||
* @fourcc: the FourCC format to look up
|
||||
* @modifiers: (out) (nullable) (element-type GstGLDmaModifier) (transfer none):
|
||||
* #GArray of modifiers for @fourcc
|
||||
*
|
||||
* Don't modify the content of @modifiers.
|
||||
*
|
||||
* Returns: %TRUE if the @modifiers for @fourcc were fetched correctly.
|
||||
*
|
||||
* Since: 1.24
|
||||
*/
|
||||
gboolean
|
||||
gst_gl_context_egl_get_format_modifiers (GstGLContext * context, gint fourcc,
|
||||
const GArray ** modifiers)
|
||||
{
|
||||
#if GST_GL_HAVE_DMABUF
|
||||
GstGLContextEGL *egl;
|
||||
GstGLDmaFormat *format;
|
||||
guint index;
|
||||
gboolean ret = FALSE;
|
||||
|
||||
g_return_val_if_fail (GST_IS_GL_CONTEXT_EGL (context), FALSE);
|
||||
|
||||
if (!gst_gl_context_egl_fetch_dma_formats (context))
|
||||
return FALSE;
|
||||
|
||||
egl = GST_GL_CONTEXT_EGL (context);
|
||||
|
||||
GST_OBJECT_LOCK (context);
|
||||
if (!egl->dma_formats)
|
||||
goto beach;
|
||||
|
||||
if (!g_array_binary_search (egl->dma_formats, &fourcc, _compare_dma_formats,
|
||||
&index))
|
||||
goto beach;
|
||||
|
||||
format = &g_array_index (egl->dma_formats, GstGLDmaFormat, index);
|
||||
if (!format)
|
||||
goto beach;
|
||||
|
||||
*modifiers = format->modifiers;
|
||||
ret = TRUE;
|
||||
|
||||
beach:
|
||||
GST_OBJECT_UNLOCK (context);
|
||||
return ret;
|
||||
#endif
|
||||
return FALSE;
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct _GstGLDmaModifier GstGLDmaModifier;
|
||||
typedef struct _GstGLContextEGL GstGLContextEGL;
|
||||
typedef struct _GstGLContextEGLClass GstGLContextEGLClass;
|
||||
|
||||
|
@ -40,6 +41,17 @@ G_GNUC_INTERNAL GType gst_gl_context_egl_get_type (void);
|
|||
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstGLContextEGL, gst_object_unref)
|
||||
|
||||
/**
|
||||
* GstGLDmaModifier: (skip)
|
||||
*
|
||||
* Opaque struct
|
||||
*/
|
||||
struct _GstGLDmaModifier
|
||||
{
|
||||
/*< private >*/
|
||||
guint64 modifier;
|
||||
gboolean external_only;
|
||||
};
|
||||
|
||||
/**
|
||||
* GstGLContextEGL:
|
||||
|
@ -70,6 +82,8 @@ struct _GstGLContextEGL
|
|||
gulong window_handle_signal;
|
||||
|
||||
GstStructure *requested_config;
|
||||
|
||||
GArray *dma_formats;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -95,6 +109,10 @@ gpointer gst_gl_context_egl_get_proc_address (GstGLAPI gl_api, co
|
|||
G_GNUC_INTERNAL
|
||||
gboolean gst_gl_context_egl_fill_info (GstGLContext * context, GError ** error);
|
||||
|
||||
G_GNUC_INTERNAL
|
||||
gboolean gst_gl_context_egl_get_format_modifiers (GstGLContext * context,
|
||||
gint fourcc,
|
||||
const GArray ** modifiers);
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GST_GL_CONTEXT_EGL_H__ */
|
||||
|
|
Loading…
Reference in a new issue