summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastian Dröge <sebastian.droege@collabora.co.uk>2012-09-13 10:11:27 +0200
committerSebastian Dröge <sebastian.droege@collabora.co.uk>2012-09-13 10:11:27 +0200
commit7a407a4456b4010e3d57fce1428d3bad655ef541 (patch)
tree60d8b2321eba0e536f171e171c929f09975707d9
parentf3c761b9559f98f16d1bcefce6e9e46d74ca657b (diff)
parent9c871940e8576dd39a172974975f794204a3c383 (diff)
Merge remote-tracking branch 'reynaldo/android' into sdk-0.10.23sdk-0.10.23
-rw-r--r--ext/eglgles/gsteglglessink.c208
-rw-r--r--ext/eglgles/gsteglglessink.h12
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;