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; }
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; }