static void gst_rtp_mp2t_pay_init (GstRTPMP2TPay * rtpmp2tpay) { GST_RTP_BASE_PAYLOAD (rtpmp2tpay)->clock_rate = 90000; GST_RTP_BASE_PAYLOAD_PT (rtpmp2tpay) = GST_RTP_PAYLOAD_MP2T; rtpmp2tpay->adapter = gst_adapter_new (); }
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 GstFlowReturn gst_rtp_asf_pay_handle_packet (GstRtpAsfPay * rtpasfpay, GstBuffer * buffer) { GstRTPBasePayload *rtppay; GstAsfPacketInfo *packetinfo; guint8 flags; guint8 *data; guint32 packet_util_size; guint32 packet_offset; guint32 size_left; GstFlowReturn ret = GST_FLOW_OK; rtppay = GST_RTP_BASE_PAYLOAD (rtpasfpay); packetinfo = &rtpasfpay->packetinfo; if (!gst_asf_parse_packet (buffer, packetinfo, TRUE, rtpasfpay->asfinfo.packet_size)) { GST_ERROR_OBJECT (rtpasfpay, "Error while parsing asf packet"); gst_buffer_unref (buffer); return GST_FLOW_ERROR; } if (packetinfo->packet_size == 0) packetinfo->packet_size = rtpasfpay->asfinfo.packet_size; GST_LOG_OBJECT (rtpasfpay, "Packet size: %" G_GUINT32_FORMAT ", padding: %" G_GUINT32_FORMAT, packetinfo->packet_size, packetinfo->padding); /* update padding field to 0 */ if (packetinfo->padding > 0) { GstAsfPacketInfo info; /* find padding field offset */ guint offset = packetinfo->err_cor_len + 2 + gst_asf_get_var_size_field_len (packetinfo->packet_field_type) + gst_asf_get_var_size_field_len (packetinfo->seq_field_type); buffer = gst_buffer_make_writable (buffer); switch (packetinfo->padd_field_type) { case ASF_FIELD_TYPE_DWORD: gst_buffer_memset (buffer, offset, 0, 4); break; case ASF_FIELD_TYPE_WORD: gst_buffer_memset (buffer, offset, 0, 2); break; case ASF_FIELD_TYPE_BYTE: gst_buffer_memset (buffer, offset, 0, 1); break; case ASF_FIELD_TYPE_NONE: default: break; } gst_asf_parse_packet (buffer, &info, FALSE, 0); } if (packetinfo->padding != 0) packet_util_size = rtpasfpay->asfinfo.packet_size - packetinfo->padding; else packet_util_size = packetinfo->packet_size; packet_offset = 0; while (packet_util_size > 0) { /* Even if we don't fill completely an output buffer we * push it when we add an fragment. Because it seems that * it is not possible to determine where a asf packet * fragment ends inside a rtp packet payload. * This flag tells us to push the packet. */ gboolean force_push = FALSE; GstRTPBuffer rtp = GST_RTP_BUFFER_INIT; /* we have no output buffer pending, create one */ if (rtpasfpay->current == NULL) { GST_LOG_OBJECT (rtpasfpay, "Creating new output buffer"); rtpasfpay->current = gst_rtp_buffer_new_allocate_len (GST_RTP_BASE_PAYLOAD_MTU (rtpasfpay), 0, 0); rtpasfpay->cur_off = 0; rtpasfpay->has_ts = FALSE; rtpasfpay->marker = FALSE; } gst_rtp_buffer_map (rtpasfpay->current, GST_MAP_READWRITE, &rtp); data = gst_rtp_buffer_get_payload (&rtp); data += rtpasfpay->cur_off; size_left = gst_rtp_buffer_get_payload_len (&rtp) - rtpasfpay->cur_off; GST_DEBUG_OBJECT (rtpasfpay, "Input buffer bytes consumed: %" G_GUINT32_FORMAT "/%" G_GSIZE_FORMAT, packet_offset, gst_buffer_get_size (buffer)); GST_DEBUG_OBJECT (rtpasfpay, "Output rtpbuffer status"); GST_DEBUG_OBJECT (rtpasfpay, "Current offset: %" G_GUINT32_FORMAT, rtpasfpay->cur_off); GST_DEBUG_OBJECT (rtpasfpay, "Size left: %" G_GUINT32_FORMAT, size_left); GST_DEBUG_OBJECT (rtpasfpay, "Has ts: %s", rtpasfpay->has_ts ? "yes" : "no"); if (rtpasfpay->has_ts) { GST_DEBUG_OBJECT (rtpasfpay, "Ts: %" G_GUINT32_FORMAT, rtpasfpay->ts); } flags = 0; if (packetinfo->has_keyframe) { flags = flags | 0x80; } flags = flags | 0x20; /* Relative timestamp is present */ if (!rtpasfpay->has_ts) { /* this is the first asf packet, its send time is the * rtp packet timestamp */ rtpasfpay->has_ts = TRUE; rtpasfpay->ts = packetinfo->send_time; } if (size_left >= packet_util_size + 8) { /* enough space for the rest of the packet */ if (packet_offset == 0) { flags = flags | 0x40; GST_WRITE_UINT24_BE (data + 1, packet_util_size); } else { GST_WRITE_UINT24_BE (data + 1, packet_offset); force_push = TRUE; } data[0] = flags; GST_WRITE_UINT32_BE (data + 4, (gint32) (packetinfo->send_time) - (gint32) rtpasfpay->ts); gst_buffer_extract (buffer, packet_offset, data + 8, packet_util_size); /* updating status variables */ rtpasfpay->cur_off += 8 + packet_util_size; size_left -= packet_util_size + 8; packet_offset += packet_util_size; packet_util_size = 0; rtpasfpay->marker = TRUE; } else { /* fragment packet */ data[0] = flags; GST_WRITE_UINT24_BE (data + 1, packet_offset); GST_WRITE_UINT32_BE (data + 4, (gint32) (packetinfo->send_time) - (gint32) rtpasfpay->ts); gst_buffer_extract (buffer, packet_offset, data + 8, size_left - 8); /* updating status variables */ rtpasfpay->cur_off += size_left; packet_offset += size_left - 8; packet_util_size -= size_left - 8; size_left = 0; force_push = TRUE; } /* there is not enough room for any more buffers */ if (force_push || size_left <= 8) { gst_rtp_buffer_set_ssrc (&rtp, rtppay->current_ssrc); gst_rtp_buffer_set_marker (&rtp, rtpasfpay->marker); gst_rtp_buffer_set_payload_type (&rtp, GST_RTP_BASE_PAYLOAD_PT (rtppay)); gst_rtp_buffer_set_seq (&rtp, rtppay->seqnum + 1); gst_rtp_buffer_set_timestamp (&rtp, packetinfo->send_time); gst_rtp_buffer_unmap (&rtp); /* trim remaining bytes not used */ if (size_left != 0) { gst_buffer_set_size (rtpasfpay->current, gst_buffer_get_size (rtpasfpay->current) - size_left); } GST_BUFFER_TIMESTAMP (rtpasfpay->current) = GST_BUFFER_TIMESTAMP (buffer); rtppay->seqnum++; rtppay->timestamp = packetinfo->send_time; GST_DEBUG_OBJECT (rtpasfpay, "Pushing rtp buffer"); ret = gst_rtp_base_payload_push (rtppay, rtpasfpay->current); rtpasfpay->current = NULL; if (ret != GST_FLOW_OK) { gst_buffer_unref (buffer); return ret; } } } gst_buffer_unref (buffer); return ret; }
/** * gst_rtp_base_payload_set_outcaps: * @payload: a #GstRTPBasePayload * @fieldname: the first field name or %NULL * @...: field values * * Configure the output caps with the optional parameters. * * Variable arguments should be in the form field name, field type * (as a GType), value(s). The last variable argument should be NULL. * * Returns: %TRUE if the caps could be set. */ gboolean gst_rtp_base_payload_set_outcaps (GstRTPBasePayload * payload, const gchar * fieldname, ...) { GstCaps *srccaps, *peercaps; gboolean res; /* fill in the defaults, their properties cannot be negotiated. */ srccaps = gst_caps_new_simple ("application/x-rtp", "media", G_TYPE_STRING, payload->media, "clock-rate", G_TYPE_INT, payload->clock_rate, "encoding-name", G_TYPE_STRING, payload->encoding_name, NULL); GST_DEBUG_OBJECT (payload, "defaults: %" GST_PTR_FORMAT, srccaps); if (fieldname) { va_list varargs; /* override with custom properties */ va_start (varargs, fieldname); gst_caps_set_simple_valist (srccaps, fieldname, varargs); va_end (varargs); GST_DEBUG_OBJECT (payload, "custom added: %" GST_PTR_FORMAT, srccaps); } payload->priv->caps_max_ptime = DEFAULT_MAX_PTIME; payload->ptime = 0; /* the peer caps can override some of the defaults */ peercaps = gst_pad_peer_query_caps (payload->srcpad, srccaps); if (peercaps == NULL) { /* no peer caps, just add the other properties */ gst_caps_set_simple (srccaps, "payload", G_TYPE_INT, GST_RTP_BASE_PAYLOAD_PT (payload), "ssrc", G_TYPE_UINT, payload->current_ssrc, "timestamp-offset", G_TYPE_UINT, payload->ts_base, "seqnum-offset", G_TYPE_UINT, payload->seqnum_base, NULL); GST_DEBUG_OBJECT (payload, "no peer caps: %" GST_PTR_FORMAT, srccaps); } else { GstCaps *temp; GstStructure *s, *d; const GValue *value; gint pt; guint max_ptime, ptime; /* peer provides caps we can use to fixate. They are already intersected * with our srccaps, just make them writable */ temp = gst_caps_make_writable (peercaps); gst_caps_unref (srccaps); if (gst_caps_is_empty (temp)) { gst_caps_unref (temp); return FALSE; } /* now fixate, start by taking the first caps */ temp = gst_caps_truncate (temp); /* get first structure */ s = gst_caps_get_structure (temp, 0); if (gst_structure_get_uint (s, "maxptime", &max_ptime)) payload->priv->caps_max_ptime = max_ptime * GST_MSECOND; if (gst_structure_get_uint (s, "ptime", &ptime)) payload->ptime = ptime * GST_MSECOND; if (gst_structure_get_int (s, "payload", &pt)) { /* use peer pt */ GST_RTP_BASE_PAYLOAD_PT (payload) = pt; GST_LOG_OBJECT (payload, "using peer pt %d", pt); } else { if (gst_structure_has_field (s, "payload")) { /* can only fixate if there is a field */ gst_structure_fixate_field_nearest_int (s, "payload", GST_RTP_BASE_PAYLOAD_PT (payload)); gst_structure_get_int (s, "payload", &pt); GST_LOG_OBJECT (payload, "using peer pt %d", pt); } else { /* no pt field, use the internal pt */ pt = GST_RTP_BASE_PAYLOAD_PT (payload); gst_structure_set (s, "payload", G_TYPE_INT, pt, NULL); GST_LOG_OBJECT (payload, "using internal pt %d", pt); } } if (gst_structure_has_field_typed (s, "ssrc", G_TYPE_UINT)) { value = gst_structure_get_value (s, "ssrc"); payload->current_ssrc = g_value_get_uint (value); GST_LOG_OBJECT (payload, "using peer ssrc %08x", payload->current_ssrc); } else { /* FIXME, fixate_nearest_uint would be even better */ gst_structure_set (s, "ssrc", G_TYPE_UINT, payload->current_ssrc, NULL); GST_LOG_OBJECT (payload, "using internal ssrc %08x", payload->current_ssrc); } if (gst_structure_has_field_typed (s, "timestamp-offset", G_TYPE_UINT)) { value = gst_structure_get_value (s, "timestamp-offset"); payload->ts_base = g_value_get_uint (value); GST_LOG_OBJECT (payload, "using peer timestamp-offset %u", payload->ts_base); } else { /* FIXME, fixate_nearest_uint would be even better */ gst_structure_set (s, "timestamp-offset", G_TYPE_UINT, payload->ts_base, NULL); GST_LOG_OBJECT (payload, "using internal timestamp-offset %u", payload->ts_base); } if (gst_structure_has_field_typed (s, "seqnum-offset", G_TYPE_UINT)) { value = gst_structure_get_value (s, "seqnum-offset"); payload->seqnum_base = g_value_get_uint (value); GST_LOG_OBJECT (payload, "using peer seqnum-offset %u", payload->seqnum_base); } else { /* FIXME, fixate_nearest_uint would be even better */ gst_structure_set (s, "seqnum-offset", G_TYPE_UINT, payload->seqnum_base, NULL); GST_LOG_OBJECT (payload, "using internal seqnum-offset %u", payload->seqnum_base); } /* make the target caps by copying over all the fixed caps, removing the * unfixed caps. */ srccaps = gst_caps_new_empty_simple (gst_structure_get_name (s)); d = gst_caps_get_structure (srccaps, 0); gst_structure_foreach (s, (GstStructureForeachFunc) copy_fixed, d); gst_caps_unref (temp); GST_DEBUG_OBJECT (payload, "with peer caps: %" GST_PTR_FORMAT, srccaps); } update_max_ptime (payload); res = gst_pad_set_caps (GST_RTP_BASE_PAYLOAD_SRCPAD (payload), srccaps); gst_caps_unref (srccaps); return res; }
static void gst_rtp_gsm_pay_init (GstRTPGSMPay * rtpgsmpay) { GST_RTP_BASE_PAYLOAD (rtpgsmpay)->clock_rate = 8000; GST_RTP_BASE_PAYLOAD_PT (rtpgsmpay) = GST_RTP_PAYLOAD_GSM; }