--- /dev/null
+/* GStreamer
+ * Copyright (C) 2006 Edward Hervey <edward@fluendo.com>
+ *
+ * gstdataqueue.c:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * SECTION:gstdataqueue
+ * @short_description: Threadsafe queueing object
+ *
+ * #EGLGstDataQueue is an object that handles threadsafe queueing of objects. It
+ * also provides size-related functionality. This object should be used for
+ * any #GstElement that wishes to provide some sort of queueing functionality.
+ */
+
+#include <gst/gst.h>
+#include <string.h>
+
+#include "gstdataqueue.h"
+#include "gstqueuearray.h"
+
+GST_DEBUG_CATEGORY_STATIC (data_queue_debug);
+#define GST_CAT_DEFAULT (data_queue_debug)
+GST_DEBUG_CATEGORY_STATIC (data_queue_dataflow);
+
+
+/* Queue signals and args */
+enum
+{
+ SIGNAL_EMPTY,
+ SIGNAL_FULL,
+ LAST_SIGNAL
+};
+
+enum
+{
+ PROP_0,
+ PROP_CUR_LEVEL_VISIBLE,
+ PROP_CUR_LEVEL_BYTES,
+ PROP_CUR_LEVEL_TIME
+ /* FILL ME */
+};
+
+struct _EGLGstDataQueuePrivate
+{
+ /* the array of data we're keeping our grubby hands on */
+ EGLGstQueueArray *queue;
+
+ EGLGstDataQueueSize cur_level; /* size of the queue */
+ EGLGstDataQueueCheckFullFunction checkfull; /* Callback to check if the queue is full */
+ gpointer *checkdata;
+
+ GMutex qlock; /* lock for queue (vs object lock) */
+ gboolean waiting_add;
+ GCond item_add; /* signals buffers now available for reading */
+ gboolean waiting_del;
+ GCond item_del; /* signals space now available for writing */
+ gboolean flushing; /* indicates whether conditions where signalled because
+ * of external flushing */
+ EGLGstDataQueueFullCallback fullcallback;
+ EGLGstDataQueueEmptyCallback emptycallback;
+};
+
+#define EGL_GST_DATA_QUEUE_MUTEX_LOCK(q) G_STMT_START { \
+ GST_CAT_TRACE (data_queue_dataflow, \
+ "locking qlock from thread %p", \
+ g_thread_self ()); \
+ g_mutex_lock (&q->priv->qlock); \
+ GST_CAT_TRACE (data_queue_dataflow, \
+ "locked qlock from thread %p", \
+ g_thread_self ()); \
+} G_STMT_END
+
+#define EGL_GST_DATA_QUEUE_MUTEX_LOCK_CHECK(q, label) G_STMT_START { \
+ EGL_GST_DATA_QUEUE_MUTEX_LOCK (q); \
+ if (q->priv->flushing) \
+ goto label; \
+ } G_STMT_END
+
+#define EGL_GST_DATA_QUEUE_MUTEX_UNLOCK(q) G_STMT_START { \
+ GST_CAT_TRACE (data_queue_dataflow, \
+ "unlocking qlock from thread %p", \
+ g_thread_self ()); \
+ g_mutex_unlock (&q->priv->qlock); \
+} G_STMT_END
+
+#define STATUS(q, msg) \
+ GST_CAT_LOG (data_queue_dataflow, \
+ "queue:%p " msg ": %u visible items, %u " \
+ "bytes, %"G_GUINT64_FORMAT \
+ " ns, %u elements", \
+ queue, \
+ q->priv->cur_level.visible, \
+ q->priv->cur_level.bytes, \
+ q->priv->cur_level.time, \
+ egl_gst_queue_array_get_length (q->priv->queue))
+
+static void egl_gst_data_queue_finalize (GObject * object);
+
+static void egl_gst_data_queue_set_property (GObject * object,
+ guint prop_id, const GValue * value, GParamSpec * pspec);
+static void egl_gst_data_queue_get_property (GObject * object,
+ guint prop_id, GValue * value, GParamSpec * pspec);
+
+static guint egl_gst_data_queue_signals[LAST_SIGNAL] = { 0 };
+
+#define _do_init \
+{ \
+ GST_DEBUG_CATEGORY_INIT (data_queue_debug, "egldataqueue", 0, \
+ "data queue object"); \
+ GST_DEBUG_CATEGORY_INIT (data_queue_dataflow, "egldata_queue_dataflow", 0, \
+ "dataflow inside the data queue object"); \
+}
+
+#define parent_class egl_gst_data_queue_parent_class
+G_DEFINE_TYPE_WITH_CODE (EGLGstDataQueue, egl_gst_data_queue, G_TYPE_OBJECT, _do_init);
+
+static void
+egl_gst_data_queue_class_init (EGLGstDataQueueClass * klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ g_type_class_add_private (klass, sizeof (EGLGstDataQueuePrivate));
+
+ gobject_class->set_property = egl_gst_data_queue_set_property;
+ gobject_class->get_property = egl_gst_data_queue_get_property;
+
+ /* signals */
+ /**
+ * EGLGstDataQueue::empty:
+ * @queue: the queue instance
+ *
+ * Reports that the queue became empty (empty).
+ * A queue is empty if the total amount of visible items inside it (num-visible, time,
+ * size) is lower than the boundary values which can be set through the GObject
+ * properties.
+ */
+ egl_gst_data_queue_signals[SIGNAL_EMPTY] =
+ g_signal_new ("empty", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (EGLGstDataQueueClass, empty), NULL, NULL,
+ g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
+
+ /**
+ * EGLGstDataQueue::full:
+ * @queue: the queue instance
+ *
+ * Reports that the queue became full (full).
+ * A queue is full if the total amount of data inside it (num-visible, time,
+ * size) is higher than the boundary values which can be set through the GObject
+ * properties.
+ */
+ egl_gst_data_queue_signals[SIGNAL_FULL] =
+ g_signal_new ("full", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (EGLGstDataQueueClass, full), NULL, NULL,
+ g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
+
+ /* properties */
+ g_object_class_install_property (gobject_class, PROP_CUR_LEVEL_BYTES,
+ g_param_spec_uint ("current-level-bytes", "Current level (kB)",
+ "Current amount of data in the queue (bytes)",
+ 0, G_MAXUINT, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+ g_object_class_install_property (gobject_class, PROP_CUR_LEVEL_VISIBLE,
+ g_param_spec_uint ("current-level-visible",
+ "Current level (visible items)",
+ "Current number of visible items in the queue", 0, G_MAXUINT, 0,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+ g_object_class_install_property (gobject_class, PROP_CUR_LEVEL_TIME,
+ g_param_spec_uint64 ("current-level-time", "Current level (ns)",
+ "Current amount of data in the queue (in ns)", 0, G_MAXUINT64, 0,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+
+ gobject_class->finalize = egl_gst_data_queue_finalize;
+}
+
+static void
+egl_gst_data_queue_init (EGLGstDataQueue * queue)
+{
+ queue->priv =
+ G_TYPE_INSTANCE_GET_PRIVATE (queue, EGL_GST_TYPE_DATA_QUEUE,
+ EGLGstDataQueuePrivate);
+
+ queue->priv->cur_level.visible = 0; /* no content */
+ queue->priv->cur_level.bytes = 0; /* no content */
+ queue->priv->cur_level.time = 0; /* no content */
+
+ queue->priv->checkfull = NULL;
+
+ g_mutex_init (&queue->priv->qlock);
+ g_cond_init (&queue->priv->item_add);
+ g_cond_init (&queue->priv->item_del);
+ queue->priv->queue = egl_gst_queue_array_new (50);
+
+ GST_DEBUG ("initialized queue's not_empty & not_full conditions");
+}
+
+/**
+ * egl_gst_data_queue_new:
+ * @checkfull: the callback used to tell if the element considers the queue full
+ * or not.
+ * @fullcallback: the callback which will be called when the queue is considered full.
+ * @emptycallback: the callback which will be called when the queue is considered empty.
+ * @checkdata: a #gpointer that will be given in the @checkfull callback.
+ *
+ * Creates a new #EGLGstDataQueue. The difference with @egl_gst_data_queue_new is that it will
+ * not emit the 'full' and 'empty' signals, but instead calling directly @fullcallback
+ * or @emptycallback.
+ *
+ * Returns: a new #EGLGstDataQueue.
+ *
+ * Since: 1.2.0
+ */
+EGLGstDataQueue *
+egl_gst_data_queue_new (EGLGstDataQueueCheckFullFunction checkfull,
+ EGLGstDataQueueFullCallback fullcallback,
+ EGLGstDataQueueEmptyCallback emptycallback, gpointer checkdata)
+{
+ EGLGstDataQueue *ret;
+
+ g_return_val_if_fail (checkfull != NULL, NULL);
+
+ ret = g_object_newv (EGL_GST_TYPE_DATA_QUEUE, 0, NULL);
+ ret->priv->checkfull = checkfull;
+ ret->priv->checkdata = checkdata;
+ ret->priv->fullcallback = fullcallback;
+ ret->priv->emptycallback = emptycallback;
+
+ return ret;
+}
+
+static void
+egl_gst_data_queue_cleanup (EGLGstDataQueue * queue)
+{
+ EGLGstDataQueuePrivate *priv = queue->priv;
+
+ while (!egl_gst_queue_array_is_empty (priv->queue)) {
+ EGLGstDataQueueItem *item = egl_gst_queue_array_pop_head (priv->queue);
+
+ /* Just call the destroy notify on the item */
+ item->destroy (item);
+ }
+ priv->cur_level.visible = 0;
+ priv->cur_level.bytes = 0;
+ priv->cur_level.time = 0;
+}
+
+/* called only once, as opposed to dispose */
+static void
+egl_gst_data_queue_finalize (GObject * object)
+{
+ EGLGstDataQueue *queue = EGL_GST_DATA_QUEUE (object);
+ EGLGstDataQueuePrivate *priv = queue->priv;
+
+ GST_DEBUG ("finalizing queue");
+
+ egl_gst_data_queue_cleanup (queue);
+ egl_gst_queue_array_free (priv->queue);
+
+ GST_DEBUG ("free mutex");
+ g_mutex_clear (&priv->qlock);
+ GST_DEBUG ("done free mutex");
+
+ g_cond_clear (&priv->item_add);
+ g_cond_clear (&priv->item_del);
+
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static inline void
+egl_gst_data_queue_locked_flush (EGLGstDataQueue * queue)
+{
+ EGLGstDataQueuePrivate *priv = queue->priv;
+
+ STATUS (queue, "before flushing");
+ egl_gst_data_queue_cleanup (queue);
+ STATUS (queue, "after flushing");
+ /* we deleted something... */
+ if (priv->waiting_del)
+ g_cond_signal (&priv->item_del);
+}
+
+static inline gboolean
+egl_gst_data_queue_locked_is_empty (EGLGstDataQueue * queue)
+{
+ EGLGstDataQueuePrivate *priv = queue->priv;
+
+ return (egl_gst_queue_array_get_length (priv->queue) == 0);
+}
+
+static inline gboolean
+egl_gst_data_queue_locked_is_full (EGLGstDataQueue * queue)
+{
+ EGLGstDataQueuePrivate *priv = queue->priv;
+
+ return priv->checkfull (queue, priv->cur_level.visible,
+ priv->cur_level.bytes, priv->cur_level.time, priv->checkdata);
+}
+
+/**
+ * egl_gst_data_queue_flush:
+ * @queue: a #EGLGstDataQueue.
+ *
+ * Flushes all the contents of the @queue. Any call to #egl_gst_data_queue_push and
+ * #egl_gst_data_queue_pop will be released.
+ * MT safe.
+ *
+ * Since: 1.2.0
+ */
+void
+egl_gst_data_queue_flush (EGLGstDataQueue * queue)
+{
+ GST_DEBUG ("queue:%p", queue);
+ EGL_GST_DATA_QUEUE_MUTEX_LOCK (queue);
+ egl_gst_data_queue_locked_flush (queue);
+ EGL_GST_DATA_QUEUE_MUTEX_UNLOCK (queue);
+}
+
+/**
+ * egl_gst_data_queue_is_empty:
+ * @queue: a #EGLGstDataQueue.
+ *
+ * Queries if there are any items in the @queue.
+ * MT safe.
+ *
+ * Returns: #TRUE if @queue is empty.
+ *
+ * Since: 1.2.0
+ */
+gboolean
+egl_gst_data_queue_is_empty (EGLGstDataQueue * queue)
+{
+ gboolean res;
+
+ EGL_GST_DATA_QUEUE_MUTEX_LOCK (queue);
+ res = egl_gst_data_queue_locked_is_empty (queue);
+ EGL_GST_DATA_QUEUE_MUTEX_UNLOCK (queue);
+
+ return res;
+}
+
+/**
+ * egl_gst_data_queue_is_full:
+ * @queue: a #EGLGstDataQueue.
+ *
+ * Queries if @queue is full. This check will be done using the
+ * #EGLGstDataQueueCheckFullFunction registered with @queue.
+ * MT safe.
+ *
+ * Returns: #TRUE if @queue is full.
+ *
+ * Since: 1.2.0
+ */
+gboolean
+egl_gst_data_queue_is_full (EGLGstDataQueue * queue)
+{
+ gboolean res;
+
+ EGL_GST_DATA_QUEUE_MUTEX_LOCK (queue);
+ res = egl_gst_data_queue_locked_is_full (queue);
+ EGL_GST_DATA_QUEUE_MUTEX_UNLOCK (queue);
+
+ return res;
+}
+
+/**
+ * egl_gst_data_queue_set_flushing:
+ * @queue: a #EGLGstDataQueue.
+ * @flushing: a #gboolean stating if the queue will be flushing or not.
+ *
+ * Sets the queue to flushing state if @flushing is #TRUE. If set to flushing
+ * state, any incoming data on the @queue will be discarded. Any call currently
+ * blocking on #egl_gst_data_queue_push or #egl_gst_data_queue_pop will return straight
+ * away with a return value of #FALSE. While the @queue is in flushing state,
+ * all calls to those two functions will return #FALSE.
+ *
+ * MT Safe.
+ *
+ * Since: 1.2.0
+ */
+void
+egl_gst_data_queue_set_flushing (EGLGstDataQueue * queue, gboolean flushing)
+{
+ EGLGstDataQueuePrivate *priv = queue->priv;
+
+ GST_DEBUG ("queue:%p , flushing:%d", queue, flushing);
+
+ EGL_GST_DATA_QUEUE_MUTEX_LOCK (queue);
+ priv->flushing = flushing;
+ if (flushing) {
+ /* release push/pop functions */
+ if (priv->waiting_add)
+ g_cond_signal (&priv->item_add);
+ if (priv->waiting_del)
+ g_cond_signal (&priv->item_del);
+ }
+ EGL_GST_DATA_QUEUE_MUTEX_UNLOCK (queue);
+}
+
+/**
+ * egl_gst_data_queue_push:
+ * @queue: a #EGLGstDataQueue.
+ * @item: a #EGLGstDataQueueItem.
+ *
+ * Pushes a #EGLGstDataQueueItem (or a structure that begins with the same fields)
+ * on the @queue. If the @queue is full, the call will block until space is
+ * available, OR the @queue is set to flushing state.
+ * MT safe.
+ *
+ * Note that this function has slightly different semantics than gst_pad_push()
+ * and gst_pad_push_event(): this function only takes ownership of @item and
+ * the #GstMiniObject contained in @item if the push was successful. If FALSE
+ * is returned, the caller is responsible for freeing @item and its contents.
+ *
+ * Returns: #TRUE if the @item was successfully pushed on the @queue.
+ *
+ * Since: 1.2.0
+ */
+gboolean
+egl_gst_data_queue_push (EGLGstDataQueue * queue, EGLGstDataQueueItem * item)
+{
+ EGLGstDataQueuePrivate *priv = queue->priv;
+
+ g_return_val_if_fail (EGL_GST_IS_DATA_QUEUE (queue), FALSE);
+ g_return_val_if_fail (item != NULL, FALSE);
+
+ EGL_GST_DATA_QUEUE_MUTEX_LOCK_CHECK (queue, flushing);
+
+ STATUS (queue, "before pushing");
+
+ /* We ALWAYS need to check for queue fillness */
+ if (egl_gst_data_queue_locked_is_full (queue)) {
+ EGL_GST_DATA_QUEUE_MUTEX_UNLOCK (queue);
+ if (G_LIKELY (priv->fullcallback))
+ priv->fullcallback (queue, priv->checkdata);
+ else
+ g_signal_emit (queue, egl_gst_data_queue_signals[SIGNAL_FULL], 0);
+ EGL_GST_DATA_QUEUE_MUTEX_LOCK_CHECK (queue, flushing);
+
+ /* signal might have removed some items */
+ while (egl_gst_data_queue_locked_is_full (queue)) {
+ priv->waiting_del = TRUE;
+ g_cond_wait (&priv->item_del, &priv->qlock);
+ priv->waiting_del = FALSE;
+ if (priv->flushing)
+ goto flushing;
+ }
+ }
+
+ egl_gst_queue_array_push_tail (priv->queue, item);
+
+ if (item->visible)
+ priv->cur_level.visible++;
+ priv->cur_level.bytes += item->size;
+ priv->cur_level.time += item->duration;
+
+ STATUS (queue, "after pushing");
+ if (priv->waiting_add)
+ g_cond_signal (&priv->item_add);
+
+ EGL_GST_DATA_QUEUE_MUTEX_UNLOCK (queue);
+
+ return TRUE;
+
+ /* ERRORS */
+flushing:
+ {
+ GST_DEBUG ("queue:%p, we are flushing", queue);
+ EGL_GST_DATA_QUEUE_MUTEX_UNLOCK (queue);
+ return FALSE;
+ }
+}
+
+/**
+ * egl_gst_data_queue_pop:
+ * @queue: a #EGLGstDataQueue.
+ * @item: pointer to store the returned #EGLGstDataQueueItem.
+ *
+ * Retrieves the first @item available on the @queue. If the queue is currently
+ * empty, the call will block until at least one item is available, OR the
+ * @queue is set to the flushing state.
+ * MT safe.
+ *
+ * Returns: #TRUE if an @item was successfully retrieved from the @queue.
+ *
+ * Since: 1.2.0
+ */
+gboolean
+egl_gst_data_queue_pop (EGLGstDataQueue * queue, EGLGstDataQueueItem ** item)
+{
+ EGLGstDataQueuePrivate *priv = queue->priv;
+
+ g_return_val_if_fail (EGL_GST_IS_DATA_QUEUE (queue), FALSE);
+ g_return_val_if_fail (item != NULL, FALSE);
+
+ EGL_GST_DATA_QUEUE_MUTEX_LOCK_CHECK (queue, flushing);
+
+ STATUS (queue, "before popping");
+
+ if (egl_gst_data_queue_locked_is_empty (queue)) {
+ EGL_GST_DATA_QUEUE_MUTEX_UNLOCK (queue);
+ if (G_LIKELY (priv->emptycallback))
+ priv->emptycallback (queue, priv->checkdata);
+ else
+ g_signal_emit (queue, egl_gst_data_queue_signals[SIGNAL_EMPTY], 0);
+ EGL_GST_DATA_QUEUE_MUTEX_LOCK_CHECK (queue, flushing);
+
+ while (egl_gst_data_queue_locked_is_empty (queue)) {
+ priv->waiting_add = TRUE;
+ g_cond_wait (&priv->item_add, &priv->qlock);
+ priv->waiting_add = FALSE;
+ if (priv->flushing)
+ goto flushing;
+ }
+ }
+
+ /* Get the item from the GQueue */
+ *item = egl_gst_queue_array_pop_head (priv->queue);
+
+ /* update current level counter */
+ if ((*item)->visible)
+ priv->cur_level.visible--;
+ priv->cur_level.bytes -= (*item)->size;
+ priv->cur_level.time -= (*item)->duration;
+
+ STATUS (queue, "after popping");
+ if (priv->waiting_del)
+ g_cond_signal (&priv->item_del);
+
+ EGL_GST_DATA_QUEUE_MUTEX_UNLOCK (queue);
+
+ return TRUE;
+
+ /* ERRORS */
+flushing:
+ {
+ GST_DEBUG ("queue:%p, we are flushing", queue);
+ EGL_GST_DATA_QUEUE_MUTEX_UNLOCK (queue);
+ return FALSE;
+ }
+}
+
+static gint
+is_of_type (gconstpointer a, gconstpointer b)
+{
+ return !G_TYPE_CHECK_INSTANCE_TYPE (a, GPOINTER_TO_SIZE (b));
+}
+
+/**
+ * egl_gst_data_queue_drop_head:
+ * @queue: The #EGLGstDataQueue to drop an item from.
+ * @type: The #GType of the item to drop.
+ *
+ * Pop and unref the head-most #GstMiniObject with the given #GType.
+ *
+ * Returns: TRUE if an element was removed.
+ *
+ * Since: 1.2.0
+ */
+gboolean
+egl_gst_data_queue_drop_head (EGLGstDataQueue * queue, GType type)
+{
+ gboolean res = FALSE;
+ EGLGstDataQueueItem *leak = NULL;
+ guint idx;
+ EGLGstDataQueuePrivate *priv = queue->priv;
+
+ g_return_val_if_fail (EGL_GST_IS_DATA_QUEUE (queue), FALSE);
+
+ GST_DEBUG ("queue:%p", queue);
+
+ EGL_GST_DATA_QUEUE_MUTEX_LOCK (queue);
+ idx = egl_gst_queue_array_find (priv->queue, is_of_type, GSIZE_TO_POINTER (type));
+
+ if (idx == -1)
+ goto done;
+
+ leak = egl_gst_queue_array_drop_element (priv->queue, idx);
+
+ if (leak->visible)
+ priv->cur_level.visible--;
+ priv->cur_level.bytes -= leak->size;
+ priv->cur_level.time -= leak->duration;
+
+ leak->destroy (leak);
+
+ res = TRUE;
+
+done:
+ EGL_GST_DATA_QUEUE_MUTEX_UNLOCK (queue);
+
+ GST_DEBUG ("queue:%p , res:%d", queue, res);
+
+ return res;
+}
+
+/**
+ * egl_gst_data_queue_limits_changed:
+ * @queue: The #EGLGstDataQueue
+ *
+ * Inform the queue that the limits for the fullness check have changed and that
+ * any blocking egl_gst_data_queue_push() should be unblocked to recheck the limts.
+ *
+ * Since: 1.2.0
+ */
+void
+egl_gst_data_queue_limits_changed (EGLGstDataQueue * queue)
+{
+ EGLGstDataQueuePrivate *priv = queue->priv;
+
+ g_return_if_fail (EGL_GST_IS_DATA_QUEUE (queue));
+
+ EGL_GST_DATA_QUEUE_MUTEX_LOCK (queue);
+ if (priv->waiting_del) {
+ GST_DEBUG ("signal del");
+ g_cond_signal (&priv->item_del);
+ }
+ EGL_GST_DATA_QUEUE_MUTEX_UNLOCK (queue);
+}
+
+/**
+ * egl_gst_data_queue_get_level:
+ * @queue: The #EGLGstDataQueue
+ * @level: the location to store the result
+ *
+ * Get the current level of the queue.
+ *
+ * Since: 1.2.0
+ */
+void
+egl_gst_data_queue_get_level (EGLGstDataQueue * queue, EGLGstDataQueueSize * level)
+{
+ EGLGstDataQueuePrivate *priv = queue->priv;
+
+ memcpy (level, (&priv->cur_level), sizeof (EGLGstDataQueueSize));
+}
+
+static void
+egl_gst_data_queue_set_property (GObject * object,
+ guint prop_id, const GValue * value, GParamSpec * pspec)
+{
+ switch (prop_id) {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+egl_gst_data_queue_get_property (GObject * object,
+ guint prop_id, GValue * value, GParamSpec * pspec)
+{
+ EGLGstDataQueue *queue = EGL_GST_DATA_QUEUE (object);
+ EGLGstDataQueuePrivate *priv = queue->priv;
+
+ EGL_GST_DATA_QUEUE_MUTEX_LOCK (queue);
+
+ switch (prop_id) {
+ case PROP_CUR_LEVEL_BYTES:
+ g_value_set_uint (value, priv->cur_level.bytes);
+ break;
+ case PROP_CUR_LEVEL_VISIBLE:
+ g_value_set_uint (value, priv->cur_level.visible);
+ break;
+ case PROP_CUR_LEVEL_TIME:
+ g_value_set_uint64 (value, priv->cur_level.time);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+
+ EGL_GST_DATA_QUEUE_MUTEX_UNLOCK (queue);
+}
gboolean reset);
static gboolean
gst_eglglessink_configure_caps (GstEglGlesSink * eglglessink, GstCaps * caps);
-static GstFlowReturn gst_eglglessink_render_and_display (GstEglGlesSink * sink,
+static GstFlowReturn gst_eglglessink_upload (GstEglGlesSink * sink,
GstBuffer * buf);
+static GstFlowReturn gst_eglglessink_render (GstEglGlesSink * sink);
static GstFlowReturn gst_eglglessink_queue_object (GstEglGlesSink * sink,
GstMiniObject * obj);
static inline gboolean got_gl_error (const char *wtf);
{
GstMessage *message;
GValue val = { 0 };
- GstDataQueueItem *item = NULL;
+ EGLGstDataQueueItem *item = NULL;
GstFlowReturn last_flow = GST_FLOW_OK;
g_value_init (&val, G_TYPE_POINTER);
eglBindAPI (EGL_OPENGL_ES_API);
- while (gst_data_queue_pop (eglglessink->queue, &item)) {
- GST_DEBUG_OBJECT (eglglessink, "Handling object %" GST_PTR_FORMAT,
- item->object);
+ while (egl_gst_data_queue_pop (eglglessink->queue, &item)) {
+ GstMiniObject *object = item->object;
- if (GST_IS_CAPS (item->object)) {
- GstCaps *caps = GST_CAPS_CAST (item->object);
+ GST_DEBUG_OBJECT (eglglessink, "Handling object %" GST_PTR_FORMAT, object);
+
+ if (GST_IS_CAPS (object)) {
+ GstCaps *caps = GST_CAPS_CAST (object);
if (caps != eglglessink->configured_caps) {
if (!gst_eglglessink_configure_caps (eglglessink, caps)) {
last_flow = GST_FLOW_NOT_NEGOTIATED;
}
}
- } else if (GST_IS_BUFFER (item->object) || !item->object) {
- GstBuffer *buf = GST_BUFFER_CAST (item->object);
+ } else if (GST_IS_BUFFER (object) || !object) {
+ GstBuffer *buf = GST_BUFFER_CAST (object);
if (eglglessink->configured_caps) {
- last_flow = gst_eglglessink_render_and_display (eglglessink, buf);
+ last_flow = gst_eglglessink_upload (eglglessink, buf);
+ if (last_flow == GST_FLOW_OK)
+ last_flow = gst_eglglessink_render (eglglessink);
} else {
last_flow = GST_FLOW_OK;
GST_DEBUG_OBJECT (eglglessink,
"No caps configured yet, not drawing anything");
}
+ } else {
+ g_assert_not_reached ();
}
+ item->destroy (item);
+ g_mutex_lock (&eglglessink->render_lock);
+ eglglessink->last_flow = last_flow;
+ g_cond_broadcast (&eglglessink->render_cond);
+ g_mutex_unlock (&eglglessink->render_lock);
- if (item->object) {
- item->destroy (item);
- g_mutex_lock (&eglglessink->render_lock);
- eglglessink->last_flow = last_flow;
- g_cond_broadcast (&eglglessink->render_cond);
- g_mutex_unlock (&eglglessink->render_lock);
- } else {
- item->destroy (item);
- }
if (last_flow != GST_FLOW_OK)
break;
GST_DEBUG_OBJECT (eglglessink, "Successfully handled object");
static void
gst_eglglessink_wipe_eglglesctx (GstEglGlesSink * eglglessink)
{
+ gint i;
+
glUseProgram (0);
if (eglglessink->have_vbo) {
eglglessink->eglglesctx.n_textures = 0;
}
- if (eglglessink->eglglesctx.glslprogram[0]) {
- glDetachShader (eglglessink->eglglesctx.glslprogram[0],
- eglglessink->eglglesctx.fragshader[0]);
- glDetachShader (eglglessink->eglglesctx.glslprogram[0],
- eglglessink->eglglesctx.vertshader[0]);
- glDeleteProgram (eglglessink->eglglesctx.glslprogram[0]);
- glDeleteShader (eglglessink->eglglesctx.fragshader[0]);
- glDeleteShader (eglglessink->eglglesctx.vertshader[0]);
- eglglessink->eglglesctx.glslprogram[0] = 0;
- }
-
- if (eglglessink->eglglesctx.glslprogram[1]) {
- glDetachShader (eglglessink->eglglesctx.glslprogram[1],
- eglglessink->eglglesctx.fragshader[1]);
- glDetachShader (eglglessink->eglglesctx.glslprogram[1],
- eglglessink->eglglesctx.vertshader[1]);
- glDeleteProgram (eglglessink->eglglesctx.glslprogram[1]);
- glDeleteShader (eglglessink->eglglesctx.fragshader[1]);
- glDeleteShader (eglglessink->eglglesctx.vertshader[1]);
- eglglessink->eglglesctx.glslprogram[1] = 0;
+ for (i = 0; i < 2; i++) {
+ if (eglglessink->eglglesctx.glslprogram[i]) {
+ glDetachShader (eglglessink->eglglesctx.glslprogram[i],
+ eglglessink->eglglesctx.fragshader[i]);
+ glDetachShader (eglglessink->eglglesctx.glslprogram[i],
+ eglglessink->eglglesctx.vertshader[i]);
+ glDeleteProgram (eglglessink->eglglesctx.glslprogram[i]);
+ glDeleteShader (eglglessink->eglglesctx.fragshader[i]);
+ glDeleteShader (eglglessink->eglglesctx.vertshader[i]);
+ eglglessink->eglglesctx.glslprogram[i] = 0;
+ eglglessink->eglglesctx.fragshader[i] = 0;
+ eglglessink->eglglesctx.vertshader[i] = 0;
+ }
}
gst_eglglessink_context_make_current (eglglessink, FALSE);
eglglessink->display_region.w = 0;
eglglessink->display_region.h = 0;
- gst_data_queue_set_flushing (eglglessink->queue, FALSE);
+ egl_gst_data_queue_set_flushing (eglglessink->queue, FALSE);
#if !GLIB_CHECK_VERSION (2, 31, 0)
eglglessink->thread =
{
GST_DEBUG_OBJECT (eglglessink, "Stopping");
- gst_data_queue_set_flushing (eglglessink->queue, TRUE);
+ egl_gst_data_queue_set_flushing (eglglessink->queue, TRUE);
g_mutex_lock (&eglglessink->render_lock);
g_cond_broadcast (&eglglessink->render_cond);
g_mutex_unlock (&eglglessink->render_lock);
display_par > EGL_SANE_DAR_MAX) {
GST_DEBUG_OBJECT (eglglessink, "Nonsensical PAR value returned: %d. "
"Bad EGL implementation? "
- "Will use default: %d/%d", eglglessink->eglglesctx.pixel_aspect_ratio,
- EGL_DISPLAY_SCALING, EGL_DISPLAY_SCALING);
+ "Will use default: %d/%d",
+ eglglessink->eglglesctx.pixel_aspect_ratio, EGL_DISPLAY_SCALING,
+ EGL_DISPLAY_SCALING);
eglglessink->eglglesctx.pixel_aspect_ratio = EGL_DISPLAY_SCALING;
} else {
eglglessink->eglglesctx.pixel_aspect_ratio = display_par;
if (!eglglessink->have_texture) {
GST_INFO_OBJECT (eglglessink, "Performing initial texture setup");
- for (i = 0; i < eglglessink->eglglesctx.n_textures; i++) {
- if (i == 0)
- glActiveTexture (GL_TEXTURE0);
- else if (i == 1)
- glActiveTexture (GL_TEXTURE1);
- else if (i == 2)
- glActiveTexture (GL_TEXTURE2);
-
- glGenTextures (1, &eglglessink->eglglesctx.texture[i]);
- if (got_gl_error ("glGenTextures"))
- goto HANDLE_ERROR_LOCKED;
+ glGenTextures (eglglessink->eglglesctx.n_textures,
+ eglglessink->eglglesctx.texture);
+ if (got_gl_error ("glGenTextures"))
+ goto HANDLE_ERROR_LOCKED;
+ for (i = 0; i < eglglessink->eglglesctx.n_textures; i++) {
glBindTexture (GL_TEXTURE_2D, eglglessink->eglglesctx.texture[i]);
if (got_gl_error ("glBindTexture"))
goto HANDLE_ERROR;
}
static void
-gst_eglglessink_set_render_rectangle (GstVideoOverlay * overlay, gint x, gint y,
- gint width, gint height)
+gst_eglglessink_set_render_rectangle (GstVideoOverlay * overlay, gint x,
+ gint y, gint width, gint height)
{
GstEglGlesSink *eglglessink = GST_EGLGLESSINK (overlay);
}
static void
-queue_item_destroy (GstDataQueueItem * item)
+queue_item_destroy (EGLGstDataQueueItem * item)
{
gst_mini_object_replace (&item->object, NULL);
- g_slice_free (GstDataQueueItem, item);
+ g_slice_free (EGLGstDataQueueItem, item);
}
static GstFlowReturn
gst_eglglessink_queue_object (GstEglGlesSink * eglglessink, GstMiniObject * obj)
{
- GstDataQueueItem *item;
+ EGLGstDataQueueItem *item;
GstFlowReturn last_flow;
g_mutex_lock (&eglglessink->render_lock);
if (last_flow != GST_FLOW_OK)
return last_flow;
- item = g_slice_new0 (GstDataQueueItem);
+ item = g_slice_new0 (EGLGstDataQueueItem);
item->object = obj ? gst_mini_object_ref (obj) : NULL;
item->size = 0;
GST_DEBUG_OBJECT (eglglessink, "Queueing object %" GST_PTR_FORMAT, obj);
- if (obj)
- g_mutex_lock (&eglglessink->render_lock);
- if (!gst_data_queue_push (eglglessink->queue, item)) {
+ g_mutex_lock (&eglglessink->render_lock);
+
+ if (!egl_gst_data_queue_push (eglglessink->queue, item)) {
item->destroy (item);
g_mutex_unlock (&eglglessink->render_lock);
GST_DEBUG_OBJECT (eglglessink, "Flushing");
return GST_FLOW_FLUSHING;
}
- if (obj) {
- GST_DEBUG_OBJECT (eglglessink, "Waiting for obj to be handled");
- g_cond_wait (&eglglessink->render_cond, &eglglessink->render_lock);
- GST_DEBUG_OBJECT (eglglessink, "Buffer rendered: %s",
- gst_flow_get_name (eglglessink->last_flow));
- last_flow = eglglessink->last_flow;
- g_mutex_unlock (&eglglessink->render_lock);
- }
+ GST_DEBUG_OBJECT (eglglessink, "Waiting for obj to be handled");
+ g_cond_wait (&eglglessink->render_cond, &eglglessink->render_lock);
+ GST_DEBUG_OBJECT (eglglessink, "Buffer rendered: %s",
+ gst_flow_get_name (eglglessink->last_flow));
+ last_flow = eglglessink->last_flow;
+ g_mutex_unlock (&eglglessink->render_lock);
return (obj ? last_flow : GST_FLOW_OK);
}
}
/* Rendering and display */
-static GstFlowReturn
-gst_eglglessink_render_and_display (GstEglGlesSink * eglglessink,
- GstBuffer * buf)
+static gboolean
+gst_eglglessink_fill_texture (GstEglGlesSink * eglglessink, GstBuffer * buf)
{
GstVideoFrame vframe;
- guint dar_n, dar_d;
- GstVideoCropMeta *crop = NULL;
- gint i;
+ gint w, h;
memset (&vframe, 0, sizeof (vframe));
- if (buf) {
- crop = gst_buffer_get_video_crop_meta (buf);
-
- if (!gst_video_frame_map (&vframe, &eglglessink->configured_info, buf,
- GST_MAP_READ)) {
- GST_ERROR_OBJECT (eglglessink, "Couldn't map frame");
- goto HANDLE_ERROR;
- }
- } else {
- GST_DEBUG_OBJECT (eglglessink, "Rendering previous buffer again");
+ if (!gst_video_frame_map (&vframe, &eglglessink->configured_info, buf,
+ GST_MAP_READ)) {
+ GST_ERROR_OBJECT (eglglessink, "Couldn't map frame");
+ goto HANDLE_ERROR;
}
- if (buf) {
- gint w, h;
+ w = GST_VIDEO_FRAME_WIDTH (&vframe);
+ h = GST_VIDEO_FRAME_HEIGHT (&vframe);
- w = GST_VIDEO_FRAME_WIDTH (&vframe);
- h = GST_VIDEO_FRAME_HEIGHT (&vframe);
+ GST_DEBUG_OBJECT (eglglessink,
+ "Got buffer %p: %dx%d size %d", buf, w, h, gst_buffer_get_size (buf));
- GST_DEBUG_OBJECT (eglglessink,
- "Got buffer %p: %dx%d size %d", buf, w, h, gst_buffer_get_size (buf));
+ switch (eglglessink->configured_info.finfo->format) {
+ case GST_VIDEO_FORMAT_BGR:
+ case GST_VIDEO_FORMAT_RGB:{
+ gint stride;
+ gint stride_width;
+ gint c_w;
- switch (eglglessink->configured_info.finfo->format) {
- case GST_VIDEO_FORMAT_BGR:
- case GST_VIDEO_FORMAT_RGB:{
- gint stride;
- gint stride_width;
- gint c_w;
+ stride = GST_VIDEO_FRAME_PLANE_STRIDE (&vframe, 0);
+ stride_width = c_w = GST_VIDEO_FRAME_WIDTH (&vframe);
- stride = GST_VIDEO_FRAME_PLANE_STRIDE (&vframe, 0);
- stride_width = c_w = GST_VIDEO_FRAME_WIDTH (&vframe);
+ glActiveTexture (GL_TEXTURE0);
- glActiveTexture (GL_TEXTURE0);
+ if (GST_ROUND_UP_8 (c_w * 3) == stride) {
+ glPixelStorei (GL_UNPACK_ALIGNMENT, 8);
+ } else if (GST_ROUND_UP_4 (c_w * 3) == stride) {
+ glPixelStorei (GL_UNPACK_ALIGNMENT, 4);
+ } else if (GST_ROUND_UP_2 (c_w * 3) == stride) {
+ glPixelStorei (GL_UNPACK_ALIGNMENT, 2);
+ } else if (c_w * 3 == stride) {
+ glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
+ } else {
+ stride_width = stride;
- if (GST_ROUND_UP_8 (c_w * 3) == stride) {
+ if (GST_ROUND_UP_8 (stride_width * 3) == stride) {
glPixelStorei (GL_UNPACK_ALIGNMENT, 8);
- } else if (GST_ROUND_UP_4 (c_w * 3) == stride) {
+ } else if (GST_ROUND_UP_4 (stride_width * 3) == stride) {
glPixelStorei (GL_UNPACK_ALIGNMENT, 4);
- } else if (GST_ROUND_UP_2 (c_w * 3) == stride) {
+ } else if (GST_ROUND_UP_2 (stride_width * 3) == stride) {
glPixelStorei (GL_UNPACK_ALIGNMENT, 2);
- } else if (c_w * 3 == stride) {
+ } else if (stride_width * 3 == stride) {
glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
} else {
- stride_width = stride;
-
- if (GST_ROUND_UP_8 (stride_width * 3) == stride) {
- glPixelStorei (GL_UNPACK_ALIGNMENT, 8);
- } else if (GST_ROUND_UP_4 (stride_width * 3) == stride) {
- glPixelStorei (GL_UNPACK_ALIGNMENT, 4);
- } else if (GST_ROUND_UP_2 (stride_width * 3) == stride) {
- glPixelStorei (GL_UNPACK_ALIGNMENT, 2);
- } else if (stride_width * 3 == stride) {
- glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
- } else {
- GST_ERROR_OBJECT (eglglessink, "Unsupported stride %d", stride);
- goto HANDLE_ERROR;
- }
- }
- if (got_gl_error ("glPixelStorei"))
+ GST_ERROR_OBJECT (eglglessink, "Unsupported stride %d", stride);
goto HANDLE_ERROR;
-
- eglglessink->stride[0] = ((gdouble) stride_width) / ((gdouble) c_w);
- glBindTexture (GL_TEXTURE_2D, eglglessink->eglglesctx.texture[0]);
- glTexImage2D (GL_TEXTURE_2D, 0, GL_RGB, stride_width, h, 0, GL_RGB,
- GL_UNSIGNED_BYTE, GST_VIDEO_FRAME_PLANE_DATA (&vframe, 0));
- break;
+ }
}
- case GST_VIDEO_FORMAT_RGB16:{
- gint stride;
- gint stride_width;
- gint c_w;
+ if (got_gl_error ("glPixelStorei"))
+ goto HANDLE_ERROR;
+
+ eglglessink->stride[0] = ((gdouble) stride_width) / ((gdouble) c_w);
+
+ glBindTexture (GL_TEXTURE_2D, eglglessink->eglglesctx.texture[0]);
+ glTexImage2D (GL_TEXTURE_2D, 0, GL_RGB, stride_width, h, 0, GL_RGB,
+ GL_UNSIGNED_BYTE, GST_VIDEO_FRAME_PLANE_DATA (&vframe, 0));
+ break;
+ }
+ case GST_VIDEO_FORMAT_RGB16:{
+ gint stride;
+ gint stride_width;
+ gint c_w;
- stride = GST_VIDEO_FRAME_PLANE_STRIDE (&vframe, 0);
- stride_width = c_w = GST_VIDEO_FRAME_WIDTH (&vframe);
+ stride = GST_VIDEO_FRAME_PLANE_STRIDE (&vframe, 0);
+ stride_width = c_w = GST_VIDEO_FRAME_WIDTH (&vframe);
- glActiveTexture (GL_TEXTURE0);
+ glActiveTexture (GL_TEXTURE0);
+
+ if (GST_ROUND_UP_8 (c_w * 2) == stride) {
+ glPixelStorei (GL_UNPACK_ALIGNMENT, 8);
+ } else if (GST_ROUND_UP_4 (c_w * 2) == stride) {
+ glPixelStorei (GL_UNPACK_ALIGNMENT, 4);
+ } else if (c_w * 2 == stride) {
+ glPixelStorei (GL_UNPACK_ALIGNMENT, 2);
+ } else {
+ stride_width = stride;
- if (GST_ROUND_UP_8 (c_w * 2) == stride) {
+ if (GST_ROUND_UP_8 (stride_width * 4) == stride) {
glPixelStorei (GL_UNPACK_ALIGNMENT, 8);
- } else if (GST_ROUND_UP_4 (c_w * 2) == stride) {
+ } else if (GST_ROUND_UP_4 (stride_width * 2) == stride) {
glPixelStorei (GL_UNPACK_ALIGNMENT, 4);
- } else if (c_w * 2 == stride) {
+ } else if (stride_width * 2 == stride) {
glPixelStorei (GL_UNPACK_ALIGNMENT, 2);
} else {
- stride_width = stride;
-
- if (GST_ROUND_UP_8 (stride_width * 2) == stride) {
- glPixelStorei (GL_UNPACK_ALIGNMENT, 8);
- } else if (GST_ROUND_UP_4 (stride_width * 2) == stride) {
- glPixelStorei (GL_UNPACK_ALIGNMENT, 4);
- } else if (stride_width * 2 == stride) {
- glPixelStorei (GL_UNPACK_ALIGNMENT, 2);
- } else {
- GST_ERROR_OBJECT (eglglessink, "Unsupported stride %d", stride);
- goto HANDLE_ERROR;
- }
- }
- if (got_gl_error ("glPixelStorei"))
+ GST_ERROR_OBJECT (eglglessink, "Unsupported stride %d", stride);
goto HANDLE_ERROR;
-
- eglglessink->stride[0] = ((gdouble) stride_width) / ((gdouble) c_w);
- glBindTexture (GL_TEXTURE_2D, eglglessink->eglglesctx.texture[0]);
- glTexImage2D (GL_TEXTURE_2D, 0, GL_RGB, stride_width, h, 0, GL_RGB,
- GL_UNSIGNED_SHORT_5_6_5, GST_VIDEO_FRAME_PLANE_DATA (&vframe, 0));
- break;
+ }
}
- case GST_VIDEO_FORMAT_RGBA:
- case GST_VIDEO_FORMAT_BGRA:
- case GST_VIDEO_FORMAT_ARGB:
- case GST_VIDEO_FORMAT_ABGR:
- case GST_VIDEO_FORMAT_RGBx:
- case GST_VIDEO_FORMAT_BGRx:
- case GST_VIDEO_FORMAT_xRGB:
- case GST_VIDEO_FORMAT_xBGR:{
- gint stride;
- gint stride_width;
- gint c_w;
-
- stride = GST_VIDEO_FRAME_PLANE_STRIDE (&vframe, 0);
- stride_width = c_w = GST_VIDEO_FRAME_WIDTH (&vframe);
-
- glActiveTexture (GL_TEXTURE0);
-
- if (GST_ROUND_UP_8 (c_w * 4) == stride) {
+ if (got_gl_error ("glPixelStorei"))
+ goto HANDLE_ERROR;
+
+ eglglessink->stride[0] = ((gdouble) stride_width) / ((gdouble) c_w);
+
+ glBindTexture (GL_TEXTURE_2D, eglglessink->eglglesctx.texture[0]);
+ glTexImage2D (GL_TEXTURE_2D, 0, GL_RGB, stride_width, h, 0, GL_RGB,
+ GL_UNSIGNED_SHORT_5_6_5, GST_VIDEO_FRAME_PLANE_DATA (&vframe, 0));
+ break;
+ }
+ case GST_VIDEO_FORMAT_RGBA:
+ case GST_VIDEO_FORMAT_BGRA:
+ case GST_VIDEO_FORMAT_ARGB:
+ case GST_VIDEO_FORMAT_ABGR:
+ case GST_VIDEO_FORMAT_RGBx:
+ case GST_VIDEO_FORMAT_BGRx:
+ case GST_VIDEO_FORMAT_xRGB:
+ case GST_VIDEO_FORMAT_xBGR:{
+ gint stride;
+ gint stride_width;
+ gint c_w;
+
+ stride = GST_VIDEO_FRAME_PLANE_STRIDE (&vframe, 0);
+ stride_width = c_w = GST_VIDEO_FRAME_WIDTH (&vframe);
+
+ glActiveTexture (GL_TEXTURE0);
+
+ if (GST_ROUND_UP_8 (c_w * 4) == stride) {
+ glPixelStorei (GL_UNPACK_ALIGNMENT, 8);
+ } else if (c_w * 4 == stride) {
+ glPixelStorei (GL_UNPACK_ALIGNMENT, 4);
+ } else {
+ stride_width = stride;
+
+ if (GST_ROUND_UP_8 (stride_width * 4) == stride) {
glPixelStorei (GL_UNPACK_ALIGNMENT, 8);
- } else if (c_w * 4 == stride) {
+ } else if (stride_width * 4 == stride) {
glPixelStorei (GL_UNPACK_ALIGNMENT, 4);
} else {
- stride_width = stride;
-
- if (GST_ROUND_UP_8 (stride_width * 4) == stride) {
- glPixelStorei (GL_UNPACK_ALIGNMENT, 8);
- } else if (stride_width * 4 == stride) {
- glPixelStorei (GL_UNPACK_ALIGNMENT, 4);
- } else {
- GST_ERROR_OBJECT (eglglessink, "Unsupported stride %d", stride);
- goto HANDLE_ERROR;
- }
- }
- if (got_gl_error ("glPixelStorei"))
+ GST_ERROR_OBJECT (eglglessink, "Unsupported stride %d", stride);
goto HANDLE_ERROR;
+ }
+ }
+ if (got_gl_error ("glPixelStorei"))
+ goto HANDLE_ERROR;
- eglglessink->stride[0] = ((gdouble) stride_width) / ((gdouble) c_w);
+ eglglessink->stride[0] = ((gdouble) stride_width) / ((gdouble) c_w);
- glBindTexture (GL_TEXTURE_2D, eglglessink->eglglesctx.texture[0]);
- glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, stride_width, h, 0,
- GL_RGBA, GL_UNSIGNED_BYTE, GST_VIDEO_FRAME_PLANE_DATA (&vframe, 0));
- break;
- }
- case GST_VIDEO_FORMAT_AYUV:{
- gint stride;
- gint stride_width;
- gint c_w;
+ glBindTexture (GL_TEXTURE_2D, eglglessink->eglglesctx.texture[0]);
+ glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, stride_width, h, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, GST_VIDEO_FRAME_PLANE_DATA (&vframe, 0));
+ break;
+ }
+ case GST_VIDEO_FORMAT_AYUV:{
+ gint stride;
+ gint stride_width;
+ gint c_w;
- stride = GST_VIDEO_FRAME_PLANE_STRIDE (&vframe, 0);
- stride_width = c_w = GST_VIDEO_FRAME_WIDTH (&vframe);
+ stride = GST_VIDEO_FRAME_PLANE_STRIDE (&vframe, 0);
+ stride_width = c_w = GST_VIDEO_FRAME_WIDTH (&vframe);
- glActiveTexture (GL_TEXTURE0);
+ glActiveTexture (GL_TEXTURE0);
- if (GST_ROUND_UP_8 (c_w * 4) == stride) {
+ if (GST_ROUND_UP_8 (c_w * 4) == stride) {
+ glPixelStorei (GL_UNPACK_ALIGNMENT, 8);
+ } else if (c_w * 4 == stride) {
+ glPixelStorei (GL_UNPACK_ALIGNMENT, 4);
+ } else {
+ stride_width = stride;
+
+ if (GST_ROUND_UP_8 (stride_width * 4) == stride) {
glPixelStorei (GL_UNPACK_ALIGNMENT, 8);
- } else if (c_w * 4 == stride) {
+ } else if (stride_width * 4 == stride) {
glPixelStorei (GL_UNPACK_ALIGNMENT, 4);
} else {
- stride_width = stride;
-
- if (GST_ROUND_UP_8 (stride_width * 4) == stride) {
- glPixelStorei (GL_UNPACK_ALIGNMENT, 8);
- } else if (stride_width * 4 == stride) {
- glPixelStorei (GL_UNPACK_ALIGNMENT, 4);
- } else {
- GST_ERROR_OBJECT (eglglessink, "Unsupported stride %d", stride);
- goto HANDLE_ERROR;
- }
- }
- if (got_gl_error ("glPixelStorei"))
+ GST_ERROR_OBJECT (eglglessink, "Unsupported stride %d", stride);
goto HANDLE_ERROR;
+ }
+ }
+ if (got_gl_error ("glPixelStorei"))
+ goto HANDLE_ERROR;
- eglglessink->stride[0] = ((gdouble) stride_width) / ((gdouble) c_w);
+ eglglessink->stride[0] = ((gdouble) stride_width) / ((gdouble) c_w);
- glBindTexture (GL_TEXTURE_2D, eglglessink->eglglesctx.texture[0]);
- glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, stride_width, h, 0,
- GL_RGBA, GL_UNSIGNED_BYTE, GST_VIDEO_FRAME_PLANE_DATA (&vframe, 0));
- break;
- }
- case GST_VIDEO_FORMAT_Y444:
- case GST_VIDEO_FORMAT_I420:
- case GST_VIDEO_FORMAT_YV12:
- case GST_VIDEO_FORMAT_Y42B:
- case GST_VIDEO_FORMAT_Y41B:{
- gint stride;
- gint stride_width;
- gint c_w;
+ glBindTexture (GL_TEXTURE_2D, eglglessink->eglglesctx.texture[0]);
+ glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, stride_width, h, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, GST_VIDEO_FRAME_PLANE_DATA (&vframe, 0));
+ break;
+ }
+ case GST_VIDEO_FORMAT_Y444:
+ case GST_VIDEO_FORMAT_I420:
+ case GST_VIDEO_FORMAT_YV12:
+ case GST_VIDEO_FORMAT_Y42B:
+ case GST_VIDEO_FORMAT_Y41B:{
+ gint stride;
+ gint stride_width;
+ gint c_w;
- stride = GST_VIDEO_FRAME_PLANE_STRIDE (&vframe, 0);
- stride_width = c_w = GST_VIDEO_FRAME_COMP_WIDTH (&vframe, 0);
+ stride = GST_VIDEO_FRAME_PLANE_STRIDE (&vframe, 0);
+ stride_width = c_w = GST_VIDEO_FRAME_COMP_WIDTH (&vframe, 0);
- glActiveTexture (GL_TEXTURE0);
+ glActiveTexture (GL_TEXTURE0);
+
+ if (GST_ROUND_UP_8 (c_w) == stride) {
+ glPixelStorei (GL_UNPACK_ALIGNMENT, 8);
+ } else if (GST_ROUND_UP_4 (c_w) == stride) {
+ glPixelStorei (GL_UNPACK_ALIGNMENT, 4);
+ } else if (GST_ROUND_UP_2 (c_w) == stride) {
+ glPixelStorei (GL_UNPACK_ALIGNMENT, 2);
+ } else if (c_w == stride) {
+ glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
+ } else {
+ stride_width = stride;
- if (GST_ROUND_UP_8 (c_w) == stride) {
+ if (GST_ROUND_UP_8 (stride_width) == stride) {
glPixelStorei (GL_UNPACK_ALIGNMENT, 8);
- } else if (GST_ROUND_UP_4 (c_w) == stride) {
+ } else if (GST_ROUND_UP_4 (stride_width) == stride) {
glPixelStorei (GL_UNPACK_ALIGNMENT, 4);
- } else if (GST_ROUND_UP_2 (c_w) == stride) {
+ } else if (GST_ROUND_UP_2 (stride_width) == stride) {
glPixelStorei (GL_UNPACK_ALIGNMENT, 2);
- } else if (c_w == stride) {
+ } else if (stride_width == stride) {
glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
} else {
- stride_width = stride;
-
- if (GST_ROUND_UP_8 (stride_width) == stride) {
- glPixelStorei (GL_UNPACK_ALIGNMENT, 8);
- } else if (GST_ROUND_UP_4 (stride_width) == stride) {
- glPixelStorei (GL_UNPACK_ALIGNMENT, 4);
- } else if (GST_ROUND_UP_2 (stride_width) == stride) {
- glPixelStorei (GL_UNPACK_ALIGNMENT, 2);
- } else if (stride_width == stride) {
- glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
- } else {
- GST_ERROR_OBJECT (eglglessink, "Unsupported stride %d", stride);
- goto HANDLE_ERROR;
- }
- }
- if (got_gl_error ("glPixelStorei"))
+ GST_ERROR_OBJECT (eglglessink, "Unsupported stride %d", stride);
goto HANDLE_ERROR;
+ }
+ }
+ if (got_gl_error ("glPixelStorei"))
+ goto HANDLE_ERROR;
- eglglessink->stride[0] = ((gdouble) stride_width) / ((gdouble) c_w);
+ eglglessink->stride[0] = ((gdouble) stride_width) / ((gdouble) c_w);
- glBindTexture (GL_TEXTURE_2D, eglglessink->eglglesctx.texture[0]);
- glTexImage2D (GL_TEXTURE_2D, 0, GL_LUMINANCE,
- stride_width,
- GST_VIDEO_FRAME_COMP_HEIGHT (&vframe, 0),
- 0, GL_LUMINANCE, GL_UNSIGNED_BYTE,
- GST_VIDEO_FRAME_COMP_DATA (&vframe, 0));
+ glBindTexture (GL_TEXTURE_2D, eglglessink->eglglesctx.texture[0]);
+ glTexImage2D (GL_TEXTURE_2D, 0, GL_LUMINANCE,
+ stride_width,
+ GST_VIDEO_FRAME_COMP_HEIGHT (&vframe, 0),
+ 0, GL_LUMINANCE, GL_UNSIGNED_BYTE,
+ GST_VIDEO_FRAME_COMP_DATA (&vframe, 0));
- stride = GST_VIDEO_FRAME_PLANE_STRIDE (&vframe, 1);
- stride_width = c_w = GST_VIDEO_FRAME_COMP_WIDTH (&vframe, 1);
+ stride = GST_VIDEO_FRAME_PLANE_STRIDE (&vframe, 1);
+ stride_width = c_w = GST_VIDEO_FRAME_COMP_WIDTH (&vframe, 1);
- glActiveTexture (GL_TEXTURE1);
+ glActiveTexture (GL_TEXTURE1);
+
+ if (GST_ROUND_UP_8 (c_w) == stride) {
+ glPixelStorei (GL_UNPACK_ALIGNMENT, 8);
+ } else if (GST_ROUND_UP_4 (c_w) == stride) {
+ glPixelStorei (GL_UNPACK_ALIGNMENT, 4);
+ } else if (GST_ROUND_UP_2 (c_w) == stride) {
+ glPixelStorei (GL_UNPACK_ALIGNMENT, 2);
+ } else if (c_w == stride) {
+ glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
+ } else {
+ stride_width = stride;
- if (GST_ROUND_UP_8 (c_w) == stride) {
+ if (GST_ROUND_UP_8 (stride_width) == stride) {
glPixelStorei (GL_UNPACK_ALIGNMENT, 8);
- } else if (GST_ROUND_UP_4 (c_w) == stride) {
+ } else if (GST_ROUND_UP_4 (stride_width) == stride) {
glPixelStorei (GL_UNPACK_ALIGNMENT, 4);
- } else if (GST_ROUND_UP_2 (c_w) == stride) {
+ } else if (GST_ROUND_UP_2 (stride_width) == stride) {
glPixelStorei (GL_UNPACK_ALIGNMENT, 2);
- } else if (c_w == stride) {
+ } else if (stride_width == stride) {
glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
} else {
- stride_width = stride;
-
- if (GST_ROUND_UP_8 (stride_width) == stride) {
- glPixelStorei (GL_UNPACK_ALIGNMENT, 8);
- } else if (GST_ROUND_UP_4 (stride_width) == stride) {
- glPixelStorei (GL_UNPACK_ALIGNMENT, 4);
- } else if (GST_ROUND_UP_2 (stride_width) == stride) {
- glPixelStorei (GL_UNPACK_ALIGNMENT, 2);
- } else if (stride_width == stride) {
- glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
- } else {
- GST_ERROR_OBJECT (eglglessink, "Unsupported stride %d", stride);
- goto HANDLE_ERROR;
- }
- }
- if (got_gl_error ("glPixelStorei"))
+ GST_ERROR_OBJECT (eglglessink, "Unsupported stride %d", stride);
goto HANDLE_ERROR;
+ }
+ }
+ if (got_gl_error ("glPixelStorei"))
+ goto HANDLE_ERROR;
+
+ eglglessink->stride[1] = ((gdouble) stride_width) / ((gdouble) c_w);
- eglglessink->stride[1] = ((gdouble) stride_width) / ((gdouble) c_w);
+ glBindTexture (GL_TEXTURE_2D, eglglessink->eglglesctx.texture[1]);
+ glTexImage2D (GL_TEXTURE_2D, 0, GL_LUMINANCE,
+ stride_width,
+ GST_VIDEO_FRAME_COMP_HEIGHT (&vframe, 1),
+ 0, GL_LUMINANCE, GL_UNSIGNED_BYTE,
+ GST_VIDEO_FRAME_COMP_DATA (&vframe, 1));
- glBindTexture (GL_TEXTURE_2D, eglglessink->eglglesctx.texture[1]);
- glTexImage2D (GL_TEXTURE_2D, 0, GL_LUMINANCE,
- stride_width,
- GST_VIDEO_FRAME_COMP_HEIGHT (&vframe, 1),
- 0, GL_LUMINANCE, GL_UNSIGNED_BYTE,
- GST_VIDEO_FRAME_COMP_DATA (&vframe, 1));
+ stride = GST_VIDEO_FRAME_PLANE_STRIDE (&vframe, 2);
+ stride_width = c_w = GST_VIDEO_FRAME_COMP_WIDTH (&vframe, 2);
- stride = GST_VIDEO_FRAME_PLANE_STRIDE (&vframe, 2);
- stride_width = c_w = GST_VIDEO_FRAME_COMP_WIDTH (&vframe, 2);
+ glActiveTexture (GL_TEXTURE2);
- glActiveTexture (GL_TEXTURE2);
+ if (GST_ROUND_UP_8 (c_w) == stride) {
+ glPixelStorei (GL_UNPACK_ALIGNMENT, 8);
+ } else if (GST_ROUND_UP_4 (c_w) == stride) {
+ glPixelStorei (GL_UNPACK_ALIGNMENT, 4);
+ } else if (GST_ROUND_UP_2 (c_w) == stride) {
+ glPixelStorei (GL_UNPACK_ALIGNMENT, 2);
+ } else if (c_w == stride) {
+ glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
+ } else {
+ stride_width = stride;
- if (GST_ROUND_UP_8 (c_w) == stride) {
+ if (GST_ROUND_UP_8 (stride_width) == stride) {
glPixelStorei (GL_UNPACK_ALIGNMENT, 8);
- } else if (GST_ROUND_UP_4 (c_w) == stride) {
+ } else if (GST_ROUND_UP_4 (stride_width) == stride) {
glPixelStorei (GL_UNPACK_ALIGNMENT, 4);
- } else if (GST_ROUND_UP_2 (c_w) == stride) {
+ } else if (GST_ROUND_UP_2 (stride_width) == stride) {
glPixelStorei (GL_UNPACK_ALIGNMENT, 2);
- } else if (c_w == stride) {
+ } else if (stride_width == stride) {
glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
} else {
- stride_width = stride;
-
- if (GST_ROUND_UP_8 (stride_width) == stride) {
- glPixelStorei (GL_UNPACK_ALIGNMENT, 8);
- } else if (GST_ROUND_UP_4 (stride_width) == stride) {
- glPixelStorei (GL_UNPACK_ALIGNMENT, 4);
- } else if (GST_ROUND_UP_2 (stride_width) == stride) {
- glPixelStorei (GL_UNPACK_ALIGNMENT, 2);
- } else if (stride_width == stride) {
- glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
- } else {
- GST_ERROR_OBJECT (eglglessink, "Unsupported stride %d", stride);
- goto HANDLE_ERROR;
- }
- }
- if (got_gl_error ("glPixelStorei"))
+ GST_ERROR_OBJECT (eglglessink, "Unsupported stride %d", stride);
goto HANDLE_ERROR;
+ }
+ }
+ if (got_gl_error ("glPixelStorei"))
+ goto HANDLE_ERROR;
- eglglessink->stride[2] = ((gdouble) stride_width) / ((gdouble) c_w);
+ eglglessink->stride[2] = ((gdouble) stride_width) / ((gdouble) c_w);
- glBindTexture (GL_TEXTURE_2D, eglglessink->eglglesctx.texture[2]);
- glTexImage2D (GL_TEXTURE_2D, 0, GL_LUMINANCE,
- stride_width,
- GST_VIDEO_FRAME_COMP_HEIGHT (&vframe, 2),
- 0, GL_LUMINANCE, GL_UNSIGNED_BYTE,
- GST_VIDEO_FRAME_COMP_DATA (&vframe, 2));
- break;
- }
- case GST_VIDEO_FORMAT_NV12:
- case GST_VIDEO_FORMAT_NV21:{
- gint stride;
- gint stride_width;
- gint c_w;
+ glBindTexture (GL_TEXTURE_2D, eglglessink->eglglesctx.texture[2]);
+ glTexImage2D (GL_TEXTURE_2D, 0, GL_LUMINANCE,
+ stride_width,
+ GST_VIDEO_FRAME_COMP_HEIGHT (&vframe, 2),
+ 0, GL_LUMINANCE, GL_UNSIGNED_BYTE,
+ GST_VIDEO_FRAME_COMP_DATA (&vframe, 2));
+ break;
+ }
+ case GST_VIDEO_FORMAT_NV12:
+ case GST_VIDEO_FORMAT_NV21:{
+ gint stride;
+ gint stride_width;
+ gint c_w;
- stride = GST_VIDEO_FRAME_PLANE_STRIDE (&vframe, 0);
- stride_width = c_w = GST_VIDEO_FRAME_COMP_WIDTH (&vframe, 0);
+ stride = GST_VIDEO_FRAME_PLANE_STRIDE (&vframe, 0);
+ stride_width = c_w = GST_VIDEO_FRAME_COMP_WIDTH (&vframe, 0);
- glActiveTexture (GL_TEXTURE0);
+ glActiveTexture (GL_TEXTURE0);
+
+ if (GST_ROUND_UP_8 (c_w) == stride) {
+ glPixelStorei (GL_UNPACK_ALIGNMENT, 8);
+ } else if (GST_ROUND_UP_4 (c_w) == stride) {
+ glPixelStorei (GL_UNPACK_ALIGNMENT, 4);
+ } else if (GST_ROUND_UP_2 (c_w) == stride) {
+ glPixelStorei (GL_UNPACK_ALIGNMENT, 2);
+ } else if (c_w == stride) {
+ glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
+ } else {
+ stride_width = stride;
- if (GST_ROUND_UP_8 (c_w) == stride) {
+ if (GST_ROUND_UP_8 (stride_width) == stride) {
glPixelStorei (GL_UNPACK_ALIGNMENT, 8);
- } else if (GST_ROUND_UP_4 (c_w) == stride) {
+ } else if (GST_ROUND_UP_4 (stride_width) == stride) {
glPixelStorei (GL_UNPACK_ALIGNMENT, 4);
- } else if (GST_ROUND_UP_2 (c_w) == stride) {
+ } else if (GST_ROUND_UP_2 (stride_width) == stride) {
glPixelStorei (GL_UNPACK_ALIGNMENT, 2);
- } else if (c_w == stride) {
+ } else if (stride_width == stride) {
glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
} else {
- stride_width = stride;
-
- if (GST_ROUND_UP_8 (stride_width) == stride) {
- glPixelStorei (GL_UNPACK_ALIGNMENT, 8);
- } else if (GST_ROUND_UP_4 (stride_width) == stride) {
- glPixelStorei (GL_UNPACK_ALIGNMENT, 4);
- } else if (GST_ROUND_UP_2 (stride_width) == stride) {
- glPixelStorei (GL_UNPACK_ALIGNMENT, 2);
- } else if (stride_width == stride) {
- glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
- } else {
- GST_ERROR_OBJECT (eglglessink, "Unsupported stride %d", stride);
- goto HANDLE_ERROR;
- }
- }
- if (got_gl_error ("glPixelStorei"))
+ GST_ERROR_OBJECT (eglglessink, "Unsupported stride %d", stride);
goto HANDLE_ERROR;
+ }
+ }
+ if (got_gl_error ("glPixelStorei"))
+ goto HANDLE_ERROR;
- eglglessink->stride[0] = ((gdouble) stride_width) / ((gdouble) c_w);
+ eglglessink->stride[0] = ((gdouble) stride_width) / ((gdouble) c_w);
- glBindTexture (GL_TEXTURE_2D, eglglessink->eglglesctx.texture[0]);
- glTexImage2D (GL_TEXTURE_2D, 0, GL_LUMINANCE,
- stride_width,
- GST_VIDEO_FRAME_COMP_HEIGHT (&vframe, 0),
- 0, GL_LUMINANCE, GL_UNSIGNED_BYTE,
- GST_VIDEO_FRAME_PLANE_DATA (&vframe, 0));
+ glBindTexture (GL_TEXTURE_2D, eglglessink->eglglesctx.texture[0]);
+ glTexImage2D (GL_TEXTURE_2D, 0, GL_LUMINANCE,
+ stride_width,
+ GST_VIDEO_FRAME_COMP_HEIGHT (&vframe, 0),
+ 0, GL_LUMINANCE, GL_UNSIGNED_BYTE,
+ GST_VIDEO_FRAME_PLANE_DATA (&vframe, 0));
- stride = GST_VIDEO_FRAME_PLANE_STRIDE (&vframe, 1);
- stride_width = c_w = GST_VIDEO_FRAME_COMP_WIDTH (&vframe, 1);
+ stride = GST_VIDEO_FRAME_PLANE_STRIDE (&vframe, 1);
+ stride_width = c_w = GST_VIDEO_FRAME_COMP_WIDTH (&vframe, 1);
- glActiveTexture (GL_TEXTURE1);
+ glActiveTexture (GL_TEXTURE1);
+
+ if (GST_ROUND_UP_8 (c_w * 2) == stride) {
+ glPixelStorei (GL_UNPACK_ALIGNMENT, 8);
+ } else if (GST_ROUND_UP_4 (c_w * 2) == stride) {
+ glPixelStorei (GL_UNPACK_ALIGNMENT, 4);
+ } else if (c_w * 2 == stride) {
+ glPixelStorei (GL_UNPACK_ALIGNMENT, 2);
+ } else {
+ stride_width = stride / 2;
- if (GST_ROUND_UP_8 (c_w * 2) == stride) {
+ if (GST_ROUND_UP_8 (stride_width * 2) == stride) {
glPixelStorei (GL_UNPACK_ALIGNMENT, 8);
- } else if (GST_ROUND_UP_4 (c_w * 2) == stride) {
+ } else if (GST_ROUND_UP_4 (stride_width * 2) == stride) {
glPixelStorei (GL_UNPACK_ALIGNMENT, 4);
- } else if (c_w * 2 == stride) {
+ } else if (stride_width * 2 == stride) {
glPixelStorei (GL_UNPACK_ALIGNMENT, 2);
} else {
- stride_width = stride / 2;
-
- if (GST_ROUND_UP_8 (stride_width * 2) == stride) {
- glPixelStorei (GL_UNPACK_ALIGNMENT, 8);
- } else if (GST_ROUND_UP_4 (stride_width * 2) == stride) {
- glPixelStorei (GL_UNPACK_ALIGNMENT, 4);
- } else if (stride_width * 2 == stride) {
- glPixelStorei (GL_UNPACK_ALIGNMENT, 2);
- } else {
- GST_ERROR_OBJECT (eglglessink, "Unsupported stride %d", stride);
- goto HANDLE_ERROR;
- }
- }
- if (got_gl_error ("glPixelStorei"))
+ GST_ERROR_OBJECT (eglglessink, "Unsupported stride %d", stride);
goto HANDLE_ERROR;
+ }
+ }
+ if (got_gl_error ("glPixelStorei"))
+ goto HANDLE_ERROR;
- eglglessink->stride[1] = ((gdouble) stride_width) / ((gdouble) c_w);
+ eglglessink->stride[1] = ((gdouble) stride_width) / ((gdouble) c_w);
- glBindTexture (GL_TEXTURE_2D, eglglessink->eglglesctx.texture[1]);
- glTexImage2D (GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA,
- stride_width,
- GST_VIDEO_FRAME_COMP_HEIGHT (&vframe, 1),
- 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE,
- GST_VIDEO_FRAME_PLANE_DATA (&vframe, 1));
- break;
- }
- default:
- g_assert_not_reached ();
- break;
+ glBindTexture (GL_TEXTURE_2D, eglglessink->eglglesctx.texture[1]);
+ glTexImage2D (GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA,
+ stride_width,
+ GST_VIDEO_FRAME_COMP_HEIGHT (&vframe, 1),
+ 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE,
+ GST_VIDEO_FRAME_PLANE_DATA (&vframe, 1));
+ break;
}
+ default:
+ g_assert_not_reached ();
+ break;
}
if (got_gl_error ("glTexImage2D"))
if (!buf) {
GST_DEBUG_OBJECT (eglglessink, "Rendering previous buffer again");
} else if (buf) {
- GstMemory *mem;
-
crop = gst_buffer_get_video_crop_meta (buf);
if (gst_eglglessink_crop_changed (eglglessink, crop)) {
eglglessink->crop.h = eglglessink->configured_info.height;
}
eglglessink->crop_changed = TRUE;
- >>>>>>>ebe5849 ... eglglessink:Always use an RGBA configuration}
+ }
- if (got_gl_error ("glTexImage2D"))
+ if (!gst_eglglessink_fill_texture (eglglessink, buf))
goto HANDLE_ERROR;
}
+ return GST_FLOW_OK;
+
+HANDLE_ERROR:
+ {
+ GST_ERROR_OBJECT (eglglessink, "Failed to upload texture");
+ return GST_FLOW_ERROR;
+ }
+}
+
+static GstFlowReturn
+gst_eglglessink_render (GstEglGlesSink * eglglessink)
+{
+ guint dar_n, dar_d;
+ gint i;
+
/* If no one has set a display rectangle on us initialize
* a sane default. According to the docs on the xOverlay
* interface we are supposed to fill the overlay 100%. We
if (gst_eglglessink_update_surface_dimensions (eglglessink) ||
eglglessink->render_region_changed ||
!eglglessink->display_region.w || !eglglessink->display_region.h ||
- gst_eglglessink_crop_changed (eglglessink, crop)) {
+ eglglessink->crop_changed) {
GST_OBJECT_LOCK (eglglessink);
if (!eglglessink->render_region_user) {
eglglessink->render_region.h = eglglessink->eglglesctx.surface_height;
}
eglglessink->render_region_changed = FALSE;
-
- if (crop) {
- eglglessink->crop.x = crop->x;
- eglglessink->crop.y = crop->y;
- eglglessink->crop.w = crop->width;
- eglglessink->crop.h = crop->height;
- } else if (buf) {
- eglglessink->crop.x = 0;
- eglglessink->crop.y = 0;
- eglglessink->crop.w = eglglessink->configured_info.width;
- eglglessink->crop.h = eglglessink->configured_info.height;
- }
+ eglglessink->crop_changed = FALSE;
if (!eglglessink->force_aspect_ratio) {
eglglessink->display_region.x = 0;
eglglessink->stride[2], 1);
for (i = 0; i < eglglessink->eglglesctx.n_textures; i++) {
- if (i == 0)
- glActiveTexture (GL_TEXTURE0);
- else if (i == 1)
- glActiveTexture (GL_TEXTURE1);
- else if (i == 2)
- glActiveTexture (GL_TEXTURE2);
-
glUniform1i (eglglessink->eglglesctx.tex_loc[0][i], i);
if (got_gl_error ("glUniform1i"))
goto HANDLE_ERROR;
if (got_gl_error ("glVertexAttribPointer"))
goto HANDLE_ERROR;
- glVertexAttribPointer (eglglessink->eglglesctx.texpos_loc[0], 2, GL_FLOAT,
- GL_FALSE, sizeof (coord5), (gpointer) (3 * sizeof (gfloat)));
+ glVertexAttribPointer (eglglessink->eglglesctx.texpos_loc[0], 2,
+ GL_FLOAT, GL_FALSE, sizeof (coord5), (gpointer) (3 * sizeof (gfloat)));
if (got_gl_error ("glVertexAttribPointer"))
goto HANDLE_ERROR;
goto HANDLE_ERROR;
}
- if (buf)
- gst_video_frame_unmap (&vframe);
GST_DEBUG_OBJECT (eglglessink, "Succesfully rendered 1 frame");
return GST_FLOW_OK;
HANDLE_ERROR:
GST_ERROR_OBJECT (eglglessink, "Rendering disabled for this frame");
- if (vframe.buffer)
- gst_video_frame_unmap (&vframe);
return GST_FLOW_ERROR;
}
}
static gboolean
-queue_check_full_func (GstDataQueue * queue, guint visible, guint bytes,
+queue_check_full_func (EGLGstDataQueue * queue, guint visible, guint bytes,
guint64 time, gpointer checkdata)
{
return visible != 0;
g_mutex_init (&eglglessink->render_lock);
g_cond_init (&eglglessink->render_cond);
eglglessink->queue =
- gst_data_queue_new (queue_check_full_func, NULL, NULL, NULL);
+ egl_gst_data_queue_new (queue_check_full_func, NULL, NULL, NULL);
eglglessink->last_flow = GST_FLOW_FLUSHING;
eglglessink->render_region.x = 0;