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;
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;
}

View file

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