rtph265pay: Fix handling of config-interval

Insert VPS/SPS/PPS before the first NAL unit containing an I-frame in an
access unit only. If an access unit consists of several such NAL units
(tiles) VPS/SPS/PPS should only be inserted before the first of them so
that parameters are only updated between frames.

Do not insert VPS/SPS/PPS before P-frames when config-interval is -1.

https://bugzilla.gnome.org/show_bug.cgi?id=775817
This commit is contained in:
Jonas Holmberg 2016-12-08 15:59:33 +01:00 committed by Sebastian Dröge
parent c08a0493ff
commit 494246f75c

View file

@ -808,7 +808,7 @@ gst_rtp_h265_pay_decode_nal (GstRtpH265Pay * payloader,
static GstFlowReturn static GstFlowReturn
gst_rtp_h265_pay_payload_nal (GstRTPBasePayload * basepayload, gst_rtp_h265_pay_payload_nal (GstRTPBasePayload * basepayload,
GstBuffer * paybuf, GstClockTime dts, GstClockTime pts, gboolean end_of_au); GPtrArray * paybufs, GstClockTime dts, GstClockTime pts);
static GstFlowReturn static GstFlowReturn
gst_rtp_h265_pay_send_vps_sps_pps (GstRTPBasePayload * basepayload, gst_rtp_h265_pay_send_vps_sps_pps (GstRTPBasePayload * basepayload,
@ -817,48 +817,38 @@ gst_rtp_h265_pay_send_vps_sps_pps (GstRTPBasePayload * basepayload,
GstFlowReturn ret = GST_FLOW_OK; GstFlowReturn ret = GST_FLOW_OK;
gboolean sent_all_vps_sps_pps = TRUE; gboolean sent_all_vps_sps_pps = TRUE;
guint i; guint i;
GPtrArray *bufs;
bufs = g_ptr_array_new ();
for (i = 0; i < rtph265pay->vps->len; i++) { for (i = 0; i < rtph265pay->vps->len; i++) {
GstBuffer *vps_buf = GstBuffer *vps_buf =
GST_BUFFER_CAST (g_ptr_array_index (rtph265pay->vps, i)); GST_BUFFER_CAST (g_ptr_array_index (rtph265pay->vps, i));
GST_DEBUG_OBJECT (rtph265pay, "inserting VPS in the stream"); GST_DEBUG_OBJECT (rtph265pay, "inserting VPS in the stream");
/* resend VPS */ g_ptr_array_add (bufs, gst_buffer_ref (vps_buf));
ret = gst_rtp_h265_pay_payload_nal (basepayload, gst_buffer_ref (vps_buf),
dts, pts, FALSE);
/* Not critical here; but throw a warning */
if (ret != GST_FLOW_OK) {
sent_all_vps_sps_pps = FALSE;
GST_WARNING_OBJECT (basepayload, "Problem pushing VPS");
}
} }
for (i = 0; i < rtph265pay->sps->len; i++) { for (i = 0; i < rtph265pay->sps->len; i++) {
GstBuffer *sps_buf = GstBuffer *sps_buf =
GST_BUFFER_CAST (g_ptr_array_index (rtph265pay->sps, i)); GST_BUFFER_CAST (g_ptr_array_index (rtph265pay->sps, i));
GST_DEBUG_OBJECT (rtph265pay, "inserting SPS in the stream"); GST_DEBUG_OBJECT (rtph265pay, "inserting SPS in the stream");
/* resend SPS */ g_ptr_array_add (bufs, gst_buffer_ref (sps_buf));
ret = gst_rtp_h265_pay_payload_nal (basepayload, gst_buffer_ref (sps_buf),
dts, pts, FALSE);
/* Not critical here; but throw a warning */
if (ret != GST_FLOW_OK) {
sent_all_vps_sps_pps = FALSE;
GST_WARNING_OBJECT (basepayload, "Problem pushing SPS");
}
} }
for (i = 0; i < rtph265pay->pps->len; i++) { for (i = 0; i < rtph265pay->pps->len; i++) {
GstBuffer *pps_buf = GstBuffer *pps_buf =
GST_BUFFER_CAST (g_ptr_array_index (rtph265pay->pps, i)); GST_BUFFER_CAST (g_ptr_array_index (rtph265pay->pps, i));
GST_DEBUG_OBJECT (rtph265pay, "inserting PPS in the stream"); GST_DEBUG_OBJECT (rtph265pay, "inserting PPS in the stream");
/* resend PPS */ g_ptr_array_add (bufs, gst_buffer_ref (pps_buf));
ret = gst_rtp_h265_pay_payload_nal (basepayload, gst_buffer_ref (pps_buf), }
dts, pts, FALSE);
/* Not critical here; but throw a warning */ ret = gst_rtp_h265_pay_payload_nal (basepayload, bufs, dts, pts);
if (ret != GST_FLOW_OK) { if (ret != GST_FLOW_OK) {
sent_all_vps_sps_pps = FALSE; /* not critical but warn */
GST_WARNING ("Problem pushing PPS"); GST_WARNING_OBJECT (basepayload, "failed pushing VPS/SPS/PPS");
}
sent_all_vps_sps_pps = FALSE;
} }
if (pts != -1 && sent_all_vps_sps_pps) if (pts != -1 && sent_all_vps_sps_pps)
@ -869,207 +859,239 @@ gst_rtp_h265_pay_send_vps_sps_pps (GstRTPBasePayload * basepayload,
static GstFlowReturn static GstFlowReturn
gst_rtp_h265_pay_payload_nal (GstRTPBasePayload * basepayload, gst_rtp_h265_pay_payload_nal (GstRTPBasePayload * basepayload,
GstBuffer * paybuf, GstClockTime dts, GstClockTime pts, gboolean end_of_au) GPtrArray * paybufs, GstClockTime dts, GstClockTime pts)
{ {
GstRtpH265Pay *rtph265pay; GstRtpH265Pay *rtph265pay;
guint mtu;
GstFlowReturn ret; GstFlowReturn ret;
guint8 nalHeader[2]; gint i;
guint8 nalType; gboolean sent_ps;
guint packet_len, payload_len, mtu;
GstBuffer *outbuf;
guint8 *payload;
GstBufferList *list = NULL;
gboolean send_vps_sps_pps;
GstRTPBuffer rtp = { NULL };
guint size = gst_buffer_get_size (paybuf);
rtph265pay = GST_RTP_H265_PAY (basepayload); rtph265pay = GST_RTP_H265_PAY (basepayload);
mtu = GST_RTP_BASE_PAYLOAD_MTU (rtph265pay); mtu = GST_RTP_BASE_PAYLOAD_MTU (rtph265pay);
gst_buffer_extract (paybuf, 0, nalHeader, 2);
nalType = (nalHeader[0] >> 1) & 0x3f;
GST_DEBUG_OBJECT (rtph265pay, "Processing Buffer with NAL TYPE=%d", nalType);
/* should set src caps before pushing stuff, /* should set src caps before pushing stuff,
* and if we did not see enough VPS/SPS/PPS, that may not be the case */ * and if we did not see enough VPS/SPS/PPS, that may not be the case */
if (G_UNLIKELY (!gst_pad_has_current_caps (GST_RTP_BASE_PAYLOAD_SRCPAD if (G_UNLIKELY (!gst_pad_has_current_caps (GST_RTP_BASE_PAYLOAD_SRCPAD
(basepayload)))) (basepayload))))
gst_rtp_h265_pay_set_vps_sps_pps (basepayload); gst_rtp_h265_pay_set_vps_sps_pps (basepayload);
send_vps_sps_pps = FALSE; ret = GST_FLOW_OK;
sent_ps = FALSE;
for (i = 0; i < paybufs->len; i++) {
guint8 nalHeader[2];
guint8 nalType;
guint packet_len, payload_len;
GstBuffer *paybuf;
GstBuffer *outbuf;
guint8 *payload;
GstBufferList *outlist = NULL;
gboolean send_ps;
GstRTPBuffer rtp = { NULL };
guint size;
/* check if we need to emit an VPS/SPS/PPS now */ paybuf = g_ptr_array_index (paybufs, i);
if ((nalType == GST_H265_NAL_SLICE_TRAIL_N)
|| (nalType == GST_H265_NAL_SLICE_TRAIL_R)
|| (nalType == GST_H265_NAL_SLICE_TSA_N)
|| (nalType == GST_H265_NAL_SLICE_TSA_R)
|| (nalType == GST_H265_NAL_SLICE_STSA_N)
|| (nalType == GST_H265_NAL_SLICE_STSA_R)
|| (nalType == GST_H265_NAL_SLICE_RASL_N)
|| (nalType == GST_H265_NAL_SLICE_RASL_R)
|| (nalType == GST_H265_NAL_SLICE_BLA_W_LP)
|| (nalType == GST_H265_NAL_SLICE_BLA_W_RADL)
|| (nalType == GST_H265_NAL_SLICE_BLA_N_LP)
|| (nalType == GST_H265_NAL_SLICE_IDR_W_RADL)
|| (nalType == GST_H265_NAL_SLICE_IDR_N_LP)
|| (nalType == GST_H265_NAL_SLICE_CRA_NUT)) {
if (rtph265pay->vps_sps_pps_interval > 0) {
if (rtph265pay->last_vps_sps_pps != -1) {
guint64 diff;
GST_LOG_OBJECT (rtph265pay,
"now %" GST_TIME_FORMAT ", last VPS/SPS/PPS %" GST_TIME_FORMAT,
GST_TIME_ARGS (pts), GST_TIME_ARGS (rtph265pay->last_vps_sps_pps));
/* calculate diff between last SPS/PPS in milliseconds */
if (pts > rtph265pay->last_vps_sps_pps)
diff = pts - rtph265pay->last_vps_sps_pps;
else
diff = 0;
GST_DEBUG_OBJECT (rtph265pay,
"interval since last VPS/SPS/PPS %" GST_TIME_FORMAT,
GST_TIME_ARGS (diff));
/* bigger than interval, queue SPS/PPS */
if (GST_TIME_AS_SECONDS (diff) >= rtph265pay->vps_sps_pps_interval) {
GST_DEBUG_OBJECT (rtph265pay, "time to send VPS/SPS/PPS");
send_vps_sps_pps = TRUE;
}
} else {
/* no known previous SPS/PPS time, send now */
GST_DEBUG_OBJECT (rtph265pay, "no previous VPS/SPS/PPS time, send now");
send_vps_sps_pps = TRUE;
}
} else if (rtph265pay->vps_sps_pps_interval == -1) {
GST_DEBUG_OBJECT (rtph265pay,
"sending VPS/SPS/PPS before current IDR frame");
/* send VPS/SPS/PPS before every IDR frame */
send_vps_sps_pps = TRUE;
}
}
if (send_vps_sps_pps || rtph265pay->send_vps_sps_pps) {
/* we need to send SPS/PPS now first. FIXME, don't use the pts for
* checking when we need to send SPS/PPS but convert to running_time first. */
rtph265pay->send_vps_sps_pps = FALSE;
ret = gst_rtp_h265_pay_send_vps_sps_pps (basepayload, rtph265pay, dts, pts);
if (ret != GST_FLOW_OK) { if (ret != GST_FLOW_OK) {
/* unref buffers that will not be payloaded after a flow error */
gst_buffer_unref (paybuf); gst_buffer_unref (paybuf);
return ret; continue;
}
}
packet_len = gst_rtp_buffer_calc_packet_len (size, 0, 0);
if (packet_len < mtu) {
GST_DEBUG_OBJECT (rtph265pay,
"NAL Unit fit in one packet datasize=%d mtu=%d", size, mtu);
/* will fit in one packet */
/* use buffer lists
* create buffer without payload containing only the RTP header
* (memory block at index 0) */
outbuf = gst_rtp_buffer_new_allocate (0, 0, 0);
gst_rtp_buffer_map (outbuf, GST_MAP_WRITE, &rtp);
/* only set the marker bit on packets containing access units */
if (IS_ACCESS_UNIT (nalType) && end_of_au) {
gst_rtp_buffer_set_marker (&rtp, 1);
} }
/* timestamp the outbuffer */ size = gst_buffer_get_size (paybuf);
GST_BUFFER_PTS (outbuf) = pts; gst_buffer_extract (paybuf, 0, nalHeader, 2);
GST_BUFFER_DTS (outbuf) = dts; nalType = (nalHeader[0] >> 1) & 0x3f;
/* insert payload memory block */ GST_DEBUG_OBJECT (rtph265pay, "Processing Buffer with NAL TYPE=%d",
gst_rtp_copy_meta (GST_ELEMENT_CAST (rtph265pay), outbuf, paybuf, nalType);
g_quark_from_static_string (GST_META_TAG_VIDEO_STR));
outbuf = gst_buffer_append (outbuf, paybuf);
list = gst_buffer_list_new (); send_ps = FALSE;
/* add the buffer to the buffer list */ /* check if we need to emit an VPS/SPS/PPS now */
gst_buffer_list_add (list, outbuf); if ((nalType == GST_H265_NAL_SLICE_TRAIL_N)
|| (nalType == GST_H265_NAL_SLICE_TRAIL_R)
|| (nalType == GST_H265_NAL_SLICE_TSA_N)
|| (nalType == GST_H265_NAL_SLICE_TSA_R)
|| (nalType == GST_H265_NAL_SLICE_STSA_N)
|| (nalType == GST_H265_NAL_SLICE_STSA_R)
|| (nalType == GST_H265_NAL_SLICE_RASL_N)
|| (nalType == GST_H265_NAL_SLICE_RASL_R)
|| (nalType == GST_H265_NAL_SLICE_BLA_W_LP)
|| (nalType == GST_H265_NAL_SLICE_BLA_W_RADL)
|| (nalType == GST_H265_NAL_SLICE_BLA_N_LP)
|| (nalType == GST_H265_NAL_SLICE_IDR_W_RADL)
|| (nalType == GST_H265_NAL_SLICE_IDR_N_LP)
|| (nalType == GST_H265_NAL_SLICE_CRA_NUT)) {
if (rtph265pay->vps_sps_pps_interval > 0) {
if (rtph265pay->last_vps_sps_pps != -1) {
guint64 diff;
gst_rtp_buffer_unmap (&rtp); GST_LOG_OBJECT (rtph265pay,
"now %" GST_TIME_FORMAT ", last VPS/SPS/PPS %" GST_TIME_FORMAT,
GST_TIME_ARGS (pts),
GST_TIME_ARGS (rtph265pay->last_vps_sps_pps));
/* push the list to the next element in the pipe */ /* calculate diff between last SPS/PPS in milliseconds */
ret = gst_rtp_base_payload_push_list (basepayload, list); if (pts > rtph265pay->last_vps_sps_pps)
} else { diff = pts - rtph265pay->last_vps_sps_pps;
/* fragmentation Units */ else
guint limitedSize; diff = 0;
int ii = 0, start = 1, end = 0, pos = 0;
GST_DEBUG_OBJECT (basepayload, GST_DEBUG_OBJECT (rtph265pay,
"NAL Unit DOES NOT fit in one packet datasize=%d mtu=%d", size, mtu); "interval since last VPS/SPS/PPS %" GST_TIME_FORMAT,
GST_TIME_ARGS (diff));
pos += 2; /* bigger than interval, queue SPS/PPS */
size -= 2; if (GST_TIME_AS_SECONDS (diff) >= rtph265pay->vps_sps_pps_interval) {
GST_DEBUG_OBJECT (rtph265pay, "time to send VPS/SPS/PPS");
send_ps = TRUE;
}
} else {
/* no known previous SPS/PPS time, send now */
GST_DEBUG_OBJECT (rtph265pay,
"no previous VPS/SPS/PPS time, send now");
send_ps = TRUE;
}
} else if (rtph265pay->vps_sps_pps_interval == -1
&& (nalType == GST_H265_NAL_SLICE_IDR_W_RADL
|| nalType == GST_H265_NAL_SLICE_IDR_N_LP)) {
/* send VPS/SPS/PPS before every IDR frame */
send_ps = TRUE;
}
}
GST_DEBUG_OBJECT (basepayload, "Using FU fragmentation for data size=%d", if (!sent_ps && (send_ps || rtph265pay->send_vps_sps_pps)) {
size); /* we need to send SPS/PPS now first. FIXME, don't use the pts for
* checking when we need to send SPS/PPS but convert to running_time
* first */
rtph265pay->send_vps_sps_pps = FALSE;
sent_ps = TRUE;
GST_DEBUG_OBJECT (rtph265pay, "sending VPS/SPS/PPS before current frame");
ret =
gst_rtp_h265_pay_send_vps_sps_pps (basepayload, rtph265pay, dts, pts);
if (ret != GST_FLOW_OK) {
gst_buffer_unref (paybuf);
continue;
}
}
/* We keep 3 bytes for PayloadHdr and FU Header */ packet_len = gst_rtp_buffer_calc_packet_len (size, 0, 0);
payload_len = gst_rtp_buffer_calc_payload_len (mtu - 3, 0, 0);
list = gst_buffer_list_new (); if (packet_len < mtu) {
GST_DEBUG_OBJECT (rtph265pay,
while (end == 0) { "NAL Unit fit in one packet datasize=%d mtu=%d", size, mtu);
limitedSize = size < payload_len ? size : payload_len; /* will fit in one packet */
GST_DEBUG_OBJECT (basepayload,
"Inside FU fragmentation limitedSize=%d iteration=%d", limitedSize,
ii);
/* use buffer lists /* use buffer lists
* create buffer without payload containing only the RTP header * create buffer without payload containing only the RTP header
* (memory block at index 0), and with space for PayloadHdr and FU header */ * (memory block at index 0) */
outbuf = gst_rtp_buffer_new_allocate (3, 0, 0); outbuf = gst_rtp_buffer_new_allocate (0, 0, 0);
gst_rtp_buffer_map (outbuf, GST_MAP_WRITE, &rtp); gst_rtp_buffer_map (outbuf, GST_MAP_WRITE, &rtp);
GST_BUFFER_DTS (outbuf) = dts; /* only set the marker bit on packets containing access units */
if (i == paybufs->len - 1
&& rtph265pay->alignment == GST_H265_ALIGNMENT_AU
&& IS_ACCESS_UNIT (nalType)) {
gst_rtp_buffer_set_marker (&rtp, 1);
}
/* timestamp the outbuffer */
GST_BUFFER_PTS (outbuf) = pts; GST_BUFFER_PTS (outbuf) = pts;
payload = gst_rtp_buffer_get_payload (&rtp); GST_BUFFER_DTS (outbuf) = dts;
if (limitedSize == size) {
GST_DEBUG_OBJECT (basepayload, "end size=%d iteration=%d", size, ii);
end = 1;
}
/* PayloadHdr (type = 49) */
payload[0] = (nalHeader[0] & 0x81) | (49 << 1);
payload[1] = nalHeader[1];
/* set the marker bit on the last packet of an access unit */
if (IS_ACCESS_UNIT (nalType)) {
gst_rtp_buffer_set_marker (&rtp, end && end_of_au);
}
/* FU Header */
payload[2] = (start << 7) | (end << 6) | (nalType & 0x3f);
gst_rtp_buffer_unmap (&rtp);
/* insert payload memory block */ /* insert payload memory block */
gst_rtp_copy_meta (GST_ELEMENT_CAST (rtph265pay), outbuf, paybuf, gst_rtp_copy_meta (GST_ELEMENT_CAST (rtph265pay), outbuf, paybuf,
g_quark_from_static_string (GST_META_TAG_VIDEO_STR)); g_quark_from_static_string (GST_META_TAG_VIDEO_STR));
gst_buffer_copy_into (outbuf, paybuf, GST_BUFFER_COPY_MEMORY, pos, outbuf = gst_buffer_append (outbuf, paybuf);
limitedSize);
outlist = gst_buffer_list_new ();
/* add the buffer to the buffer list */ /* add the buffer to the buffer list */
gst_buffer_list_add (list, outbuf); gst_buffer_list_add (outlist, outbuf);
size -= limitedSize; gst_rtp_buffer_unmap (&rtp);
pos += limitedSize;
ii++; /* push the list to the next element in the pipe */
start = 0; ret = gst_rtp_base_payload_push_list (basepayload, outlist);
} else {
/* fragmentation Units */
guint limitedSize;
int ii = 0, start = 1, end = 0, pos = 0;
GST_DEBUG_OBJECT (basepayload,
"NAL Unit DOES NOT fit in one packet datasize=%d mtu=%d", size, mtu);
pos += 2;
size -= 2;
GST_DEBUG_OBJECT (basepayload, "Using FU fragmentation for data size=%d",
size);
/* We keep 3 bytes for PayloadHdr and FU Header */
payload_len = gst_rtp_buffer_calc_payload_len (mtu - 3, 0, 0);
outlist = gst_buffer_list_new ();
while (end == 0) {
limitedSize = size < payload_len ? size : payload_len;
GST_DEBUG_OBJECT (basepayload,
"Inside FU fragmentation limitedSize=%d iteration=%d", limitedSize,
ii);
/* use buffer lists
* create buffer without payload containing only the RTP header
* (memory block at index 0), and with space for PayloadHdr and FU header */
outbuf = gst_rtp_buffer_new_allocate (3, 0, 0);
gst_rtp_buffer_map (outbuf, GST_MAP_WRITE, &rtp);
GST_BUFFER_DTS (outbuf) = dts;
GST_BUFFER_PTS (outbuf) = pts;
payload = gst_rtp_buffer_get_payload (&rtp);
if (limitedSize == size) {
GST_DEBUG_OBJECT (basepayload, "end size=%d iteration=%d", size, ii);
end = 1;
}
/* PayloadHdr (type = 49) */
payload[0] = (nalHeader[0] & 0x81) | (49 << 1);
payload[1] = nalHeader[1];
/* set the marker bit on the last packet of an access unit */
if (IS_ACCESS_UNIT (nalType)) {
gst_rtp_buffer_set_marker (&rtp,
end && i == paybufs->len - 1
&& rtph265pay->alignment == GST_H265_ALIGNMENT_AU);
}
/* FU Header */
payload[2] = (start << 7) | (end << 6) | (nalType & 0x3f);
gst_rtp_buffer_unmap (&rtp);
/* insert payload memory block */
gst_rtp_copy_meta (GST_ELEMENT_CAST (rtph265pay), outbuf, paybuf,
g_quark_from_static_string (GST_META_TAG_VIDEO_STR));
gst_buffer_copy_into (outbuf, paybuf, GST_BUFFER_COPY_MEMORY, pos,
limitedSize);
/* add the buffer to the buffer list */
gst_buffer_list_add (outlist, outbuf);
size -= limitedSize;
pos += limitedSize;
ii++;
start = 0;
}
ret = gst_rtp_base_payload_push_list (basepayload, outlist);
gst_buffer_unref (paybuf);
} }
ret = gst_rtp_base_payload_push_list (basepayload, list);
gst_buffer_unref (paybuf);
} }
g_ptr_array_free (paybufs, TRUE);
return ret; return ret;
} }
@ -1136,12 +1158,13 @@ gst_rtp_h265_pay_handle_buffer (GstRTPBasePayload * basepayload,
if (hevc) { if (hevc) {
guint nal_length_size; guint nal_length_size;
gsize offset = 0; gsize offset = 0;
GPtrArray *paybufs;
paybufs = g_ptr_array_new ();
nal_length_size = rtph265pay->nal_length_size; nal_length_size = rtph265pay->nal_length_size;
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++) {
@ -1161,30 +1184,19 @@ gst_rtp_h265_pay_handle_buffer (GstRTPBasePayload * 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 (rtph265pay->alignment == GST_H265_ALIGNMENT_AU
&& size - nal_len <= nal_length_size) {
end_of_au = TRUE;
}
paybuf = gst_buffer_copy_region (buffer, GST_BUFFER_COPY_ALL, offset, paybuf = gst_buffer_copy_region (buffer, GST_BUFFER_COPY_ALL, offset,
nal_len); nal_len);
g_ptr_array_add (paybufs, paybuf);
ret =
gst_rtp_h265_pay_payload_nal (basepayload, paybuf, dts, pts,
end_of_au);
if (ret != GST_FLOW_OK)
break;
data += nal_len; data += nal_len;
offset += nal_len; offset += nal_len;
size -= nal_len; size -= nal_len;
} }
ret = gst_rtp_h265_pay_payload_nal (basepayload, paybufs, dts, pts);
} else { } else {
guint next; guint next;
gboolean update = FALSE; gboolean update = FALSE;
GPtrArray *paybufs;
/* get offset of first start code */ /* get offset of first start code */
next = next_start_code (data, size); next = next_start_code (data, size);
@ -1202,6 +1214,8 @@ gst_rtp_h265_pay_handle_buffer (GstRTPBasePayload * basepayload,
GST_DEBUG_OBJECT (basepayload, GST_DEBUG_OBJECT (basepayload,
"found first start at %u, bytes left %" G_GSIZE_FORMAT, next, size); "found first start at %u, bytes left %" G_GSIZE_FORMAT, next, size);
paybufs = g_ptr_array_new ();
/* first pass to locate NALs and parse VPS/SPS/PPS */ /* first pass to locate NALs and parse VPS/SPS/PPS */
while (size > 4) { while (size > 4) {
/* skip start code */ /* skip start code */
@ -1254,7 +1268,6 @@ gst_rtp_h265_pay_handle_buffer (GstRTPBasePayload * 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 */
@ -1270,32 +1283,21 @@ gst_rtp_h265_pay_handle_buffer (GstRTPBasePayload * basepayload,
for (; size > 1 && data[size - 1] == 0x0; size--) for (; size > 1 && data[size - 1] == 0x0; size--)
/* skip */ ; /* skip */ ;
/* FIXME: We need to wait until the next packet or EOS to
/* 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 * 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 * the last one of an access unit or not if we are in bytestream mode
*/ */
if ((rtph265pay->alignment == GST_H265_ALIGNMENT_AU || buffer == NULL) &&
i == nal_queue->len - 1)
end_of_au = TRUE;
paybuf = gst_adapter_take_buffer (rtph265pay->adapter, size); paybuf = gst_adapter_take_buffer (rtph265pay->adapter, size);
g_assert (paybuf); g_assert (paybuf);
g_ptr_array_add (paybufs, paybuf);
/* put the data in one or more RTP packets */
ret =
gst_rtp_h265_pay_payload_nal (basepayload, paybuf, dts, pts,
end_of_au);
if (ret != GST_FLOW_OK) {
break;
}
/* move to next NAL packet */ /* move to next NAL packet */
/* Skips the trailing zeros */ /* Skips the trailing zeros */
gst_adapter_flush (rtph265pay->adapter, nal_len - size); gst_adapter_flush (rtph265pay->adapter, nal_len - size);
} }
/* put the data in one or more RTP packets */
ret = gst_rtp_h265_pay_payload_nal (basepayload, paybufs, dts, pts);
g_array_set_size (nal_queue, 0); g_array_set_size (nal_queue, 0);
} }