mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-20 07:16:55 +00:00
eglglessink: Drop drafted fast rendering path logic
This commit is contained in:
parent
9e8ad1097b
commit
ab81bd8f1e
2 changed files with 289 additions and 975 deletions
|
@ -55,9 +55,7 @@
|
||||||
* This sink has been tested to work on X11/Mesa and on Android
|
* This sink has been tested to work on X11/Mesa and on Android
|
||||||
* (From Gingerbread on to Jelly Bean) and while it's currently
|
* (From Gingerbread on to Jelly Bean) and while it's currently
|
||||||
* using an slow copy-over rendering path it has proven to be fast
|
* using an slow copy-over rendering path it has proven to be fast
|
||||||
* enough on the devices we have tried it on. That being said, there's
|
* enough on the devices we have tried it on.
|
||||||
* an currently unfinished and drafted fast rendering path in the code,
|
|
||||||
* relying on a set of EGL/GLES extensions.
|
|
||||||
*
|
*
|
||||||
* <refsect2>
|
* <refsect2>
|
||||||
* <title>Supported EGL/OpenGL ES versions</title>
|
* <title>Supported EGL/OpenGL ES versions</title>
|
||||||
|
@ -74,18 +72,6 @@
|
||||||
* </refsect2>
|
* </refsect2>
|
||||||
*
|
*
|
||||||
* <refsect2>
|
* <refsect2>
|
||||||
* <title>Example launch line with forced slow path rendering</title>
|
|
||||||
* <para>
|
|
||||||
* By setting the force_rendering_slow property you can force the sink
|
|
||||||
* to chose the buffer-copy slow rendering path even if the needed
|
|
||||||
* EGL/GLES extensions for the fast rendering path are available.
|
|
||||||
* </para>
|
|
||||||
* |[
|
|
||||||
* gst-launch -v -m videotestsrc ! eglglessink force_rendering_slow=TRUE
|
|
||||||
* ]|
|
|
||||||
* </refsect2>
|
|
||||||
*
|
|
||||||
* <refsect2>
|
|
||||||
* <title>Example launch line with internal window creation disabled</title>
|
* <title>Example launch line with internal window creation disabled</title>
|
||||||
* <para>
|
* <para>
|
||||||
* By setting the can_create_window property to FALSE you can force the
|
* By setting the can_create_window property to FALSE you can force the
|
||||||
|
@ -156,28 +142,6 @@
|
||||||
GST_DEBUG_CATEGORY_STATIC (gst_eglglessink_debug);
|
GST_DEBUG_CATEGORY_STATIC (gst_eglglessink_debug);
|
||||||
#define GST_CAT_DEFAULT gst_eglglessink_debug
|
#define GST_CAT_DEFAULT gst_eglglessink_debug
|
||||||
|
|
||||||
/* These are only needed for the fast rendering path */
|
|
||||||
#ifdef EGL_KHR_image
|
|
||||||
static PFNEGLCREATEIMAGEKHRPROC my_eglCreateImageKHR;
|
|
||||||
static PFNEGLDESTROYIMAGEKHRPROC my_eglDestroyImageKHR;
|
|
||||||
|
|
||||||
#ifdef EGL_KHR_lock_surface
|
|
||||||
static PFNEGLLOCKSURFACEKHRPROC my_eglLockSurfaceKHR;
|
|
||||||
static PFNEGLUNLOCKSURFACEKHRPROC my_eglUnlockSurfaceKHR;
|
|
||||||
|
|
||||||
static EGLint lock_attribs[] = {
|
|
||||||
EGL_MAP_PRESERVE_PIXELS_KHR, EGL_TRUE,
|
|
||||||
EGL_LOCK_USAGE_HINT_KHR, EGL_READ_SURFACE_BIT_KHR | EGL_WRITE_SURFACE_BIT_KHR,
|
|
||||||
EGL_NONE
|
|
||||||
};
|
|
||||||
|
|
||||||
#ifdef GL_OES_EGL_image
|
|
||||||
static PFNGLEGLIMAGETARGETTEXTURE2DOESPROC my_glEGLImageTargetTexture2DOES;
|
|
||||||
#define EGL_FAST_RENDERING_POSSIBLE 1
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* GLESv2 GLSL Shaders
|
/* GLESv2 GLSL Shaders
|
||||||
*
|
*
|
||||||
* OpenGL ES Standard does not mandate YUV support. This is
|
* OpenGL ES Standard does not mandate YUV support. This is
|
||||||
|
@ -358,7 +322,6 @@ enum
|
||||||
PROP_0,
|
PROP_0,
|
||||||
PROP_CREATE_WINDOW,
|
PROP_CREATE_WINDOW,
|
||||||
PROP_FORCE_ASPECT_RATIO,
|
PROP_FORCE_ASPECT_RATIO,
|
||||||
PROP_FORCE_RENDERING_SLOW
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* will probably move elsewhere */
|
/* will probably move elsewhere */
|
||||||
|
@ -400,8 +363,6 @@ static GstStateChangeReturn gst_eglglessink_change_state (GstElement * element,
|
||||||
static GstFlowReturn gst_eglglessink_show_frame (GstVideoSink * vsink,
|
static GstFlowReturn gst_eglglessink_show_frame (GstVideoSink * vsink,
|
||||||
GstBuffer * buf);
|
GstBuffer * buf);
|
||||||
static gboolean gst_eglglessink_setcaps (GstBaseSink * bsink, GstCaps * caps);
|
static gboolean gst_eglglessink_setcaps (GstBaseSink * bsink, GstCaps * caps);
|
||||||
static GstFlowReturn gst_eglglessink_buffer_alloc (GstBaseSink * sink,
|
|
||||||
guint64 offset, guint size, GstCaps * caps, GstBuffer ** buf);
|
|
||||||
static GstCaps *gst_eglglessink_getcaps (GstBaseSink * bsink);
|
static GstCaps *gst_eglglessink_getcaps (GstBaseSink * bsink);
|
||||||
|
|
||||||
/* XOverlay interface cruft */
|
/* XOverlay interface cruft */
|
||||||
|
@ -419,23 +380,9 @@ static void gst_eglglessink_set_window_handle (GstXOverlay * overlay,
|
||||||
static void gst_eglglessink_set_render_rectangle (GstXOverlay * overlay, gint x,
|
static void gst_eglglessink_set_render_rectangle (GstXOverlay * overlay, gint x,
|
||||||
gint y, gint width, gint height);
|
gint y, gint width, gint height);
|
||||||
|
|
||||||
/* Custom Buffer funcs */
|
/* Utility */
|
||||||
static void gst_eglglesbuffer_destroy (GstEglGlesBuffer * eglglessink);
|
|
||||||
static void gst_eglglesbuffer_init (GstEglGlesBuffer * eglglessink,
|
|
||||||
gpointer g_class);
|
|
||||||
static GType gst_eglglesbuffer_get_type (void);
|
|
||||||
static GstEglGlesImageFmt *gst_eglglessink_get_compat_format_from_caps
|
static GstEglGlesImageFmt *gst_eglglessink_get_compat_format_from_caps
|
||||||
(GstEglGlesSink * eglglessink, GstCaps * caps);
|
(GstEglGlesSink * eglglessink, GstCaps * caps);
|
||||||
static void gst_eglglesbuffer_finalize (GstEglGlesBuffer * eglglessink);
|
|
||||||
static void gst_eglglesbuffer_class_init (gpointer g_class,
|
|
||||||
gpointer class_data);
|
|
||||||
static void gst_eglglesbuffer_free (GstEglGlesBuffer * eglglesbuffer);
|
|
||||||
static GstEglGlesBuffer *gst_eglglesbuffer_new (GstEglGlesSink * eglglessink,
|
|
||||||
GstCaps * caps);
|
|
||||||
static EGLint *gst_eglglesbuffer_create_native (EGLNativeWindowType win,
|
|
||||||
EGLConfig config, EGLNativeDisplayType display, const EGLint * egl_attribs);
|
|
||||||
|
|
||||||
/* Utility */
|
|
||||||
static EGLNativeWindowType gst_eglglessink_create_window (GstEglGlesSink *
|
static EGLNativeWindowType gst_eglglessink_create_window (GstEglGlesSink *
|
||||||
eglglessink, gint width, gint height);
|
eglglessink, gint width, gint height);
|
||||||
static inline gint
|
static inline gint
|
||||||
|
@ -459,248 +406,9 @@ static inline gboolean egl_init (GstEglGlesSink * eglglessink);
|
||||||
static gboolean gst_eglglessink_context_make_current (GstEglGlesSink *
|
static gboolean gst_eglglessink_context_make_current (GstEglGlesSink *
|
||||||
eglglessink, gboolean bind);
|
eglglessink, gboolean bind);
|
||||||
|
|
||||||
static GstBufferClass *gsteglglessink_buffer_parent_class = NULL;
|
|
||||||
#define GST_TYPE_EGLGLESBUFFER (gst_eglglesbuffer_get_type())
|
|
||||||
#define GST_IS_EGLGLESBUFFER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_EGLGLESBUFFER))
|
|
||||||
#define GST_EGLGLESBUFFER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_EGLGLESBUFFER, GstEglGlesBuffer))
|
|
||||||
#define GST_EGLGLESBUFFER_CAST(obj) ((GstEglGlesBuffer *)(obj))
|
|
||||||
|
|
||||||
|
|
||||||
GST_BOILERPLATE_FULL (GstEglGlesSink, gst_eglglessink, GstVideoSink,
|
GST_BOILERPLATE_FULL (GstEglGlesSink, gst_eglglessink, GstVideoSink,
|
||||||
GST_TYPE_VIDEO_SINK, gst_eglglessink_init_interfaces);
|
GST_TYPE_VIDEO_SINK, gst_eglglessink_init_interfaces);
|
||||||
|
|
||||||
/* Custom Buffer Funcs */
|
|
||||||
/* XXX: Drafted implementation */
|
|
||||||
static EGLint *
|
|
||||||
gst_eglglesbuffer_create_native (EGLNativeWindowType win,
|
|
||||||
EGLConfig config, EGLNativeDisplayType display, const EGLint * egl_attribs)
|
|
||||||
{
|
|
||||||
EGLNativePixmapType pix = 0;
|
|
||||||
EGLSurface pix_surface;
|
|
||||||
EGLint *buffer = NULL;
|
|
||||||
|
|
||||||
/* XXX: Need to figure out how to create an egl_native_pixmap_t to
|
|
||||||
* feed to eglCreatePixmapSurface. An option on android: create an
|
|
||||||
* android_native_buffer_t to pass straight to eglCreateImageKHR.
|
|
||||||
*/
|
|
||||||
|
|
||||||
pix_surface = eglCreatePixmapSurface (display, config, pix, egl_attribs);
|
|
||||||
|
|
||||||
if (pix_surface == EGL_NO_SURFACE) {
|
|
||||||
show_egl_error ("eglCreatePixmapSurface");
|
|
||||||
GST_CAT_ERROR (GST_CAT_DEFAULT, "Unable to create pixmap surface");
|
|
||||||
goto EGL_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (my_eglLockSurfaceKHR (display, pix_surface, lock_attribs) == EGL_FALSE) {
|
|
||||||
show_egl_error ("eglLockSurfaceKHR");
|
|
||||||
GST_CAT_ERROR (GST_CAT_DEFAULT, "Unable to lock surface");
|
|
||||||
goto EGL_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (eglQuerySurface (display, pix_surface, EGL_BITMAP_POINTER_KHR, buffer)
|
|
||||||
== EGL_FALSE) {
|
|
||||||
show_egl_error ("eglQuerySurface");
|
|
||||||
GST_CAT_ERROR (GST_CAT_DEFAULT,
|
|
||||||
"Unable to query surface for bitmap pointer");
|
|
||||||
goto EGL_ERROR_LOCKED;
|
|
||||||
}
|
|
||||||
|
|
||||||
return buffer;
|
|
||||||
|
|
||||||
EGL_ERROR_LOCKED:
|
|
||||||
my_eglUnlockSurfaceKHR (display, pix_surface);
|
|
||||||
EGL_ERROR:
|
|
||||||
GST_CAT_ERROR (GST_CAT_DEFAULT, "EGL call returned error %x", eglGetError ());
|
|
||||||
if (!eglDestroySurface (display, pix_surface)) {
|
|
||||||
show_egl_error ("eglDestroySurface");
|
|
||||||
GST_CAT_ERROR (GST_CAT_DEFAULT, "Couldn't destroy surface");
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static GstEglGlesBuffer *
|
|
||||||
gst_eglglesbuffer_new (GstEglGlesSink * eglglessink, GstCaps * caps)
|
|
||||||
{
|
|
||||||
GstEglGlesBuffer *eglglesbuffer = NULL;
|
|
||||||
GstStructure *structure = NULL;
|
|
||||||
GstEglGlesImageFmt *format;
|
|
||||||
|
|
||||||
g_return_val_if_fail (GST_IS_EGLGLESSINK (eglglessink), NULL);
|
|
||||||
g_return_val_if_fail (caps, NULL);
|
|
||||||
|
|
||||||
eglglesbuffer =
|
|
||||||
(GstEglGlesBuffer *) gst_mini_object_new (GST_TYPE_EGLGLESBUFFER);
|
|
||||||
GST_DEBUG_OBJECT (eglglesbuffer, "Creating new GstEglGlesBuffer");
|
|
||||||
|
|
||||||
structure = gst_caps_get_structure (caps, 0);
|
|
||||||
|
|
||||||
if (!gst_structure_get_int (structure, "width", &eglglesbuffer->width) ||
|
|
||||||
!gst_structure_get_int (structure, "height", &eglglesbuffer->height)) {
|
|
||||||
GST_WARNING ("Failed getting geometry from caps %" GST_PTR_FORMAT, caps);
|
|
||||||
}
|
|
||||||
|
|
||||||
GST_LOG_OBJECT (eglglessink, "creating %dx%d", eglglesbuffer->width,
|
|
||||||
eglglesbuffer->height);
|
|
||||||
|
|
||||||
format = gst_eglglessink_get_compat_format_from_caps (eglglessink, caps);
|
|
||||||
|
|
||||||
if (!format) {
|
|
||||||
GST_WARNING_OBJECT (eglglessink,
|
|
||||||
"Failed to get format from caps %" GST_PTR_FORMAT, caps);
|
|
||||||
GST_ERROR_OBJECT (eglglessink,
|
|
||||||
"Invalid input caps. Failed to create %dx%d buffer",
|
|
||||||
eglglesbuffer->width, eglglesbuffer->height);
|
|
||||||
goto BEACH_UNLOCKED;
|
|
||||||
}
|
|
||||||
|
|
||||||
eglglesbuffer->format = format->fmt;
|
|
||||||
eglglesbuffer->eglglessink = gst_object_ref (eglglessink);
|
|
||||||
|
|
||||||
eglglesbuffer->image = gst_eglglesbuffer_create_native
|
|
||||||
(eglglessink->eglglesctx.used_window, eglglessink->eglglesctx.config,
|
|
||||||
eglglessink->eglglesctx.display, NULL);
|
|
||||||
if (!eglglesbuffer->image) {
|
|
||||||
GST_ERROR_OBJECT (eglglessink,
|
|
||||||
"Failed to create native %dx%d image buffer", eglglesbuffer->width,
|
|
||||||
eglglesbuffer->height);
|
|
||||||
goto BEACH_UNLOCKED;
|
|
||||||
}
|
|
||||||
|
|
||||||
GST_BUFFER_DATA (eglglesbuffer) = (guchar *) eglglesbuffer->image;
|
|
||||||
GST_BUFFER_SIZE (eglglesbuffer) = eglglesbuffer->size;
|
|
||||||
|
|
||||||
return eglglesbuffer;
|
|
||||||
|
|
||||||
BEACH_UNLOCKED:
|
|
||||||
gst_eglglesbuffer_free (eglglesbuffer);
|
|
||||||
eglglesbuffer = NULL;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
gst_eglglesbuffer_destroy (GstEglGlesBuffer * eglglesbuffer)
|
|
||||||
{
|
|
||||||
|
|
||||||
GstEglGlesSink *eglglessink;
|
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (eglglesbuffer, "Destroying buffer");
|
|
||||||
|
|
||||||
eglglessink = eglglesbuffer->eglglessink;
|
|
||||||
if (G_UNLIKELY (eglglessink == NULL))
|
|
||||||
goto NO_SINK;
|
|
||||||
|
|
||||||
g_return_if_fail (GST_IS_EGLGLESSINK (eglglessink));
|
|
||||||
|
|
||||||
GST_OBJECT_LOCK (eglglessink);
|
|
||||||
GST_DEBUG_OBJECT (eglglessink, "Destroying image");
|
|
||||||
|
|
||||||
if (eglglesbuffer->image) {
|
|
||||||
if (GST_BUFFER_DATA (eglglesbuffer)) {
|
|
||||||
g_free (GST_BUFFER_DATA (eglglesbuffer));
|
|
||||||
}
|
|
||||||
eglglesbuffer->image = NULL;
|
|
||||||
/* XXX: Unallocate EGL/GL especific resources asociated with this
|
|
||||||
* Image here
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
GST_OBJECT_UNLOCK (eglglessink);
|
|
||||||
eglglesbuffer->eglglessink = NULL;
|
|
||||||
gst_object_unref (eglglessink);
|
|
||||||
|
|
||||||
GST_MINI_OBJECT_CLASS (gsteglglessink_buffer_parent_class)->finalize
|
|
||||||
(GST_MINI_OBJECT (eglglesbuffer));
|
|
||||||
|
|
||||||
return;
|
|
||||||
|
|
||||||
NO_SINK:
|
|
||||||
GST_WARNING ("No sink found");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* XXX: Missing implementation.
|
|
||||||
* This function will have the code for maintaing the pool. readding or
|
|
||||||
* destroying the buffers on size or runing/status change. Right now all
|
|
||||||
* it does is to call _destroy.
|
|
||||||
* for a proper implementation take a look at xvimagesink's image buffer
|
|
||||||
* destroy func.
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
gst_eglglesbuffer_finalize (GstEglGlesBuffer * eglglesbuffer)
|
|
||||||
{
|
|
||||||
GstEglGlesSink *eglglessink;
|
|
||||||
|
|
||||||
eglglessink = eglglesbuffer->eglglessink;
|
|
||||||
if (G_UNLIKELY (eglglessink == NULL))
|
|
||||||
goto NO_SINK;
|
|
||||||
|
|
||||||
g_return_if_fail (GST_IS_EGLGLESSINK (eglglessink));
|
|
||||||
|
|
||||||
gst_eglglesbuffer_destroy (eglglesbuffer);
|
|
||||||
|
|
||||||
return;
|
|
||||||
|
|
||||||
NO_SINK:
|
|
||||||
GST_WARNING ("No sink found");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
gst_eglglesbuffer_free (GstEglGlesBuffer * eglglesbuffer)
|
|
||||||
{
|
|
||||||
/* Make sure it is not recycled. This is meaningless without
|
|
||||||
* a pool but was left here as a reference
|
|
||||||
*/
|
|
||||||
eglglesbuffer->width = -1;
|
|
||||||
eglglesbuffer->height = -1;
|
|
||||||
gst_buffer_unref (GST_BUFFER (eglglesbuffer));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
gst_eglglesbuffer_init (GstEglGlesBuffer * eglglesbuffer, gpointer g_class)
|
|
||||||
{
|
|
||||||
eglglesbuffer->width = 0;
|
|
||||||
eglglesbuffer->height = 0;
|
|
||||||
eglglesbuffer->size = 0;
|
|
||||||
eglglesbuffer->image = NULL;
|
|
||||||
eglglesbuffer->format = GST_EGLGLESSINK_IMAGE_NOFMT;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
gst_eglglesbuffer_class_init (gpointer g_class, gpointer class_data)
|
|
||||||
{
|
|
||||||
GstMiniObjectClass *mini_object_class = GST_MINI_OBJECT_CLASS (g_class);
|
|
||||||
|
|
||||||
gsteglglessink_buffer_parent_class = g_type_class_peek_parent (g_class);
|
|
||||||
|
|
||||||
mini_object_class->finalize = (GstMiniObjectFinalizeFunction)
|
|
||||||
gst_eglglesbuffer_finalize;
|
|
||||||
}
|
|
||||||
|
|
||||||
static GType
|
|
||||||
gst_eglglesbuffer_get_type (void)
|
|
||||||
{
|
|
||||||
static GType _gst_eglglessink_buffer_type;
|
|
||||||
|
|
||||||
if (G_UNLIKELY (_gst_eglglessink_buffer_type == 0)) {
|
|
||||||
static const GTypeInfo eglglessink_buffer_info = {
|
|
||||||
sizeof (GstBufferClass),
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
gst_eglglesbuffer_class_init,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
sizeof (GstEglGlesBuffer),
|
|
||||||
0,
|
|
||||||
(GInstanceInitFunc) gst_eglglesbuffer_init,
|
|
||||||
NULL
|
|
||||||
};
|
|
||||||
_gst_eglglessink_buffer_type = g_type_register_static (GST_TYPE_BUFFER,
|
|
||||||
"GstEglGlesBuffer", &eglglessink_buffer_info, 0);
|
|
||||||
}
|
|
||||||
return _gst_eglglessink_buffer_type;
|
|
||||||
}
|
|
||||||
|
|
||||||
static GstEglGlesImageFmt *
|
static GstEglGlesImageFmt *
|
||||||
gst_eglglessink_get_compat_format_from_caps (GstEglGlesSink * eglglessink,
|
gst_eglglessink_get_compat_format_from_caps (GstEglGlesSink * eglglessink,
|
||||||
|
@ -735,222 +443,6 @@ gst_eglglessink_get_compat_format_from_caps (GstEglGlesSink * eglglessink,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstCaps *
|
|
||||||
gst_eglglessink_different_size_suggestion (GstEglGlesSink * eglglessink,
|
|
||||||
GstCaps * caps)
|
|
||||||
{
|
|
||||||
GstCaps *intersection;
|
|
||||||
GstCaps *new_caps;
|
|
||||||
GstStructure *s;
|
|
||||||
gint width, height;
|
|
||||||
gint par_n = 1, par_d = 1;
|
|
||||||
gint dar_n, dar_d;
|
|
||||||
gint w, h;
|
|
||||||
|
|
||||||
new_caps = gst_caps_copy (caps);
|
|
||||||
|
|
||||||
s = gst_caps_get_structure (new_caps, 0);
|
|
||||||
|
|
||||||
gst_structure_get_int (s, "width", &width);
|
|
||||||
gst_structure_get_int (s, "height", &height);
|
|
||||||
gst_structure_get_fraction (s, "pixel-aspect-ratio", &par_n, &par_d);
|
|
||||||
|
|
||||||
gst_structure_remove_field (s, "width");
|
|
||||||
gst_structure_remove_field (s, "height");
|
|
||||||
gst_structure_remove_field (s, "pixel-aspect-ratio");
|
|
||||||
|
|
||||||
intersection = gst_caps_intersect (eglglessink->current_caps, new_caps);
|
|
||||||
gst_caps_unref (new_caps);
|
|
||||||
|
|
||||||
if (gst_caps_is_empty (intersection))
|
|
||||||
return intersection;
|
|
||||||
|
|
||||||
s = gst_caps_get_structure (intersection, 0);
|
|
||||||
|
|
||||||
gst_util_fraction_multiply (width, height, par_n, par_d, &dar_n, &dar_d);
|
|
||||||
|
|
||||||
gst_structure_fixate_field_nearest_int (s, "width", width);
|
|
||||||
gst_structure_fixate_field_nearest_int (s, "height", height);
|
|
||||||
gst_structure_get_int (s, "width", &w);
|
|
||||||
gst_structure_get_int (s, "height", &h);
|
|
||||||
|
|
||||||
gst_util_fraction_multiply (h, w, dar_n, dar_d, &par_n, &par_d);
|
|
||||||
gst_structure_set (s, "pixel-aspect-ratio", GST_TYPE_FRACTION, par_n, par_d,
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
return intersection;
|
|
||||||
}
|
|
||||||
|
|
||||||
static GstFlowReturn
|
|
||||||
gst_eglglessink_buffer_alloc (GstBaseSink * bsink, guint64 offset,
|
|
||||||
guint size, GstCaps * caps, GstBuffer ** buf)
|
|
||||||
{
|
|
||||||
|
|
||||||
GstEglGlesSink *eglglessink;
|
|
||||||
GstFlowReturn ret = GST_FLOW_OK;
|
|
||||||
GstEglGlesBuffer *eglglesbuffer = NULL;
|
|
||||||
GstCaps *intersection = NULL;
|
|
||||||
GstStructure *structure = NULL;
|
|
||||||
gint width, height;
|
|
||||||
GstEglGlesImageFmt *format;
|
|
||||||
|
|
||||||
eglglessink = GST_EGLGLESSINK (bsink);
|
|
||||||
|
|
||||||
/* No custom alloc for the slow rendering path */
|
|
||||||
if (eglglessink->rendering_path == GST_EGLGLESSINK_RENDER_SLOW) {
|
|
||||||
GST_INFO_OBJECT (eglglessink, "No custom alloc for slow rendering path");
|
|
||||||
*buf = NULL;
|
|
||||||
return GST_FLOW_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (G_UNLIKELY (!caps))
|
|
||||||
goto NO_CAPS;
|
|
||||||
|
|
||||||
if (G_LIKELY (gst_caps_is_equal (caps, eglglessink->current_caps))) {
|
|
||||||
GST_LOG_OBJECT (eglglessink,
|
|
||||||
"Buffer alloc for same last_caps, reusing caps");
|
|
||||||
intersection = gst_caps_ref (caps);
|
|
||||||
width = GST_VIDEO_SINK_WIDTH (eglglessink);
|
|
||||||
height = GST_VIDEO_SINK_HEIGHT (eglglessink);
|
|
||||||
|
|
||||||
goto REUSE_LAST_CAPS;
|
|
||||||
}
|
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (eglglessink, "Buffer alloc requested size %d with caps %"
|
|
||||||
GST_PTR_FORMAT ", intersecting with our caps %" GST_PTR_FORMAT, size,
|
|
||||||
caps, eglglessink->current_caps);
|
|
||||||
|
|
||||||
/* Check the caps against our current caps */
|
|
||||||
intersection = gst_caps_intersect (eglglessink->current_caps, caps);
|
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (eglglessink, "Intersection in buffer alloc returned %"
|
|
||||||
GST_PTR_FORMAT, intersection);
|
|
||||||
|
|
||||||
if (gst_caps_is_empty (intersection)) {
|
|
||||||
GstCaps *new_caps;
|
|
||||||
|
|
||||||
gst_caps_unref (intersection);
|
|
||||||
|
|
||||||
/* So we don't support this kind of buffer, let's define one we'd like */
|
|
||||||
new_caps = gst_caps_copy (caps);
|
|
||||||
|
|
||||||
structure = gst_caps_get_structure (new_caps, 0);
|
|
||||||
if (!gst_structure_has_field (structure, "width") ||
|
|
||||||
!gst_structure_has_field (structure, "height")) {
|
|
||||||
gst_caps_unref (new_caps);
|
|
||||||
goto INVALID;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Try different dimensions */
|
|
||||||
intersection =
|
|
||||||
gst_eglglessink_different_size_suggestion (eglglessink, new_caps);
|
|
||||||
|
|
||||||
/* YUV not implemented yet */
|
|
||||||
if (gst_caps_is_empty (intersection)) {
|
|
||||||
|
|
||||||
gst_structure_set_name (structure, "video/x-raw-rgb");
|
|
||||||
|
|
||||||
/* Remove format specific fields */
|
|
||||||
gst_structure_remove_field (structure, "format");
|
|
||||||
gst_structure_remove_field (structure, "endianness");
|
|
||||||
gst_structure_remove_field (structure, "depth");
|
|
||||||
gst_structure_remove_field (structure, "bpp");
|
|
||||||
gst_structure_remove_field (structure, "red_mask");
|
|
||||||
gst_structure_remove_field (structure, "green_mask");
|
|
||||||
gst_structure_remove_field (structure, "blue_mask");
|
|
||||||
gst_structure_remove_field (structure, "alpha_mask");
|
|
||||||
|
|
||||||
/* Reuse intersection with current_caps */
|
|
||||||
intersection = gst_caps_intersect (eglglessink->current_caps, new_caps);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Try with different dimensions and RGB formats */
|
|
||||||
if (gst_caps_is_empty (intersection))
|
|
||||||
intersection =
|
|
||||||
gst_eglglessink_different_size_suggestion (eglglessink, new_caps);
|
|
||||||
|
|
||||||
/* Clean this copy */
|
|
||||||
gst_caps_unref (new_caps);
|
|
||||||
|
|
||||||
if (gst_caps_is_empty (intersection))
|
|
||||||
goto INCOMPATIBLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Ensure the returned caps are fixed */
|
|
||||||
gst_caps_truncate (intersection);
|
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (eglglessink, "Allocating a buffer with caps %"
|
|
||||||
GST_PTR_FORMAT, intersection);
|
|
||||||
if (gst_caps_is_equal (intersection, caps)) {
|
|
||||||
/* Things work better if we return a buffer with the same caps ptr
|
|
||||||
* as was asked for when we can */
|
|
||||||
gst_caps_replace (&intersection, caps);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get image format from caps */
|
|
||||||
format = gst_eglglessink_get_compat_format_from_caps (eglglessink,
|
|
||||||
intersection);
|
|
||||||
|
|
||||||
if (!format)
|
|
||||||
GST_WARNING_OBJECT (eglglessink, "Can't get a compatible format from caps");
|
|
||||||
|
|
||||||
/* Get geometry from caps */
|
|
||||||
structure = gst_caps_get_structure (intersection, 0);
|
|
||||||
if (!gst_structure_get_int (structure, "width", &width) ||
|
|
||||||
!gst_structure_get_int (structure, "height", &height) || !format)
|
|
||||||
goto INVALID_CAPS;
|
|
||||||
|
|
||||||
REUSE_LAST_CAPS:
|
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (eglglessink, "Creating eglglesbuffer");
|
|
||||||
eglglesbuffer = gst_eglglesbuffer_new (eglglessink, intersection);
|
|
||||||
|
|
||||||
if (eglglesbuffer) {
|
|
||||||
/* Make sure the buffer is cleared of any previously used flags */
|
|
||||||
GST_MINI_OBJECT_CAST (eglglesbuffer)->flags = 0;
|
|
||||||
gst_buffer_set_caps (GST_BUFFER_CAST (eglglesbuffer), intersection);
|
|
||||||
}
|
|
||||||
|
|
||||||
*buf = GST_BUFFER_CAST (eglglesbuffer);
|
|
||||||
|
|
||||||
BEACH:
|
|
||||||
if (intersection) {
|
|
||||||
gst_caps_unref (intersection);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
/* ERRORS */
|
|
||||||
INVALID:
|
|
||||||
{
|
|
||||||
GST_DEBUG_OBJECT (eglglessink, "No width/height on caps!?");
|
|
||||||
ret = GST_FLOW_WRONG_STATE;
|
|
||||||
goto BEACH;
|
|
||||||
}
|
|
||||||
INCOMPATIBLE:
|
|
||||||
{
|
|
||||||
GST_WARNING_OBJECT (eglglessink, "We were requested a buffer with "
|
|
||||||
"caps %" GST_PTR_FORMAT ", but our current caps %" GST_PTR_FORMAT
|
|
||||||
" are completely incompatible!", caps, eglglessink->current_caps);
|
|
||||||
ret = GST_FLOW_NOT_NEGOTIATED;
|
|
||||||
goto BEACH;
|
|
||||||
}
|
|
||||||
INVALID_CAPS:
|
|
||||||
{
|
|
||||||
GST_WARNING_OBJECT (eglglessink, "Invalid caps for buffer allocation %"
|
|
||||||
GST_PTR_FORMAT, intersection);
|
|
||||||
ret = GST_FLOW_NOT_NEGOTIATED;
|
|
||||||
goto BEACH;
|
|
||||||
}
|
|
||||||
NO_CAPS:
|
|
||||||
{
|
|
||||||
GST_WARNING_OBJECT (eglglessink, "Have no caps, doing fallback allocation");
|
|
||||||
*buf = NULL;
|
|
||||||
ret = GST_FLOW_OK;
|
|
||||||
goto BEACH;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline gint
|
static inline gint
|
||||||
gst_eglglessink_fill_supported_fbuffer_configs (GstEglGlesSink * eglglessink)
|
gst_eglglessink_fill_supported_fbuffer_configs (GstEglGlesSink * eglglessink)
|
||||||
{
|
{
|
||||||
|
@ -1130,7 +622,6 @@ render_thread_func (GstEglGlesSink * eglglessink)
|
||||||
GST_DEBUG_OBJECT (eglglessink, "Shutting down thread");
|
GST_DEBUG_OBJECT (eglglessink, "Shutting down thread");
|
||||||
|
|
||||||
/* EGL/GLES cleanup */
|
/* EGL/GLES cleanup */
|
||||||
if (eglglessink->rendering_path == GST_EGLGLESSINK_RENDER_SLOW) {
|
|
||||||
glUseProgram (0);
|
glUseProgram (0);
|
||||||
|
|
||||||
if (eglglessink->have_vbo) {
|
if (eglglessink->have_vbo) {
|
||||||
|
@ -1167,7 +658,6 @@ render_thread_func (GstEglGlesSink * eglglessink)
|
||||||
glDeleteShader (eglglessink->eglglesctx.vertshader[1]);
|
glDeleteShader (eglglessink->eglglesctx.vertshader[1]);
|
||||||
eglglessink->eglglesctx.glslprogram[1] = 0;
|
eglglessink->eglglesctx.glslprogram[1] = 0;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
gst_eglglessink_context_make_current (eglglessink, FALSE);
|
gst_eglglessink_context_make_current (eglglessink, FALSE);
|
||||||
|
|
||||||
|
@ -1357,10 +847,10 @@ gst_eglglessink_expose (GstXOverlay * overlay)
|
||||||
GST_ERROR_OBJECT (eglglessink, "Redisplay failed");
|
GST_ERROR_OBJECT (eglglessink, "Redisplay failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Checks available EGL/GLES extensions and chooses
|
/* Prints available EGL/GLES extensions
|
||||||
* a suitable rendering path from GstEglGlesSinkRenderingPath
|
* If another rendering path is implemented this is the place
|
||||||
* accordingly. This function can only be called after an
|
* where you want to check for the availability of its supporting
|
||||||
* EGL context has been made current.
|
* EGL/GLES extensions.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
gst_eglglessink_init_egl_exts (GstEglGlesSink * eglglessink)
|
gst_eglglessink_init_egl_exts (GstEglGlesSink * eglglessink)
|
||||||
|
@ -1376,75 +866,6 @@ gst_eglglessink_init_egl_exts (GstEglGlesSink * eglglessink)
|
||||||
GST_DEBUG_OBJECT (eglglessink, "Available GLES extensions: %s\n",
|
GST_DEBUG_OBJECT (eglglessink, "Available GLES extensions: %s\n",
|
||||||
GST_STR_NULL ((const char *) glexts));
|
GST_STR_NULL ((const char *) glexts));
|
||||||
|
|
||||||
#ifdef EGL_FAST_RENDERING_POSSIBLE
|
|
||||||
/* OK Fast rendering should be possible from the declared
|
|
||||||
* extensions on the eglexts/glexts.h headers
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Check for support from claimed EGL/GLES extensions */
|
|
||||||
|
|
||||||
if (!eglexts || !strstr (eglexts, "EGL_KHR_image"))
|
|
||||||
goto KHR_IMAGE_NA;
|
|
||||||
if (!eglexts || !strstr (eglexts, "EGL_KHR_lock_surface"))
|
|
||||||
goto SURFACE_LOCK_NA;
|
|
||||||
if (!glexts || !strstr ((char *) glexts, "GL_OES_EGL_image"))
|
|
||||||
goto TEXTURE_2DOES_NA;
|
|
||||||
|
|
||||||
/* Check for actual extension proc addresses */
|
|
||||||
|
|
||||||
my_eglCreateImageKHR =
|
|
||||||
(PFNEGLCREATEIMAGEKHRPROC) eglGetProcAddress ("eglCreateImageKHR");
|
|
||||||
my_eglDestroyImageKHR =
|
|
||||||
(PFNEGLDESTROYIMAGEKHRPROC) eglGetProcAddress ("eglDestroyImageKHR");
|
|
||||||
|
|
||||||
if (!my_eglCreateImageKHR || !my_eglDestroyImageKHR) {
|
|
||||||
KHR_IMAGE_NA:
|
|
||||||
GST_INFO_OBJECT (eglglessink, "Extension missing: EGL_KHR_image");
|
|
||||||
goto MISSING_EXTS;
|
|
||||||
}
|
|
||||||
|
|
||||||
my_eglLockSurfaceKHR =
|
|
||||||
(PFNEGLLOCKSURFACEKHRPROC) eglGetProcAddress ("eglLockSurfaceKHR");
|
|
||||||
my_eglUnlockSurfaceKHR =
|
|
||||||
(PFNEGLUNLOCKSURFACEKHRPROC) eglGetProcAddress ("eglUnlockSurfaceKHR");
|
|
||||||
|
|
||||||
if (!my_eglLockSurfaceKHR || !my_eglUnlockSurfaceKHR) {
|
|
||||||
SURFACE_LOCK_NA:
|
|
||||||
GST_INFO_OBJECT (eglglessink, "Extension missing: EGL_KHR_lock_surface");
|
|
||||||
goto MISSING_EXTS;
|
|
||||||
}
|
|
||||||
|
|
||||||
my_glEGLImageTargetTexture2DOES =
|
|
||||||
(PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) eglGetProcAddress
|
|
||||||
("glEGLImageTargetTexture2DOES");
|
|
||||||
|
|
||||||
if (!my_glEGLImageTargetTexture2DOES) {
|
|
||||||
TEXTURE_2DOES_NA:
|
|
||||||
GST_INFO_OBJECT (eglglessink, "Extension missing: GL_OES_EGL_image");
|
|
||||||
goto MISSING_EXTS;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!eglglessink->force_rendering_slow) {
|
|
||||||
GST_INFO_OBJECT (eglglessink,
|
|
||||||
"Have needed extensions for fast rendering path");
|
|
||||||
} else {
|
|
||||||
GST_WARNING_OBJECT (eglglessink,
|
|
||||||
"Extension check passed but slow rendering path being forced");
|
|
||||||
goto SLOW_PATH_SELECTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Extension check passed. Enable fast rendering path */
|
|
||||||
eglglessink->rendering_path = GST_EGLGLESSINK_RENDER_FAST;
|
|
||||||
GST_INFO_OBJECT (eglglessink, "Using fast rendering path");
|
|
||||||
return;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
MISSING_EXTS:
|
|
||||||
GST_WARNING_OBJECT (eglglessink,
|
|
||||||
"Extensions missing. Can't use fast rendering path");
|
|
||||||
SLOW_PATH_SELECTED:
|
|
||||||
eglglessink->rendering_path = GST_EGLGLESSINK_RENDER_SLOW;
|
|
||||||
GST_INFO_OBJECT (eglglessink, "Using slow rendering path");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1736,9 +1157,7 @@ gst_eglglessink_init_egl_surface (GstEglGlesSink * eglglessink)
|
||||||
/* We have a surface! */
|
/* We have a surface! */
|
||||||
eglglessink->have_surface = TRUE;
|
eglglessink->have_surface = TRUE;
|
||||||
|
|
||||||
/* Init vertex and fragment GLSL shaders. This entire block might need to be
|
/* Init vertex and fragment GLSL shaders.
|
||||||
* runtime conditional once the fast rendering path gets fully implemented.
|
|
||||||
*
|
|
||||||
* Note: Shader compiler support is optional but we currently rely on it.
|
* Note: Shader compiler support is optional but we currently rely on it.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -2254,13 +1673,6 @@ gst_eglglessink_render_and_display (GstEglGlesSink * eglglessink,
|
||||||
gint w, h;
|
gint w, h;
|
||||||
guint dar_n, dar_d;
|
guint dar_n, dar_d;
|
||||||
|
|
||||||
#ifdef EGL_FAST_RENDERING_POSSIBLE
|
|
||||||
EGLImageKHR img = EGL_NO_IMAGE_KHR;
|
|
||||||
EGLint attrs[] = { EGL_IMAGE_PRESERVED_KHR,
|
|
||||||
EGL_FALSE, EGL_NONE, EGL_NONE
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
w = GST_VIDEO_SINK_WIDTH (eglglessink);
|
w = GST_VIDEO_SINK_WIDTH (eglglessink);
|
||||||
h = GST_VIDEO_SINK_HEIGHT (eglglessink);
|
h = GST_VIDEO_SINK_HEIGHT (eglglessink);
|
||||||
|
|
||||||
|
@ -2268,26 +1680,6 @@ gst_eglglessink_render_and_display (GstEglGlesSink * eglglessink,
|
||||||
"Got good buffer %p. Sink geometry is %dx%d size %d", buf, w, h,
|
"Got good buffer %p. Sink geometry is %dx%d size %d", buf, w, h,
|
||||||
buf ? GST_BUFFER_SIZE (buf) : -1);
|
buf ? GST_BUFFER_SIZE (buf) : -1);
|
||||||
|
|
||||||
switch (eglglessink->rendering_path) {
|
|
||||||
#ifdef EGL_FAST_RENDERING_POSSIBLE
|
|
||||||
case GST_EGLGLESSINK_RENDER_FAST:
|
|
||||||
/* XXX: Not Fully implemented */
|
|
||||||
img =
|
|
||||||
my_eglCreateImageKHR (eglglessink->eglglesctx.display,
|
|
||||||
EGL_NO_CONTEXT, EGL_NATIVE_PIXMAP_KHR,
|
|
||||||
(EGLClientBuffer) GST_BUFFER_DATA (buf), attrs);
|
|
||||||
|
|
||||||
if (img == EGL_NO_IMAGE_KHR) {
|
|
||||||
GST_ERROR_OBJECT (eglglessink, "my_eglCreateImageKHR failed");
|
|
||||||
goto HANDLE_EGL_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
my_glEGLImageTargetTexture2DOES (GL_TEXTURE_2D, img);
|
|
||||||
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
default: /* case GST_EGLGLESSINK_RENDER_SLOW */
|
|
||||||
|
|
||||||
if (buf) {
|
if (buf) {
|
||||||
switch (eglglessink->selected_fmt->fmt) {
|
switch (eglglessink->selected_fmt->fmt) {
|
||||||
case GST_EGLGLESSINK_IMAGE_RGB888:
|
case GST_EGLGLESSINK_IMAGE_RGB888:
|
||||||
|
@ -2303,6 +1695,7 @@ gst_eglglessink_render_and_display (GstEglGlesSink * eglglessink,
|
||||||
GL_UNSIGNED_SHORT_5_6_5, GST_BUFFER_DATA (buf));
|
GL_UNSIGNED_SHORT_5_6_5, GST_BUFFER_DATA (buf));
|
||||||
break;
|
break;
|
||||||
case GST_EGLGLESSINK_IMAGE_RGBA8888:
|
case GST_EGLGLESSINK_IMAGE_RGBA8888:
|
||||||
|
|
||||||
switch (eglglessink->format) {
|
switch (eglglessink->format) {
|
||||||
case GST_VIDEO_FORMAT_RGBA:
|
case GST_VIDEO_FORMAT_RGBA:
|
||||||
case GST_VIDEO_FORMAT_BGRA:
|
case GST_VIDEO_FORMAT_BGRA:
|
||||||
|
@ -2313,15 +1706,13 @@ gst_eglglessink_render_and_display (GstEglGlesSink * eglglessink,
|
||||||
case GST_VIDEO_FORMAT_xRGB:
|
case GST_VIDEO_FORMAT_xRGB:
|
||||||
case GST_VIDEO_FORMAT_xBGR:
|
case GST_VIDEO_FORMAT_xBGR:
|
||||||
glActiveTexture (GL_TEXTURE0);
|
glActiveTexture (GL_TEXTURE0);
|
||||||
glBindTexture (GL_TEXTURE_2D,
|
glBindTexture (GL_TEXTURE_2D, eglglessink->eglglesctx.texture[0]);
|
||||||
eglglessink->eglglesctx.texture[0]);
|
|
||||||
glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA,
|
glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA,
|
||||||
GL_UNSIGNED_BYTE, GST_BUFFER_DATA (buf));
|
GL_UNSIGNED_BYTE, GST_BUFFER_DATA (buf));
|
||||||
break;
|
break;
|
||||||
case GST_VIDEO_FORMAT_AYUV:
|
case GST_VIDEO_FORMAT_AYUV:
|
||||||
glActiveTexture (GL_TEXTURE0);
|
glActiveTexture (GL_TEXTURE0);
|
||||||
glBindTexture (GL_TEXTURE_2D,
|
glBindTexture (GL_TEXTURE_2D, eglglessink->eglglesctx.texture[0]);
|
||||||
eglglessink->eglglesctx.texture[0]);
|
|
||||||
glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA,
|
glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA,
|
||||||
GL_UNSIGNED_BYTE, GST_BUFFER_DATA (buf));
|
GL_UNSIGNED_BYTE, GST_BUFFER_DATA (buf));
|
||||||
break;
|
break;
|
||||||
|
@ -2340,8 +1731,7 @@ gst_eglglessink_render_and_display (GstEglGlesSink * eglglessink,
|
||||||
ch = gst_video_format_get_component_height (eglglessink->format,
|
ch = gst_video_format_get_component_height (eglglessink->format,
|
||||||
0, h);
|
0, h);
|
||||||
glActiveTexture (GL_TEXTURE0);
|
glActiveTexture (GL_TEXTURE0);
|
||||||
glBindTexture (GL_TEXTURE_2D,
|
glBindTexture (GL_TEXTURE_2D, eglglessink->eglglesctx.texture[0]);
|
||||||
eglglessink->eglglesctx.texture[0]);
|
|
||||||
glTexImage2D (GL_TEXTURE_2D, 0, GL_LUMINANCE, cw, ch, 0,
|
glTexImage2D (GL_TEXTURE_2D, 0, GL_LUMINANCE, cw, ch, 0,
|
||||||
GL_LUMINANCE, GL_UNSIGNED_BYTE,
|
GL_LUMINANCE, GL_UNSIGNED_BYTE,
|
||||||
GST_BUFFER_DATA (buf) + coffset);
|
GST_BUFFER_DATA (buf) + coffset);
|
||||||
|
@ -2353,8 +1743,7 @@ gst_eglglessink_render_and_display (GstEglGlesSink * eglglessink,
|
||||||
ch = gst_video_format_get_component_height (eglglessink->format,
|
ch = gst_video_format_get_component_height (eglglessink->format,
|
||||||
1, h);
|
1, h);
|
||||||
glActiveTexture (GL_TEXTURE1);
|
glActiveTexture (GL_TEXTURE1);
|
||||||
glBindTexture (GL_TEXTURE_2D,
|
glBindTexture (GL_TEXTURE_2D, eglglessink->eglglesctx.texture[1]);
|
||||||
eglglessink->eglglesctx.texture[1]);
|
|
||||||
glTexImage2D (GL_TEXTURE_2D, 0, GL_LUMINANCE, cw, ch, 0,
|
glTexImage2D (GL_TEXTURE_2D, 0, GL_LUMINANCE, cw, ch, 0,
|
||||||
GL_LUMINANCE, GL_UNSIGNED_BYTE,
|
GL_LUMINANCE, GL_UNSIGNED_BYTE,
|
||||||
GST_BUFFER_DATA (buf) + coffset);
|
GST_BUFFER_DATA (buf) + coffset);
|
||||||
|
@ -2366,8 +1755,7 @@ gst_eglglessink_render_and_display (GstEglGlesSink * eglglessink,
|
||||||
ch = gst_video_format_get_component_height (eglglessink->format,
|
ch = gst_video_format_get_component_height (eglglessink->format,
|
||||||
2, h);
|
2, h);
|
||||||
glActiveTexture (GL_TEXTURE2);
|
glActiveTexture (GL_TEXTURE2);
|
||||||
glBindTexture (GL_TEXTURE_2D,
|
glBindTexture (GL_TEXTURE_2D, eglglessink->eglglesctx.texture[2]);
|
||||||
eglglessink->eglglesctx.texture[2]);
|
|
||||||
glTexImage2D (GL_TEXTURE_2D, 0, GL_LUMINANCE, cw, ch, 0,
|
glTexImage2D (GL_TEXTURE_2D, 0, GL_LUMINANCE, cw, ch, 0,
|
||||||
GL_LUMINANCE, GL_UNSIGNED_BYTE,
|
GL_LUMINANCE, GL_UNSIGNED_BYTE,
|
||||||
GST_BUFFER_DATA (buf) + coffset);
|
GST_BUFFER_DATA (buf) + coffset);
|
||||||
|
@ -2377,14 +1765,11 @@ gst_eglglessink_render_and_display (GstEglGlesSink * eglglessink,
|
||||||
case GST_VIDEO_FORMAT_YVYU:
|
case GST_VIDEO_FORMAT_YVYU:
|
||||||
case GST_VIDEO_FORMAT_UYVY:
|
case GST_VIDEO_FORMAT_UYVY:
|
||||||
glActiveTexture (GL_TEXTURE0);
|
glActiveTexture (GL_TEXTURE0);
|
||||||
glBindTexture (GL_TEXTURE_2D,
|
glBindTexture (GL_TEXTURE_2D, eglglessink->eglglesctx.texture[0]);
|
||||||
eglglessink->eglglesctx.texture[0]);
|
|
||||||
glTexImage2D (GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, w, h, 0,
|
glTexImage2D (GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, w, h, 0,
|
||||||
GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE,
|
GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, GST_BUFFER_DATA (buf));
|
||||||
GST_BUFFER_DATA (buf));
|
|
||||||
glActiveTexture (GL_TEXTURE1);
|
glActiveTexture (GL_TEXTURE1);
|
||||||
glBindTexture (GL_TEXTURE_2D,
|
glBindTexture (GL_TEXTURE_2D, eglglessink->eglglesctx.texture[1]);
|
||||||
eglglessink->eglglesctx.texture[1]);
|
|
||||||
glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, GST_ROUND_UP_2 (w) / 2,
|
glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, GST_ROUND_UP_2 (w) / 2,
|
||||||
h, 0, GL_RGBA, GL_UNSIGNED_BYTE, GST_BUFFER_DATA (buf));
|
h, 0, GL_RGBA, GL_UNSIGNED_BYTE, GST_BUFFER_DATA (buf));
|
||||||
break;
|
break;
|
||||||
|
@ -2400,23 +1785,20 @@ gst_eglglessink_render_and_display (GstEglGlesSink * eglglessink,
|
||||||
ch = gst_video_format_get_component_height (eglglessink->format,
|
ch = gst_video_format_get_component_height (eglglessink->format,
|
||||||
0, h);
|
0, h);
|
||||||
glActiveTexture (GL_TEXTURE0);
|
glActiveTexture (GL_TEXTURE0);
|
||||||
glBindTexture (GL_TEXTURE_2D,
|
glBindTexture (GL_TEXTURE_2D, eglglessink->eglglesctx.texture[0]);
|
||||||
eglglessink->eglglesctx.texture[0]);
|
|
||||||
glTexImage2D (GL_TEXTURE_2D, 0, GL_LUMINANCE, cw, ch, 0,
|
glTexImage2D (GL_TEXTURE_2D, 0, GL_LUMINANCE, cw, ch, 0,
|
||||||
GL_LUMINANCE, GL_UNSIGNED_BYTE,
|
GL_LUMINANCE, GL_UNSIGNED_BYTE,
|
||||||
GST_BUFFER_DATA (buf) + coffset);
|
GST_BUFFER_DATA (buf) + coffset);
|
||||||
|
|
||||||
coffset =
|
coffset =
|
||||||
gst_video_format_get_component_offset (eglglessink->format,
|
gst_video_format_get_component_offset (eglglessink->format,
|
||||||
(eglglessink->format == GST_VIDEO_FORMAT_NV12 ? 1 : 2), w,
|
(eglglessink->format == GST_VIDEO_FORMAT_NV12 ? 1 : 2), w, h);
|
||||||
|
cw = gst_video_format_get_component_width (eglglessink->format, 1,
|
||||||
|
w);
|
||||||
|
ch = gst_video_format_get_component_height (eglglessink->format, 1,
|
||||||
h);
|
h);
|
||||||
cw = gst_video_format_get_component_width (eglglessink->format,
|
|
||||||
1, w);
|
|
||||||
ch = gst_video_format_get_component_height (eglglessink->format,
|
|
||||||
1, h);
|
|
||||||
glActiveTexture (GL_TEXTURE1);
|
glActiveTexture (GL_TEXTURE1);
|
||||||
glBindTexture (GL_TEXTURE_2D,
|
glBindTexture (GL_TEXTURE_2D, eglglessink->eglglesctx.texture[1]);
|
||||||
eglglessink->eglglesctx.texture[1]);
|
|
||||||
glTexImage2D (GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, cw, ch, 0,
|
glTexImage2D (GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, cw, ch, 0,
|
||||||
GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE,
|
GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE,
|
||||||
GST_BUFFER_DATA (buf) + coffset);
|
GST_BUFFER_DATA (buf) + coffset);
|
||||||
|
@ -2446,8 +1828,7 @@ gst_eglglessink_render_and_display (GstEglGlesSink * eglglessink,
|
||||||
eglglessink->display_region.x = 0;
|
eglglessink->display_region.x = 0;
|
||||||
eglglessink->display_region.y = 0;
|
eglglessink->display_region.y = 0;
|
||||||
eglglessink->display_region.w = eglglessink->eglglesctx.surface_width;
|
eglglessink->display_region.w = eglglessink->eglglesctx.surface_width;
|
||||||
eglglessink->display_region.h =
|
eglglessink->display_region.h = eglglessink->eglglesctx.surface_height;
|
||||||
eglglessink->eglglesctx.surface_height;
|
|
||||||
} else {
|
} else {
|
||||||
if (!gst_video_calculate_display_ratio (&dar_n, &dar_d, w, h,
|
if (!gst_video_calculate_display_ratio (&dar_n, &dar_d, w, h,
|
||||||
eglglessink->par_n, eglglessink->par_d,
|
eglglessink->par_n, eglglessink->par_d,
|
||||||
|
@ -2499,8 +1880,7 @@ gst_eglglessink_render_and_display (GstEglGlesSink * eglglessink,
|
||||||
glUseProgram (eglglessink->eglglesctx.glslprogram[1]);
|
glUseProgram (eglglessink->eglglesctx.glslprogram[1]);
|
||||||
|
|
||||||
glVertexAttribPointer (eglglessink->eglglesctx.position_loc[1], 3,
|
glVertexAttribPointer (eglglessink->eglglesctx.position_loc[1], 3,
|
||||||
GL_FLOAT, GL_FALSE, sizeof (coord5),
|
GL_FLOAT, GL_FALSE, sizeof (coord5), (gpointer) (4 * sizeof (coord5)));
|
||||||
(gpointer) (4 * sizeof (coord5)));
|
|
||||||
if (got_gl_error ("glVertexAttribPointer"))
|
if (got_gl_error ("glVertexAttribPointer"))
|
||||||
goto HANDLE_ERROR;
|
goto HANDLE_ERROR;
|
||||||
|
|
||||||
|
@ -2511,8 +1891,7 @@ gst_eglglessink_render_and_display (GstEglGlesSink * eglglessink,
|
||||||
GST_DEBUG_OBJECT (eglglessink, "Drawing black border 2");
|
GST_DEBUG_OBJECT (eglglessink, "Drawing black border 2");
|
||||||
|
|
||||||
glVertexAttribPointer (eglglessink->eglglesctx.position_loc[1], 3,
|
glVertexAttribPointer (eglglessink->eglglesctx.position_loc[1], 3,
|
||||||
GL_FLOAT, GL_FALSE, sizeof (coord5),
|
GL_FLOAT, GL_FALSE, sizeof (coord5), (gpointer) (8 * sizeof (coord5)));
|
||||||
(gpointer) (8 * sizeof (coord5)));
|
|
||||||
if (got_gl_error ("glVertexAttribPointer"))
|
if (got_gl_error ("glVertexAttribPointer"))
|
||||||
goto HANDLE_ERROR;
|
goto HANDLE_ERROR;
|
||||||
|
|
||||||
|
@ -2525,8 +1904,7 @@ gst_eglglessink_render_and_display (GstEglGlesSink * eglglessink,
|
||||||
glUseProgram (eglglessink->eglglesctx.glslprogram[0]);
|
glUseProgram (eglglessink->eglglesctx.glslprogram[0]);
|
||||||
|
|
||||||
glVertexAttribPointer (eglglessink->eglglesctx.position_loc[0], 3,
|
glVertexAttribPointer (eglglessink->eglglesctx.position_loc[0], 3,
|
||||||
GL_FLOAT, GL_FALSE, sizeof (coord5),
|
GL_FLOAT, GL_FALSE, sizeof (coord5), (gpointer) (0 * sizeof (coord5)));
|
||||||
(gpointer) (0 * sizeof (coord5)));
|
|
||||||
if (got_gl_error ("glVertexAttribPointer"))
|
if (got_gl_error ("glVertexAttribPointer"))
|
||||||
goto HANDLE_ERROR;
|
goto HANDLE_ERROR;
|
||||||
|
|
||||||
|
@ -2545,7 +1923,6 @@ gst_eglglessink_render_and_display (GstEglGlesSink * eglglessink,
|
||||||
show_egl_error ("eglSwapBuffers");
|
show_egl_error ("eglSwapBuffers");
|
||||||
goto HANDLE_ERROR;
|
goto HANDLE_ERROR;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (eglglessink, "Succesfully rendered 1 frame");
|
GST_DEBUG_OBJECT (eglglessink, "Succesfully rendered 1 frame");
|
||||||
return GST_FLOW_OK;
|
return GST_FLOW_OK;
|
||||||
|
@ -2568,11 +1945,6 @@ gst_eglglessink_show_frame (GstVideoSink * vsink, GstBuffer * buf)
|
||||||
eglglessink = GST_EGLGLESSINK (vsink);
|
eglglessink = GST_EGLGLESSINK (vsink);
|
||||||
GST_DEBUG_OBJECT (eglglessink, "Got buffer: %p", buf);
|
GST_DEBUG_OBJECT (eglglessink, "Got buffer: %p", buf);
|
||||||
|
|
||||||
#ifndef EGL_ANDROID_image_native_buffer
|
|
||||||
GST_WARNING_OBJECT (eglglessink, "EGL_ANDROID_image_native_buffer not "
|
|
||||||
"available");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
buf = gst_buffer_make_metadata_writable (gst_buffer_ref (buf));
|
buf = gst_buffer_make_metadata_writable (gst_buffer_ref (buf));
|
||||||
gst_buffer_set_caps (buf, eglglessink->current_caps);
|
gst_buffer_set_caps (buf, eglglessink->current_caps);
|
||||||
return gst_eglglessink_queue_buffer (eglglessink, buf);
|
return gst_eglglessink_queue_buffer (eglglessink, buf);
|
||||||
|
@ -2645,7 +2017,6 @@ gst_eglglessink_configure_caps (GstEglGlesSink * eglglessink, GstCaps * caps)
|
||||||
GST_DEBUG_OBJECT (eglglessink, "Caps are not compatible, reconfiguring");
|
GST_DEBUG_OBJECT (eglglessink, "Caps are not compatible, reconfiguring");
|
||||||
|
|
||||||
/* Cleanup */
|
/* Cleanup */
|
||||||
if (eglglessink->rendering_path == GST_EGLGLESSINK_RENDER_SLOW) {
|
|
||||||
glUseProgram (0);
|
glUseProgram (0);
|
||||||
|
|
||||||
if (eglglessink->have_vbo) {
|
if (eglglessink->have_vbo) {
|
||||||
|
@ -2682,7 +2053,6 @@ gst_eglglessink_configure_caps (GstEglGlesSink * eglglessink, GstCaps * caps)
|
||||||
glDeleteShader (eglglessink->eglglesctx.vertshader[1]);
|
glDeleteShader (eglglessink->eglglesctx.vertshader[1]);
|
||||||
eglglessink->eglglesctx.glslprogram[1] = 0;
|
eglglessink->eglglesctx.glslprogram[1] = 0;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (!gst_eglglessink_context_make_current (eglglessink, FALSE))
|
if (!gst_eglglessink_context_make_current (eglglessink, FALSE))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
@ -2900,9 +2270,6 @@ gst_eglglessink_set_property (GObject * object, guint prop_id,
|
||||||
case PROP_CREATE_WINDOW:
|
case PROP_CREATE_WINDOW:
|
||||||
eglglessink->create_window = g_value_get_boolean (value);
|
eglglessink->create_window = g_value_get_boolean (value);
|
||||||
break;
|
break;
|
||||||
case PROP_FORCE_RENDERING_SLOW:
|
|
||||||
eglglessink->force_rendering_slow = g_value_get_boolean (value);
|
|
||||||
break;
|
|
||||||
case PROP_FORCE_ASPECT_RATIO:
|
case PROP_FORCE_ASPECT_RATIO:
|
||||||
eglglessink->force_aspect_ratio = g_value_get_boolean (value);
|
eglglessink->force_aspect_ratio = g_value_get_boolean (value);
|
||||||
break;
|
break;
|
||||||
|
@ -2926,9 +2293,6 @@ gst_eglglessink_get_property (GObject * object, guint prop_id,
|
||||||
case PROP_CREATE_WINDOW:
|
case PROP_CREATE_WINDOW:
|
||||||
g_value_set_boolean (value, eglglessink->create_window);
|
g_value_set_boolean (value, eglglessink->create_window);
|
||||||
break;
|
break;
|
||||||
case PROP_FORCE_RENDERING_SLOW:
|
|
||||||
g_value_set_boolean (value, eglglessink->force_rendering_slow);
|
|
||||||
break;
|
|
||||||
case PROP_FORCE_ASPECT_RATIO:
|
case PROP_FORCE_ASPECT_RATIO:
|
||||||
g_value_set_boolean (value, eglglessink->force_aspect_ratio);
|
g_value_set_boolean (value, eglglessink->force_aspect_ratio);
|
||||||
break;
|
break;
|
||||||
|
@ -2976,8 +2340,6 @@ gst_eglglessink_class_init (GstEglGlesSinkClass * klass)
|
||||||
|
|
||||||
gstbasesink_class->set_caps = GST_DEBUG_FUNCPTR (gst_eglglessink_setcaps);
|
gstbasesink_class->set_caps = GST_DEBUG_FUNCPTR (gst_eglglessink_setcaps);
|
||||||
gstbasesink_class->get_caps = GST_DEBUG_FUNCPTR (gst_eglglessink_getcaps);
|
gstbasesink_class->get_caps = GST_DEBUG_FUNCPTR (gst_eglglessink_getcaps);
|
||||||
gstbasesink_class->buffer_alloc = GST_DEBUG_FUNCPTR
|
|
||||||
(gst_eglglessink_buffer_alloc);
|
|
||||||
|
|
||||||
gstvideosink_class->show_frame =
|
gstvideosink_class->show_frame =
|
||||||
GST_DEBUG_FUNCPTR (gst_eglglessink_show_frame);
|
GST_DEBUG_FUNCPTR (gst_eglglessink_show_frame);
|
||||||
|
@ -2988,12 +2350,6 @@ gst_eglglessink_class_init (GstEglGlesSinkClass * klass)
|
||||||
"render to if none is provided. This is currently only supported "
|
"render to if none is provided. This is currently only supported "
|
||||||
"when the sink is used under X11",
|
"when the sink is used under X11",
|
||||||
TRUE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
TRUE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||||
g_object_class_install_property (gobject_class, PROP_FORCE_RENDERING_SLOW,
|
|
||||||
g_param_spec_boolean ("force-rendering-slow", "Force slow rendering path",
|
|
||||||
"If set to true, the sink will use the slow rendering path even "
|
|
||||||
"if needed EGL/GLES extensions for the fast rendering path are found "
|
|
||||||
"to be available at runtime",
|
|
||||||
FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
|
||||||
g_object_class_install_property (gobject_class, PROP_FORCE_ASPECT_RATIO,
|
g_object_class_install_property (gobject_class, PROP_FORCE_ASPECT_RATIO,
|
||||||
g_param_spec_boolean ("force-aspect-ratio",
|
g_param_spec_boolean ("force-aspect-ratio",
|
||||||
"Respect aspect ratio when scaling",
|
"Respect aspect ratio when scaling",
|
||||||
|
@ -3027,7 +2383,6 @@ gst_eglglessink_init (GstEglGlesSink * eglglessink,
|
||||||
/** Props */
|
/** Props */
|
||||||
eglglessink->create_window = TRUE;
|
eglglessink->create_window = TRUE;
|
||||||
eglglessink->force_aspect_ratio = TRUE;
|
eglglessink->force_aspect_ratio = TRUE;
|
||||||
eglglessink->force_rendering_slow = FALSE;
|
|
||||||
|
|
||||||
eglglessink->par_n = 1;
|
eglglessink->par_n = 1;
|
||||||
eglglessink->par_d = 1;
|
eglglessink->par_d = 1;
|
||||||
|
|
|
@ -71,24 +71,12 @@ G_BEGIN_DECLS
|
||||||
#define GST_EGLGLESSINK_IMAGE_RGB565 2
|
#define GST_EGLGLESSINK_IMAGE_RGB565 2
|
||||||
#define GST_EGLGLESSINK_IMAGE_RGBA8888 3
|
#define GST_EGLGLESSINK_IMAGE_RGBA8888 3
|
||||||
#define GST_EGLGLESSINK_EGL_MIN_VERSION 1
|
#define GST_EGLGLESSINK_EGL_MIN_VERSION 1
|
||||||
typedef struct _GstEglGlesBuffer GstEglGlesBuffer;
|
|
||||||
typedef struct _GstEglGlesBufferClass GstEglGlesBufferClass;
|
|
||||||
|
|
||||||
typedef struct _GstEglGlesSink GstEglGlesSink;
|
typedef struct _GstEglGlesSink GstEglGlesSink;
|
||||||
typedef struct _GstEglGlesSinkClass GstEglGlesSinkClass;
|
typedef struct _GstEglGlesSinkClass GstEglGlesSinkClass;
|
||||||
typedef struct _GstEglGlesRenderContext GstEglGlesRenderContext;
|
typedef struct _GstEglGlesRenderContext GstEglGlesRenderContext;
|
||||||
|
|
||||||
typedef struct _GstEglGlesImageFmt GstEglGlesImageFmt;
|
typedef struct _GstEglGlesImageFmt GstEglGlesImageFmt;
|
||||||
|
|
||||||
/* Should be extended if new rendering methods
|
|
||||||
* get implemented.
|
|
||||||
*/
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
GST_EGLGLESSINK_RENDER_SLOW,
|
|
||||||
GST_EGLGLESSINK_RENDER_FAST
|
|
||||||
} GstEglGlesSinkRenderingPath;
|
|
||||||
|
|
||||||
typedef struct _coord5
|
typedef struct _coord5
|
||||||
{
|
{
|
||||||
float x;
|
float x;
|
||||||
|
@ -166,33 +154,6 @@ struct _GstEglGlesImageFmt
|
||||||
GstCaps *caps; /* Matching caps for the attribs */
|
GstCaps *caps; /* Matching caps for the attribs */
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
|
||||||
* GstEglGlesBuffer:
|
|
||||||
* @buffer: GST buffer
|
|
||||||
* @eglglessink: Pointer to the eglglessink instance this buffer belongs to
|
|
||||||
* @image: Pointer to the EGL image data
|
|
||||||
* @format: Image's picture format
|
|
||||||
* @width: Image's pixel width
|
|
||||||
* @height: Image's pixel height
|
|
||||||
* @size: Image's data size
|
|
||||||
*
|
|
||||||
* This struct holds the internal representation of the sink's custom
|
|
||||||
* buffer. This implementation is just a draft and only makes sense for
|
|
||||||
* the fast rendering path logic.
|
|
||||||
*/
|
|
||||||
struct _GstEglGlesBuffer
|
|
||||||
{
|
|
||||||
/* XXX: Maybe use GstVideoRectangle for the image data? */
|
|
||||||
GstBuffer buffer;
|
|
||||||
GstEglGlesSink *eglglessink;
|
|
||||||
|
|
||||||
EGLint *image;
|
|
||||||
gint format;
|
|
||||||
|
|
||||||
gint width, height;
|
|
||||||
size_t size;
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* GstEglGlesSink:
|
* GstEglGlesSink:
|
||||||
* @par_n: Incoming frame's aspect ratio numerator
|
* @par_n: Incoming frame's aspect ratio numerator
|
||||||
|
@ -229,7 +190,6 @@ struct _GstEglGlesSink
|
||||||
GstCaps *current_caps, *configured_caps;
|
GstCaps *current_caps, *configured_caps;
|
||||||
|
|
||||||
GstEglGlesImageFmt *selected_fmt;
|
GstEglGlesImageFmt *selected_fmt;
|
||||||
GstEglGlesSinkRenderingPath rendering_path;
|
|
||||||
GstEglGlesRenderContext eglglesctx;
|
GstEglGlesRenderContext eglglesctx;
|
||||||
|
|
||||||
GList *supported_fmts;
|
GList *supported_fmts;
|
||||||
|
@ -251,7 +211,6 @@ struct _GstEglGlesSink
|
||||||
|
|
||||||
/* Properties */
|
/* Properties */
|
||||||
gboolean create_window;
|
gboolean create_window;
|
||||||
gboolean force_rendering_slow;
|
|
||||||
gboolean force_aspect_ratio;
|
gboolean force_aspect_ratio;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue