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);
}
GstFlowReturn
gst_splitmux_part_reader_pop (GstSplitMuxPartReader * reader, GstPad * pad,
    GstDataQueueItem ** item)
{
  GstSplitMuxPartPad *part_pad = (GstSplitMuxPartPad *) (pad);
  GstDataQueue *q;
  GstFlowReturn ret;

  /* Get one item from the appropriate dataqueue */
  SPLITMUX_PART_LOCK (reader);
  if (reader->prep_state == PART_STATE_FAILED) {
    SPLITMUX_PART_UNLOCK (reader);
    return GST_FLOW_ERROR;
  }

  q = gst_object_ref (part_pad->queue);

  /* Have to drop the lock around pop, so we can be woken up for flush */
  SPLITMUX_PART_UNLOCK (reader);
  if (!gst_data_queue_pop (q, item) || (*item == NULL)) {
    ret = GST_FLOW_FLUSHING;
    goto out;
  }

  SPLITMUX_PART_LOCK (reader);

  SPLITMUX_PART_BROADCAST (reader);
  if (GST_IS_EVENT ((*item)->object)) {
    GstEvent *e = (GstEvent *) ((*item)->object);
    /* Mark this pad as EOS */
    if (GST_EVENT_TYPE (e) == GST_EVENT_EOS)
      part_pad->is_eos = TRUE;
  }

  SPLITMUX_PART_UNLOCK (reader);

  ret = GST_FLOW_OK;
out:
  gst_object_unref (q);
  return ret;
}
Beispiel #4
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;
}
static void gst_scream_queue_srcpad_loop(GstScreamQueue *self)
{
    GstScreamDataQueueItem *item;
    GstScreamDataQueueRtpItem *rtp_item;
    GstScreamStream *stream;
    guint stream_id;
    guint64 time_now_us, time_until_next_approve = 0;
    GstBuffer *buffer;

    time_now_us = get_gst_time_us(self);
    if (G_UNLIKELY(time_now_us == 0)) {
        goto end;
    }

    if (time_now_us >= self->next_approve_time) {
        time_until_next_approve = gst_scream_controller_approve_transmits(self->scream_controller,
            time_now_us);
    } else {
        GST_LOG_OBJECT(self, "Time is %" G_GUINT64_FORMAT ", waiting %" G_GUINT64_FORMAT,
            time_now_us, self->next_approve_time);
    }

    /* Send all approved packets */
    while (!gst_data_queue_is_empty(self->approved_packets)) {
        if (G_UNLIKELY(!gst_data_queue_pop(self->approved_packets,
            (GstDataQueueItem **)&rtp_item))) {
            GST_WARNING_OBJECT(self, "Failed to pop from approved packets queue. Flushing?");
            goto end; /* flushing */
        }

        buffer = GST_BUFFER(((GstDataQueueItem *)rtp_item)->object);
        gst_pad_push(self->src_pad, buffer);

        GST_LOG_OBJECT(self, "pushing: pt = %u, seq: %u, pass: %u", rtp_item->rtp_pt, rtp_item->rtp_seq, self->pass_through);

        if (rtp_item->adapted) {
            guint tmp_time;
            stream_id = ((GstScreamDataQueueItem *)rtp_item)->rtp_ssrc;
            tmp_time = gst_scream_controller_packet_transmitted(self->scream_controller, stream_id,
                rtp_item->rtp_payload_size, rtp_item->rtp_seq, time_now_us);
            time_until_next_approve = MIN(time_until_next_approve, tmp_time);
        }
        g_slice_free(GstScreamDataQueueRtpItem, rtp_item);
    }
    self->next_approve_time = time_now_us + time_until_next_approve;

    GST_LOG_OBJECT(self, "Popping or waiting %" G_GUINT64_FORMAT, time_until_next_approve);
    item = (GstScreamDataQueueItem *)g_async_queue_timeout_pop(self->incoming_packets, time_until_next_approve);
    if (!item) {
        goto end;
    }

    stream_id = item->rtp_ssrc;
    if (item->type == GST_SCREAM_DATA_QUEUE_ITEM_TYPE_RTP) {
        GstScreamDataQueueRtpItem *rtp_item = (GstScreamDataQueueRtpItem *)item;
        stream = get_stream(self, item->rtp_ssrc, rtp_item->rtp_pt);
        if (!stream) {
            rtp_item->adapted = FALSE;
            GST_LOG_OBJECT(self, "!adapted, approving: pt = %u, seq: %u, pass: %u",
                    rtp_item->rtp_pt, rtp_item->rtp_seq, self->pass_through);
            gst_data_queue_push(self->approved_packets, (GstDataQueueItem *)item);
        } else {
            gst_atomic_queue_push(stream->packet_queue, rtp_item);
            stream->enqueued_payload_size += rtp_item->rtp_payload_size;
            stream->enqueued_packets++;
            rtp_item->adapted = TRUE;
            self->next_approve_time = 0;
            gst_scream_controller_new_rtp_packet(self->scream_controller, stream_id, rtp_item->rtp_ts,
                rtp_item->enqueued_time, stream->enqueued_payload_size, rtp_item->rtp_payload_size);
        }
    } else { /* item->type == GST_SCREAM_DATA_QUEUE_ITEM_TYPE_RTCP */
        GstScreamDataQueueRtcpItem *rtcp_item = (GstScreamDataQueueRtcpItem *)item;

        gst_scream_controller_incoming_feedback(self->scream_controller, stream_id, time_now_us,
            rtcp_item->timestamp, rtcp_item->highest_seq, rtcp_item->n_loss, rtcp_item->n_ecn, rtcp_item->qbit);

        ((GstDataQueueItem *)item)->destroy(item);
    }

end:
    return;

}