From ce9b6e5afb52eb04802aa690a8868cac4eb475ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Thu, 28 Mar 2013 17:48:04 +0100 Subject: [PATCH] eglglessink: Implement GstContext handling --- ext/eglgles/gsteglglessink.c | 136 +++++++++++++++++++++++++++++++++-- ext/eglgles/gsteglglessink.h | 2 +- gst-libs/gst/egl/egl.c | 20 ++++++ gst-libs/gst/egl/egl.h | 36 +++++++--- 4 files changed, 177 insertions(+), 17 deletions(-) diff --git a/ext/eglgles/gsteglglessink.c b/ext/eglgles/gsteglglessink.c index 5eed2fd168..e8f966e564 100644 --- a/ext/eglgles/gsteglglessink.c +++ b/ext/eglgles/gsteglglessink.c @@ -356,6 +356,8 @@ static void gst_eglglessink_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec); static GstStateChangeReturn gst_eglglessink_change_state (GstElement * element, GstStateChange transition); +static void gst_eglglessink_set_context (GstElement * element, + GstContext * context); static GstFlowReturn gst_eglglessink_prepare (GstBaseSink * bsink, GstBuffer * buf); 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 gboolean gst_eglglessink_propose_allocation (GstBaseSink * bsink, GstQuery * query); +static gboolean gst_eglglessink_query (GstBaseSink * bsink, GstQuery * query); +static gboolean gst_eglglessink_event (GstBaseSink * bsink, GstEvent * event); /* VideoOverlay interface cruft */ static void gst_eglglessink_videooverlay_init (GstVideoOverlayInterface * @@ -1518,6 +1522,7 @@ HANDLE_ERROR: static gboolean gst_eglglessink_init_egl_display (GstEglGlesSink * eglglessink) { + GstMessage *msg; EGLDisplay display; GST_DEBUG_OBJECT (eglglessink, "Enter EGL initial configuration"); @@ -1531,12 +1536,33 @@ gst_eglglessink_init_egl_display (GstEglGlesSink * eglglessink) } #endif - 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() */ + msg = gst_message_new_need_context (GST_OBJECT_CAST (eglglessink)); + gst_message_add_context_type (msg, GST_EGL_DISPLAY_CONTEXT_TYPE); + gst_element_post_message (GST_ELEMENT_CAST (eglglessink), msg); + + 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), &eglglessink->eglglesctx.egl_major, @@ -2511,6 +2537,103 @@ gst_eglglessink_getcaps (GstBaseSink * bsink, GstCaps * filter) 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 gst_eglglessink_propose_allocation (GstBaseSink * bsink, GstQuery * query) { @@ -2914,12 +3037,15 @@ gst_eglglessink_class_init (GstEglGlesSinkClass * klass) gobject_class->finalize = gst_eglglessink_finalize; 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->get_caps = GST_DEBUG_FUNCPTR (gst_eglglessink_getcaps); gstbasesink_class->propose_allocation = GST_DEBUG_FUNCPTR (gst_eglglessink_propose_allocation); 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 = GST_DEBUG_FUNCPTR (gst_eglglessink_show_frame); diff --git a/ext/eglgles/gsteglglessink.h b/ext/eglgles/gsteglglessink.h index d1cfbb736c..58fd68a04a 100644 --- a/ext/eglgles/gsteglglessink.h +++ b/ext/eglgles/gsteglglessink.h @@ -120,7 +120,7 @@ struct _GstEglGlesRenderContext { EGLConfig config; EGLContext eglcontext; - GstEGLDisplay *display; + GstEGLDisplay *display, *set_display; EGLNativeWindowType window, used_window; EGLSurface surface; gboolean buffer_preserved; diff --git a/gst-libs/gst/egl/egl.c b/gst-libs/gst/egl/egl.c index 73b9c5e913..374a6ffdd7 100644 --- a/gst-libs/gst/egl/egl.c +++ b/gst-libs/gst/egl/egl.c @@ -290,6 +290,26 @@ gst_egl_image_allocator_wrap (GstAllocator * allocator, 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 { EGLDisplay display; diff --git a/gst-libs/gst/egl/egl.h b/gst-libs/gst/egl/egl.h index 099c900d20..542446288a 100644 --- a/gst-libs/gst/egl/egl.h +++ b/gst-libs/gst/egl/egl.h @@ -28,7 +28,8 @@ #define GST_EGL_IMAGE_MEMORY_TYPE "EGLImage" -typedef enum { +typedef enum +{ GST_EGL_IMAGE_MEMORY_TYPE_INVALID = -1, /* GL formats */ GST_EGL_IMAGE_MEMORY_TYPE_LUMINANCE = 0x0000, @@ -42,7 +43,8 @@ typedef enum { GST_EGL_IMAGE_MEMORY_TYPE_OTHER = 0xffff } GstEGLImageType; -typedef enum { +typedef enum +{ /* GStreamer orientation, top line first in memory, left row first */ GST_EGL_IMAGE_ORIENTATION_X_NORMAL_Y_NORMAL, /* 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_is_egl_image_memory (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); -GstEGLImageOrientation gst_egl_image_memory_get_orientation (GstMemory *mem); -void gst_egl_image_memory_set_orientation (GstMemory *mem, GstEGLImageOrientation orientation); +GstEGLImageOrientation gst_egl_image_memory_get_orientation (GstMemory * mem); +void gst_egl_image_memory_set_orientation (GstMemory * mem, + GstEGLImageOrientation orientation); /* Generic EGLImage allocator that doesn't support mapping, copying or anything */ -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_wrap (GstAllocator * allocator, GstEGLDisplay * display, EGLImageKHR image, GstEGLImageType type, GstMemoryFlags flags, gsize size, gpointer user_data, GDestroyNotify user_data_destroy); +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_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 */ #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_ref (GstEGLDisplay * display); +GstEGLDisplay *gst_egl_display_new (EGLDisplay display); +GstEGLDisplay *gst_egl_display_ref (GstEGLDisplay * display); void gst_egl_display_unref (GstEGLDisplay * display); EGLDisplay gst_egl_display_get (GstEGLDisplay * display);