eglglessink: Caps nego. Start extending RGB support to a set.
This commit is contained in:
parent
bd28c42fae
commit
a8f60690aa
@ -157,14 +157,26 @@ static const char *frag_prog = {
|
|||||||
/* Input capabilities.
|
/* Input capabilities.
|
||||||
*
|
*
|
||||||
* OpenGL ES Standard does not mandate YUV support
|
* OpenGL ES Standard does not mandate YUV support
|
||||||
*
|
* so we are going to stick to RGB for the time being
|
||||||
* XXX: Extend RGB support to a set. Maybe implement YUV too.
|
|
||||||
*/
|
*/
|
||||||
static GstStaticPadTemplate gst_eglglessink_sink_template_factory =
|
static GstStaticPadTemplate gst_eglglessink_sink_template_factory =
|
||||||
GST_STATIC_PAD_TEMPLATE ("sink",
|
GST_STATIC_PAD_TEMPLATE ("sink",
|
||||||
GST_PAD_SINK,
|
GST_PAD_SINK,
|
||||||
GST_PAD_ALWAYS,
|
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 */
|
/* Filter signals and args */
|
||||||
enum
|
enum
|
||||||
@ -183,11 +195,26 @@ enum
|
|||||||
PROP_FORCE_RENDERING_SLOW
|
PROP_FORCE_RENDERING_SLOW
|
||||||
};
|
};
|
||||||
|
|
||||||
/* XXX: Harcoded for now */
|
/* will probably move elsewhere */
|
||||||
static EGLint eglglessink_RGB24_config[] = {
|
static EGLint eglglessink_RGBA8888_config[] = {
|
||||||
EGL_RED_SIZE, 8,
|
EGL_RED_SIZE, 8,
|
||||||
EGL_GREEN_SIZE, 8,
|
EGL_GREEN_SIZE, 8,
|
||||||
EGL_BLUE_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
|
EGL_NONE
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -244,6 +271,7 @@ static GstFlowReturn gst_eglglessink_render_and_display (GstEglGlesSink * sink,
|
|||||||
GstBuffer * buf);
|
GstBuffer * buf);
|
||||||
static inline gboolean got_gl_error (const char *wtf);
|
static inline gboolean got_gl_error (const char *wtf);
|
||||||
static inline void show_egl_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;
|
static GstBufferClass *gsteglglessink_buffer_parent_class = NULL;
|
||||||
#define GST_TYPE_EGLGLESBUFFER (gst_eglglesbuffer_get_type())
|
#define GST_TYPE_EGLGLESBUFFER (gst_eglglesbuffer_get_type())
|
||||||
@ -260,7 +288,7 @@ GST_BOILERPLATE_FULL (GstEglGlesSink, gst_eglglessink, GstVideoSink,
|
|||||||
static EGLint *gst_eglglesbuffer_create_native (EGLNativeWindowType win,
|
static EGLint *gst_eglglesbuffer_create_native (EGLNativeWindowType win,
|
||||||
EGLConfig config, EGLNativeDisplayType display, const EGLint * egl_attribs)
|
EGLConfig config, EGLNativeDisplayType display, const EGLint * egl_attribs)
|
||||||
{
|
{
|
||||||
EGLNativePixmapType pix;
|
EGLNativePixmapType pix = 0;
|
||||||
EGLSurface pix_surface;
|
EGLSurface pix_surface;
|
||||||
EGLint *buffer = NULL;
|
EGLint *buffer = NULL;
|
||||||
|
|
||||||
@ -509,12 +537,14 @@ gst_eglglessink_get_compat_format_from_caps (GstEglGlesSink * eglglessink,
|
|||||||
GST_PTR_FORMAT " and %" GST_PTR_FORMAT, format->caps, caps);
|
GST_PTR_FORMAT " and %" GST_PTR_FORMAT, format->caps, caps);
|
||||||
if (format) {
|
if (format) {
|
||||||
if (gst_caps_can_intersect (caps, format->caps)) {
|
if (gst_caps_can_intersect (caps, format->caps)) {
|
||||||
|
eglglessink->selected_fmt = format;
|
||||||
return format->fmt;
|
return format->fmt;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
list = g_list_next (list);
|
list = g_list_next (list);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
eglglessink->selected_fmt = NULL;
|
||||||
return GST_EGLGLESSINK_IMAGE_NOFMT;
|
return GST_EGLGLESSINK_IMAGE_NOFMT;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -652,7 +682,7 @@ gst_eglglessink_buffer_alloc (GstBaseSink * bsink, guint64 offset,
|
|||||||
intersection = gst_caps_intersect (eglglessink->current_caps, new_caps);
|
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))
|
if (gst_caps_is_empty (intersection))
|
||||||
intersection =
|
intersection =
|
||||||
gst_eglglessink_different_size_suggestion (eglglessink, new_caps);
|
gst_eglglessink_different_size_suggestion (eglglessink, new_caps);
|
||||||
@ -750,13 +780,6 @@ gst_eglglessink_start (GstBaseSink * sink)
|
|||||||
eglglessink->flow_lock = g_mutex_new ();
|
eglglessink->flow_lock = g_mutex_new ();
|
||||||
g_mutex_lock (eglglessink->flow_lock);
|
g_mutex_lock (eglglessink->flow_lock);
|
||||||
|
|
||||||
ret = gst_eglglessink_init_egl_display (eglglessink);
|
|
||||||
|
|
||||||
if (!ret) {
|
|
||||||
GST_ERROR_OBJECT (eglglessink, "Couldn't init EGL display");
|
|
||||||
goto HANDLE_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = platform_wrapper_init ();
|
ret = platform_wrapper_init ();
|
||||||
|
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
@ -764,17 +787,30 @@ gst_eglglessink_start (GstBaseSink * sink)
|
|||||||
goto HANDLE_ERROR;
|
goto HANDLE_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Init supported caps list (Right now we just harcode the only one we support)
|
/* Init supported format/caps list */
|
||||||
* XXX: Not sure this is the right place to do it.
|
format = g_new0 (GstEglGlesImageFmt, 2);
|
||||||
*/
|
|
||||||
format = g_new0 (GstEglGlesImageFmt, 1);
|
format->fmt = GST_EGLGLESSINK_IMAGE_RGB888;
|
||||||
if (format) {
|
format->eglcfg = eglglessink_RGB888_config;
|
||||||
format->fmt = GST_EGLGLESSINK_IMAGE_RGB24;
|
format->caps = gst_caps_new_simple ("video/x-raw-rgb", "bpp", G_TYPE_INT, 24,
|
||||||
format->caps = gst_caps_copy (gst_pad_get_pad_template_caps
|
NULL);
|
||||||
(GST_VIDEO_SINK_PAD (eglglessink)));
|
eglglessink->supported_fmts = g_list_append
|
||||||
|
(eglglessink->supported_fmts, format);
|
||||||
|
|
||||||
|
format++;
|
||||||
|
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);
|
||||||
|
|
||||||
|
format++;
|
||||||
|
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 = g_list_append
|
||||||
(eglglessink->supported_fmts, format);
|
(eglglessink->supported_fmts, format);
|
||||||
}
|
|
||||||
|
|
||||||
g_mutex_unlock (eglglessink->flow_lock);
|
g_mutex_unlock (eglglessink->flow_lock);
|
||||||
|
|
||||||
@ -785,6 +821,14 @@ HANDLE_ERROR:
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_eglglessink_wipe_fmt (gpointer data)
|
||||||
|
{
|
||||||
|
GstEglGlesImageFmt *format = data;
|
||||||
|
gst_caps_unref (format->caps);
|
||||||
|
g_free (format);
|
||||||
|
}
|
||||||
|
|
||||||
/* XXX: Should implement */
|
/* XXX: Should implement */
|
||||||
gboolean
|
gboolean
|
||||||
gst_eglglessink_stop (GstBaseSink * sink)
|
gst_eglglessink_stop (GstBaseSink * sink)
|
||||||
@ -792,6 +836,10 @@ gst_eglglessink_stop (GstBaseSink * sink)
|
|||||||
GstEglGlesSink *eglglessink = GST_EGLGLESSINK (sink);
|
GstEglGlesSink *eglglessink = GST_EGLGLESSINK (sink);
|
||||||
|
|
||||||
platform_destroy_native_window (eglglessink->display, eglglessink->window);
|
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);
|
g_mutex_free (eglglessink->flow_lock);
|
||||||
eglglessink->flow_lock = NULL;
|
eglglessink->flow_lock = NULL;
|
||||||
|
|
||||||
@ -871,13 +919,18 @@ static void
|
|||||||
gst_eglglessink_expose (GstXOverlay * overlay)
|
gst_eglglessink_expose (GstXOverlay * overlay)
|
||||||
{
|
{
|
||||||
GstEglGlesSink *eglglessink;
|
GstEglGlesSink *eglglessink;
|
||||||
|
GstFlowReturn ret;
|
||||||
|
|
||||||
eglglessink = GST_EGLGLESSINK (overlay);
|
eglglessink = GST_EGLGLESSINK (overlay);
|
||||||
GST_DEBUG_OBJECT (eglglessink, "Expose catched, redisplay");
|
GST_DEBUG_OBJECT (eglglessink, "Expose catched, redisplay");
|
||||||
|
|
||||||
/* Logic would be to get _render_and_display() to use
|
/* Logic would be to get _render_and_display() to use
|
||||||
* last seen buffer to render from when NULL it's
|
* last seen buffer to render from when NULL it's
|
||||||
* passed on */
|
* 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
|
/* Checks available egl/gles extensions and chooses
|
||||||
@ -908,7 +961,7 @@ gst_eglglessink_init_egl_exts (GstEglGlesSink * eglglessink)
|
|||||||
goto KHR_IMAGE_NA;
|
goto KHR_IMAGE_NA;
|
||||||
if (!strstr (eglexts, "EGL_KHR_lock_surface"))
|
if (!strstr (eglexts, "EGL_KHR_lock_surface"))
|
||||||
goto SURFACE_LOCK_NA;
|
goto SURFACE_LOCK_NA;
|
||||||
if (!strstr (glexts, "GL_OES_EGL_image"))
|
if (!strstr ((char *) glexts, "GL_OES_EGL_image"))
|
||||||
goto TEXTURE_2DOES_NA;
|
goto TEXTURE_2DOES_NA;
|
||||||
|
|
||||||
/* Check for actual extension proc addresses */
|
/* Check for actual extension proc addresses */
|
||||||
@ -1188,7 +1241,7 @@ gst_eglglessink_init_egl_display (GstEglGlesSink * eglglessink)
|
|||||||
GST_INFO_OBJECT (eglglessink, "System reports supported EGL version v%d.%d",
|
GST_INFO_OBJECT (eglglessink, "System reports supported EGL version v%d.%d",
|
||||||
egl_major, egl_minor);
|
egl_major, egl_minor);
|
||||||
|
|
||||||
if (!eglChooseConfig (eglglessink->display, eglglessink_RGB24_config,
|
if (!eglChooseConfig (eglglessink->display, eglglessink->selected_fmt->eglcfg,
|
||||||
&eglglessink->config, 1, &egl_configs)) {
|
&eglglessink->config, 1, &egl_configs)) {
|
||||||
show_egl_error ("eglChooseConfig");
|
show_egl_error ("eglChooseConfig");
|
||||||
GST_ERROR_OBJECT (eglglessink, "Could not choose EGL config");
|
GST_ERROR_OBJECT (eglglessink, "Could not choose EGL config");
|
||||||
@ -1228,7 +1281,7 @@ gst_eglglessink_set_window_handle (GstXOverlay * overlay, guintptr id)
|
|||||||
|
|
||||||
if (!id) {
|
if (!id) {
|
||||||
/* We are being requested to create our own window.
|
/* We are being requested to create our own window.
|
||||||
* 0x0 fires default size creation
|
* 0x0 fires default size creation.
|
||||||
*/
|
*/
|
||||||
GST_WARNING_OBJECT (eglglessink, "OH NOES they want a new window");
|
GST_WARNING_OBJECT (eglglessink, "OH NOES they want a new window");
|
||||||
g_mutex_lock (eglglessink->flow_lock);
|
g_mutex_lock (eglglessink->flow_lock);
|
||||||
@ -1325,8 +1378,20 @@ gst_eglglessink_render_and_display (GstEglGlesSink * eglglessink,
|
|||||||
* width and height values when non power of two
|
* width and height values when non power of two
|
||||||
* and no npot extension available.
|
* and no npot extension available.
|
||||||
*/
|
*/
|
||||||
|
switch (eglglessink->selected_fmt->fmt) {
|
||||||
|
case GST_EGLGLESSINK_IMAGE_RGB888:
|
||||||
glTexImage2D (GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, GL_RGB,
|
glTexImage2D (GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, GL_RGB,
|
||||||
GL_UNSIGNED_BYTE, GST_BUFFER_DATA (buf));
|
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"))
|
if (got_gl_error ("glTexImage2D"))
|
||||||
goto HANDLE_ERROR;
|
goto HANDLE_ERROR;
|
||||||
|
|
||||||
@ -1432,6 +1497,11 @@ gst_eglglessink_setcaps (GstBaseSink * bsink, GstCaps * caps)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!gst_eglglessink_init_egl_display (eglglessink)) {
|
||||||
|
GST_ERROR_OBJECT (eglglessink, "Couldn't init EGL display");
|
||||||
|
goto HANDLE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
/* OK, got caps and had none. Ask application to give us a window */
|
/* OK, got caps and had none. Ask application to give us a window */
|
||||||
if (!eglglessink->have_window) {
|
if (!eglglessink->have_window) {
|
||||||
gst_x_overlay_prepare_xwindow_id (GST_X_OVERLAY (eglglessink));
|
gst_x_overlay_prepare_xwindow_id (GST_X_OVERLAY (eglglessink));
|
||||||
|
@ -63,9 +63,11 @@ G_BEGIN_DECLS
|
|||||||
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_EGLGLESSINK))
|
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_EGLGLESSINK))
|
||||||
#define GST_IS_EGLGLESSINK_CLASS(klass) \
|
#define GST_IS_EGLGLESSINK_CLASS(klass) \
|
||||||
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_EGLGLESSINK))
|
(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 0
|
||||||
#define GST_EGLGLESSINK_IMAGE_NOFMT -1
|
#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
|
#define GST_EGLGLESSINK_EGL_MIN_VERSION 1
|
||||||
|
|
||||||
@ -95,6 +97,7 @@ typedef struct _coord
|
|||||||
struct _GstEglGlesImageFmt
|
struct _GstEglGlesImageFmt
|
||||||
{
|
{
|
||||||
gint fmt;
|
gint fmt;
|
||||||
|
const EGLint *eglcfg;
|
||||||
GstCaps *caps;
|
GstCaps *caps;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -124,6 +127,7 @@ struct _GstEglGlesSink
|
|||||||
* format/caps at init.
|
* format/caps at init.
|
||||||
*/
|
*/
|
||||||
GList *supported_fmts;
|
GList *supported_fmts;
|
||||||
|
GstEglGlesImageFmt *selected_fmt;
|
||||||
|
|
||||||
GMutex *flow_lock;
|
GMutex *flow_lock;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user