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
This commit is contained in:
Olivier Crête 2011-07-18 20:27:38 -04:00 committed by Mark Nauwelaerts
parent 216dc602c3
commit 118a7cc36a
2 changed files with 37 additions and 8 deletions

View file

@ -420,6 +420,7 @@ gst_rtp_h264_pay_setcaps (GstBaseRTPPayload * basepayload, GstCaps * caps)
const GValue *value; const GValue *value;
guint8 *data; guint8 *data;
guint size; guint size;
const gchar *alignment;
rtph264pay = GST_RTP_H264_PAY (basepayload); rtph264pay = GST_RTP_H264_PAY (basepayload);
@ -429,6 +430,12 @@ gst_rtp_h264_pay_setcaps (GstBaseRTPPayload * basepayload, GstCaps * caps)
* NALs */ * NALs */
gst_basertppayload_set_options (basepayload, "video", TRUE, "H264", 90000); 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 */ /* packetized AVC video has a codec_data */
if ((value = gst_structure_get_value (str, "codec_data"))) { if ((value = gst_structure_get_value (str, "codec_data"))) {
GstBuffer *buffer; GstBuffer *buffer;
@ -763,7 +770,7 @@ gst_rtp_h264_pay_decode_nal (GstRtpH264Pay * payloader,
static GstFlowReturn static GstFlowReturn
gst_rtp_h264_pay_payload_nal (GstBaseRTPPayload * basepayload, gst_rtp_h264_pay_payload_nal (GstBaseRTPPayload * basepayload,
const guint8 * data, guint size, GstClockTime timestamp, const guint8 * data, guint size, GstClockTime timestamp,
GstBuffer * buffer_orig); GstBuffer * buffer_orig, gboolean end_of_au);
static GstFlowReturn static GstFlowReturn
gst_rtp_h264_pay_send_sps_pps (GstBaseRTPPayload * basepayload, gst_rtp_h264_pay_send_sps_pps (GstBaseRTPPayload * basepayload,
@ -779,7 +786,7 @@ gst_rtp_h264_pay_send_sps_pps (GstBaseRTPPayload * basepayload,
/* resend SPS */ /* resend SPS */
ret = gst_rtp_h264_pay_payload_nal (basepayload, ret = gst_rtp_h264_pay_payload_nal (basepayload,
GST_BUFFER_DATA (sps_buf), GST_BUFFER_SIZE (sps_buf), timestamp, GST_BUFFER_DATA (sps_buf), GST_BUFFER_SIZE (sps_buf), timestamp,
sps_buf); sps_buf, FALSE);
/* Not critical here; but throw a warning */ /* Not critical here; but throw a warning */
if (ret != GST_FLOW_OK) if (ret != GST_FLOW_OK)
GST_WARNING ("Problem pushing SPS"); GST_WARNING ("Problem pushing SPS");
@ -791,7 +798,7 @@ gst_rtp_h264_pay_send_sps_pps (GstBaseRTPPayload * basepayload,
/* resend PPS */ /* resend PPS */
ret = gst_rtp_h264_pay_payload_nal (basepayload, ret = gst_rtp_h264_pay_payload_nal (basepayload,
GST_BUFFER_DATA (pps_buf), GST_BUFFER_SIZE (pps_buf), timestamp, GST_BUFFER_DATA (pps_buf), GST_BUFFER_SIZE (pps_buf), timestamp,
pps_buf); pps_buf, FALSE);
/* Not critical here; but throw a warning */ /* Not critical here; but throw a warning */
if (ret != GST_FLOW_OK) if (ret != GST_FLOW_OK)
GST_WARNING ("Problem pushing PPS"); GST_WARNING ("Problem pushing PPS");
@ -806,7 +813,7 @@ gst_rtp_h264_pay_send_sps_pps (GstBaseRTPPayload * basepayload,
static GstFlowReturn static GstFlowReturn
gst_rtp_h264_pay_payload_nal (GstBaseRTPPayload * basepayload, gst_rtp_h264_pay_payload_nal (GstBaseRTPPayload * basepayload,
const guint8 * data, guint size, GstClockTime timestamp, const guint8 * data, guint size, GstClockTime timestamp,
GstBuffer * buffer_orig) GstBuffer * buffer_orig, gboolean end_of_au)
{ {
GstRtpH264Pay *rtph264pay; GstRtpH264Pay *rtph264pay;
GstFlowReturn ret; GstFlowReturn ret;
@ -885,7 +892,7 @@ gst_rtp_h264_pay_payload_nal (GstBaseRTPPayload * basepayload,
} }
/* only set the marker bit on packets containing access units */ /* 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); gst_rtp_buffer_set_marker (outbuf, 1);
} }
@ -975,7 +982,7 @@ gst_rtp_h264_pay_payload_nal (GstBaseRTPPayload * basepayload,
end = 1; end = 1;
} }
if (IS_ACCESS_UNIT (nalType)) { if (IS_ACCESS_UNIT (nalType)) {
gst_rtp_buffer_set_marker (outbuf, end); gst_rtp_buffer_set_marker (outbuf, end && end_of_au);
} }
/* FU indicator */ /* FU indicator */
@ -1075,6 +1082,7 @@ gst_rtp_h264_pay_handle_buffer (GstBaseRTPPayload * basepayload,
while (size > nal_length_size) { while (size > nal_length_size) {
gint i; gint i;
gboolean end_of_au = FALSE;
nal_len = 0; nal_len = 0;
for (i = 0; i < nal_length_size; i++) { for (i = 0; i < nal_length_size; i++) {
@ -1093,9 +1101,16 @@ gst_rtp_h264_pay_handle_buffer (GstBaseRTPPayload * basepayload,
nal_len); 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 = ret =
gst_rtp_h264_pay_payload_nal (basepayload, data, nal_len, timestamp, gst_rtp_h264_pay_payload_nal (basepayload, data, nal_len, timestamp,
buffer); buffer, end_of_au);
if (ret != GST_FLOW_OK) if (ret != GST_FLOW_OK)
break; break;
@ -1197,6 +1212,7 @@ gst_rtp_h264_pay_handle_buffer (GstBaseRTPPayload * basepayload,
for (i = 0; i < nal_queue->len; i++) { for (i = 0; i < nal_queue->len; i++) {
guint size; guint size;
gboolean end_of_au = FALSE;
nal_len = g_array_index (nal_queue, guint, i); nal_len = g_array_index (nal_queue, guint, i);
/* skip start code */ /* skip start code */
@ -1212,10 +1228,22 @@ gst_rtp_h264_pay_handle_buffer (GstBaseRTPPayload * basepayload,
for (; size > 1 && data[size - 1] == 0x0; size--) for (; size > 1 && data[size - 1] == 0x0; size--)
/* skip */ ; /* 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 */ /* put the data in one or more RTP packets */
ret = ret =
gst_rtp_h264_pay_payload_nal (basepayload, data, size, timestamp, gst_rtp_h264_pay_payload_nal (basepayload, data, size, timestamp,
buffer); buffer, end_of_au);
if (ret != GST_FLOW_OK) { if (ret != GST_FLOW_OK) {
break; break;
} }

View file

@ -55,6 +55,7 @@ struct _GstRtpH264Pay
GList *sps, *pps; GList *sps, *pps;
gboolean packetized; gboolean packetized;
gboolean au_alignment;
guint nal_length_size; guint nal_length_size;
GArray *queue; GArray *queue;