static GstFlowReturn gst_rtp_mp2t_pay_handle_buffer (GstBaseRTPPayload * basepayload, GstBuffer * buffer) { GstRTPMP2TPay *rtpmp2tpay; guint size, avail, packet_len; GstClockTime timestamp, duration; GstFlowReturn ret; rtpmp2tpay = GST_RTP_MP2T_PAY (basepayload); size = GST_BUFFER_SIZE (buffer); timestamp = GST_BUFFER_TIMESTAMP (buffer); duration = GST_BUFFER_DURATION (buffer); ret = GST_FLOW_OK; avail = gst_adapter_available (rtpmp2tpay->adapter); /* Initialize new RTP payload */ if (avail == 0) { rtpmp2tpay->first_ts = timestamp; rtpmp2tpay->duration = duration; } /* get packet length of previous data and this new data, * payload length includes a 4 byte header */ packet_len = gst_rtp_buffer_calc_packet_len (4 + avail + size, 0, 0); /* if this buffer is going to overflow the packet, flush what we * have. */ if (gst_basertppayload_is_filled (basepayload, packet_len, rtpmp2tpay->duration + duration)) { ret = gst_rtp_mp2t_pay_flush (rtpmp2tpay); rtpmp2tpay->first_ts = timestamp; rtpmp2tpay->duration = duration; /* keep filling the payload */ } else { if (GST_CLOCK_TIME_IS_VALID (duration)) rtpmp2tpay->duration += duration; } /* copy buffer to adapter */ gst_adapter_push (rtpmp2tpay->adapter, buffer); return ret; }
static GstFlowReturn gst_rtp_mpv_pay_handle_buffer (GstBaseRTPPayload * basepayload, GstBuffer * buffer) { GstRTPMPVPay *rtpmpvpay; guint avail, packet_len; GstClockTime timestamp, duration; GstFlowReturn ret = GST_FLOW_OK; rtpmpvpay = GST_RTP_MPV_PAY (basepayload); timestamp = GST_BUFFER_TIMESTAMP (buffer); duration = GST_BUFFER_DURATION (buffer); avail = gst_adapter_available (rtpmpvpay->adapter); if (duration == -1) duration = 0; if (rtpmpvpay->first_ts == GST_CLOCK_TIME_NONE || avail == 0) rtpmpvpay->first_ts = timestamp; if (avail == 0) { rtpmpvpay->duration = duration; } else { rtpmpvpay->duration += duration; } gst_adapter_push (rtpmpvpay->adapter, buffer); avail = gst_adapter_available (rtpmpvpay->adapter); /* get packet length of previous data and this new data, * payload length includes a 4 byte MPEG video-specific header */ packet_len = gst_rtp_buffer_calc_packet_len (avail, 4, 0); GST_LOG_OBJECT (rtpmpvpay, "available %d, rtp packet length %d", avail, packet_len); if (gst_basertppayload_is_filled (basepayload, packet_len, rtpmpvpay->duration)) { ret = gst_rtp_mpv_pay_flush (rtpmpvpay); } else { rtpmpvpay->first_ts = timestamp; } return ret; }
static GstFlowReturn gst_rtp_mpa_pay_handle_buffer (GstBaseRTPPayload * basepayload, GstBuffer * buffer) { GstRtpMPAPay *rtpmpapay; GstFlowReturn ret; guint size, avail; guint packet_len; GstClockTime duration; rtpmpapay = GST_RTP_MPA_PAY (basepayload); size = GST_BUFFER_SIZE (buffer); duration = GST_BUFFER_DURATION (buffer); avail = gst_adapter_available (rtpmpapay->adapter); if (avail == 0) { rtpmpapay->first_ts = GST_BUFFER_TIMESTAMP (buffer); rtpmpapay->duration = 0; } /* get packet length of previous data and this new data, * payload length includes a 4 byte header */ packet_len = gst_rtp_buffer_calc_packet_len (4 + avail + size, 0, 0); /* if this buffer is going to overflow the packet, flush what we * have. */ if (gst_basertppayload_is_filled (basepayload, packet_len, rtpmpapay->duration + duration)) { ret = gst_rtp_mpa_pay_flush (rtpmpapay); rtpmpapay->first_ts = GST_BUFFER_TIMESTAMP (buffer); rtpmpapay->duration = 0; } else { ret = GST_FLOW_OK; } gst_adapter_push (rtpmpapay->adapter, buffer); rtpmpapay->duration += duration; return ret; }
static GstFlowReturn gst_rtp_mpv_pay_handle_buffer (GstBaseRTPPayload * basepayload, GstBuffer * buffer) { GstRTPMPVPay *rtpmpvpay; guint size, avail, packet_len; guint8 *data; GstClockTime timestamp, duration; GstFlowReturn ret; rtpmpvpay = GST_RTP_MPV_PAY (basepayload); size = GST_BUFFER_SIZE (buffer); data = GST_BUFFER_DATA (buffer); timestamp = GST_BUFFER_TIMESTAMP (buffer); duration = GST_BUFFER_DURATION (buffer); gst_adapter_push (rtpmpvpay->adapter, buffer); avail = gst_adapter_available (rtpmpvpay->adapter); /* Initialize new RTP payload */ if (avail == 0) { rtpmpvpay->first_ts = timestamp; rtpmpvpay->duration = duration; } /* get packet length of previous data and this new data, * payload length includes a 4 byte MPEG video-specific header */ packet_len = gst_rtp_buffer_calc_packet_len (4 + avail, 0, 0); if (gst_basertppayload_is_filled (basepayload, packet_len, rtpmpvpay->duration + duration)) { ret = gst_rtp_mpv_pay_flush (rtpmpvpay, timestamp, duration); } else { if (GST_CLOCK_TIME_IS_VALID (duration)) rtpmpvpay->duration += duration; ret = GST_FLOW_OK; } return ret; }
static GstFlowReturn gst_rtp_celt_pay_handle_buffer (GstBaseRTPPayload * basepayload, GstBuffer * buffer) { GstFlowReturn ret; GstRtpCELTPay *rtpceltpay; guint size, payload_len; guint8 *data; GstClockTime duration, packet_dur; guint i, ssize, packet_len; rtpceltpay = GST_RTP_CELT_PAY (basepayload); ret = GST_FLOW_OK; size = GST_BUFFER_SIZE (buffer); data = GST_BUFFER_DATA (buffer); switch (rtpceltpay->packet) { case 0: /* ident packet. We need to parse the headers to construct the RTP * properties. */ if (!gst_rtp_celt_pay_parse_ident (rtpceltpay, data, size)) goto parse_error; goto done; case 1: /* comment packet, we ignore it */ goto done; default: /* other packets go in the payload */ break; } duration = GST_BUFFER_DURATION (buffer); GST_DEBUG_OBJECT (rtpceltpay, "got buffer of duration %" GST_TIME_FORMAT ", size %u", GST_TIME_ARGS (duration), size); /* calculate the size of the size field and the payload */ ssize = 1; for (i = size; i > 0xff; i -= 0xff) ssize++; GST_DEBUG_OBJECT (rtpceltpay, "bytes for size %u", ssize); /* calculate the size and duration of the packet */ payload_len = ssize + size + rtpceltpay->bytes + rtpceltpay->sbytes; packet_dur = rtpceltpay->qduration + duration; packet_len = gst_rtp_buffer_calc_packet_len (payload_len, 0, 0); if (gst_basertppayload_is_filled (basepayload, packet_len, packet_dur)) { /* size or duration would overflow the packet, flush the queued data */ ret = gst_rtp_celt_pay_flush_queued (rtpceltpay); } /* queue the packet */ gst_rtp_celt_pay_add_queued (rtpceltpay, buffer, ssize, size, duration); done: rtpceltpay->packet++; return ret; /* ERRORS */ parse_error: { GST_ELEMENT_ERROR (rtpceltpay, STREAM, DECODE, (NULL), ("Error parsing first identification packet.")); return GST_FLOW_ERROR; } }
/* we expect buffers starting on startcodes. */ static GstFlowReturn gst_rtp_mp4v_pay_handle_buffer (GstBaseRTPPayload * basepayload, GstBuffer * buffer) { GstRtpMP4VPay *rtpmp4vpay; GstFlowReturn ret; guint size, avail; guint packet_len; guint8 *data; gboolean flush; gint strip; GstClockTime timestamp, duration; ret = GST_FLOW_OK; rtpmp4vpay = GST_RTP_MP4V_PAY (basepayload); size = GST_BUFFER_SIZE (buffer); data = GST_BUFFER_DATA (buffer); timestamp = GST_BUFFER_TIMESTAMP (buffer); duration = GST_BUFFER_DURATION (buffer); avail = gst_adapter_available (rtpmp4vpay->adapter); if (duration == -1) duration = 0; /* empty buffer, take timestamp */ if (avail == 0) { rtpmp4vpay->first_timestamp = timestamp; rtpmp4vpay->duration = 0; } /* depay incomming data and see if we need to start a new RTP * packet */ flush = gst_rtp_mp4v_pay_depay_data (rtpmp4vpay, data, size, &strip); if (strip) { /* strip off config if requested */ if (!rtpmp4vpay->send_config) { GstBuffer *subbuf; /* strip off header */ subbuf = gst_buffer_create_sub (buffer, strip, size - strip); GST_BUFFER_TIMESTAMP (subbuf) = timestamp; gst_buffer_unref (buffer); buffer = subbuf; size = GST_BUFFER_SIZE (buffer); data = GST_BUFFER_DATA (buffer); } } /* if we need to flush, do so now */ if (flush) { ret = gst_rtp_mp4v_pay_flush (rtpmp4vpay); rtpmp4vpay->first_timestamp = timestamp; rtpmp4vpay->duration = 0; avail = 0; } /* get packet length of data and see if we exceeded MTU. */ packet_len = gst_rtp_buffer_calc_packet_len (avail + size, 0, 0); if (gst_basertppayload_is_filled (basepayload, packet_len, rtpmp4vpay->duration + duration)) { ret = gst_rtp_mp4v_pay_flush (rtpmp4vpay); rtpmp4vpay->first_timestamp = timestamp; rtpmp4vpay->duration = 0; } /* push new data */ gst_adapter_push (rtpmp4vpay->adapter, buffer); rtpmp4vpay->duration += duration; return ret; }
static GstFlowReturn gst_rtp_g723_pay_handle_buffer (GstBaseRTPPayload * payload, GstBuffer * buf) { GstFlowReturn ret = GST_FLOW_OK; guint8 *data; guint size; guint8 HDR; GstRTPG723Pay *pay; GstClockTime packet_dur, timestamp; guint payload_len, packet_len; pay = GST_RTP_G723_PAY (payload); size = GST_BUFFER_SIZE (buf); data = GST_BUFFER_DATA (buf); timestamp = GST_BUFFER_TIMESTAMP (buf); if (GST_BUFFER_IS_DISCONT (buf)) { /* flush everything on discont */ gst_adapter_clear (pay->adapter); pay->timestamp = GST_CLOCK_TIME_NONE; pay->duration = 0; pay->discont = TRUE; } /* should be one of these sizes */ if (size != 4 && size != 20 && size != 24) goto invalid_size; /* check size by looking at the header bits */ HDR = data[0] & 0x3; if (size_tab[HDR] != size) goto wrong_size; /* calculate packet size and duration */ payload_len = gst_adapter_available (pay->adapter) + size; packet_dur = pay->duration + G723_FRAME_DURATION; packet_len = gst_rtp_buffer_calc_packet_len (payload_len, 0, 0); if (gst_basertppayload_is_filled (payload, packet_len, packet_dur)) { /* size or duration would overflow the packet, flush the queued data */ ret = gst_rtp_g723_pay_flush (pay); } /* update timestamp, we keep the timestamp for the first packet in the adapter * but are able to calculate it from next packets. */ if (timestamp != GST_CLOCK_TIME_NONE && pay->timestamp == GST_CLOCK_TIME_NONE) { if (timestamp > pay->duration) pay->timestamp = timestamp - pay->duration; else pay->timestamp = 0; } /* add packet to the queue */ gst_adapter_push (pay->adapter, buf); pay->duration = packet_dur; /* check if we can flush now */ if (pay->duration >= payload->min_ptime) { ret = gst_rtp_g723_pay_flush (pay); } return ret; /* WARNINGS */ invalid_size: { GST_ELEMENT_WARNING (pay, STREAM, WRONG_TYPE, ("Invalid input buffer size"), ("Input size should be 4, 20 or 24, got %u", size)); gst_buffer_unref (buf); return GST_FLOW_OK; } wrong_size: { GST_ELEMENT_WARNING (pay, STREAM, WRONG_TYPE, ("Wrong input buffer size"), ("Expected input buffer size %u but got %u", size_tab[HDR], size)); gst_buffer_unref (buf); return GST_FLOW_OK; } }