/** * gst_data_queue_push_force: (skip) * @queue: a #GstDataQueue. * @item: a #GstDataQueueItem. * * Pushes a #GstDataQueueItem (or a structure that begins with the same fields) * on the @queue. It ignores if the @queue is full or not and forces the @item * to be pushed anyway. * 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 */ gboolean gst_data_queue_push_force (GstDataQueue * queue, GstDataQueueItem * item) { GstDataQueuePrivate *priv = queue->priv; g_return_val_if_fail (GST_IS_DATA_QUEUE (queue), FALSE); g_return_val_if_fail (item != NULL, FALSE); GST_DATA_QUEUE_MUTEX_LOCK_CHECK (queue, flushing); STATUS (queue, "before pushing"); gst_data_queue_push_force_unlocked (queue, item); STATUS (queue, "after pushing"); if (priv->waiting_add) g_cond_signal (&priv->item_add); GST_DATA_QUEUE_MUTEX_UNLOCK (queue); return TRUE; /* ERRORS */ flushing: { GST_DEBUG ("queue:%p, we are flushing", queue); GST_DATA_QUEUE_MUTEX_UNLOCK (queue); return FALSE; } }
/** * gst_data_queue_push: * @queue: a #GstDataQueue. * @item: a #GstDataQueueItem. * * Pushes a #GstDataQueueItem (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 gst_data_queue_push (GstDataQueue * queue, GstDataQueueItem * item) { GstDataQueuePrivate *priv = queue->priv; g_return_val_if_fail (GST_IS_DATA_QUEUE (queue), FALSE); g_return_val_if_fail (item != NULL, FALSE); GST_DATA_QUEUE_MUTEX_LOCK_CHECK (queue, flushing); STATUS (queue, "before pushing"); /* We ALWAYS need to check for queue fillness */ if (gst_data_queue_locked_is_full (queue)) { GST_DATA_QUEUE_MUTEX_UNLOCK (queue); if (G_LIKELY (priv->fullcallback)) priv->fullcallback (queue, priv->checkdata); else g_signal_emit (queue, gst_data_queue_signals[SIGNAL_FULL], 0); GST_DATA_QUEUE_MUTEX_LOCK_CHECK (queue, flushing); /* signal might have removed some items */ while (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; } } 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); GST_DATA_QUEUE_MUTEX_UNLOCK (queue); return TRUE; /* ERRORS */ flushing: { GST_DEBUG ("queue:%p, we are flushing", queue); GST_DATA_QUEUE_MUTEX_UNLOCK (queue); return FALSE; } }
/** * gst_data_queue_pop: * @queue: a #GstDataQueue. * @item: pointer to store the returned #GstDataQueueItem. * * 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 gst_data_queue_pop (GstDataQueue * queue, GstDataQueueItem ** item) { GstDataQueuePrivate *priv = queue->priv; g_return_val_if_fail (GST_IS_DATA_QUEUE (queue), FALSE); g_return_val_if_fail (item != NULL, FALSE); GST_DATA_QUEUE_MUTEX_LOCK_CHECK (queue, flushing); STATUS (queue, "before popping"); if (gst_data_queue_locked_is_empty (queue)) { GST_DATA_QUEUE_MUTEX_UNLOCK (queue); if (G_LIKELY (priv->emptycallback)) priv->emptycallback (queue, priv->checkdata); else g_signal_emit (queue, gst_data_queue_signals[SIGNAL_EMPTY], 0); GST_DATA_QUEUE_MUTEX_LOCK_CHECK (queue, flushing); while (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 = 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); GST_DATA_QUEUE_MUTEX_UNLOCK (queue); return TRUE; /* ERRORS */ flushing: { GST_DEBUG ("queue:%p, we are flushing", queue); GST_DATA_QUEUE_MUTEX_UNLOCK (queue); return FALSE; } }
EXPORT_C #endif gboolean gst_data_queue_pop (GstDataQueue * queue, GstDataQueueItem ** item) { g_return_val_if_fail (GST_IS_DATA_QUEUE (queue), FALSE); g_return_val_if_fail (item != NULL, FALSE); GST_DATA_QUEUE_MUTEX_LOCK_CHECK (queue, flushing); STATUS (queue, "before popping"); if (gst_data_queue_locked_is_empty (queue)) { GST_DATA_QUEUE_MUTEX_UNLOCK (queue); g_signal_emit (G_OBJECT (queue), gst_data_queue_signals[SIGNAL_EMPTY], 0); GST_DATA_QUEUE_MUTEX_LOCK_CHECK (queue, flushing); while (gst_data_queue_locked_is_empty (queue)) { g_cond_wait (queue->item_add, queue->qlock); if (queue->flushing) goto flushing; } } /* Get the item from the GQueue */ *item = g_queue_pop_head (queue->queue); /* update current level counter */ if ((*item)->visible) queue->cur_level.visible--; queue->cur_level.bytes -= (*item)->size; queue->cur_level.time -= (*item)->duration; STATUS (queue, "after popping"); g_cond_signal (queue->item_del); GST_DATA_QUEUE_MUTEX_UNLOCK (queue); return TRUE; /* ERRORS */ flushing: { GST_DEBUG ("queue:%p, we are flushing", queue); GST_DATA_QUEUE_MUTEX_UNLOCK (queue); return FALSE; } }
EXPORT_C #endif gboolean gst_data_queue_push (GstDataQueue * queue, GstDataQueueItem * item) { g_return_val_if_fail (GST_IS_DATA_QUEUE (queue), FALSE); g_return_val_if_fail (item != NULL, FALSE); GST_DATA_QUEUE_MUTEX_LOCK_CHECK (queue, flushing); STATUS (queue, "before pushing"); /* We ALWAYS need to check for queue fillness */ if (gst_data_queue_locked_is_full (queue)) { GST_DATA_QUEUE_MUTEX_UNLOCK (queue); g_signal_emit (G_OBJECT (queue), gst_data_queue_signals[SIGNAL_FULL], 0); GST_DATA_QUEUE_MUTEX_LOCK_CHECK (queue, flushing); /* signal might have removed some items */ while (gst_data_queue_locked_is_full (queue)) { g_cond_wait (queue->item_del, queue->qlock); if (queue->flushing) goto flushing; } } g_queue_push_tail (queue->queue, item); if (item->visible) queue->cur_level.visible++; queue->cur_level.bytes += item->size; queue->cur_level.time += item->duration; STATUS (queue, "after pushing"); g_cond_signal (queue->item_add); GST_DATA_QUEUE_MUTEX_UNLOCK (queue); return TRUE; /* ERRORS */ flushing: { GST_DEBUG ("queue:%p, we are flushing", queue); GST_DATA_QUEUE_MUTEX_UNLOCK (queue); return FALSE; } }
static void gst_data_queue_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec) { GstDataQueue *queue = GST_DATA_QUEUE (object); GstDataQueuePrivate *priv = queue->priv; 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; } GST_DATA_QUEUE_MUTEX_UNLOCK (queue); }
/** * gst_data_queue_flush: * @queue: a #GstDataQueue. * * Flushes all the contents of the @queue. Any call to #gst_data_queue_push and * #gst_data_queue_pop will be released. * MT safe. * * Since: 1.2.0 */ void gst_data_queue_flush (GstDataQueue * queue) { GST_DEBUG ("queue:%p", queue); GST_DATA_QUEUE_MUTEX_LOCK (queue); gst_data_queue_locked_flush (queue); GST_DATA_QUEUE_MUTEX_UNLOCK (queue); }
/** * gst_data_queue_limits_changed: * @queue: The #GstDataQueue * * Inform the queue that the limits for the fullness check have changed and that * any blocking gst_data_queue_push() should be unblocked to recheck the limts. */ void gst_data_queue_limits_changed (GstDataQueue * queue) { g_return_if_fail (GST_IS_DATA_QUEUE (queue)); GST_DATA_QUEUE_MUTEX_LOCK (queue); GST_DEBUG ("signal del"); g_cond_signal (queue->item_del); GST_DATA_QUEUE_MUTEX_UNLOCK (queue); }
/** * gst_data_queue_is_full: * @queue: a #GstDataQueue. * * Queries if @queue is full. This check will be done using the * #GstDataQueueCheckFullFunction registered with @queue. * MT safe. * * Returns: #TRUE if @queue is full. * * Since: 1.2.0 */ gboolean gst_data_queue_is_full (GstDataQueue * queue) { gboolean res; GST_DATA_QUEUE_MUTEX_LOCK (queue); res = gst_data_queue_locked_is_full (queue); GST_DATA_QUEUE_MUTEX_UNLOCK (queue); return res; }
/** * gst_data_queue_peek: * @queue: a #GstDataQueue. * @item: pointer to store the returned #GstDataQueueItem. * * Retrieves the first @item available on the @queue without removing it. * 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 gst_data_queue_peek (GstDataQueue * queue, GstDataQueueItem ** item) { GstDataQueuePrivate *priv = queue->priv; g_return_val_if_fail (GST_IS_DATA_QUEUE (queue), FALSE); g_return_val_if_fail (item != NULL, FALSE); GST_DATA_QUEUE_MUTEX_LOCK_CHECK (queue, flushing); STATUS (queue, "before peeking"); if (gst_data_queue_locked_is_empty (queue)) { GST_DATA_QUEUE_MUTEX_UNLOCK (queue); if (G_LIKELY (priv->emptycallback)) priv->emptycallback (queue, priv->checkdata); else g_signal_emit (queue, gst_data_queue_signals[SIGNAL_EMPTY], 0); GST_DATA_QUEUE_MUTEX_LOCK_CHECK (queue, flushing); if (!_gst_data_queue_wait_non_empty (queue)) goto flushing; } /* Get the item from the GQueue */ *item = gst_queue_array_peek_head (priv->queue); STATUS (queue, "after peeking"); GST_DATA_QUEUE_MUTEX_UNLOCK (queue); return TRUE; /* ERRORS */ flushing: { GST_DEBUG ("queue:%p, we are flushing", queue); GST_DATA_QUEUE_MUTEX_UNLOCK (queue); return FALSE; } }
/** * gst_data_queue_limits_changed: * @queue: The #GstDataQueue * * Inform the queue that the limits for the fullness check have changed and that * any blocking gst_data_queue_push() should be unblocked to recheck the limts. * * Since: 1.2.0 */ void gst_data_queue_limits_changed (GstDataQueue * queue) { GstDataQueuePrivate *priv = queue->priv; g_return_if_fail (GST_IS_DATA_QUEUE (queue)); GST_DATA_QUEUE_MUTEX_LOCK (queue); if (priv->waiting_del) { GST_DEBUG ("signal del"); g_cond_signal (&priv->item_del); } GST_DATA_QUEUE_MUTEX_UNLOCK (queue); }
EXPORT_C #endif gboolean gst_data_queue_is_empty (GstDataQueue * queue) { gboolean res; GST_DATA_QUEUE_MUTEX_LOCK (queue); res = gst_data_queue_locked_is_empty (queue); GST_DATA_QUEUE_MUTEX_UNLOCK (queue); return res; }
/** * gst_data_queue_set_flushing: * @queue: a #GstDataQueue. * @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 #gst_data_queue_push or #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. */ void gst_data_queue_set_flushing (GstDataQueue * queue, gboolean flushing) { GST_DEBUG ("queue:%p , flushing:%d", queue, flushing); GST_DATA_QUEUE_MUTEX_LOCK (queue); queue->flushing = flushing; if (flushing) { /* release push/pop functions */ g_cond_signal (queue->item_add); g_cond_signal (queue->item_del); } GST_DATA_QUEUE_MUTEX_UNLOCK (queue); }
EXPORT_C #endif gboolean gst_data_queue_drop_head (GstDataQueue * queue, GType type) { gboolean res = FALSE; GList *item; GstDataQueueItem *leak = NULL; g_return_val_if_fail (GST_IS_DATA_QUEUE (queue), FALSE); GST_DEBUG ("queue:%p", queue); GST_DATA_QUEUE_MUTEX_LOCK (queue); for (item = g_queue_peek_head_link (queue->queue); item; item = item->next) { GstDataQueueItem *tmp = (GstDataQueueItem *) item->data; if (G_TYPE_CHECK_INSTANCE_TYPE (tmp->object, type)) { leak = tmp; break; } } if (!leak) goto done; g_queue_delete_link (queue->queue, item); if (leak->visible) queue->cur_level.visible--; queue->cur_level.bytes -= leak->size; queue->cur_level.time -= leak->duration; leak->destroy (leak); res = TRUE; done: GST_DATA_QUEUE_MUTEX_UNLOCK (queue); GST_DEBUG ("queue:%p , res:%d", queue, res); return res; }
/** * gst_data_queue_set_flushing: * @queue: a #GstDataQueue. * @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 #gst_data_queue_push or #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 gst_data_queue_set_flushing (GstDataQueue * queue, gboolean flushing) { GstDataQueuePrivate *priv = queue->priv; GST_DEBUG ("queue:%p , flushing:%d", queue, flushing); 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); } GST_DATA_QUEUE_MUTEX_UNLOCK (queue); }
/** * gst_data_queue_drop_head: * @queue: The #GstDataQueue 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 gst_data_queue_drop_head (GstDataQueue * queue, GType type) { gboolean res = FALSE; GstDataQueueItem *leak = NULL; guint idx; GstDataQueuePrivate *priv = queue->priv; g_return_val_if_fail (GST_IS_DATA_QUEUE (queue), FALSE); GST_DEBUG ("queue:%p", queue); GST_DATA_QUEUE_MUTEX_LOCK (queue); idx = gst_queue_array_find (priv->queue, is_of_type, GSIZE_TO_POINTER (type)); if (idx == -1) goto done; leak = 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: GST_DATA_QUEUE_MUTEX_UNLOCK (queue); GST_DEBUG ("queue:%p , res:%d", queue, res); return res; }