/** * rtp_jitter_buffer_get_ts_diff: * @jbuf: an #RTPJitterBuffer * * Get the difference between the timestamps of first and last packet in the * jitterbuffer. * * Returns: The difference expressed in the timestamp units of the packets. */ guint32 rtp_jitter_buffer_get_ts_diff (RTPJitterBuffer * jbuf) { guint64 high_ts, low_ts; GstBuffer *high_buf, *low_buf; guint32 result; GstRTPBuffer rtp = {NULL}; g_return_val_if_fail (jbuf != NULL, 0); high_buf = g_queue_peek_head (jbuf->packets); low_buf = g_queue_peek_tail (jbuf->packets); if (!high_buf || !low_buf || high_buf == low_buf) return 0; gst_rtp_buffer_map (high_buf, GST_MAP_READ, &rtp); high_ts = gst_rtp_buffer_get_timestamp (&rtp); gst_rtp_buffer_unmap (&rtp); gst_rtp_buffer_map (low_buf, GST_MAP_READ, &rtp); low_ts = gst_rtp_buffer_get_timestamp (&rtp); gst_rtp_buffer_unmap (&rtp); /* it needs to work if ts wraps */ if (high_ts >= low_ts) { result = (guint32) (high_ts - low_ts); } else { result = (guint32) (high_ts + G_MAXUINT32 + 1 - low_ts); } return result; }
static gboolean set_headers (GstBuffer ** buffer, guint idx, gpointer user_data) { HeaderData *data = user_data; GstRTPBuffer rtp = { NULL, }; if (!gst_rtp_buffer_map (*buffer, GST_MAP_WRITE, &rtp)) goto map_failed; gst_rtp_buffer_set_ssrc (&rtp, data->ssrc); gst_rtp_buffer_set_payload_type (&rtp, data->pt); gst_rtp_buffer_set_seq (&rtp, data->seqnum); gst_rtp_buffer_set_timestamp (&rtp, data->rtptime); gst_rtp_buffer_unmap (&rtp); /* increment the seqnum for each buffer */ data->seqnum++; return TRUE; /* ERRORS */ map_failed: { GST_ERROR ("failed to map buffer %p", *buffer); return FALSE; } }
static GstBuffer * generate_test_buffer_full (GstClockTime dts, guint seq_num, guint32 rtp_ts, guint ssrc) { GstBuffer *buf; guint8 *payload; guint i; GstRTPBuffer rtp = GST_RTP_BUFFER_INIT; buf = gst_rtp_buffer_new_allocate (TEST_BUF_SIZE, 0, 0); GST_BUFFER_DTS (buf) = dts; gst_rtp_buffer_map (buf, GST_MAP_READWRITE, &rtp); gst_rtp_buffer_set_payload_type (&rtp, TEST_BUF_PT); gst_rtp_buffer_set_seq (&rtp, seq_num); gst_rtp_buffer_set_timestamp (&rtp, rtp_ts); gst_rtp_buffer_set_ssrc (&rtp, ssrc); payload = gst_rtp_buffer_get_payload (&rtp); for (i = 0; i < TEST_BUF_SIZE; i++) payload[i] = 0xff; gst_rtp_buffer_unmap (&rtp); return buf; }
static GstBuffer * generate_test_buffer (guint seq_num, guint ssrc) { GstBuffer *buf; guint8 *payload; guint i; GstRTPBuffer rtp = GST_RTP_BUFFER_INIT; gsize size = 10; buf = gst_rtp_buffer_new_allocate (size, 0, 0); GST_BUFFER_DTS (buf) = GST_MSECOND * 20 * seq_num; GST_BUFFER_PTS (buf) = GST_MSECOND * 20 * seq_num; gst_rtp_buffer_map (buf, GST_MAP_READWRITE, &rtp); gst_rtp_buffer_set_payload_type (&rtp, 0); gst_rtp_buffer_set_seq (&rtp, seq_num); gst_rtp_buffer_set_timestamp (&rtp, 160 * seq_num); gst_rtp_buffer_set_ssrc (&rtp, ssrc); payload = gst_rtp_buffer_get_payload (&rtp); for (i = 0; i < size; i++) payload[i] = 0xff; gst_rtp_buffer_unmap (&rtp); return buf; }
static GstBuffer * generate_test_buffer (GstClockTime gst_ts, gboolean marker_bit, guint seq_num, guint32 rtp_ts, guint ssrc) { GstBuffer *buf; guint8 *payload; guint i; GstRTPBuffer rtp = GST_RTP_BUFFER_INIT; buf = gst_rtp_buffer_new_allocate (payload_size, 0, 0); GST_BUFFER_DTS (buf) = gst_ts; GST_BUFFER_PTS (buf) = gst_ts; gst_rtp_buffer_map (buf, GST_MAP_READWRITE, &rtp); gst_rtp_buffer_set_payload_type (&rtp, payload_type); gst_rtp_buffer_set_marker (&rtp, marker_bit); gst_rtp_buffer_set_seq (&rtp, seq_num); gst_rtp_buffer_set_timestamp (&rtp, rtp_ts); gst_rtp_buffer_set_ssrc (&rtp, ssrc); payload = gst_rtp_buffer_get_payload (&rtp); for (i = 0; i < payload_size; i++) payload[i] = 0xff; gst_rtp_buffer_unmap (&rtp); return buf; }
static GstBuffer * gst_rtp_pcmu_depay_process (GstRTPBaseDepayload * depayload, GstBuffer * buf) { GstBuffer *outbuf = NULL; guint len; gboolean marker; GstRTPBuffer rtp = { NULL }; gst_rtp_buffer_map (buf, GST_MAP_READ, &rtp); marker = gst_rtp_buffer_get_marker (&rtp); GST_DEBUG ("process : got %" G_GSIZE_FORMAT " bytes, mark %d ts %u seqn %d", gst_buffer_get_size (buf), marker, gst_rtp_buffer_get_timestamp (&rtp), gst_rtp_buffer_get_seq (&rtp)); len = gst_rtp_buffer_get_payload_len (&rtp); outbuf = gst_rtp_buffer_get_payload_buffer (&rtp); gst_rtp_buffer_unmap (&rtp); if (outbuf) { GST_BUFFER_DURATION (outbuf) = gst_util_uint64_scale_int (len, GST_SECOND, depayload->clock_rate); if (marker) { /* mark start of talkspurt with RESYNC */ GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_RESYNC); } } return outbuf; }
static GstPadProbeReturn drop_theora_config (GstPad *pad, GstPadProbeInfo *info, gpointer user_data) { GstBuffer *buffer = GST_PAD_PROBE_INFO_BUFFER (info); GstRTPBuffer rtpbuffer = GST_RTP_BUFFER_INIT; guint8 *payload; guint32 header; guchar TDT; gst_rtp_buffer_map (buffer, GST_MAP_READ, &rtpbuffer); payload = gst_rtp_buffer_get_payload (&rtpbuffer); header = GST_READ_UINT32_BE (payload); /* * 0 1 2 3 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Ident | F |TDT|# pkts.| * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * * F: Fragment type (0=none, 1=start, 2=cont, 3=end) * TDT: Theora data type (0=theora, 1=config, 2=comment, 3=reserved) * pkts: number of packets. */ TDT = (header & 0x30) >> 4; gst_rtp_buffer_unmap (&rtpbuffer); if (TDT == 1) return GST_PAD_PROBE_DROP; else return GST_PAD_PROBE_OK; }
static GstBuffer * gst_rtp_mp4v_depay_process (GstRTPBaseDepayload * depayload, GstBuffer * buf) { GstRtpMP4VDepay *rtpmp4vdepay; GstBuffer *pbuf, *outbuf = NULL; GstRTPBuffer rtp = { NULL }; gboolean marker; rtpmp4vdepay = GST_RTP_MP4V_DEPAY (depayload); /* flush remaining data on discont */ if (GST_BUFFER_IS_DISCONT (buf)) gst_adapter_clear (rtpmp4vdepay->adapter); gst_rtp_buffer_map (buf, GST_MAP_READ, &rtp); pbuf = gst_rtp_buffer_get_payload_buffer (&rtp); marker = gst_rtp_buffer_get_marker (&rtp); gst_rtp_buffer_unmap (&rtp); gst_adapter_push (rtpmp4vdepay->adapter, pbuf); /* if this was the last packet of the VOP, create and push a buffer */ if (marker) { guint avail; avail = gst_adapter_available (rtpmp4vdepay->adapter); outbuf = gst_adapter_take_buffer (rtpmp4vdepay->adapter, avail); GST_DEBUG ("gst_rtp_mp4v_depay_chain: pushing buffer of size %" G_GSIZE_FORMAT, gst_buffer_get_size (outbuf)); } return outbuf; }
static GstBuffer * gst_rtp_ilbc_depay_process (GstRTPBaseDepayload * depayload, GstBuffer * buf) { GstBuffer *outbuf; gboolean marker; GstRTPBuffer rtp = { NULL }; gst_rtp_buffer_map (buf, GST_MAP_READ, &rtp); marker = gst_rtp_buffer_get_marker (&rtp); GST_DEBUG ("process : got %" G_GSIZE_FORMAT " bytes, mark %d ts %u seqn %d", gst_buffer_get_size (buf), marker, gst_rtp_buffer_get_timestamp (&rtp), gst_rtp_buffer_get_seq (&rtp)); outbuf = gst_rtp_buffer_get_payload_buffer (&rtp); gst_rtp_buffer_unmap (&rtp); if (marker && outbuf) { /* mark start of talkspurt with RESYNC */ GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_RESYNC); } if (outbuf) { gst_rtp_drop_meta (GST_ELEMENT_CAST (depayload), outbuf, g_quark_from_static_string (GST_META_TAG_AUDIO_STR)); } return outbuf; }
/* Return a stream structure for a given buffer */ static GstSrtpDecSsrcStream * validate_buffer (GstSrtpDec * filter, GstBuffer * buf, guint32 * ssrc, gboolean * is_rtcp) { GstSrtpDecSsrcStream *stream = NULL; GstRTPBuffer rtpbuf = GST_RTP_BUFFER_INIT; if (gst_rtp_buffer_map (buf, GST_MAP_READ, &rtpbuf)) { if (gst_rtp_buffer_get_payload_type (&rtpbuf) < 64 || gst_rtp_buffer_get_payload_type (&rtpbuf) > 80) { *ssrc = gst_rtp_buffer_get_ssrc (&rtpbuf); gst_rtp_buffer_unmap (&rtpbuf); *is_rtcp = FALSE; goto have_ssrc; } gst_rtp_buffer_unmap (&rtpbuf); } if (rtcp_buffer_get_ssrc (buf, ssrc)) { *is_rtcp = TRUE; } else { GST_WARNING_OBJECT (filter, "No SSRC found in buffer"); return NULL; } have_ssrc: stream = find_stream_by_ssrc (filter, *ssrc); if (stream) return stream; return request_key_with_signal (filter, *ssrc, SIGNAL_REQUEST_KEY); }
static void check_rtp_buffer (GstClockTime ts, GstClockTime duration, gboolean start, gboolean end, guint rtpts, guint ssrc, guint volume, guint number, guint rtpduration) { GstBuffer *buffer; GstRTPBuffer rtpbuffer = GST_RTP_BUFFER_INIT; gchar *payload; g_mutex_lock (&check_mutex); while (buffers == NULL) g_cond_wait (&check_cond, &check_mutex); g_mutex_unlock (&check_mutex); fail_unless (buffers != NULL); buffer = buffers->data; buffers = g_list_delete_link (buffers, buffers); fail_unless (GST_BUFFER_PTS (buffer) == ts); fail_unless (GST_BUFFER_DURATION (buffer) == duration); fail_unless (gst_rtp_buffer_map (buffer, GST_MAP_READ, &rtpbuffer)); fail_unless (gst_rtp_buffer_get_marker (&rtpbuffer) == start); fail_unless (gst_rtp_buffer_get_timestamp (&rtpbuffer) == rtpts); payload = gst_rtp_buffer_get_payload (&rtpbuffer); fail_unless (payload[0] == number); fail_unless ((payload[1] & 0x7F) == volume); fail_unless (! !(payload[1] & 0x80) == end); fail_unless (GST_READ_UINT16_BE (payload + 2) == rtpduration); gst_rtp_buffer_unmap (&rtpbuffer); gst_buffer_unref (buffer); }
static GstBuffer * gst_rtp_ilbc_depay_process (GstRTPBaseDepayload * depayload, GstBuffer * buf) { GstBuffer *outbuf; gboolean marker; GstRTPBuffer rtp = { NULL }; gst_rtp_buffer_map (buf, GST_MAP_READ, &rtp); marker = gst_rtp_buffer_get_marker (&rtp); GST_DEBUG ("process : got %" G_GSIZE_FORMAT " bytes, mark %d ts %u seqn %d", gst_buffer_get_size (buf), marker, gst_rtp_buffer_get_timestamp (&rtp), gst_rtp_buffer_get_seq (&rtp)); outbuf = gst_rtp_buffer_get_payload_buffer (&rtp); gst_rtp_buffer_unmap (&rtp); if (marker && outbuf) { /* mark start of talkspurt with DISCONT */ GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DISCONT); } return outbuf; }
/** * gst_rtp_base_audio_payload_push: * @baseaudiopayload: a #GstRTPBasePayload * @data: data to set as payload * @payload_len: length of payload * @timestamp: a #GstClockTime * * Create an RTP buffer and store @payload_len bytes of @data as the * payload. Set the timestamp on the new buffer to @timestamp before pushing * the buffer downstream. * * Returns: a #GstFlowReturn */ GstFlowReturn gst_rtp_base_audio_payload_push (GstRTPBaseAudioPayload * baseaudiopayload, const guint8 * data, guint payload_len, GstClockTime timestamp) { GstRTPBasePayload *basepayload; GstBuffer *outbuf; guint8 *payload; GstFlowReturn ret; GstRTPBuffer rtp = { NULL }; basepayload = GST_RTP_BASE_PAYLOAD (baseaudiopayload); GST_DEBUG_OBJECT (baseaudiopayload, "Pushing %d bytes ts %" GST_TIME_FORMAT, payload_len, GST_TIME_ARGS (timestamp)); /* create buffer to hold the payload */ outbuf = gst_rtp_base_payload_allocate_output_buffer (basepayload, payload_len, 0, 0); /* copy payload */ gst_rtp_buffer_map (outbuf, GST_MAP_WRITE, &rtp); payload = gst_rtp_buffer_get_payload (&rtp); memcpy (payload, data, payload_len); gst_rtp_buffer_unmap (&rtp); /* set metadata */ gst_rtp_base_audio_payload_set_meta (baseaudiopayload, outbuf, payload_len, timestamp); ret = gst_rtp_base_payload_push (basepayload, outbuf); return ret; }
static GstFlowReturn gst_rtp_celt_pay_flush_queued (GstRtpCELTPay * rtpceltpay) { GstFlowReturn ret; GstBuffer *buf, *outbuf; guint8 *payload, *spayload; guint payload_len; GstClockTime duration; GstRTPBuffer rtp = { NULL, }; payload_len = rtpceltpay->bytes + rtpceltpay->sbytes; duration = rtpceltpay->qduration; GST_DEBUG_OBJECT (rtpceltpay, "flushing out %u, duration %" GST_TIME_FORMAT, payload_len, GST_TIME_ARGS (rtpceltpay->qduration)); /* get a big enough packet for the sizes + payloads */ outbuf = gst_rtp_buffer_new_allocate (payload_len, 0, 0); GST_BUFFER_DURATION (outbuf) = duration; gst_rtp_buffer_map (outbuf, GST_MAP_WRITE, &rtp); /* point to the payload for size headers and data */ spayload = gst_rtp_buffer_get_payload (&rtp); payload = spayload + rtpceltpay->sbytes; while ((buf = g_queue_pop_head (rtpceltpay->queue))) { guint size; /* copy first timestamp to output */ if (GST_BUFFER_TIMESTAMP (outbuf) == -1) GST_BUFFER_TIMESTAMP (outbuf) = GST_BUFFER_TIMESTAMP (buf); /* write the size to the header */ size = gst_buffer_get_size (buf); while (size > 0xff) { *spayload++ = 0xff; size -= 0xff; } *spayload++ = size; /* copy payload */ size = gst_buffer_get_size (buf); gst_buffer_extract (buf, 0, payload, size); payload += size; gst_buffer_unref (buf); } gst_rtp_buffer_unmap (&rtp); /* we consumed it all */ rtpceltpay->bytes = 0; rtpceltpay->sbytes = 0; rtpceltpay->qduration = 0; ret = gst_rtp_base_payload_push (GST_RTP_BASE_PAYLOAD (rtpceltpay), outbuf); return ret; }
static gboolean process_list_item (GstBuffer ** buffer, guint idx, gpointer user_data) { struct BufferListData *bd = user_data; GstRTPBuffer rtpbuffer = GST_RTP_BUFFER_INIT; *buffer = gst_buffer_make_writable (*buffer); gst_rtp_buffer_map (*buffer, GST_MAP_READWRITE, &rtpbuffer); bd->drop = !process_buffer_locked (bd->rtp_mux, bd->padpriv, &rtpbuffer); gst_rtp_buffer_unmap (&rtpbuffer); if (bd->drop) return FALSE; if (GST_BUFFER_DURATION_IS_VALID (*buffer) && GST_BUFFER_PTS_IS_VALID (*buffer)) bd->rtp_mux->last_stop = GST_BUFFER_PTS (*buffer) + GST_BUFFER_DURATION (*buffer); else bd->rtp_mux->last_stop = GST_CLOCK_TIME_NONE; return TRUE; }
static GstFlowReturn gst_rtp_ssrc_demux_chain (GstPad * pad, GstObject * parent, GstBuffer * buf) { GstFlowReturn ret; GstRtpSsrcDemux *demux; guint32 ssrc; GstRTPBuffer rtp = { NULL }; GstPad *srcpad; GstRtpSsrcDemuxPad *dpad; demux = GST_RTP_SSRC_DEMUX (parent); if (!gst_rtp_buffer_map (buf, GST_MAP_READ, &rtp)) goto invalid_payload; ssrc = gst_rtp_buffer_get_ssrc (&rtp); gst_rtp_buffer_unmap (&rtp); GST_DEBUG_OBJECT (demux, "received buffer of SSRC %08x", ssrc); srcpad = find_or_create_demux_pad_for_ssrc (demux, ssrc, RTP_PAD); if (srcpad == NULL) goto create_failed; /* push to srcpad */ ret = gst_pad_push (srcpad, buf); if (ret != GST_FLOW_OK) { /* check if the ssrc still there, may have been removed */ GST_PAD_LOCK (demux); dpad = find_demux_pad_for_ssrc (demux, ssrc); if (dpad == NULL || dpad->rtp_pad != srcpad) { /* SSRC was removed during the push ... ignore the error */ ret = GST_FLOW_OK; } GST_PAD_UNLOCK (demux); } gst_object_unref (srcpad); return ret; /* ERRORS */ invalid_payload: { /* this is fatal and should be filtered earlier */ GST_ELEMENT_ERROR (demux, STREAM, DECODE, (NULL), ("Dropping invalid RTP payload")); gst_buffer_unref (buf); return GST_FLOW_ERROR; } create_failed: { GST_ELEMENT_ERROR (demux, STREAM, DECODE, (NULL), ("Could not create new pad")); gst_buffer_unref (buf); return GST_FLOW_ERROR; } }
static GstBuffer * gst_rtp_dtmf_src_create_next_rtp_packet (GstRTPDTMFSrc * dtmfsrc) { GstBuffer *buf; GstRTPDTMFPayload *payload; GstRTPBuffer rtpbuffer = GST_RTP_BUFFER_INIT; buf = gst_rtp_buffer_new_allocate (sizeof (GstRTPDTMFPayload), 0, 0); gst_rtp_buffer_map (buf, GST_MAP_READWRITE, &rtpbuffer); gst_rtp_dtmf_prepare_rtp_headers (dtmfsrc, &rtpbuffer); /* timestamp and duration of GstBuffer */ /* Redundant buffer have no duration ... */ if (dtmfsrc->redundancy_count > 1) GST_BUFFER_DURATION (buf) = 0; else GST_BUFFER_DURATION (buf) = dtmfsrc->ptime * GST_MSECOND; GST_BUFFER_PTS (buf) = dtmfsrc->timestamp; payload = (GstRTPDTMFPayload *) gst_rtp_buffer_get_payload (&rtpbuffer); /* copy payload and convert to network-byte order */ memmove (payload, dtmfsrc->payload, sizeof (GstRTPDTMFPayload)); payload->duration = g_htons (payload->duration); if (dtmfsrc->redundancy_count <= 1 && dtmfsrc->last_packet) { GstClockTime inter_digit_interval = MIN_INTER_DIGIT_INTERVAL; if (inter_digit_interval % dtmfsrc->ptime != 0) inter_digit_interval += dtmfsrc->ptime - (MIN_INTER_DIGIT_INTERVAL % dtmfsrc->ptime); GST_BUFFER_DURATION (buf) += inter_digit_interval * GST_MSECOND; } GST_LOG_OBJECT (dtmfsrc, "Creating new buffer with event %u duration " " gst: %" GST_TIME_FORMAT " at %" GST_TIME_FORMAT "(rtp ts:%u dur:%u)", dtmfsrc->payload->event, GST_TIME_ARGS (GST_BUFFER_DURATION (buf)), GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)), dtmfsrc->rtp_timestamp, dtmfsrc->payload->duration); /* duration of DTMF payloadfor the NEXT packet */ /* not updated for redundant packets */ if (dtmfsrc->redundancy_count <= 1) dtmfsrc->payload->duration += dtmfsrc->ptime * dtmfsrc->clock_rate / 1000; if (GST_CLOCK_TIME_IS_VALID (dtmfsrc->timestamp)) dtmfsrc->timestamp += GST_BUFFER_DURATION (buf); gst_rtp_buffer_unmap (&rtpbuffer); return buf; }
static GstFlowReturn gst_rtp_sbc_pay_flush_buffers (GstRtpSBCPay * sbcpay) { GstRTPBuffer rtp = GST_RTP_BUFFER_INIT; guint available; guint max_payload; GstBuffer *outbuf; guint8 *payload_data; guint frame_count; guint payload_length; struct rtp_payload *payload; if (sbcpay->frame_length == 0) { GST_ERROR_OBJECT (sbcpay, "Frame length is 0"); return GST_FLOW_ERROR; } available = gst_adapter_available (sbcpay->adapter); max_payload = gst_rtp_buffer_calc_payload_len (GST_RTP_BASE_PAYLOAD_MTU (sbcpay) - RTP_SBC_PAYLOAD_HEADER_SIZE, 0, 0); max_payload = MIN (max_payload, available); frame_count = max_payload / sbcpay->frame_length; payload_length = frame_count * sbcpay->frame_length; if (payload_length == 0) /* Nothing to send */ return GST_FLOW_OK; outbuf = gst_rtp_buffer_new_allocate (payload_length + RTP_SBC_PAYLOAD_HEADER_SIZE, 0, 0); /* get payload */ gst_rtp_buffer_map (outbuf, GST_MAP_WRITE, &rtp); gst_rtp_buffer_set_payload_type (&rtp, GST_RTP_BASE_PAYLOAD_PT (sbcpay)); /* write header and copy data into payload */ payload_data = gst_rtp_buffer_get_payload (&rtp); payload = (struct rtp_payload *) payload_data; memset (payload, 0, sizeof (struct rtp_payload)); payload->frame_count = frame_count; gst_adapter_copy (sbcpay->adapter, payload_data + RTP_SBC_PAYLOAD_HEADER_SIZE, 0, payload_length); gst_rtp_buffer_unmap (&rtp); gst_adapter_flush (sbcpay->adapter, payload_length); /* FIXME: what about duration? */ GST_BUFFER_PTS (outbuf) = sbcpay->timestamp; GST_DEBUG_OBJECT (sbcpay, "Pushing %d bytes", payload_length); return gst_rtp_base_payload_push (GST_RTP_BASE_PAYLOAD (sbcpay), outbuf); }
static guint32 _rtp_buffer_get_ssrc (GstBuffer * buf) { GstRTPBuffer rtp = GST_RTP_BUFFER_INIT; guint32 ret; g_assert (gst_rtp_buffer_map (buf, GST_MAP_READ, &rtp)); ret = gst_rtp_buffer_get_ssrc (&rtp); gst_rtp_buffer_unmap (&rtp); return ret; }
static GstBuffer * gst_rtp_L16_depay_process (GstRTPBaseDepayload * depayload, GstBuffer * buf) { GstRtpL16Depay *rtpL16depay; GstBuffer *outbuf; gint payload_len; gboolean marker; GstRTPBuffer rtp = { NULL }; rtpL16depay = GST_RTP_L16_DEPAY (depayload); gst_rtp_buffer_map (buf, GST_MAP_READ, &rtp); payload_len = gst_rtp_buffer_get_payload_len (&rtp); if (payload_len <= 0) goto empty_packet; GST_DEBUG_OBJECT (rtpL16depay, "got payload of %d bytes", payload_len); outbuf = gst_rtp_buffer_get_payload_buffer (&rtp); marker = gst_rtp_buffer_get_marker (&rtp); if (marker) { /* mark talk spurt with DISCONT */ GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DISCONT); } outbuf = gst_buffer_make_writable (outbuf); if (rtpL16depay->order && !gst_audio_buffer_reorder_channels (outbuf, rtpL16depay->info.finfo->format, rtpL16depay->info.channels, rtpL16depay->info.position, rtpL16depay->order->pos)) { goto reorder_failed; } gst_rtp_buffer_unmap (&rtp); return outbuf; /* ERRORS */ empty_packet: { GST_ELEMENT_WARNING (rtpL16depay, STREAM, DECODE, ("Empty Payload."), (NULL)); gst_rtp_buffer_unmap (&rtp); return NULL; } reorder_failed: { GST_ELEMENT_ERROR (rtpL16depay, STREAM, DECODE, ("Channel reordering failed."), (NULL)); gst_rtp_buffer_unmap (&rtp); return NULL; } }
static GstBuffer * create_rtp_buffer_with_timestamp (guint32 ssrc, guint8 payload_type, guint16 seqnum, guint32 timestamp) { GstRTPBuffer rtpbuf = GST_RTP_BUFFER_INIT; GstBuffer *buf = create_rtp_buffer (ssrc, payload_type, seqnum); gst_rtp_buffer_map (buf, GST_MAP_WRITE, &rtpbuf); gst_rtp_buffer_set_timestamp (&rtpbuf, timestamp); gst_rtp_buffer_unmap (&rtpbuf); return buf; }
static gboolean buffer_is_rtcp (GstBuffer * buffer) { GstRTPBuffer rtp_buffer = { NULL }; if (!gst_rtp_buffer_map (buffer, GST_MAP_READ, &rtp_buffer)) { return TRUE; } gst_rtp_buffer_unmap (&rtp_buffer); return FALSE; }
static GstPadProbeReturn rtpsession_sinkpad_probe2 (GstPad * pad, GstPadProbeInfo * info, gpointer user_data) { GstPadProbeReturn ret = GST_PAD_PROBE_OK; if (info->type == (GST_PAD_PROBE_TYPE_BUFFER | GST_PAD_PROBE_TYPE_PUSH)) { GstBuffer *buffer = GST_BUFFER (info->data); GstRTPBuffer rtp = GST_RTP_BUFFER_INIT; guint payload_type = 0; static gint i = 0; /* retrieve current ssrc for retransmission stream only */ gst_rtp_buffer_map (buffer, GST_MAP_READ, &rtp); payload_type = gst_rtp_buffer_get_payload_type (&rtp); if (payload_type == 99) { if (i < 3) rtx_ssrc_before = gst_rtp_buffer_get_ssrc (&rtp); else rtx_ssrc_after = gst_rtp_buffer_get_ssrc (&rtp); } else { /* ask to retransmit every packet */ GstEvent *event = gst_event_new_custom (GST_EVENT_CUSTOM_UPSTREAM, gst_structure_new ("GstRTPRetransmissionRequest", "seqnum", G_TYPE_UINT, gst_rtp_buffer_get_seq (&rtp), "ssrc", G_TYPE_UINT, gst_rtp_buffer_get_ssrc (&rtp), NULL)); gst_pad_push_event (pad, event); if (i < 3) ssrc_before = gst_rtp_buffer_get_ssrc (&rtp); else ssrc_after = gst_rtp_buffer_get_ssrc (&rtp); } gst_rtp_buffer_unmap (&rtp); /* feint a collision on recv_rtcp_sink pad of gstrtpsession * (note that after being marked as collied the rtpsession ignores * all non bye packets) */ if (i == 2) { GstBuffer *rtcp_buffer = create_rtcp_app (rtx_ssrc_before, 0); /* push collied packet on recv_rtcp_sink */ gst_pad_push (srcpad, rtcp_buffer); } ++i; } return ret; }
static GstBuffer * gst_rtp_opus_depay_process (GstRTPBaseDepayload * depayload, GstBuffer * buf) { GstBuffer *outbuf; GstRTPBuffer rtpbuf = { NULL, }; gst_rtp_buffer_map (buf, GST_MAP_READ, &rtpbuf); outbuf = gst_rtp_buffer_get_payload_buffer (&rtpbuf); gst_rtp_buffer_unmap (&rtpbuf); return outbuf; }
static void basic_check_cb (GstPad * pad, int i) { GstRTPBuffer rtpbuffer = GST_RTP_BUFFER_INIT; fail_unless (buffers && g_list_length (buffers) == 1); gst_rtp_buffer_map (buffers->data, GST_MAP_READ, &rtpbuffer); fail_unless_equals_int (66, gst_rtp_buffer_get_ssrc (&rtpbuffer)); fail_unless_equals_int64 (200 - 57 + 1000 + i, gst_rtp_buffer_get_timestamp (&rtpbuffer)); fail_unless_equals_int (100 + 1 + i, gst_rtp_buffer_get_seq (&rtpbuffer)); gst_rtp_buffer_unmap (&rtpbuffer); }
static GstBuffer * gst_rtp_g729_depay_process (GstRTPBaseDepayload * depayload, GstBuffer * buf) { GstRtpG729Depay *rtpg729depay; GstBuffer *outbuf = NULL; gint payload_len; gboolean marker; GstRTPBuffer rtp = { NULL }; rtpg729depay = GST_RTP_G729_DEPAY (depayload); gst_rtp_buffer_map (buf, GST_MAP_READ, &rtp); payload_len = gst_rtp_buffer_get_payload_len (&rtp); /* At least 2 bytes (CNG from G729 Annex B) */ if (payload_len < 2) { GST_ELEMENT_WARNING (rtpg729depay, STREAM, DECODE, (NULL), ("G729 RTP payload too small (%d)", payload_len)); goto bad_packet; } GST_LOG_OBJECT (rtpg729depay, "payload len %d", payload_len); if ((payload_len % 10) == 2) { GST_LOG_OBJECT (rtpg729depay, "G729 payload contains CNG frame"); } outbuf = gst_rtp_buffer_get_payload_buffer (&rtp); marker = gst_rtp_buffer_get_marker (&rtp); gst_rtp_buffer_unmap (&rtp); if (marker) { /* marker bit starts talkspurt */ GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_RESYNC); } GST_LOG_OBJECT (depayload, "pushing buffer of size %" G_GSIZE_FORMAT, gst_buffer_get_size (outbuf)); return outbuf; /* ERRORS */ bad_packet: { /* no fatal error */ return NULL; } }
static gboolean handle_buffer (GstRtpOnvifParse * self, GstBuffer * buf) { GstRTPBuffer rtp = GST_RTP_BUFFER_INIT; guint8 *data; guint16 bits; guint wordlen; guint8 flags; /* guint64 timestamp; guint8 cseq; */ if (!gst_rtp_buffer_map (buf, GST_MAP_READ, &rtp)) { GST_ELEMENT_ERROR (self, STREAM, FAILED, ("Failed to map RTP buffer"), (NULL)); return FALSE; } /* Check if the ONVIF RTP extension is present in the packet */ if (!gst_rtp_buffer_get_extension_data (&rtp, &bits, (gpointer) & data, &wordlen)) goto out; if (bits != EXTENSION_ID || wordlen != EXTENSION_SIZE) goto out; /* timestamp = GST_READ_UINT64_BE (data); TODO */ flags = GST_READ_UINT8 (data + 8); /* cseq = GST_READ_UINT8 (data + 9); TODO */ /* C */ if (flags & (1 << 7)) GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DELTA_UNIT); else GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT); /* E */ /* if (flags & (1 << 6)); TODO */ /* D */ if (flags & (1 << 5)) GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT); else GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT); out: gst_rtp_buffer_unmap (&rtp); return TRUE; }
static void compare_rtp_packets (GstBuffer * a, GstBuffer * b) { GstRTPBuffer rtp_a = GST_RTP_BUFFER_INIT; GstRTPBuffer rtp_b = GST_RTP_BUFFER_INIT; gst_rtp_buffer_map (a, GST_MAP_READ, &rtp_a); gst_rtp_buffer_map (b, GST_MAP_READ, &rtp_b); fail_unless_equals_int (gst_rtp_buffer_get_header_len (&rtp_a), gst_rtp_buffer_get_header_len (&rtp_b)); fail_unless_equals_int (gst_rtp_buffer_get_version (&rtp_a), gst_rtp_buffer_get_version (&rtp_b)); fail_unless_equals_int (gst_rtp_buffer_get_ssrc (&rtp_a), gst_rtp_buffer_get_ssrc (&rtp_b)); fail_unless_equals_int (gst_rtp_buffer_get_seq (&rtp_a), gst_rtp_buffer_get_seq (&rtp_b)); fail_unless_equals_int (gst_rtp_buffer_get_csrc_count (&rtp_a), gst_rtp_buffer_get_csrc_count (&rtp_b)); fail_unless_equals_int (gst_rtp_buffer_get_marker (&rtp_a), gst_rtp_buffer_get_marker (&rtp_b)); fail_unless_equals_int (gst_rtp_buffer_get_payload_type (&rtp_a), gst_rtp_buffer_get_payload_type (&rtp_b)); fail_unless_equals_int (gst_rtp_buffer_get_timestamp (&rtp_a), gst_rtp_buffer_get_timestamp (&rtp_b)); fail_unless_equals_int (gst_rtp_buffer_get_extension (&rtp_a), gst_rtp_buffer_get_extension (&rtp_b)); fail_unless_equals_int (gst_rtp_buffer_get_payload_len (&rtp_a), gst_rtp_buffer_get_payload_len (&rtp_b)); fail_unless_equals_int (memcmp (gst_rtp_buffer_get_payload (&rtp_a), gst_rtp_buffer_get_payload (&rtp_b), gst_rtp_buffer_get_payload_len (&rtp_a)), 0); gst_rtp_buffer_unmap (&rtp_a); gst_rtp_buffer_unmap (&rtp_b); }
static void lock_check_cb (GstPad * pad, int i) { GstBuffer *inbuf; if (i % 2) { fail_unless (buffers == NULL); } else { GstRTPBuffer rtpbuffer = GST_RTP_BUFFER_INIT; fail_unless (buffers && g_list_length (buffers) == 1); gst_rtp_buffer_map (buffers->data, GST_MAP_READ, &rtpbuffer); fail_unless_equals_int (66, gst_rtp_buffer_get_ssrc (&rtpbuffer)); fail_unless_equals_int64 (200 - 57 + 1000 + i, gst_rtp_buffer_get_timestamp (&rtpbuffer)); fail_unless_equals_int (100 + 1 + i, gst_rtp_buffer_get_seq (&rtpbuffer)); gst_rtp_buffer_unmap (&rtpbuffer); inbuf = gst_rtp_buffer_new_allocate (10, 0, 0); GST_BUFFER_PTS (inbuf) = i * 1000 + 500; GST_BUFFER_DURATION (inbuf) = 1000; gst_rtp_buffer_map (inbuf, GST_MAP_WRITE, &rtpbuffer); gst_rtp_buffer_set_version (&rtpbuffer, 2); gst_rtp_buffer_set_payload_type (&rtpbuffer, 98); gst_rtp_buffer_set_ssrc (&rtpbuffer, 44); gst_rtp_buffer_set_timestamp (&rtpbuffer, 200 + i); gst_rtp_buffer_set_seq (&rtpbuffer, 2000 + i); gst_rtp_buffer_unmap (&rtpbuffer); fail_unless (gst_pad_push (pad, inbuf) == GST_FLOW_OK); g_list_foreach (buffers, (GFunc) gst_buffer_unref, NULL); g_list_free (buffers); buffers = NULL; } }
static GstFlowReturn gst_scream_queue_sink_chain(GstPad *pad, GstObject *parent, GstBuffer *buffer) { GstScreamQueue *self = GST_SCREAM_QUEUE(parent); GstRTPBuffer rtp_buffer = GST_RTP_BUFFER_INIT; GstFlowReturn flow_ret = GST_FLOW_OK; GstScreamDataQueueRtpItem *rtp_item; if (GST_PAD_IS_FLUSHING(pad)) { flow_ret = GST_FLOW_FLUSHING; goto end; } if (!gst_rtp_buffer_map(buffer, GST_MAP_READ, &rtp_buffer)) { flow_ret = GST_FLOW_ERROR; goto end; } rtp_item = g_slice_new(GstScreamDataQueueRtpItem); ((GstDataQueueItem *)rtp_item)->object = GST_MINI_OBJECT(buffer); ((GstDataQueueItem *)rtp_item)->size = gst_buffer_get_size(buffer); ((GstDataQueueItem *)rtp_item)->visible = TRUE; ((GstDataQueueItem *)rtp_item)->duration = GST_BUFFER_DURATION(buffer); ((GstDataQueueItem *)rtp_item)->destroy = (GDestroyNotify) gst_scream_data_queue_rtp_item_free; ((GstScreamDataQueueItem *)rtp_item)->type = GST_SCREAM_DATA_QUEUE_ITEM_TYPE_RTP; ((GstScreamDataQueueItem *)rtp_item)->rtp_ssrc = gst_rtp_buffer_get_ssrc(&rtp_buffer); rtp_item->rtp_pt = gst_rtp_buffer_get_payload_type(&rtp_buffer); rtp_item->gst_ts = GST_BUFFER_PTS(buffer); rtp_item->rtp_seq = gst_rtp_buffer_get_seq(&rtp_buffer); rtp_item->rtp_ts = gst_rtp_buffer_get_timestamp(&rtp_buffer); rtp_item->rtp_marker = gst_rtp_buffer_get_marker(&rtp_buffer); rtp_item->rtp_payload_size = gst_rtp_buffer_get_payload_len(&rtp_buffer); rtp_item->enqueued_time = get_gst_time_us(self); gst_rtp_buffer_unmap(&rtp_buffer); if (self->pass_through) { rtp_item->adapted = FALSE; GST_LOG_OBJECT(self, "passing through: 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 *)rtp_item); goto end; } GST_LOG_OBJECT(self, "queuing: pt = %u, seq: %u, pass: %u", rtp_item->rtp_pt, rtp_item->rtp_seq, self->pass_through); g_async_queue_push(self->incoming_packets, (gpointer)rtp_item); end: return flow_ret; }