diff options
author | Sebastian Dröge <sebastian.droege@collabora.co.uk> | 2012-09-13 10:11:27 +0200 |
---|---|---|
committer | Sebastian Dröge <sebastian.droege@collabora.co.uk> | 2012-09-13 10:11:27 +0200 |
commit | 7a407a4456b4010e3d57fce1428d3bad655ef541 (patch) | |
tree | 60d8b2321eba0e536f171e171c929f09975707d9 | |
parent | f3c761b9559f98f16d1bcefce6e9e46d74ca657b (diff) | |
parent | 9c871940e8576dd39a172974975f794204a3c383 (diff) |
Merge remote-tracking branch 'reynaldo/android' into sdk-0.10.23sdk-0.10.23
-rw-r--r-- | ext/eglgles/gsteglglessink.c | 208 | ||||
-rw-r--r-- | ext/eglgles/gsteglglessink.h | 12 |
2 files changed, 170 insertions, 50 deletions
diff --git a/ext/eglgles/gsteglglessink.c b/ext/eglgles/gsteglglessink.c index b71762b6e..cbce9ee23 100644 --- a/ext/eglgles/gsteglglessink.c +++ b/ext/eglgles/gsteglglessink.c @@ -45,8 +45,8 @@ /** * SECTION:element-eglglessink * - * This is a vout sink using EGL/GLES. - * + * This is a vout sink using EGL/GLES. + * * <refsect2> * <title>Rationale on OpenGL ES version</title> * <para> @@ -69,7 +69,7 @@ * available. * </para> * |[ - * gst-launch -v -m videotestsrc ! eglglessink force_rendering_slow=TRUE + * gst-launch -v -m videotestsrc ! eglglessink force_rendering_slow=TRUE * ]| * </refsect2> * @@ -157,14 +157,26 @@ static const char *frag_prog = { /* Input capabilities. * * OpenGL ES Standard does not mandate YUV support - * - * XXX: Extend RGB support to a set. Maybe implement YUV too. + * so we are going to stick to RGB for the time being */ static GstStaticPadTemplate gst_eglglessink_sink_template_factory = -GST_STATIC_PAD_TEMPLATE ("sink", + GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, - GST_STATIC_CAPS (GST_VIDEO_CAPS_RGB)); + GST_STATIC_CAPS ("video/x-raw-rgb, " + "framerate = (fraction) [ 0, MAX ], " + "width = (int) [ 1, MAX ], " + "height = (int) [ 1, MAX ], " + "bpp = 24; " + "video/x-raw-rgb, " + "framerate = (fraction) [ 0, MAX ], " + "width = (int) [ 1, MAX ], " + "height = (int) [ 1, MAX ], " + "depth = (int) 24, " + "bpp = 32; " + "video/x-raw-rgb, " + "framerate = (fraction) [ 0, MAX ], " + "width = (int) [ 1, MAX ], " "height = (int) [ 1, MAX ], " "bpp = 16")); /* Filter signals and args */ enum @@ -183,14 +195,29 @@ enum PROP_FORCE_RENDERING_SLOW }; -/* XXX: Harcoded for now */ -static EGLint eglglessink_RGB24_config[] = { +/* will probably move elsewhere */ +static EGLint eglglessink_RGBA8888_config[] = { + EGL_RED_SIZE, 8, + EGL_GREEN_SIZE, 8, + EGL_BLUE_SIZE, 8, + EGL_ALPHA_SIZE, 8, + EGL_NONE +}; + +static EGLint eglglessink_RGB888_config[] = { EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_BLUE_SIZE, 8, EGL_NONE }; +static EGLint eglglessink_RGB565_config[] = { + EGL_RED_SIZE, 5, + EGL_GREEN_SIZE, 6, + EGL_BLUE_SIZE, 5, + EGL_NONE +}; + static void gst_eglglessink_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec); static void gst_eglglessink_set_property (GObject * object, guint prop_id, @@ -235,7 +262,10 @@ static EGLint *gst_eglglesbuffer_create_native (EGLNativeWindowType win, /* Utility */ static EGLNativeWindowType gst_eglglessink_create_window (GstEglGlesSink * eglglessink, gint width, gint height); +static inline gint +gst_eglglessink_fill_supported_fbuffer_configs (GstEglGlesSink * eglglessink); static gboolean gst_eglglessink_init_egl_display (GstEglGlesSink * eglglessink); +static gboolean gst_eglglessink_choose_config (GstEglGlesSink * eglglessink); static gboolean gst_eglglessink_init_egl_surface (GstEglGlesSink * eglglessink); static void gst_eglglessink_init_egl_exts (GstEglGlesSink * eglglessink); static gboolean gst_eglglessink_setup_vbo (GstEglGlesSink * eglglessink, @@ -244,6 +274,7 @@ static GstFlowReturn gst_eglglessink_render_and_display (GstEglGlesSink * sink, GstBuffer * buf); static inline gboolean got_gl_error (const char *wtf); static inline void show_egl_error (const char *wtf); +static void gst_eglglessink_wipe_fmt (gpointer data); static GstBufferClass *gsteglglessink_buffer_parent_class = NULL; #define GST_TYPE_EGLGLESBUFFER (gst_eglglesbuffer_get_type()) @@ -260,7 +291,7 @@ GST_BOILERPLATE_FULL (GstEglGlesSink, gst_eglglessink, GstVideoSink, static EGLint *gst_eglglesbuffer_create_native (EGLNativeWindowType win, EGLConfig config, EGLNativeDisplayType display, const EGLint * egl_attribs) { - EGLNativePixmapType pix; + EGLNativePixmapType pix = 0; EGLSurface pix_surface; EGLint *buffer = NULL; @@ -486,10 +517,6 @@ gst_eglglesbuffer_get_type (void) } -/* This function is sort of meaningless right now as we - * Only Support one image format / caps but was left here - * as a reference for future improvements. - */ static gint gst_eglglessink_get_compat_format_from_caps (GstEglGlesSink * eglglessink, GstCaps * caps) @@ -509,12 +536,14 @@ gst_eglglessink_get_compat_format_from_caps (GstEglGlesSink * eglglessink, GST_PTR_FORMAT " and %" GST_PTR_FORMAT, format->caps, caps); if (format) { if (gst_caps_can_intersect (caps, format->caps)) { + eglglessink->selected_fmt = format; return format->fmt; } } list = g_list_next (list); } + eglglessink->selected_fmt = NULL; return GST_EGLGLESSINK_IMAGE_NOFMT; } @@ -652,7 +681,7 @@ gst_eglglessink_buffer_alloc (GstBaseSink * bsink, guint64 offset, intersection = gst_caps_intersect (eglglessink->current_caps, new_caps); } - /* Try with different dimensions */ + /* Try with different dimensions and RGB formats */ if (gst_caps_is_empty (intersection)) intersection = gst_eglglessink_different_size_suggestion (eglglessink, new_caps); @@ -740,40 +769,81 @@ NO_CAPS: } } +/* This one needs refactoring like a LOT */ +static inline gint +gst_eglglessink_fill_supported_fbuffer_configs (GstEglGlesSink * eglglessink) +{ + gint ret = 0; + EGLint cfg_number; + GstEglGlesImageFmt *format; + + /* Init supported format/caps list */ + if (eglChooseConfig (eglglessink->display, eglglessink_RGB888_config, + NULL, 1, &cfg_number) != EGL_FALSE) { + format = g_new0 (GstEglGlesImageFmt, 1); + format->fmt = GST_EGLGLESSINK_IMAGE_RGB888; + format->eglcfg = eglglessink_RGB888_config; + format->caps = + gst_caps_new_simple ("video/x-raw-rgb", "bpp", G_TYPE_INT, 24, NULL); + eglglessink->supported_fmts = + g_list_append (eglglessink->supported_fmts, format); + ret++; + } else + GST_INFO_OBJECT (eglglessink, "EGL display doesn't support RGB888 config"); + + if (eglChooseConfig (eglglessink->display, eglglessink_RGB565_config, + NULL, 1, &cfg_number) != EGL_FALSE) { + format = g_new0 (GstEglGlesImageFmt, 1); + format->fmt = GST_EGLGLESSINK_IMAGE_RGB565; + format->eglcfg = eglglessink_RGB565_config; + format->caps = + gst_caps_new_simple ("video/x-raw-rgb", "bpp", G_TYPE_INT, 16, NULL); + eglglessink->supported_fmts = + g_list_append (eglglessink->supported_fmts, format); + ret++; + } else + GST_INFO_OBJECT (eglglessink, "EGL display doesn't support RGB565 config"); + + if (eglChooseConfig (eglglessink->display, eglglessink_RGBA8888_config, + NULL, 1, &cfg_number) != EGL_FALSE) { + format = g_new0 (GstEglGlesImageFmt, 1); + format->fmt = GST_EGLGLESSINK_IMAGE_RGBA8888; + format->eglcfg = eglglessink_RGBA8888_config; + format->caps = gst_caps_new_simple ("video/x-raw-rgb", "depth", G_TYPE_INT, 24, "bpp", G_TYPE_INT, 32, NULL); /* proly doesn't work for rgba */ + eglglessink->supported_fmts = g_list_append + (eglglessink->supported_fmts, format); + ret++; + } else + GST_INFO_OBJECT (eglglessink, + "EGL display doesn't support RGBA8888 config"); + + return ret; +} + gboolean gst_eglglessink_start (GstBaseSink * sink) { gboolean ret; GstEglGlesSink *eglglessink = GST_EGLGLESSINK (sink); - GstEglGlesImageFmt *format; eglglessink->flow_lock = g_mutex_new (); g_mutex_lock (eglglessink->flow_lock); - ret = gst_eglglessink_init_egl_display (eglglessink); + ret = platform_wrapper_init (); if (!ret) { - GST_ERROR_OBJECT (eglglessink, "Couldn't init EGL display"); + GST_ERROR_OBJECT (eglglessink, "Couldn't init EGL platform wrapper"); goto HANDLE_ERROR; } - ret = platform_wrapper_init (); - - if (!ret) { - GST_ERROR_OBJECT (eglglessink, "Couldn't init EGL platform wrapper"); + if (!gst_eglglessink_init_egl_display (eglglessink)) { + GST_ERROR_OBJECT (eglglessink, "Couldn't init EGL display"); goto HANDLE_ERROR; } - /* Init supported caps list (Right now we just harcode the only one we support) - * XXX: Not sure this is the right place to do it. - */ - format = g_new0 (GstEglGlesImageFmt, 1); - if (format) { - format->fmt = GST_EGLGLESSINK_IMAGE_RGB24; - format->caps = gst_caps_copy (gst_pad_get_pad_template_caps - (GST_VIDEO_SINK_PAD (eglglessink))); - eglglessink->supported_fmts = g_list_append - (eglglessink->supported_fmts, format); + if (!gst_eglglessink_fill_supported_fbuffer_configs (eglglessink)) { + GST_ERROR_OBJECT (eglglessink, "Display support NONE of our configs"); + goto HANDLE_ERROR; } g_mutex_unlock (eglglessink->flow_lock); @@ -785,6 +855,14 @@ HANDLE_ERROR: return FALSE; } +static void +gst_eglglessink_wipe_fmt (gpointer data) +{ + GstEglGlesImageFmt *format = data; + gst_caps_unref (format->caps); + g_free (format); +} + /* XXX: Should implement */ gboolean gst_eglglessink_stop (GstBaseSink * sink) @@ -792,6 +870,10 @@ gst_eglglessink_stop (GstBaseSink * sink) GstEglGlesSink *eglglessink = GST_EGLGLESSINK (sink); platform_destroy_native_window (eglglessink->display, eglglessink->window); + + eglglessink->selected_fmt = NULL; + g_list_free_full (eglglessink->supported_fmts, gst_eglglessink_wipe_fmt); + g_mutex_free (eglglessink->flow_lock); eglglessink->flow_lock = NULL; @@ -871,13 +953,18 @@ static void gst_eglglessink_expose (GstXOverlay * overlay) { GstEglGlesSink *eglglessink; + GstFlowReturn ret; + eglglessink = GST_EGLGLESSINK (overlay); GST_DEBUG_OBJECT (eglglessink, "Expose catched, redisplay"); /* Logic would be to get _render_and_display() to use * last seen buffer to render from when NULL it's * passed on */ - return gst_eglglessink_render_and_display (eglglessink, NULL); + GST_WARNING_OBJECT (eglglessink, "_expose() not implemented"); + ret = gst_eglglessink_render_and_display (eglglessink, NULL); + if (ret == GST_FLOW_ERROR) + GST_ERROR_OBJECT (eglglessink, "Redisplay failed"); } /* Checks available egl/gles extensions and chooses @@ -908,7 +995,7 @@ gst_eglglessink_init_egl_exts (GstEglGlesSink * eglglessink) goto KHR_IMAGE_NA; if (!strstr (eglexts, "EGL_KHR_lock_surface")) goto SURFACE_LOCK_NA; - if (!strstr (glexts, "GL_OES_EGL_image")) + if (!strstr ((char *) glexts, "GL_OES_EGL_image")) goto TEXTURE_2DOES_NA; /* Check for actual extension proc addresses */ @@ -1159,11 +1246,8 @@ HANDLE_ERROR: static gboolean gst_eglglessink_init_egl_display (GstEglGlesSink * eglglessink) { - GLint egl_configs; EGLint egl_major, egl_minor; - EGLint con_attribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; - GST_DEBUG_OBJECT (eglglessink, "Enter EGL initial configuration"); eglglessink->display = eglGetDisplay (EGL_DEFAULT_DISPLAY); @@ -1188,15 +1272,31 @@ gst_eglglessink_init_egl_display (GstEglGlesSink * eglglessink) GST_INFO_OBJECT (eglglessink, "System reports supported EGL version v%d.%d", egl_major, egl_minor); - if (!eglChooseConfig (eglglessink->display, eglglessink_RGB24_config, + eglBindAPI (EGL_OPENGL_ES_API); + + return TRUE; + + /* Errors */ +HANDLE_EGL_ERROR: + GST_ERROR_OBJECT (eglglessink, "EGL call returned error %x", eglGetError ()); +HANDLE_ERROR: + GST_ERROR_OBJECT (eglglessink, "Couldn't setup window/surface from handle"); + return FALSE; +} + +static gboolean +gst_eglglessink_choose_config (GstEglGlesSink * eglglessink) +{ + EGLint con_attribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; + GLint egl_configs; + + if (!eglChooseConfig (eglglessink->display, eglglessink->selected_fmt->eglcfg, &eglglessink->config, 1, &egl_configs)) { show_egl_error ("eglChooseConfig"); GST_ERROR_OBJECT (eglglessink, "Could not choose EGL config"); goto HANDLE_EGL_ERROR; } - eglBindAPI (EGL_OPENGL_ES_API); - eglglessink->context = eglCreateContext (eglglessink->display, eglglessink->config, EGL_NO_CONTEXT, con_attribs); @@ -1212,8 +1312,7 @@ gst_eglglessink_init_egl_display (GstEglGlesSink * eglglessink) /* Errors */ HANDLE_EGL_ERROR: GST_ERROR_OBJECT (eglglessink, "EGL call returned error %x", eglGetError ()); -HANDLE_ERROR: - GST_ERROR_OBJECT (eglglessink, "Couldn't setup window/surface from handle"); + GST_ERROR_OBJECT (eglglessink, "Couldn't choose config"); return FALSE; } @@ -1227,8 +1326,8 @@ gst_eglglessink_set_window_handle (GstXOverlay * overlay, guintptr id) GST_DEBUG_OBJECT (eglglessink, "We got a window handle!"); if (!id) { - /* We are being requested to create our own window. - * 0x0 fires default size creation + /* We are being requested to create our own window. + * 0x0 fires default size creation. */ GST_WARNING_OBJECT (eglglessink, "OH NOES they want a new window"); g_mutex_lock (eglglessink->flow_lock); @@ -1325,8 +1424,20 @@ gst_eglglessink_render_and_display (GstEglGlesSink * eglglessink, * width and height values when non power of two * and no npot extension available. */ - glTexImage2D (GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, GL_RGB, - GL_UNSIGNED_BYTE, GST_BUFFER_DATA (buf)); + switch (eglglessink->selected_fmt->fmt) { + case GST_EGLGLESSINK_IMAGE_RGB888: + glTexImage2D (GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, GL_RGB, + GL_UNSIGNED_BYTE, GST_BUFFER_DATA (buf)); + break; + case GST_EGLGLESSINK_IMAGE_RGB565: + glTexImage2D (GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, GL_RGB, + GL_UNSIGNED_SHORT_5_6_5, GST_BUFFER_DATA (buf)); + break; + case GST_EGLGLESSINK_IMAGE_RGBA8888: + glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, + GL_UNSIGNED_BYTE, GST_BUFFER_DATA (buf)); + } + if (got_gl_error ("glTexImage2D")) goto HANDLE_ERROR; @@ -1432,6 +1543,11 @@ gst_eglglessink_setcaps (GstBaseSink * bsink, GstCaps * caps) } } + if (!gst_eglglessink_choose_config (eglglessink)) { + GST_ERROR_OBJECT (eglglessink, "Couldn't choose EGL config"); + goto HANDLE_ERROR; + } + /* OK, got caps and had none. Ask application to give us a window */ if (!eglglessink->have_window) { gst_x_overlay_prepare_xwindow_id (GST_X_OVERLAY (eglglessink)); diff --git a/ext/eglgles/gsteglglessink.h b/ext/eglgles/gsteglglessink.h index 8ead38240..80ae91d24 100644 --- a/ext/eglgles/gsteglglessink.h +++ b/ext/eglgles/gsteglglessink.h @@ -63,11 +63,13 @@ G_BEGIN_DECLS (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_EGLGLESSINK)) #define GST_IS_EGLGLESSINK_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_EGLGLESSINK)) -/* XXX: Harcoded format. Should be runtime built latter on. */ -#define GST_EGLGLESSINK_IMAGE_RGB24 1 -#define GST_EGLGLESSINK_IMAGE_NOFMT -1 -#define GST_EGLGLESSINK_EGL_MIN_VERSION 1 +#define GST_EGLGLESSINK_IMAGE_NOFMT 0 +#define GST_EGLGLESSINK_IMAGE_RGB888 1 +#define GST_EGLGLESSINK_IMAGE_RGB565 2 +#define GST_EGLGLESSINK_IMAGE_RGBA8888 3 + +#define GST_EGLGLESSINK_EGL_MIN_VERSION 1 typedef struct _GstEglGlesBuffer GstEglGlesBuffer; typedef struct _GstEglGlesBufferClass GstEglGlesBufferClass; @@ -95,6 +97,7 @@ typedef struct _coord struct _GstEglGlesImageFmt { gint fmt; + const EGLint *eglcfg; GstCaps *caps; }; @@ -124,6 +127,7 @@ struct _GstEglGlesSink * format/caps at init. */ GList *supported_fmts; + GstEglGlesImageFmt *selected_fmt; GMutex *flow_lock; |