diff --git a/gst/gl/glimagesink.c b/gst/gl/glimagesink.c index 920f51582f..067a03bef7 100644 --- a/gst/gl/glimagesink.c +++ b/gst/gl/glimagesink.c @@ -69,6 +69,7 @@ struct _GstGLImageSink Display *display; GLXContext context; + gboolean internal; int max_texture_size; gboolean have_yuv; @@ -84,6 +85,8 @@ struct _GstGLImageSinkClass }; +static void gst_glimage_sink_init_interfaces (GType type); + static void gst_glimage_sink_finalize (GObject * object); static void gst_glimage_sink_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * param_spec); @@ -99,6 +102,21 @@ static GstCaps *gst_glimage_sink_get_caps (GstBaseSink * bsink); static gboolean gst_glimage_sink_set_caps (GstBaseSink * bsink, GstCaps * caps); static GstFlowReturn gst_glimage_sink_render (GstBaseSink * bsink, GstBuffer * buf); +static gboolean gst_glimage_sink_start (GstBaseSink * bsink); +static gboolean gst_glimage_sink_stop (GstBaseSink * bsink); +static gboolean gst_glimage_sink_unlock (GstBaseSink * bsink); + +static void gst_glimage_sink_xoverlay_init (GstXOverlayClass * iface); +static void gst_glimage_sink_set_xwindow_id (GstXOverlay * overlay, + XID window_id); +static void gst_glimage_sink_expose (GstXOverlay * overlay); +static void gst_glimage_sink_set_event_handling (GstXOverlay * overlay, + gboolean handle_events); + +static gboolean gst_glimage_sink_interface_supported (GstImplementsInterface * + iface, GType type); +static void gst_glimage_sink_implements_init (GstImplementsInterfaceClass * + klass); static void gst_glimage_sink_create_window (GstGLImageSink * glimage_sink); static gboolean gst_glimage_sink_init_display (GstGLImageSink * glimage_sink); @@ -130,8 +148,27 @@ enum ARG_DISPLAY }; -GST_BOILERPLATE (GstGLImageSink, gst_glimage_sink, GstVideoSink, - GST_TYPE_VIDEO_SINK); +GST_BOILERPLATE_FULL (GstGLImageSink, gst_glimage_sink, GstVideoSink, + GST_TYPE_VIDEO_SINK, gst_glimage_sink_init_interfaces); + +static void +gst_glimage_sink_init_interfaces (GType type) +{ + static const GInterfaceInfo overlay_info = { + (GInterfaceInitFunc) gst_glimage_sink_xoverlay_init, + NULL, + NULL + }; + static const GInterfaceInfo implements_info = { + (GInterfaceInitFunc) gst_glimage_sink_implements_init, + NULL, + NULL + }; + + g_type_add_interface_static (type, GST_TYPE_IMPLEMENTS_INTERFACE, + &implements_info); + g_type_add_interface_static (type, GST_TYPE_X_OVERLAY, &overlay_info); +} static void gst_glimage_sink_base_init (gpointer g_class) @@ -171,26 +208,21 @@ gst_glimage_sink_class_init (GstGLImageSinkClass * klass) gstbasesink_class->get_times = gst_glimage_sink_get_times; gstbasesink_class->preroll = gst_glimage_sink_render; gstbasesink_class->render = gst_glimage_sink_render; + gstbasesink_class->start = gst_glimage_sink_start; + gstbasesink_class->stop = gst_glimage_sink_stop; + gstbasesink_class->unlock = gst_glimage_sink_unlock; } static void gst_glimage_sink_init (GstGLImageSink * glimage_sink, GstGLImageSinkClass * glimage_sink_class) { - int screen; - glimage_sink->display = XOpenDisplay (NULL); - if (glimage_sink->display) { - screen = DefaultScreen (glimage_sink->display); - - XSynchronize (glimage_sink->display, True); - } - /* XSetErrorHandler (error_handler); */ - glimage_sink->width = 400; - glimage_sink->height = 400; + glimage_sink->width = -1; + glimage_sink->height = -1; + glimage_sink->display_name = NULL; gst_glimage_sink_update_caps (glimage_sink); - glimage_sink->display_name = g_strdup (""); } static void @@ -205,10 +237,7 @@ gst_glimage_sink_set_property (GObject * object, guint prop_id, switch (prop_id) { case ARG_DISPLAY: - /* FIXME this should close/reopen display */ - if (glimage_sink->display_name) { - g_free (glimage_sink->display_name); - } + g_free (glimage_sink->display_name); glimage_sink->display_name = g_strdup (g_value_get_string (value)); break; default: @@ -230,10 +259,6 @@ gst_glimage_sink_finalize (GObject * object) gst_caps_unref (glimage_sink->caps); } g_free (glimage_sink->display_name); - - if (glimage_sink->display) { - XCloseDisplay (glimage_sink->display); - } } static void @@ -272,11 +297,6 @@ gst_glimage_sink_change_state (GstElement * element, GstStateChange transition) switch (transition) { case GST_STATE_CHANGE_NULL_TO_READY: - if (!gst_glimage_sink_init_display (glimage_sink)) { - GST_ELEMENT_ERROR (glimage_sink, RESOURCE, WRITE, (NULL), - ("Could not initialize OpenGL")); - return GST_STATE_CHANGE_FAILURE; - } break; case GST_STATE_CHANGE_READY_TO_PAUSED: break; @@ -314,10 +334,65 @@ gst_glimage_sink_change_state (GstElement * element, GstStateChange transition) * GstBaseSink methods */ +static gboolean +gst_glimage_sink_start (GstBaseSink * bsink) +{ + GstGLImageSink *glimage_sink; + gboolean ret; + + glimage_sink = GST_GLIMAGE_SINK (bsink); + + ret = gst_glimage_sink_init_display (glimage_sink); + + return ret; +} + +static gboolean +gst_glimage_sink_stop (GstBaseSink * bsink) +{ + GstGLImageSink *glimage_sink; + + glimage_sink = GST_GLIMAGE_SINK (bsink); + + if (glimage_sink->display) { + XCloseDisplay (glimage_sink->display); + } + return TRUE; +} + +static gboolean +gst_glimage_sink_unlock (GstBaseSink * bsink) +{ + //GstGLImageSink *glimage_sink; + + //glimage_sink = GST_GLIMAGE_SINK (bsink); + + /* FIXME */ + + return TRUE; +} + static void gst_glimage_sink_get_times (GstBaseSink * bsink, GstBuffer * buf, GstClockTime * start, GstClockTime * end) { + GstGLImageSink *glimagesink; + + glimagesink = GST_GLIMAGE_SINK (bsink); + + if (GST_BUFFER_TIMESTAMP_IS_VALID (buf)) { + *start = GST_BUFFER_TIMESTAMP (buf); + if (GST_BUFFER_DURATION_IS_VALID (buf)) { + *end = *start + GST_BUFFER_DURATION (buf); + } else { + if (glimagesink->fps_n > 0) { + *end = *start + + gst_util_uint64_scale_int (GST_SECOND, glimagesink->fps_d, + glimagesink->fps_n); + } + } + } + } @@ -408,11 +483,9 @@ gst_glimage_sink_set_caps (GstBaseSink * bsink, GstCaps * caps) } } -#if 0 if (!glimage_sink->window) { gst_x_overlay_prepare_xwindow_id (GST_X_OVERLAY (glimage_sink)); } -#endif if (!glimage_sink->window) { gst_glimage_sink_create_window (glimage_sink); @@ -433,6 +506,87 @@ gst_glimage_sink_render (GstBaseSink * bsink, GstBuffer * buf) return GST_FLOW_OK; } +/* + * XOverlay + */ +static void +gst_glimage_sink_xoverlay_init (GstXOverlayClass * iface) +{ + iface->set_xwindow_id = gst_glimage_sink_set_xwindow_id; + iface->expose = gst_glimage_sink_expose; + iface->handle_events = gst_glimage_sink_set_event_handling; +} + +static void +gst_glimage_sink_set_xwindow_id (GstXOverlay * overlay, XID window_id) +{ + GstGLImageSink *glimage_sink; + + g_return_if_fail (GST_IS_GLIMAGE_SINK (overlay)); + + glimage_sink = GST_GLIMAGE_SINK (overlay); + if (glimage_sink->window == window_id) { + return; + } + + /* FIXME check if display inited */ + + if (window_id == 0) { + /* go back to independent window */ + /* FIXME */ + glimage_sink->internal = TRUE; + } else { + XWindowAttributes attr; + + glimage_sink->window = window_id; + + XGetWindowAttributes (glimage_sink->display, window_id, &attr); + glimage_sink->width = attr.width; + glimage_sink->height = attr.height; + glimage_sink->internal = FALSE; +#if 0 + /* FIXME */ + if (glimage_sink->handle_events) { + XSelectInput (glimage_sink->display, window_id, + ExposureMask | StructureNotifyMask | PointerMotionMask | KeyPressMask + | KeyReleaseMask); + } +#endif + } + +} + +static void +gst_glimage_sink_expose (GstXOverlay * overlay) +{ + /* FIXME */ + GST_DEBUG ("expose"); +} + +static void +gst_glimage_sink_set_event_handling (GstXOverlay * overlay, + gboolean handle_events) +{ + /* FIXME */ + GST_DEBUG ("handle_events %d", handle_events); +} + +/* + * GstImplementsInterface + */ +static gboolean +gst_glimage_sink_interface_supported (GstImplementsInterface * iface, + GType type) +{ + return TRUE; +} + +static void +gst_glimage_sink_implements_init (GstImplementsInterfaceClass * klass) +{ + klass->supported = gst_glimage_sink_interface_supported; +} + /* * helper functions @@ -460,14 +614,10 @@ gst_glimage_sink_update_caps (GstGLImageSink * glimage_sink) GstCaps *caps; int max_size; - if (glimage_sink->caps) { - gst_caps_unref (glimage_sink->caps); - } - if (glimage_sink->display == NULL) { - glimage_sink->caps = - gst_caps_copy (gst_pad_get_pad_template_caps (GST_BASE_SINK_PAD + caps = gst_caps_copy (gst_pad_get_pad_template_caps (GST_BASE_SINK_PAD (glimage_sink))); + gst_caps_replace (&glimage_sink->caps, caps); return; } @@ -490,7 +640,7 @@ gst_glimage_sink_update_caps (GstGLImageSink * glimage_sink) "width", GST_TYPE_INT_RANGE, 16, max_size, "height", GST_TYPE_INT_RANGE, 16, max_size, NULL); - glimage_sink->caps = caps; + gst_caps_replace (&glimage_sink->caps, caps); } static void @@ -546,6 +696,9 @@ gst_glimage_sink_create_window (GstGLImageSink * glimage_sink) XMapWindow (glimage_sink->display, glimage_sink->window); } + gst_x_overlay_got_xwindow_id (GST_X_OVERLAY (glimage_sink), + glimage_sink->window); + glXMakeCurrent (glimage_sink->display, glimage_sink->window, glimage_sink->context); @@ -574,7 +727,7 @@ gst_glimage_sink_init_display (GstGLImageSink * glimage_sink) const char *extstring; Window window; - GST_LOG_OBJECT (glimage_sink, "initializing display"); + GST_DEBUG_OBJECT (glimage_sink, "initializing display"); glimage_sink->display = XOpenDisplay (NULL); if (glimage_sink->display == NULL) { @@ -588,13 +741,13 @@ gst_glimage_sink_init_display (GstGLImageSink * glimage_sink) ret = glXQueryExtension (glimage_sink->display, &error_base, &event_base); if (!ret) { - GST_LOG_OBJECT (glimage_sink, "No GLX extension"); + GST_DEBUG_OBJECT (glimage_sink, "No GLX extension"); return FALSE; } visinfo = glXChooseVisual (glimage_sink->display, scrnum, attrib); if (visinfo == NULL) { - GST_LOG_OBJECT (glimage_sink, "No usable visual"); + GST_DEBUG_OBJECT (glimage_sink, "No usable visual"); return FALSE; } @@ -803,7 +956,7 @@ static gboolean plugin_init (GstPlugin * plugin) { if (!gst_element_register (plugin, "glimagesink", - GST_RANK_NONE, GST_TYPE_GLIMAGE_SINK)) + GST_RANK_MARGINAL, GST_TYPE_GLIMAGE_SINK)) return FALSE; GST_DEBUG_CATEGORY_INIT (gst_debug_glimage_sink, "glimagesink", 0,