EXPORT_C #endif void gst_rtp_buffer_list_set_ssrc (GstBufferList * list, guint32 ssrc) { gst_buffer_list_foreach (list, (GstBufferListFunc) set_ssrc_header, &ssrc); }
/** * gst_rtp_buffer_list_set_payload_type: * @list: the buffer list * @payload_type: the new type * * Set the payload type of each RTP packet in @list to @payload_type. * * Since: 0.10.24 */ void gst_rtp_buffer_list_set_payload_type (GstBufferList * list, guint8 payload_type) { g_return_if_fail (payload_type < 0x80); gst_buffer_list_foreach (list, (GstBufferListFunc) set_pt_header, &payload_type); }
EXPORT_C #endif void gst_rtp_buffer_list_set_timestamp (GstBufferList * list, guint32 timestamp) { gst_buffer_list_foreach (list, (GstBufferListFunc) set_timestamp_header, ×tamp); }
EXPORT_C #endif guint16 gst_rtp_buffer_list_set_seq (GstBufferList * list, guint16 seq) { gst_buffer_list_foreach (list, (GstBufferListFunc) set_seq_header, &seq); return seq; }
/* Our assumption for now is that the buffers in a buffer list should always * end up in the same file. If someone wants different behaviour, they'll just * have to add a property for that. */ static GstFlowReturn gst_multi_file_sink_render_list (GstBaseSink * sink, GstBufferList * list) { GstBuffer *buf; guint size = 0; gst_buffer_list_foreach (list, buffer_list_calc_size, &size); GST_LOG_OBJECT (sink, "total size of buffer list %p: %u", list, size); /* copy all buffers in the list into one single buffer, so we can use * the normal render function (FIXME: optimise to avoid the memcpy) */ buf = gst_buffer_new (); gst_buffer_list_foreach (list, buffer_list_copy_data, buf); g_assert (gst_buffer_get_size (buf) == size); gst_multi_file_sink_render (sink, buf); gst_buffer_unref (buf); return GST_FLOW_OK; }
static void do_push_buffer_list_pre (GstStatsTracer * self, guint64 ts, GstPad * this_pad, GstBufferList * list) { GstPadStats *this_pad_stats = get_pad_stats (self, this_pad); GstPad *that_pad = GST_PAD_PEER (this_pad); GstPadStats *that_pad_stats = get_pad_stats (self, that_pad); DoPushBufferListArgs args = { self, this_pad, this_pad_stats, that_pad, that_pad_stats, ts }; gst_buffer_list_foreach (list, do_push_buffer_list_item, &args); }
static GstPadProbeReturn process_buffer_probe_cb (GstPad * pad, GstPadProbeInfo * info, gpointer user_data) { if (GST_PAD_PROBE_INFO_TYPE (info) & GST_PAD_PROBE_TYPE_BUFFER) { GstBuffer *buffer = GST_PAD_PROBE_INFO_BUFFER (info); process_buffer (buffer, user_data); } else if (GST_PAD_PROBE_INFO_TYPE (info) & GST_PAD_PROBE_TYPE_BUFFER_LIST) { GstBufferList *list = GST_PAD_PROBE_INFO_BUFFER_LIST (info); gst_buffer_list_foreach (list, process_buffer_list_cb, user_data); } return GST_PAD_PROBE_OK; }
static GstFlowReturn gst_rtp_mux_chain_list (GstPad * pad, GstObject * parent, GstBufferList * bufferlist) { GstRTPMux *rtp_mux; GstFlowReturn ret; GstRTPMuxPadPrivate *padpriv; struct BufferListData bd; rtp_mux = GST_RTP_MUX (parent); GST_OBJECT_LOCK (rtp_mux); padpriv = gst_pad_get_element_private (pad); if (!padpriv) { GST_OBJECT_UNLOCK (rtp_mux); ret = GST_FLOW_NOT_LINKED; gst_buffer_list_unref (bufferlist); goto out; } bd.rtp_mux = rtp_mux; bd.padpriv = padpriv; bd.drop = FALSE; bufferlist = gst_buffer_list_make_writable (bufferlist); gst_buffer_list_foreach (bufferlist, process_list_item, &bd); GST_OBJECT_UNLOCK (rtp_mux); if (bd.drop) { gst_buffer_list_unref (bufferlist); ret = GST_FLOW_OK; } else { ret = gst_pad_push_list (rtp_mux->srcpad, bufferlist); } out: return ret; }
static GstFlowReturn gst_rtp_base_depayload_prepare_push (GstRTPBaseDepayload * filter, gboolean is_list, gpointer obj) { if (is_list) { GstBufferList **blist = obj; gst_buffer_list_foreach (*blist, (GstBufferListFunc) set_headers, filter); } else { GstBuffer **buf = obj; set_headers (buf, 0, filter); } /* if this is the first buffer send a NEWSEGMENT */ if (G_UNLIKELY (filter->priv->segment_event)) { gst_pad_push_event (filter->srcpad, filter->priv->segment_event); filter->priv->segment_event = NULL; GST_DEBUG_OBJECT (filter, "Pushed newsegment event on this first buffer"); } return GST_FLOW_OK; }
static GstPadProbeReturn kms_av_muxer_injector_probe (GstPad * pad, GstPadProbeInfo * info, gpointer self) { GstElement *elem; GstPadProbeReturn ret = GST_PAD_PROBE_OK; if (info->type & GST_PAD_PROBE_TYPE_BLOCK) { return GST_PAD_PROBE_PASS; } elem = gst_pad_get_parent_element (pad); g_return_val_if_fail (elem != NULL, GST_PAD_PROBE_OK); if (info->type & GST_PAD_PROBE_TYPE_BUFFER_LIST) { GstBufferList *list = GST_PAD_PROBE_INFO_BUFFER_LIST (info); BufferListItData itData; itData.self = self; itData.elem = elem; if (G_UNLIKELY (!gst_buffer_list_foreach (list, kms_av_muxer_injector_probe_it, &itData))) { ret = GST_PAD_PROBE_DROP; } } else if (info->type & GST_PAD_PROBE_TYPE_BUFFER) { GstBuffer **buffer = (GstBuffer **) & info->data; if (G_UNLIKELY (!kms_av_muxer_injector (self, elem, buffer))) { ret = GST_PAD_PROBE_DROP; } } g_object_unref (elem); return ret; }
static GstFlowReturn sink_chain_list (GstPad * pad, GstObject * parent, GstBufferList * list) { GstDtlsDec *self = GST_DTLS_DEC (parent); GstFlowReturn ret = GST_FLOW_OK; GstPad *other_pad; list = gst_buffer_list_make_writable (list); gst_buffer_list_foreach (list, process_buffer_from_list, self); if (gst_buffer_list_length (list) == 0) { GST_DEBUG_OBJECT (self, "Not produced any buffers"); gst_buffer_list_unref (list); return GST_FLOW_OK; } g_mutex_lock (&self->src_mutex); other_pad = self->src; if (other_pad) gst_object_ref (other_pad); g_mutex_unlock (&self->src_mutex); if (other_pad) { GST_LOG_OBJECT (self, "decoded buffer list with length %u, pushing", gst_buffer_list_length (list)); ret = gst_pad_push_list (other_pad, list); gst_object_unref (other_pad); } else { GST_LOG_OBJECT (self, "dropped buffer list with length %d, not linked", gst_buffer_list_length (list)); gst_buffer_list_unref (list); } return ret; }
/* Updates the SSRC, payload type, seqnum and timestamp of the RTP buffer * before the buffer is pushed. */ static GstFlowReturn gst_rtp_base_payload_prepare_push (GstRTPBasePayload * payload, gpointer obj, gboolean is_list) { GstRTPBasePayloadPrivate *priv; HeaderData data; if (payload->clock_rate == 0) goto no_rate; priv = payload->priv; /* update first, so that the property is set to the last * seqnum pushed */ payload->seqnum = priv->next_seqnum; /* fill in the fields we want to set on all headers */ data.payload = payload; data.seqnum = payload->seqnum; data.ssrc = payload->current_ssrc; data.pt = payload->pt; /* find the first buffer with a timestamp */ if (is_list) { data.dts = -1; data.pts = -1; data.offset = GST_BUFFER_OFFSET_NONE; gst_buffer_list_foreach (GST_BUFFER_LIST_CAST (obj), find_timestamp, &data); } else { data.dts = GST_BUFFER_DTS (GST_BUFFER_CAST (obj)); data.pts = GST_BUFFER_PTS (GST_BUFFER_CAST (obj)); data.offset = GST_BUFFER_OFFSET (GST_BUFFER_CAST (obj)); } /* convert to RTP time */ if (priv->perfect_rtptime && data.offset != GST_BUFFER_OFFSET_NONE && priv->base_offset != GST_BUFFER_OFFSET_NONE) { /* if we have an offset, use that for making an RTP timestamp */ data.rtptime = payload->ts_base + priv->base_rtime + data.offset - priv->base_offset; GST_LOG_OBJECT (payload, "Using offset %" G_GUINT64_FORMAT " for RTP timestamp", data.offset); } else if (GST_CLOCK_TIME_IS_VALID (data.pts)) { gint64 rtime; /* no offset, use the gstreamer pts */ rtime = gst_segment_to_running_time (&payload->segment, GST_FORMAT_TIME, data.pts); if (rtime == -1) { GST_LOG_OBJECT (payload, "Clipped pts, using base RTP timestamp"); rtime = 0; } else { GST_LOG_OBJECT (payload, "Using running_time %" GST_TIME_FORMAT " for RTP timestamp", GST_TIME_ARGS (rtime)); rtime = gst_util_uint64_scale_int (rtime, payload->clock_rate, GST_SECOND); priv->base_offset = data.offset; priv->base_rtime = rtime; } /* add running_time in clock-rate units to the base timestamp */ data.rtptime = payload->ts_base + rtime; } else { GST_LOG_OBJECT (payload, "Using previous RTP timestamp %" G_GUINT32_FORMAT, payload->timestamp); /* no timestamp to convert, take previous timestamp */ data.rtptime = payload->timestamp; } /* set ssrc, payload type, seq number, caps and rtptime */ if (is_list) { gst_buffer_list_foreach (GST_BUFFER_LIST_CAST (obj), set_headers, &data); } else { GstBuffer *buf = GST_BUFFER_CAST (obj); set_headers (&buf, 0, &data); } priv->next_seqnum = data.seqnum; payload->timestamp = data.rtptime; GST_LOG_OBJECT (payload, "Preparing to push packet with size %" G_GSIZE_FORMAT ", seq=%d, rtptime=%u, pts %" GST_TIME_FORMAT, (is_list) ? -1 : gst_buffer_get_size (GST_BUFFER (obj)), payload->seqnum, data.rtptime, GST_TIME_ARGS (data.pts)); if (g_atomic_int_compare_and_exchange (&payload-> priv->notified_first_timestamp, 1, 0)) { g_object_notify (G_OBJECT (payload), "timestamp"); g_object_notify (G_OBJECT (payload), "seqnum"); } return GST_FLOW_OK; /* ERRORS */ no_rate: { GST_ELEMENT_ERROR (payload, STREAM, NOT_IMPLEMENTED, (NULL), ("subclass did not specify clock-rate")); return GST_FLOW_ERROR; } }
static GstFlowReturn gst_rtp_mux_chain_list (GstPad * pad, GstObject * parent, GstBufferList * bufferlist) { GstRTPMux *rtp_mux; GstFlowReturn ret; GstRTPMuxPadPrivate *padpriv; gboolean changed = FALSE; struct BufferListData bd; rtp_mux = GST_RTP_MUX (parent); if (gst_pad_check_reconfigure (rtp_mux->srcpad)) { GstCaps *current_caps = gst_pad_get_current_caps (pad); if (!gst_rtp_mux_setcaps (pad, rtp_mux, current_caps)) { ret = GST_FLOW_NOT_NEGOTIATED; gst_buffer_list_unref (bufferlist); goto out; } gst_caps_unref (current_caps); } GST_OBJECT_LOCK (rtp_mux); padpriv = gst_pad_get_element_private (pad); if (!padpriv) { GST_OBJECT_UNLOCK (rtp_mux); ret = GST_FLOW_NOT_LINKED; gst_buffer_list_unref (bufferlist); goto out; } bd.rtp_mux = rtp_mux; bd.padpriv = padpriv; bd.drop = FALSE; bufferlist = gst_buffer_list_make_writable (bufferlist); gst_buffer_list_foreach (bufferlist, process_list_item, &bd); if (!bd.drop && pad != rtp_mux->last_pad) { changed = TRUE; g_clear_object (&rtp_mux->last_pad); rtp_mux->last_pad = g_object_ref (pad); } GST_OBJECT_UNLOCK (rtp_mux); if (changed) gst_pad_sticky_events_foreach (pad, resend_events, rtp_mux); if (bd.drop) { gst_buffer_list_unref (bufferlist); ret = GST_FLOW_OK; } else { ret = gst_pad_push_list (rtp_mux->srcpad, bufferlist); } out: return ret; }