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); }
/* Called with reader lock held */ static gboolean have_empty_queue (GstSplitMuxPartReader * reader) { GList *cur; for (cur = g_list_first (reader->pads); cur != NULL; cur = g_list_next (cur)) { GstSplitMuxPartPad *part_pad = SPLITMUX_PART_PAD_CAST (cur->data); if (part_pad->is_eos) { GST_LOG_OBJECT (part_pad, "Pad is EOS"); return TRUE; } if (gst_data_queue_is_empty (part_pad->queue)) { GST_LOG_OBJECT (part_pad, "Queue is empty"); return TRUE; } } return FALSE; }
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; }