rtph264pay: propagate the GST_BUFFER_FLAG_DISCONT flag

Similarly to what we did with the DELTA_UNIT flag, this patch
propagates the DISCONT flag to the first RTP packet being used to transfer a
DISCONT buffer.

https://bugzilla.gnome.org/show_bug.cgi?id=730563
This commit is contained in:
Guillaume Desmottes 2014-05-20 12:39:31 +02:00 committed by Wim Taymans
parent 4be99ec7d5
commit f00c2b7155
2 changed files with 49 additions and 7 deletions

View file

@ -167,6 +167,7 @@ gst_rtp_h264_pay_init (GstRtpH264Pay * rtph264pay)
rtph264pay->last_spspps = -1; rtph264pay->last_spspps = -1;
rtph264pay->spspps_interval = DEFAULT_CONFIG_INTERVAL; rtph264pay->spspps_interval = DEFAULT_CONFIG_INTERVAL;
rtph264pay->delta_unit = FALSE; rtph264pay->delta_unit = FALSE;
rtph264pay->discont = FALSE;
rtph264pay->adapter = gst_adapter_new (); rtph264pay->adapter = gst_adapter_new ();
} }
@ -706,7 +707,7 @@ gst_rtp_h264_pay_decode_nal (GstRtpH264Pay * payloader,
static GstFlowReturn static GstFlowReturn
gst_rtp_h264_pay_payload_nal (GstRTPBasePayload * basepayload, gst_rtp_h264_pay_payload_nal (GstRTPBasePayload * basepayload,
GstBuffer * paybuf, GstClockTime dts, GstClockTime pts, gboolean end_of_au, GstBuffer * paybuf, GstClockTime dts, GstClockTime pts, gboolean end_of_au,
gboolean delta_unit); gboolean delta_unit, gboolean discont);
static GstFlowReturn static GstFlowReturn
gst_rtp_h264_pay_send_sps_pps (GstRTPBasePayload * basepayload, gst_rtp_h264_pay_send_sps_pps (GstRTPBasePayload * basepayload,
@ -723,7 +724,7 @@ gst_rtp_h264_pay_send_sps_pps (GstRTPBasePayload * basepayload,
GST_DEBUG_OBJECT (rtph264pay, "inserting SPS in the stream"); GST_DEBUG_OBJECT (rtph264pay, "inserting SPS in the stream");
/* resend SPS */ /* resend SPS */
ret = gst_rtp_h264_pay_payload_nal (basepayload, gst_buffer_ref (sps_buf), ret = gst_rtp_h264_pay_payload_nal (basepayload, gst_buffer_ref (sps_buf),
dts, pts, FALSE, FALSE); dts, pts, FALSE, FALSE, 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) {
sent_all_sps_pps = FALSE; sent_all_sps_pps = FALSE;
@ -737,7 +738,7 @@ gst_rtp_h264_pay_send_sps_pps (GstRTPBasePayload * basepayload,
GST_DEBUG_OBJECT (rtph264pay, "inserting PPS in the stream"); GST_DEBUG_OBJECT (rtph264pay, "inserting PPS in the stream");
/* resend PPS */ /* resend PPS */
ret = gst_rtp_h264_pay_payload_nal (basepayload, gst_buffer_ref (pps_buf), ret = gst_rtp_h264_pay_payload_nal (basepayload, gst_buffer_ref (pps_buf),
dts, pts, FALSE, FALSE); dts, pts, FALSE, FALSE, 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) {
sent_all_sps_pps = FALSE; sent_all_sps_pps = FALSE;
@ -752,11 +753,14 @@ gst_rtp_h264_pay_send_sps_pps (GstRTPBasePayload * basepayload,
} }
/* @delta_unit: if %FALSE the first packet sent won't have the /* @delta_unit: if %FALSE the first packet sent won't have the
* GST_BUFFER_FLAG_DELTA_UNIT flag. */ * GST_BUFFER_FLAG_DELTA_UNIT flag.
* @discont: if %TRUE the first packet sent will have the
* GST_BUFFER_FLAG_DISCONT flag.
*/
static GstFlowReturn static GstFlowReturn
gst_rtp_h264_pay_payload_nal (GstRTPBasePayload * basepayload, gst_rtp_h264_pay_payload_nal (GstRTPBasePayload * basepayload,
GstBuffer * paybuf, GstClockTime dts, GstClockTime pts, gboolean end_of_au, GstBuffer * paybuf, GstClockTime dts, GstClockTime pts, gboolean end_of_au,
gboolean delta_unit) gboolean delta_unit, gboolean discont)
{ {
GstRtpH264Pay *rtph264pay; GstRtpH264Pay *rtph264pay;
GstFlowReturn ret; GstFlowReturn ret;
@ -854,6 +858,12 @@ gst_rtp_h264_pay_payload_nal (GstRTPBasePayload * basepayload,
else else
GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DELTA_UNIT); GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DELTA_UNIT);
if (discont) {
GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DISCONT);
/* Only the first packet sent should have the flag */
discont = FALSE;
}
gst_rtp_buffer_unmap (&rtp); gst_rtp_buffer_unmap (&rtp);
/* insert payload memory block */ /* insert payload memory block */
@ -926,6 +936,12 @@ gst_rtp_h264_pay_payload_nal (GstRTPBasePayload * basepayload,
else else
GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DELTA_UNIT); GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DELTA_UNIT);
if (discont) {
GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DISCONT);
/* Only the first packet sent should have the flag */
discont = FALSE;
}
/* add the buffer to the buffer list */ /* add the buffer to the buffer list */
gst_buffer_list_add (list, outbuf); gst_buffer_list_add (list, outbuf);
@ -958,6 +974,7 @@ gst_rtp_h264_pay_handle_buffer (GstRTPBasePayload * basepayload,
GstBuffer *paybuf = NULL; GstBuffer *paybuf = NULL;
gsize skip; gsize skip;
gboolean delayed_not_delta_unit = FALSE; gboolean delayed_not_delta_unit = FALSE;
gboolean delayed_discont = FALSE;
rtph264pay = GST_RTP_H264_PAY (basepayload); rtph264pay = GST_RTP_H264_PAY (basepayload);
@ -976,6 +993,7 @@ gst_rtp_h264_pay_handle_buffer (GstRTPBasePayload * basepayload,
dts = GST_BUFFER_DTS (buffer); dts = GST_BUFFER_DTS (buffer);
rtph264pay->delta_unit = GST_BUFFER_FLAG_IS_SET (buffer, rtph264pay->delta_unit = GST_BUFFER_FLAG_IS_SET (buffer,
GST_BUFFER_FLAG_DELTA_UNIT); GST_BUFFER_FLAG_DELTA_UNIT);
rtph264pay->discont = GST_BUFFER_IS_DISCONT (buffer);
GST_DEBUG_OBJECT (basepayload, "got %" G_GSIZE_FORMAT " bytes", size); GST_DEBUG_OBJECT (basepayload, "got %" G_GSIZE_FORMAT " bytes", size);
} else { } else {
dts = gst_adapter_prev_dts (rtph264pay->adapter, NULL); dts = gst_adapter_prev_dts (rtph264pay->adapter, NULL);
@ -991,6 +1009,16 @@ gst_rtp_h264_pay_handle_buffer (GstRTPBasePayload * basepayload,
delayed_not_delta_unit = TRUE; delayed_not_delta_unit = TRUE;
} }
if (GST_BUFFER_IS_DISCONT (buffer)) {
if (gst_adapter_available (rtph264pay->adapter) == 0)
rtph264pay->discont = TRUE;
else
/* This buffer has the DISCONT flag but the adapter isn't empty. So
* we'll purge it first by sending a first packet and then the second
* one will have the DISCONT flag set. */
delayed_discont = TRUE;
}
if (!GST_CLOCK_TIME_IS_VALID (dts)) if (!GST_CLOCK_TIME_IS_VALID (dts))
dts = GST_BUFFER_DTS (buffer); dts = GST_BUFFER_DTS (buffer);
if (!GST_CLOCK_TIME_IS_VALID (pts)) if (!GST_CLOCK_TIME_IS_VALID (pts))
@ -1054,12 +1082,16 @@ gst_rtp_h264_pay_handle_buffer (GstRTPBasePayload * basepayload,
nal_len); nal_len);
ret = ret =
gst_rtp_h264_pay_payload_nal (basepayload, paybuf, dts, pts, gst_rtp_h264_pay_payload_nal (basepayload, paybuf, dts, pts,
end_of_au, rtph264pay->delta_unit); end_of_au, rtph264pay->delta_unit, rtph264pay->discont);
if (!rtph264pay->delta_unit) if (!rtph264pay->delta_unit)
/* Only the first outgoing packet doesn't have the DELTA_UNIT flag */ /* Only the first outgoing packet doesn't have the DELTA_UNIT flag */
rtph264pay->delta_unit = TRUE; rtph264pay->delta_unit = TRUE;
if (rtph264pay->discont)
/* Only the first outgoing packet have the DISCONT flag */
rtph264pay->discont = FALSE;
if (ret != GST_FLOW_OK) if (ret != GST_FLOW_OK)
break; break;
@ -1190,7 +1222,7 @@ gst_rtp_h264_pay_handle_buffer (GstRTPBasePayload * basepayload,
/* 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, paybuf, dts, pts, gst_rtp_h264_pay_payload_nal (basepayload, paybuf, dts, pts,
end_of_au, rtph264pay->delta_unit); end_of_au, rtph264pay->delta_unit, rtph264pay->discont);
if (delayed_not_delta_unit) { if (delayed_not_delta_unit) {
rtph264pay->delta_unit = FALSE; rtph264pay->delta_unit = FALSE;
@ -1200,6 +1232,14 @@ gst_rtp_h264_pay_handle_buffer (GstRTPBasePayload * basepayload,
rtph264pay->delta_unit = TRUE; rtph264pay->delta_unit = TRUE;
} }
if (delayed_discont) {
rtph264pay->discont = TRUE;
delayed_discont = FALSE;
} else {
/* Only the first outgoing packet have the DISCONT flag */
rtph264pay->discont = FALSE;
}
if (ret != GST_FLOW_OK) { if (ret != GST_FLOW_OK) {
break; break;
} }

View file

@ -77,6 +77,8 @@ struct _GstRtpH264Pay
/* TRUE if the next NALU processed should have the DELTA_UNIT flag */ /* TRUE if the next NALU processed should have the DELTA_UNIT flag */
gboolean delta_unit; gboolean delta_unit;
/* TRUE if the next NALU processed should have the DISCONT flag */
gboolean discont;
}; };
struct _GstRtpH264PayClass struct _GstRtpH264PayClass