From 118a7cc36a0fb6b289927f199c78441a165fbae3 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Olivier=20Cr=C3=AAte?= Date: Mon, 18 Jul 2011 20:27:38 -0400 Subject: [PATCH] rtph264pay: Only set the marker bit on the last NALU of a multi-NALU access unit An access unit could contain multiple NAL units, in that case, only the last RTP packet of the last NALU should have its marker bit set. https://bugzilla.gnome.org/show_bug.cgi?id=654850 --- gst/rtp/gstrtph264pay.c | 44 ++++++++++++++++++++++++++++++++++++-------- gst/rtp/gstrtph264pay.h | 1 + 2 files changed, 37 insertions(+), 8 deletions(-) diff --git a/gst/rtp/gstrtph264pay.c b/gst/rtp/gstrtph264pay.c index 5f574a4..738e938 100644 --- a/gst/rtp/gstrtph264pay.c +++ b/gst/rtp/gstrtph264pay.c @@ -420,6 +420,7 @@ gst_rtp_h264_pay_setcaps (GstBaseRTPPayload * basepayload, GstCaps * caps) const GValue *value; guint8 *data; guint size; + const gchar *alignment; rtph264pay = GST_RTP_H264_PAY (basepayload); @@ -429,6 +430,12 @@ gst_rtp_h264_pay_setcaps (GstBaseRTPPayload * basepayload, GstCaps * caps) * NALs */ gst_basertppayload_set_options (basepayload, "video", TRUE, "H264", 90000); + alignment = gst_structure_get_string (str, "alignment"); + if (alignment && !strcmp (alignment, "au")) + rtph264pay->au_alignment = TRUE; + else + rtph264pay->au_alignment = FALSE; + /* packetized AVC video has a codec_data */ if ((value = gst_structure_get_value (str, "codec_data"))) { GstBuffer *buffer; @@ -763,7 +770,7 @@ gst_rtp_h264_pay_decode_nal (GstRtpH264Pay * payloader, static GstFlowReturn gst_rtp_h264_pay_payload_nal (GstBaseRTPPayload * basepayload, const guint8 * data, guint size, GstClockTime timestamp, - GstBuffer * buffer_orig); + GstBuffer * buffer_orig, gboolean end_of_au); static GstFlowReturn gst_rtp_h264_pay_send_sps_pps (GstBaseRTPPayload * basepayload, @@ -779,7 +786,7 @@ gst_rtp_h264_pay_send_sps_pps (GstBaseRTPPayload * basepayload, /* resend SPS */ ret = gst_rtp_h264_pay_payload_nal (basepayload, GST_BUFFER_DATA (sps_buf), GST_BUFFER_SIZE (sps_buf), timestamp, - sps_buf); + sps_buf, FALSE); /* Not critical here; but throw a warning */ if (ret != GST_FLOW_OK) GST_WARNING ("Problem pushing SPS"); @@ -791,7 +798,7 @@ gst_rtp_h264_pay_send_sps_pps (GstBaseRTPPayload * basepayload, /* resend PPS */ ret = gst_rtp_h264_pay_payload_nal (basepayload, GST_BUFFER_DATA (pps_buf), GST_BUFFER_SIZE (pps_buf), timestamp, - pps_buf); + pps_buf, FALSE); /* Not critical here; but throw a warning */ if (ret != GST_FLOW_OK) GST_WARNING ("Problem pushing PPS"); @@ -806,7 +813,7 @@ gst_rtp_h264_pay_send_sps_pps (GstBaseRTPPayload * basepayload, static GstFlowReturn gst_rtp_h264_pay_payload_nal (GstBaseRTPPayload * basepayload, const guint8 * data, guint size, GstClockTime timestamp, - GstBuffer * buffer_orig) + GstBuffer * buffer_orig, gboolean end_of_au) { GstRtpH264Pay *rtph264pay; GstFlowReturn ret; @@ -885,7 +892,7 @@ gst_rtp_h264_pay_payload_nal (GstBaseRTPPayload * basepayload, } /* only set the marker bit on packets containing access units */ - if (IS_ACCESS_UNIT (nalType)) { + if (IS_ACCESS_UNIT (nalType) && end_of_au) { gst_rtp_buffer_set_marker (outbuf, 1); } @@ -975,7 +982,7 @@ gst_rtp_h264_pay_payload_nal (GstBaseRTPPayload * basepayload, end = 1; } if (IS_ACCESS_UNIT (nalType)) { - gst_rtp_buffer_set_marker (outbuf, end); + gst_rtp_buffer_set_marker (outbuf, end && end_of_au); } /* FU indicator */ @@ -1075,6 +1082,7 @@ gst_rtp_h264_pay_handle_buffer (GstBaseRTPPayload * basepayload, while (size > nal_length_size) { gint i; + gboolean end_of_au = FALSE; nal_len = 0; for (i = 0; i < nal_length_size; i++) { @@ -1093,9 +1101,16 @@ gst_rtp_h264_pay_handle_buffer (GstBaseRTPPayload * basepayload, nal_len); } + /* If we're at the end of the buffer, then we're at the end of the + * access unit + */ + if (rtph264pay->au_alignment && size - nal_len <= nal_length_size) { + end_of_au = TRUE; + } + ret = gst_rtp_h264_pay_payload_nal (basepayload, data, nal_len, timestamp, - buffer); + buffer, end_of_au); if (ret != GST_FLOW_OK) break; @@ -1197,6 +1212,7 @@ gst_rtp_h264_pay_handle_buffer (GstBaseRTPPayload * basepayload, for (i = 0; i < nal_queue->len; i++) { guint size; + gboolean end_of_au = FALSE; nal_len = g_array_index (nal_queue, guint, i); /* skip start code */ @@ -1212,10 +1228,22 @@ gst_rtp_h264_pay_handle_buffer (GstBaseRTPPayload * basepayload, for (; size > 1 && data[size - 1] == 0x0; size--) /* skip */ ; + /* If it's the last nal unit we have in non-bytestream mode, we can + * assume it's the end of an access-unit + * + * FIXME: We need to wait until the next packet or EOS to + * actually payload the NAL so we can know if the current NAL is + * the last one of an access unit or not if we are in bytestream mode + */ + if (rtph264pay->au_alignment && + rtph264pay->scan_mode != GST_H264_SCAN_MODE_BYTESTREAM && + i == nal_queue->len - 1) + end_of_au = TRUE; + /* put the data in one or more RTP packets */ ret = gst_rtp_h264_pay_payload_nal (basepayload, data, size, timestamp, - buffer); + buffer, end_of_au); if (ret != GST_FLOW_OK) { break; } diff --git a/gst/rtp/gstrtph264pay.h b/gst/rtp/gstrtph264pay.h index 19e5aaa..6303e30 100644 --- a/gst/rtp/gstrtph264pay.h +++ b/gst/rtp/gstrtph264pay.h @@ -55,6 +55,7 @@ struct _GstRtpH264Pay GList *sps, *pps; gboolean packetized; + gboolean au_alignment; guint nal_length_size; GArray *queue; -- 2.7.4