mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-29 18:48:44 +00:00
eglglessink: Implement GstContext handling
This commit is contained in:
parent
9e2af116f6
commit
ce9b6e5afb
4 changed files with 177 additions and 17 deletions
|
@ -356,6 +356,8 @@ static void gst_eglglessink_set_property (GObject * object, guint prop_id,
|
||||||
const GValue * value, GParamSpec * pspec);
|
const GValue * value, GParamSpec * pspec);
|
||||||
static GstStateChangeReturn gst_eglglessink_change_state (GstElement * element,
|
static GstStateChangeReturn gst_eglglessink_change_state (GstElement * element,
|
||||||
GstStateChange transition);
|
GstStateChange transition);
|
||||||
|
static void gst_eglglessink_set_context (GstElement * element,
|
||||||
|
GstContext * context);
|
||||||
static GstFlowReturn gst_eglglessink_prepare (GstBaseSink * bsink,
|
static GstFlowReturn gst_eglglessink_prepare (GstBaseSink * bsink,
|
||||||
GstBuffer * buf);
|
GstBuffer * buf);
|
||||||
static GstFlowReturn gst_eglglessink_show_frame (GstVideoSink * vsink,
|
static GstFlowReturn gst_eglglessink_show_frame (GstVideoSink * vsink,
|
||||||
|
@ -364,6 +366,8 @@ static gboolean gst_eglglessink_setcaps (GstBaseSink * bsink, GstCaps * caps);
|
||||||
static GstCaps *gst_eglglessink_getcaps (GstBaseSink * bsink, GstCaps * filter);
|
static GstCaps *gst_eglglessink_getcaps (GstBaseSink * bsink, GstCaps * filter);
|
||||||
static gboolean gst_eglglessink_propose_allocation (GstBaseSink * bsink,
|
static gboolean gst_eglglessink_propose_allocation (GstBaseSink * bsink,
|
||||||
GstQuery * query);
|
GstQuery * query);
|
||||||
|
static gboolean gst_eglglessink_query (GstBaseSink * bsink, GstQuery * query);
|
||||||
|
static gboolean gst_eglglessink_event (GstBaseSink * bsink, GstEvent * event);
|
||||||
|
|
||||||
/* VideoOverlay interface cruft */
|
/* VideoOverlay interface cruft */
|
||||||
static void gst_eglglessink_videooverlay_init (GstVideoOverlayInterface *
|
static void gst_eglglessink_videooverlay_init (GstVideoOverlayInterface *
|
||||||
|
@ -1518,6 +1522,7 @@ HANDLE_ERROR:
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_eglglessink_init_egl_display (GstEglGlesSink * eglglessink)
|
gst_eglglessink_init_egl_display (GstEglGlesSink * eglglessink)
|
||||||
{
|
{
|
||||||
|
GstMessage *msg;
|
||||||
EGLDisplay display;
|
EGLDisplay display;
|
||||||
GST_DEBUG_OBJECT (eglglessink, "Enter EGL initial configuration");
|
GST_DEBUG_OBJECT (eglglessink, "Enter EGL initial configuration");
|
||||||
|
|
||||||
|
@ -1531,12 +1536,33 @@ gst_eglglessink_init_egl_display (GstEglGlesSink * eglglessink)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
display = eglGetDisplay (EGL_DEFAULT_DISPLAY);
|
msg = gst_message_new_need_context (GST_OBJECT_CAST (eglglessink));
|
||||||
if (display == EGL_NO_DISPLAY) {
|
gst_message_add_context_type (msg, GST_EGL_DISPLAY_CONTEXT_TYPE);
|
||||||
GST_ERROR_OBJECT (eglglessink, "Could not get EGL display connection");
|
gst_element_post_message (GST_ELEMENT_CAST (eglglessink), msg);
|
||||||
goto HANDLE_ERROR; /* No EGL error is set by eglGetDisplay() */
|
|
||||||
|
GST_OBJECT_LOCK (eglglessink);
|
||||||
|
if (eglglessink->eglglesctx.set_display) {
|
||||||
|
eglglessink->eglglesctx.display =
|
||||||
|
gst_egl_display_ref (eglglessink->eglglesctx.set_display);
|
||||||
|
GST_OBJECT_UNLOCK (eglglessink);
|
||||||
|
} else {
|
||||||
|
GstContext *context;
|
||||||
|
|
||||||
|
GST_OBJECT_UNLOCK (eglglessink);
|
||||||
|
|
||||||
|
display = eglGetDisplay (EGL_DEFAULT_DISPLAY);
|
||||||
|
if (display == EGL_NO_DISPLAY) {
|
||||||
|
GST_ERROR_OBJECT (eglglessink, "Could not get EGL display connection");
|
||||||
|
goto HANDLE_ERROR; /* No EGL error is set by eglGetDisplay() */
|
||||||
|
}
|
||||||
|
eglglessink->eglglesctx.display = gst_egl_display_new (display);
|
||||||
|
|
||||||
|
context = gst_context_new ();
|
||||||
|
gst_context_set_egl_display (context, eglglessink->eglglesctx.display);
|
||||||
|
|
||||||
|
msg = gst_message_new_have_context (GST_OBJECT (eglglessink), context);
|
||||||
|
gst_element_post_message (GST_ELEMENT_CAST (eglglessink), msg);
|
||||||
}
|
}
|
||||||
eglglessink->eglglesctx.display = gst_egl_display_new (display);
|
|
||||||
|
|
||||||
if (!eglInitialize (gst_egl_display_get (eglglessink->eglglesctx.display),
|
if (!eglInitialize (gst_egl_display_get (eglglessink->eglglesctx.display),
|
||||||
&eglglessink->eglglesctx.egl_major,
|
&eglglessink->eglglesctx.egl_major,
|
||||||
|
@ -2511,6 +2537,103 @@ gst_eglglessink_getcaps (GstBaseSink * bsink, GstCaps * filter)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_eglglessink_event (GstBaseSink * bsink, GstEvent * event)
|
||||||
|
{
|
||||||
|
GstEglGlesSink *eglglessink;
|
||||||
|
|
||||||
|
eglglessink = GST_EGLGLESSINK (bsink);
|
||||||
|
|
||||||
|
switch (GST_EVENT_TYPE (event)) {
|
||||||
|
case GST_EVENT_CONTEXT:{
|
||||||
|
GstContext *context;
|
||||||
|
GstEGLDisplay *display;
|
||||||
|
|
||||||
|
gst_event_parse_context (event, &context);
|
||||||
|
|
||||||
|
if (gst_context_get_egl_display (context, &display)) {
|
||||||
|
GST_OBJECT_LOCK (eglglessink);
|
||||||
|
if (eglglessink->eglglesctx.set_display)
|
||||||
|
gst_egl_display_unref (eglglessink->eglglesctx.set_display);
|
||||||
|
eglglessink->eglglesctx.set_display = display;
|
||||||
|
GST_OBJECT_UNLOCK (eglglessink);
|
||||||
|
}
|
||||||
|
|
||||||
|
return GST_BASE_SINK_CLASS (gst_eglglessink_parent_class)->event (bsink,
|
||||||
|
event);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return GST_BASE_SINK_CLASS (gst_eglglessink_parent_class)->event (bsink,
|
||||||
|
event);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_eglglessink_query (GstBaseSink * bsink, GstQuery * query)
|
||||||
|
{
|
||||||
|
GstEglGlesSink *eglglessink;
|
||||||
|
|
||||||
|
eglglessink = GST_EGLGLESSINK (bsink);
|
||||||
|
|
||||||
|
switch (GST_QUERY_TYPE (query)) {
|
||||||
|
case GST_QUERY_CONTEXT:{
|
||||||
|
guint i, n;
|
||||||
|
|
||||||
|
GST_BASE_SINK_CLASS (gst_eglglessink_parent_class)->query (bsink, query);
|
||||||
|
|
||||||
|
n = gst_query_get_n_context_types (query);
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
const gchar *context_type = NULL;
|
||||||
|
|
||||||
|
gst_query_parse_nth_context_type (query, i, &context_type);
|
||||||
|
if (g_strcmp0 (context_type, GST_EGL_DISPLAY_CONTEXT_TYPE) == 0) {
|
||||||
|
GstContext *context, *old_context;
|
||||||
|
|
||||||
|
gst_query_parse_context (query, &old_context);
|
||||||
|
if (old_context)
|
||||||
|
context = gst_context_copy (old_context);
|
||||||
|
else
|
||||||
|
context = gst_context_new ();
|
||||||
|
|
||||||
|
gst_context_set_egl_display (context,
|
||||||
|
eglglessink->eglglesctx.display);
|
||||||
|
gst_query_set_context (query, context);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return GST_BASE_SINK_CLASS (gst_eglglessink_parent_class)->query (bsink,
|
||||||
|
query);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_eglglessink_set_context (GstElement * element, GstContext * context)
|
||||||
|
{
|
||||||
|
GstEglGlesSink *eglglessink;
|
||||||
|
GstStructure *s;
|
||||||
|
GstEGLDisplay *display = NULL;
|
||||||
|
|
||||||
|
eglglessink = GST_EGLGLESSINK (element);
|
||||||
|
|
||||||
|
s = (GstStructure *) gst_context_get_structure (context);
|
||||||
|
if (gst_structure_get (s, GST_EGL_DISPLAY_CONTEXT_TYPE, GST_TYPE_EGL_DISPLAY,
|
||||||
|
&display, NULL)) {
|
||||||
|
GST_OBJECT_LOCK (eglglessink);
|
||||||
|
if (eglglessink->eglglesctx.set_display)
|
||||||
|
gst_egl_display_unref (eglglessink->eglglesctx.set_display);
|
||||||
|
eglglessink->eglglesctx.set_display = display;
|
||||||
|
GST_OBJECT_UNLOCK (eglglessink);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_eglglessink_propose_allocation (GstBaseSink * bsink, GstQuery * query)
|
gst_eglglessink_propose_allocation (GstBaseSink * bsink, GstQuery * query)
|
||||||
{
|
{
|
||||||
|
@ -2914,12 +3037,15 @@ gst_eglglessink_class_init (GstEglGlesSinkClass * klass)
|
||||||
gobject_class->finalize = gst_eglglessink_finalize;
|
gobject_class->finalize = gst_eglglessink_finalize;
|
||||||
|
|
||||||
gstelement_class->change_state = gst_eglglessink_change_state;
|
gstelement_class->change_state = gst_eglglessink_change_state;
|
||||||
|
gstelement_class->set_context = gst_eglglessink_set_context;
|
||||||
|
|
||||||
gstbasesink_class->set_caps = GST_DEBUG_FUNCPTR (gst_eglglessink_setcaps);
|
gstbasesink_class->set_caps = GST_DEBUG_FUNCPTR (gst_eglglessink_setcaps);
|
||||||
gstbasesink_class->get_caps = GST_DEBUG_FUNCPTR (gst_eglglessink_getcaps);
|
gstbasesink_class->get_caps = GST_DEBUG_FUNCPTR (gst_eglglessink_getcaps);
|
||||||
gstbasesink_class->propose_allocation =
|
gstbasesink_class->propose_allocation =
|
||||||
GST_DEBUG_FUNCPTR (gst_eglglessink_propose_allocation);
|
GST_DEBUG_FUNCPTR (gst_eglglessink_propose_allocation);
|
||||||
gstbasesink_class->prepare = GST_DEBUG_FUNCPTR (gst_eglglessink_prepare);
|
gstbasesink_class->prepare = GST_DEBUG_FUNCPTR (gst_eglglessink_prepare);
|
||||||
|
gstbasesink_class->query = GST_DEBUG_FUNCPTR (gst_eglglessink_query);
|
||||||
|
gstbasesink_class->event = GST_DEBUG_FUNCPTR (gst_eglglessink_event);
|
||||||
|
|
||||||
gstvideosink_class->show_frame =
|
gstvideosink_class->show_frame =
|
||||||
GST_DEBUG_FUNCPTR (gst_eglglessink_show_frame);
|
GST_DEBUG_FUNCPTR (gst_eglglessink_show_frame);
|
||||||
|
|
|
@ -120,7 +120,7 @@ struct _GstEglGlesRenderContext
|
||||||
{
|
{
|
||||||
EGLConfig config;
|
EGLConfig config;
|
||||||
EGLContext eglcontext;
|
EGLContext eglcontext;
|
||||||
GstEGLDisplay *display;
|
GstEGLDisplay *display, *set_display;
|
||||||
EGLNativeWindowType window, used_window;
|
EGLNativeWindowType window, used_window;
|
||||||
EGLSurface surface;
|
EGLSurface surface;
|
||||||
gboolean buffer_preserved;
|
gboolean buffer_preserved;
|
||||||
|
|
|
@ -290,6 +290,26 @@ gst_egl_image_allocator_wrap (GstAllocator * allocator,
|
||||||
return GST_MEMORY_CAST (mem);
|
return GST_MEMORY_CAST (mem);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gst_context_set_egl_display (GstContext * context, GstEGLDisplay * display)
|
||||||
|
{
|
||||||
|
GstStructure *s;
|
||||||
|
|
||||||
|
s = (GstStructure *) gst_context_get_structure (context);
|
||||||
|
gst_structure_set (s, GST_EGL_DISPLAY_CONTEXT_TYPE, GST_TYPE_EGL_DISPLAY,
|
||||||
|
display, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gst_context_get_egl_display (GstContext * context, GstEGLDisplay ** display)
|
||||||
|
{
|
||||||
|
GstStructure *s;
|
||||||
|
|
||||||
|
s = (GstStructure *) gst_context_get_structure (context);
|
||||||
|
return gst_structure_get (s, GST_EGL_DISPLAY_CONTEXT_TYPE,
|
||||||
|
GST_TYPE_EGL_DISPLAY, display, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
struct _GstEGLDisplay
|
struct _GstEGLDisplay
|
||||||
{
|
{
|
||||||
EGLDisplay display;
|
EGLDisplay display;
|
||||||
|
|
|
@ -28,7 +28,8 @@
|
||||||
|
|
||||||
#define GST_EGL_IMAGE_MEMORY_TYPE "EGLImage"
|
#define GST_EGL_IMAGE_MEMORY_TYPE "EGLImage"
|
||||||
|
|
||||||
typedef enum {
|
typedef enum
|
||||||
|
{
|
||||||
GST_EGL_IMAGE_MEMORY_TYPE_INVALID = -1,
|
GST_EGL_IMAGE_MEMORY_TYPE_INVALID = -1,
|
||||||
/* GL formats */
|
/* GL formats */
|
||||||
GST_EGL_IMAGE_MEMORY_TYPE_LUMINANCE = 0x0000,
|
GST_EGL_IMAGE_MEMORY_TYPE_LUMINANCE = 0x0000,
|
||||||
|
@ -42,7 +43,8 @@ typedef enum {
|
||||||
GST_EGL_IMAGE_MEMORY_TYPE_OTHER = 0xffff
|
GST_EGL_IMAGE_MEMORY_TYPE_OTHER = 0xffff
|
||||||
} GstEGLImageType;
|
} GstEGLImageType;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum
|
||||||
|
{
|
||||||
/* GStreamer orientation, top line first in memory, left row first */
|
/* GStreamer orientation, top line first in memory, left row first */
|
||||||
GST_EGL_IMAGE_ORIENTATION_X_NORMAL_Y_NORMAL,
|
GST_EGL_IMAGE_ORIENTATION_X_NORMAL_Y_NORMAL,
|
||||||
/* OpenGL orientation, bottom line first in memory, left row first */
|
/* OpenGL orientation, bottom line first in memory, left row first */
|
||||||
|
@ -58,22 +60,34 @@ typedef struct _GstEGLDisplay GstEGLDisplay;
|
||||||
gboolean gst_egl_image_memory_is_mappable (void);
|
gboolean gst_egl_image_memory_is_mappable (void);
|
||||||
gboolean gst_is_egl_image_memory (GstMemory * mem);
|
gboolean gst_is_egl_image_memory (GstMemory * mem);
|
||||||
EGLImageKHR gst_egl_image_memory_get_image (GstMemory * mem);
|
EGLImageKHR gst_egl_image_memory_get_image (GstMemory * mem);
|
||||||
GstEGLDisplay * gst_egl_image_memory_get_display (GstMemory * mem);
|
GstEGLDisplay *gst_egl_image_memory_get_display (GstMemory * mem);
|
||||||
GstEGLImageType gst_egl_image_memory_get_type (GstMemory * mem);
|
GstEGLImageType gst_egl_image_memory_get_type (GstMemory * mem);
|
||||||
GstEGLImageOrientation gst_egl_image_memory_get_orientation (GstMemory *mem);
|
GstEGLImageOrientation gst_egl_image_memory_get_orientation (GstMemory * mem);
|
||||||
void gst_egl_image_memory_set_orientation (GstMemory *mem, GstEGLImageOrientation orientation);
|
void gst_egl_image_memory_set_orientation (GstMemory * mem,
|
||||||
|
GstEGLImageOrientation orientation);
|
||||||
|
|
||||||
/* Generic EGLImage allocator that doesn't support mapping, copying or anything */
|
/* Generic EGLImage allocator that doesn't support mapping, copying or anything */
|
||||||
GstAllocator * gst_egl_image_allocator_obtain (void);
|
GstAllocator *gst_egl_image_allocator_obtain (void);
|
||||||
GstMemory * gst_egl_image_allocator_alloc (GstAllocator * allocator, GstEGLDisplay * display, GstEGLImageType type, gint width, gint height, gsize * size);
|
GstMemory *gst_egl_image_allocator_alloc (GstAllocator * allocator,
|
||||||
GstMemory * gst_egl_image_allocator_wrap (GstAllocator * allocator, GstEGLDisplay * display, EGLImageKHR image, GstEGLImageType type, GstMemoryFlags flags, gsize size, gpointer user_data, GDestroyNotify user_data_destroy);
|
GstEGLDisplay * display, GstEGLImageType type, gint width, gint height,
|
||||||
|
gsize * size);
|
||||||
|
GstMemory *gst_egl_image_allocator_wrap (GstAllocator * allocator,
|
||||||
|
GstEGLDisplay * display, EGLImageKHR image, GstEGLImageType type,
|
||||||
|
GstMemoryFlags flags, gsize size, gpointer user_data,
|
||||||
|
GDestroyNotify user_data_destroy);
|
||||||
|
|
||||||
|
#define GST_EGL_DISPLAY_CONTEXT_TYPE "gst.egl.EGLDisplay"
|
||||||
|
void gst_context_set_egl_display (GstContext * context,
|
||||||
|
GstEGLDisplay * display);
|
||||||
|
gboolean gst_context_get_egl_display (GstContext * context,
|
||||||
|
GstEGLDisplay ** display);
|
||||||
|
|
||||||
/* EGLDisplay wrapper with refcount, connection is closed after last ref is gone */
|
/* EGLDisplay wrapper with refcount, connection is closed after last ref is gone */
|
||||||
#define GST_TYPE_EGL_DISPLAY (gst_egl_display_get_type())
|
#define GST_TYPE_EGL_DISPLAY (gst_egl_display_get_type())
|
||||||
GType gst_egl_display_get_type(void);
|
GType gst_egl_display_get_type (void);
|
||||||
|
|
||||||
GstEGLDisplay * gst_egl_display_new (EGLDisplay display);
|
GstEGLDisplay *gst_egl_display_new (EGLDisplay display);
|
||||||
GstEGLDisplay * gst_egl_display_ref (GstEGLDisplay * display);
|
GstEGLDisplay *gst_egl_display_ref (GstEGLDisplay * display);
|
||||||
void gst_egl_display_unref (GstEGLDisplay * display);
|
void gst_egl_display_unref (GstEGLDisplay * display);
|
||||||
EGLDisplay gst_egl_display_get (GstEGLDisplay * display);
|
EGLDisplay gst_egl_display_get (GstEGLDisplay * display);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue