static void gst_sctp_data_srcpad_loop(GstPad *pad)
{
    GstSctpDecPad *sctpdec_pad = GST_SCTP_DEC_PAD(pad);
    GstDataQueueItem *item;

    if (gst_data_queue_pop(sctpdec_pad->packet_queue, &item)) {
        GstFlowReturn flow_ret;

        flow_ret = gst_pad_push(pad, GST_BUFFER(item->object));
        item->object = NULL;
        if (G_UNLIKELY(flow_ret == GST_FLOW_FLUSHING || flow_ret == GST_FLOW_NOT_LINKED)) {
            GST_DEBUG_OBJECT(pad, "Push failed on packet source pad. Error: %s", gst_flow_get_name(flow_ret));
        } else if (G_UNLIKELY(flow_ret != GST_FLOW_OK)) {
            GST_ERROR_OBJECT(pad, "Push failed on packet source pad. Error: %s", gst_flow_get_name(flow_ret));
        }

        if (G_UNLIKELY(flow_ret != GST_FLOW_OK)) {
            GST_DEBUG_OBJECT(pad, "Pausing task because of an error");
            gst_data_queue_set_flushing(sctpdec_pad->packet_queue, TRUE);
            gst_data_queue_flush(sctpdec_pad->packet_queue);
            gst_pad_pause_task(pad);
        }

        item->destroy(item);
    } else {
        GST_DEBUG_OBJECT(pad, "Pausing task because we're flushing");
        gst_pad_pause_task(pad);
    }
}
static void gst_scream_queue_finalize(GObject *object)
{
    GstScreamQueue *self = GST_SCREAM_QUEUE(object);
    GstDataQueueItem *item;

    while (!gst_data_queue_is_empty(self->approved_packets)) {
        gst_data_queue_pop(self->approved_packets, &item);
        item->destroy(item);
    }
    gst_object_unref(self->approved_packets);

    while ((item = (GstDataQueueItem *)g_async_queue_try_pop(self->incoming_packets))) {
        item->destroy(item);
    }

    g_async_queue_unref(self->incoming_packets);

    g_hash_table_unref(self->streams);
    g_hash_table_unref(self->adapted_stream_ids);
    g_hash_table_unref(self->ignored_stream_ids);

    if (self->scream_controller) {
        g_object_unref(self->scream_controller);
    }

    G_OBJECT_CLASS(parent_class)->finalize (object);
}
static void clear_packet_queue(GstAtomicQueue *queue)
{
    GstDataQueueItem *item;

    while ((item = gst_atomic_queue_pop(queue))) {
        item->destroy(item);
    }
}
static void
gst_data_queue_cleanup (GstDataQueue * queue)
{
  while (!g_queue_is_empty (queue->queue)) {
    GstDataQueueItem *item = g_queue_pop_head (queue->queue);

    /* Just call the destroy notify on the item */
    item->destroy (item);
  }
  queue->cur_level.visible = 0;
  queue->cur_level.bytes = 0;
  queue->cur_level.time = 0;
}
static void
gst_data_queue_cleanup (GstDataQueue * queue)
{
  GstDataQueuePrivate *priv = queue->priv;

  while (!gst_queue_array_is_empty (priv->queue)) {
    GstDataQueueItem *item = 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;
}
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;
}
Beispiel #7
0
static GstFlowReturn
gst_eglglessink_queue_buffer (GstEglGlesSink * eglglessink, GstBuffer * buf)
{
  GstDataQueueItem *item;
  GstFlowReturn last_flow;

  g_mutex_lock (eglglessink->render_lock);
  last_flow = eglglessink->last_flow;
  g_mutex_unlock (eglglessink->render_lock);

  if (last_flow != GST_FLOW_OK)
    return last_flow;

  item = g_slice_new0 (GstDataQueueItem);

  item->object = GST_MINI_OBJECT_CAST (buf);
  item->size = (buf ? GST_BUFFER_SIZE (buf) : 0);
  item->duration = (buf ? GST_BUFFER_DURATION (buf) : GST_CLOCK_TIME_NONE);
  item->visible = (buf ? TRUE : FALSE);
  item->destroy = (GDestroyNotify) queue_item_destroy;

  GST_DEBUG_OBJECT (eglglessink, "Queueing buffer %" GST_PTR_FORMAT, buf);

  if (buf)
    g_mutex_lock (eglglessink->render_lock);
  if (!gst_data_queue_push (eglglessink->queue, item)) {
    item->destroy (item);
    g_mutex_unlock (eglglessink->render_lock);
    GST_DEBUG_OBJECT (eglglessink, "Flushing");
    return GST_FLOW_WRONG_STATE;
  }

  if (buf) {
    GST_DEBUG_OBJECT (eglglessink, "Waiting for buffer to be rendered");
    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 (buf ? last_flow : GST_FLOW_OK);
}
/**
 * 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;
}
Beispiel #9
0
static gpointer
render_thread_func (GstEglGlesSink * eglglessink)
{
  GstMessage *message;
  GValue val = { 0 };
  GstDataQueueItem *item = NULL;
  GstFlowReturn last_flow = GST_FLOW_OK;

  g_value_init (&val, G_TYPE_POINTER);
  g_value_set_pointer (&val, g_thread_self ());
  message = gst_message_new_stream_status (GST_OBJECT_CAST (eglglessink),
      GST_STREAM_STATUS_TYPE_ENTER, GST_ELEMENT_CAST (eglglessink));
  gst_message_set_stream_status_object (message, &val);
  GST_DEBUG_OBJECT (eglglessink, "posting ENTER stream status");
  gst_element_post_message (GST_ELEMENT_CAST (eglglessink), message);
  g_value_unset (&val);

  gst_egl_adaptation_bind_API (eglglessink->egl_context);

  while (gst_data_queue_pop (eglglessink->queue, &item)) {
    GstBuffer *buf = NULL;
    GstMiniObject *object = item->object;

    GST_DEBUG_OBJECT (eglglessink, "Handling object %" GST_PTR_FORMAT, object);

    if (GST_IS_BUFFER (object)) {
      GstCaps *caps;

      buf = GST_BUFFER_CAST (item->object);
      caps = GST_BUFFER_CAPS (buf);
      if (caps != eglglessink->configured_caps) {
        if (!gst_eglglessink_configure_caps (eglglessink, caps)) {
          g_mutex_lock (eglglessink->render_lock);
          eglglessink->last_flow = GST_FLOW_NOT_NEGOTIATED;
          g_cond_broadcast (eglglessink->render_cond);
          g_mutex_unlock (eglglessink->render_lock);
          item->destroy (item);
          break;
        }
      }
      if (eglglessink->configured_caps) {
        last_flow = gst_eglglessink_upload (eglglessink, buf);
        if (last_flow == GST_FLOW_OK) {
          last_flow = gst_eglglessink_render (eglglessink);
        }
      } else {
        GST_DEBUG_OBJECT (eglglessink,
            "No caps configured yet, not drawing anything");
      }
    } else if (!object) {
      if (eglglessink->configured_caps) {
        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 (last_flow != GST_FLOW_OK)
      break;
    GST_DEBUG_OBJECT (eglglessink, "Successfully handled object");
  }

  if (last_flow == GST_FLOW_OK) {
    g_mutex_lock (eglglessink->render_lock);
    eglglessink->last_flow = GST_FLOW_WRONG_STATE;
    g_cond_broadcast (eglglessink->render_cond);
    g_mutex_unlock (eglglessink->render_lock);
  }

  GST_DEBUG_OBJECT (eglglessink, "Shutting down thread");

  /* EGL/GLES cleanup */
  gst_egl_adaptation_cleanup (eglglessink->egl_context);

  if (eglglessink->configured_caps) {
    gst_caps_unref (eglglessink->configured_caps);
    eglglessink->configured_caps = NULL;
  }

  g_value_init (&val, G_TYPE_POINTER);
  g_value_set_pointer (&val, g_thread_self ());
  message = gst_message_new_stream_status (GST_OBJECT_CAST (eglglessink),
      GST_STREAM_STATUS_TYPE_LEAVE, GST_ELEMENT_CAST (eglglessink));
  gst_message_set_stream_status_object (message, &val);
  GST_DEBUG_OBJECT (eglglessink, "posting LEAVE stream status");
  gst_element_post_message (GST_ELEMENT_CAST (eglglessink), message);
  g_value_unset (&val);

  return NULL;
}