Hello,
I’m using gstreamer on imx8mp with NXP patches, but I’ve checked upstream code and I don’t think it’s different – I’ll try to reproduce on my PC next week.
The problem we have is that using a context created with gst_gl_context_new_wrapped()the features check don’t work, which in turn made dmabuf break since this change https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/2925/diffs#diff-content-4885cc453da9f66e3581af312f02697342c4db3b (yes that’s a bit old, we’ve been on debian oldoldstable and are only upgrading now…)
The real use case is this: flutter-elinux-plugins/packages/video_player/elinux/gst_video_player.cc at main · sony/flutter-elinux-plugins · GitHub (gst_egl_image_from_dmabuf() returns null)
Below is a minimal reproducer that fails on our platform, the check feature check is false when it should be true, and in turn we’re not getting any image because it’s not even trying due to the feature check:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <wayland-client.h>
#include <gst/gst.h>
#include <gst/app/gstappsink.h>
#include <gst/video/video.h>
#include <gst/allocators/gstdmabuf.h>
#include <gst/gl/gl.h>
#include <gst/gl/egl/egl.h>
/* --- Wayland globals --- */
static struct wl_display *wl_dpy;
static EGLDisplay egl_dpy;
static EGLContext egl_ctx;
/* -------------------------------------------------------- */
static void init_egl(void)
{
wl_dpy = wl_display_connect(NULL);
if (!wl_dpy) {
fprintf(stderr, "wl_display_connect failed\n");
exit(1);
}
egl_dpy = eglGetDisplay((EGLNativeDisplayType)wl_dpy);
eglInitialize(egl_dpy, NULL, NULL);
EGLint cfg_attr[] = {
EGL_SURFACE_TYPE, EGL_DONT_CARE,
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
EGL_NONE
};
EGLConfig cfg;
EGLint n;
eglChooseConfig(egl_dpy, cfg_attr, &cfg, 1, &n);
EGLint ctx_attr[] = {
EGL_CONTEXT_CLIENT_VERSION, 2,
EGL_NONE
};
egl_ctx = eglCreateContext(
egl_dpy, cfg, EGL_NO_CONTEXT, ctx_attr);
eglMakeCurrent(
egl_dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, egl_ctx);
}
/* -------------------------------------------------------- */
int main(int argc, char **argv)
{
gst_init(&argc, &argv);
init_egl();
/* --- GStreamer pipeline --- */
GstElement *pipeline = gst_parse_launch(
"videotestsrc is-live=true ! "
"video/x-raw,format=RGBA,width=640,height=480 ! "
"vpuenc_h264 ! h264parse ! vpudec ! imxvideoconvert_g2d ! "
"appsink name=sink sync=false",
NULL);
GstElement *appsink =
gst_bin_get_by_name(GST_BIN(pipeline), "sink");
gst_element_set_state(pipeline, GST_STATE_PLAYING);
/* --- pull one frame --- */
GstSample *sample =
gst_app_sink_pull_sample(GST_APP_SINK(appsink));
GstBuffer *buffer = gst_sample_get_buffer(sample);
GstCaps *caps = gst_sample_get_caps(sample);
GstVideoInfo vinfo;
gst_video_info_from_caps(&vinfo, caps);
GstMemory *mem = gst_buffer_peek_memory(buffer, 0);
if (!gst_is_dmabuf_memory(mem)) {
fprintf(stderr, "not dmabuf\n");
return 1;
}
int fd = gst_dmabuf_memory_get_fd(mem);
GstGLDisplayEGL *gst_gl_display_egl =
gst_gl_display_egl_new_with_egl_display((gpointer) egl_dpy);
GstGLContext *gst_gl_ctx = gst_gl_context_new_wrapped(
GST_GL_DISPLAY_CAST(gst_gl_display_egl), (guintptr) egl_ctx,
GST_GL_PLATFORM_EGL, GST_GL_API_GLES2);
printf("gst_gl_display_egl = %p, gst_gl_ctx = %p\n", gst_gl_display_egl, gst_gl_ctx);
gst_gl_context_activate(gst_gl_ctx, TRUE);
printf("has feature %d\n", gst_gl_context_check_feature (gst_gl_ctx, "EGL_KHR_image_base"));
GstEGLImage* gst_egl_image =
gst_egl_image_from_dmabuf(gst_gl_ctx, fd, &vinfo, 0, 0);
printf("gst_egl_image = %p\n", gst_egl_image);
return 0;
}
what I don’t get is that gst_gl_context_new_wrapped() properly sees context_type == GST_GL_PLATFORM_EGL but that only initializes a few of the methods, in particular context_class->check_feature is not set – forcing it to gst_gl_context_egl_check_feature() doesn’t work because it’s then passing a wrapped context to something that expects an egl context and context_egl->egl_exts is bogus and everything crashes…
I assume that check would work from a context created with gst_gl_context_new() (which calls the proper egl init underneath)?
So, should that plugin be updated to use gst_gl_context_new()instead? why doesn’t it work with the wrapped type?
Thanks!