diff --git a/gst/rtp/gstrtpmp2tpay.c b/gst/rtp/gstrtpmp2tpay.c index 84c60ab836..bb79f87b94 100644 --- a/gst/rtp/gstrtpmp2tpay.c +++ b/gst/rtp/gstrtpmp2tpay.c @@ -117,35 +117,56 @@ gst_rtp_mp2t_pay_setcaps (GstRTPBasePayload * payload, GstCaps * caps) static GstFlowReturn gst_rtp_mp2t_pay_flush (GstRTPMP2TPay * rtpmp2tpay) { - guint avail; - guint8 *payload; - GstFlowReturn ret; + guint avail, mtu; + GstFlowReturn ret = GST_FLOW_OK; GstBuffer *outbuf; - GstRTPBuffer rtp = { NULL }; avail = gst_adapter_available (rtpmp2tpay->adapter); - if (avail == 0) - return GST_FLOW_OK; - outbuf = gst_rtp_buffer_new_allocate (avail, 0, 0); - /* get payload */ - gst_rtp_buffer_map (outbuf, GST_MAP_WRITE, &rtp); - payload = gst_rtp_buffer_get_payload (&rtp); + mtu = GST_RTP_BASE_PAYLOAD_MTU (rtpmp2tpay); - /* copy stuff from adapter to payload */ - gst_adapter_copy (rtpmp2tpay->adapter, payload, 0, avail); - gst_rtp_buffer_unmap (&rtp); + while (avail > 0 && (ret == GST_FLOW_OK)) { + guint towrite; + guint8 *payload; + guint payload_len; + guint packet_len; + GstRTPBuffer rtp = { NULL }; - GST_BUFFER_TIMESTAMP (outbuf) = rtpmp2tpay->first_ts; - GST_BUFFER_DURATION (outbuf) = rtpmp2tpay->duration; + /* this will be the total length of the packet */ + packet_len = gst_rtp_buffer_calc_packet_len (avail, 0, 0); - GST_DEBUG_OBJECT (rtpmp2tpay, "pushing buffer of size %" G_GSIZE_FORMAT, - gst_buffer_get_size (outbuf)); + /* fill one MTU or all available bytes */ + towrite = MIN (packet_len, mtu); - ret = gst_rtp_base_payload_push (GST_RTP_BASE_PAYLOAD (rtpmp2tpay), outbuf); + /* this is the payload length */ + payload_len = gst_rtp_buffer_calc_payload_len (towrite, 0, 0); + payload_len -= payload_len % 188; - /* flush the adapter content */ - gst_adapter_flush (rtpmp2tpay->adapter, avail); + /* need whole packets */ + if (!payload_len) + break; + + /* create buffer to hold the payload */ + outbuf = gst_rtp_buffer_new_allocate (payload_len, 0, 0); + + /* get payload */ + gst_rtp_buffer_map (outbuf, GST_MAP_WRITE, &rtp); + payload = gst_rtp_buffer_get_payload (&rtp); + + /* copy stuff from adapter to payload */ + gst_adapter_copy (rtpmp2tpay->adapter, payload, 0, payload_len); + gst_rtp_buffer_unmap (&rtp); + gst_adapter_flush (rtpmp2tpay->adapter, payload_len); + avail -= payload_len; + + GST_BUFFER_TIMESTAMP (outbuf) = rtpmp2tpay->first_ts; + GST_BUFFER_DURATION (outbuf) = rtpmp2tpay->duration; + + GST_DEBUG_OBJECT (rtpmp2tpay, "pushing buffer of size %d", + gst_buffer_get_size (outbuf)); + + ret = gst_rtp_base_payload_push (GST_RTP_BASE_PAYLOAD (rtpmp2tpay), outbuf); + } return ret; } @@ -165,6 +186,7 @@ gst_rtp_mp2t_pay_handle_buffer (GstRTPBasePayload * basepayload, timestamp = GST_BUFFER_TIMESTAMP (buffer); duration = GST_BUFFER_DURATION (buffer); +again: ret = GST_FLOW_OK; avail = gst_adapter_available (rtpmp2tpay->adapter); @@ -174,13 +196,12 @@ gst_rtp_mp2t_pay_handle_buffer (GstRTPBasePayload * basepayload, 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); + /* 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. */ - if (gst_rtp_base_payload_is_filled (basepayload, + /* 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; @@ -193,7 +214,15 @@ gst_rtp_mp2t_pay_handle_buffer (GstRTPBasePayload * basepayload, } /* copy buffer to adapter */ - gst_adapter_push (rtpmp2tpay->adapter, buffer); + if (buffer) { + gst_adapter_push (rtpmp2tpay->adapter, buffer); + buffer = NULL; + } + + if (size >= (188 * 2)) { + size = 0; + goto again; + } return ret;