static GstFlowReturn gst_rtp_mp2t_pay_handle_buffer (GstRTPBasePayload * basepayload, GstBuffer * buffer) { GstRTPMP2TPay *rtpmp2tpay; guint size, avail, packet_len; GstClockTime timestamp, duration; GstFlowReturn ret; rtpmp2tpay = GST_RTP_MP2T_PAY (basepayload); size = gst_buffer_get_size (buffer); timestamp = GST_BUFFER_PTS (buffer); duration = GST_BUFFER_DURATION (buffer); again: 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 */ packet_len = gst_rtp_buffer_calc_packet_len (avail + size, 0, 0); /* if this buffer is going to overflow the packet, flush what we have, * or if upstream is handing us several packets, to keep latency low */ if (!size || gst_rtp_base_payload_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 */ if (buffer) { gst_adapter_push (rtpmp2tpay->adapter, buffer); buffer = NULL; } if (size >= (188 * 2)) { size = 0; goto again; } return ret; }
static GstFlowReturn gst_rtp_mpv_pay_handle_buffer (GstRTPBasePayload * 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); if (GST_BUFFER_IS_DISCONT (buffer)) { GST_DEBUG_OBJECT (rtpmpvpay, "DISCONT"); gst_rtp_mpv_pay_reset (rtpmpvpay); } 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_rtp_base_payload_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 (GstRTPBasePayload * basepayload, GstBuffer * buffer) { GstRtpMPAPay *rtpmpapay; GstFlowReturn ret; guint size, avail; guint packet_len; GstClockTime duration, timestamp; rtpmpapay = GST_RTP_MPA_PAY (basepayload); size = gst_buffer_get_size (buffer); duration = GST_BUFFER_DURATION (buffer); timestamp = GST_BUFFER_PTS (buffer); if (GST_BUFFER_IS_DISCONT (buffer)) { GST_DEBUG_OBJECT (rtpmpapay, "DISCONT"); gst_rtp_mpa_pay_reset (rtpmpapay); } avail = gst_adapter_available (rtpmpapay->adapter); /* 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_rtp_base_payload_is_filled (basepayload, packet_len, rtpmpapay->duration + duration)) { ret = gst_rtp_mpa_pay_flush (rtpmpapay); avail = 0; } else { ret = GST_FLOW_OK; } if (avail == 0) { GST_DEBUG_OBJECT (rtpmpapay, "first packet, save timestamp %" GST_TIME_FORMAT, GST_TIME_ARGS (timestamp)); rtpmpapay->first_ts = timestamp; rtpmpapay->duration = 0; } gst_adapter_push (rtpmpapay->adapter, buffer); rtpmpapay->duration = duration; return ret; }
static GstFlowReturn gst_rtp_celt_pay_handle_buffer (GstRTPBasePayload * basepayload, GstBuffer * buffer) { GstFlowReturn ret; GstRtpCELTPay *rtpceltpay; gsize payload_len; GstMapInfo map; GstClockTime duration, packet_dur; guint i, ssize, packet_len; rtpceltpay = GST_RTP_CELT_PAY (basepayload); ret = GST_FLOW_OK; gst_buffer_map (buffer, &map, GST_MAP_READ); 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, map.data, map.size)) goto parse_error; goto cleanup; case 1: /* comment packet, we ignore it */ goto cleanup; default: /* other packets go in the payload */ break; } gst_buffer_unmap (buffer, &map); duration = GST_BUFFER_DURATION (buffer); GST_LOG_OBJECT (rtpceltpay, "got buffer of duration %" GST_TIME_FORMAT ", size %" G_GSIZE_FORMAT, GST_TIME_ARGS (duration), map.size); /* calculate the size of the size field and the payload */ ssize = 1; for (i = map.size; i > 0xff; i -= 0xff) ssize++; GST_DEBUG_OBJECT (rtpceltpay, "bytes for size %u", ssize); /* calculate what the new size and duration would be of the packet */ payload_len = ssize + map.size + rtpceltpay->bytes + rtpceltpay->sbytes; if (rtpceltpay->qduration != -1 && duration != -1) packet_dur = rtpceltpay->qduration + duration; else packet_dur = 0; packet_len = gst_rtp_buffer_calc_packet_len (payload_len, 0, 0); if (gst_rtp_base_payload_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, map.size, duration); done: rtpceltpay->packet++; return ret; /* ERRORS */ cleanup: { gst_buffer_unmap (buffer, &map); goto done; } parse_error: { GST_ELEMENT_ERROR (rtpceltpay, STREAM, DECODE, (NULL), ("Error parsing first identification packet.")); gst_buffer_unmap (buffer, &map); return GST_FLOW_ERROR; } }
static GstFlowReturn gst_rtp_g723_pay_handle_buffer (GstRTPBasePayload * payload, GstBuffer * buf) { GstFlowReturn ret = GST_FLOW_OK; GstMapInfo map; guint8 HDR; GstRTPG723Pay *pay; GstClockTime packet_dur, timestamp; guint payload_len, packet_len; pay = GST_RTP_G723_PAY (payload); gst_buffer_map (buf, &map, GST_MAP_READ); timestamp = GST_BUFFER_PTS (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 (map.size != 4 && map.size != 20 && map.size != 24) goto invalid_size; /* check size by looking at the header bits */ HDR = map.data[0] & 0x3; if (size_tab[HDR] != map.size) goto wrong_size; /* calculate packet size and duration */ payload_len = gst_adapter_available (pay->adapter) + map.size; packet_dur = pay->duration + G723_FRAME_DURATION; packet_len = gst_rtp_buffer_calc_packet_len (payload_len, 0, 0); if (gst_rtp_base_payload_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; } gst_buffer_unmap (buf, &map); /* 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 %" G_GSIZE_FORMAT, map.size)); gst_buffer_unmap (buf, &map); 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 %" G_GSIZE_FORMAT, size_tab[HDR], map.size)); gst_buffer_unmap (buf, &map); gst_buffer_unref (buf); return GST_FLOW_OK; } }
static GstFlowReturn gst_rtp_ac3_pay_handle_buffer (GstRTPBasePayload * basepayload, GstBuffer * buffer) { GstRtpAC3Pay *rtpac3pay; GstFlowReturn ret; gsize avail, left, NF; GstMapInfo map; guint8 *p; guint packet_len; GstClockTime duration, timestamp; rtpac3pay = GST_RTP_AC3_PAY (basepayload); gst_buffer_map (buffer, &map, GST_MAP_READ); duration = GST_BUFFER_DURATION (buffer); timestamp = GST_BUFFER_PTS (buffer); if (GST_BUFFER_IS_DISCONT (buffer)) { GST_DEBUG_OBJECT (rtpac3pay, "DISCONT"); gst_rtp_ac3_pay_reset (rtpac3pay); } /* count the amount of incomming packets */ NF = 0; left = map.size; p = map.data; while (TRUE) { guint bsid, fscod, frmsizecod, frame_size; if (left < 6) break; if (p[0] != 0x0b || p[1] != 0x77) break; bsid = p[5] >> 3; if (bsid > 8) break; frmsizecod = p[4] & 0x3f; fscod = p[4] >> 6; GST_DEBUG_OBJECT (rtpac3pay, "fscod %u, %u", fscod, frmsizecod); if (fscod >= 3 || frmsizecod >= 38) break; frame_size = frmsizecod_tbl[frmsizecod].frm_size[fscod] * 2; if (frame_size > left) break; NF++; GST_DEBUG_OBJECT (rtpac3pay, "found frame %" G_GSIZE_FORMAT " of size %u", NF, frame_size); p += frame_size; left -= frame_size; } gst_buffer_unmap (buffer, &map); if (NF == 0) goto no_frames; avail = gst_adapter_available (rtpac3pay->adapter); /* 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 (2 + avail + map.size, 0, 0); /* if this buffer is going to overflow the packet, flush what we * have. */ if (gst_rtp_base_payload_is_filled (basepayload, packet_len, rtpac3pay->duration + duration)) { ret = gst_rtp_ac3_pay_flush (rtpac3pay); avail = 0; } else { ret = GST_FLOW_OK; } if (avail == 0) { GST_DEBUG_OBJECT (rtpac3pay, "first packet, save timestamp %" GST_TIME_FORMAT, GST_TIME_ARGS (timestamp)); rtpac3pay->first_ts = timestamp; rtpac3pay->duration = 0; rtpac3pay->NF = 0; } gst_adapter_push (rtpac3pay->adapter, buffer); rtpac3pay->duration += duration; rtpac3pay->NF += NF; return ret; /* ERRORS */ no_frames: { GST_WARNING_OBJECT (rtpac3pay, "no valid AC3 frames found"); return GST_FLOW_OK; } }