summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastian Dröge <sebastian.droege@collabora.co.uk>2013-03-28 17:48:04 +0100
committerSebastian Dröge <sebastian.droege@collabora.co.uk>2013-03-29 16:38:34 +0100
commitce9b6e5afb52eb04802aa690a8868cac4eb475ab (patch)
treebb962b26d82b22a473a0d74bb300459bec722e84
parent9e2af116f6b974dcf32b6e3e8494391355deaa01 (diff)
eglglessink: Implement GstContext handling
-rw-r--r--ext/eglgles/gsteglglessink.c136
-rw-r--r--ext/eglgles/gsteglglessink.h2
-rw-r--r--gst-libs/gst/egl/egl.c20
-rw-r--r--gst-libs/gst/egl/egl.h36
4 files changed, 177 insertions, 17 deletions
diff --git a/ext/eglgles/gsteglglessink.c b/ext/eglgles/gsteglglessink.c
index 5eed2fd16..e8f966e56 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,
@@ -2512,6 +2538,103 @@ gst_eglglessink_getcaps (GstBaseSink * bsink, GstCaps * filter)
}
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)
{
GstEglGlesSink *eglglessink;
@@ -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 d1cfbb736..58fd68a04 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 73b9c5e91..374a6ffdd 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 099c900d2..542446288 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);