From fdf95fecbd61aeb869fcbcf229bd0fe6609c486d Mon Sep 17 00:00:00 2001 From: =?utf8?q?Tim-Philipp=20M=C3=BCller?= Date: Mon, 16 Jun 2014 13:38:47 +0100 Subject: [PATCH] rtpvrawpay: use buffer lists Collect buffers to send out in buffer lists instead of pushing out single buffers one at a time. For HD video each frame might easily add up to a couple of thousand packets, multiply that by the frame rate and that's a lot of push() and sendmsg() calls per second. A good reason to push out buffers as early as possible is latency, so we don't accumulate the whole frame in a single buffer list, but instead push it out in a few chunks, which is hopefully a reasonable compromise. --- gst/rtp/gstrtpvrawpay.c | 35 +++++++++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/gst/rtp/gstrtpvrawpay.c b/gst/rtp/gstrtpvrawpay.c index cade178..4242c0d 100644 --- a/gst/rtp/gstrtpvrawpay.c +++ b/gst/rtp/gstrtpvrawpay.c @@ -239,15 +239,18 @@ gst_rtp_vraw_pay_handle_buffer (GstRTPBasePayload * payload, GstBuffer * buffer) { GstRtpVRawPay *rtpvrawpay; GstFlowReturn ret = GST_FLOW_OK; + guint lines_delay; /* after how many packed lines we push out a buffer list */ + guint last_line; /* last pack line number we pushed out a buffer list */ guint line, offset; guint8 *p0, *yp, *up, *vp; guint ystride, uvstride; guint pgroup; guint mtu; guint width, height; - gint field; + gint field, fields; GstVideoFrame frame; gint interlaced; + GstBufferList *list; GstRTPBuffer rtp = { NULL, }; rtpvrawpay = GST_RTP_VRAW_PAY (payload); @@ -275,17 +278,25 @@ gst_rtp_vraw_pay_handle_buffer (GstRTPBasePayload * payload, GstBuffer * buffer) interlaced = GST_VIDEO_INFO_IS_INTERLACED (&rtpvrawpay->vinfo); + /* after how many packed lines we push out a buffer list */ + lines_delay = GST_ROUND_UP_4 (height / 10); + + fields = 1 + interlaced; + /* start with line 0, offset 0 */ - for (field = 0; field < 1 + interlaced; field++) { + for (field = 0; field < fields; field++) { line = field; offset = 0; + last_line = 0; + + list = gst_buffer_list_new (); /* write all lines */ while (line < height) { - guint left; + guint left, pack_line; GstBuffer *out; guint8 *outdata, *headers; - gboolean next_line; + gboolean next_line, complete = FALSE; guint length, cont, pixels; /* get the max allowed payload length size, we try to fill the complete MTU */ @@ -496,6 +507,7 @@ gst_rtp_vraw_pay_handle_buffer (GstRTPBasePayload * payload, GstBuffer * buffer) if (line >= height) { GST_LOG_OBJECT (rtpvrawpay, "field/frame complete, set marker"); gst_rtp_buffer_set_marker (&rtp, TRUE); + complete = TRUE; } gst_rtp_buffer_unmap (&rtp); if (left > 0) { @@ -503,8 +515,19 @@ gst_rtp_vraw_pay_handle_buffer (GstRTPBasePayload * payload, GstBuffer * buffer) gst_buffer_resize (out, 0, gst_buffer_get_size (out) - left); } - /* push buffer */ - ret = gst_rtp_base_payload_push (payload, out); + gst_buffer_list_add (list, out); + + pack_line = (line - field) / fields; + if (complete || (pack_line > last_line && pack_line % lines_delay == 0)) { + /* push buffers */ + GST_LOG_OBJECT (rtpvrawpay, "pushing list of %u buffers up to pack " + "line %u", gst_buffer_list_length (list), pack_line); + ret = gst_rtp_base_payload_push_list (payload, list); + list = NULL; + if (!complete) + list = gst_buffer_list_new (); + last_line = pack_line; + } } } -- 2.7.4