mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-23 18:21:04 +00:00
rtph264pay: propagate the GST_BUFFER_FLAG_DELTA_UNIT flag
Downstream elements may be interested knowing if a RTP packet is the start of a key frame (to implement a RTP extension as defined in the ONVIF Streaming Spec for example). We do this by checking the GST_BUFFER_FLAG_DELTA_UNIT flag we receive from upstream and propagate it to the *first* RTP packet outputted to transfer this buffer. https://bugzilla.gnome.org/show_bug.cgi?id=730563
This commit is contained in:
parent
42ff642372
commit
4be99ec7d5
2 changed files with 53 additions and 6 deletions
|
@ -166,6 +166,7 @@ gst_rtp_h264_pay_init (GstRtpH264Pay * rtph264pay)
|
|||
(GDestroyNotify) gst_buffer_unref);
|
||||
rtph264pay->last_spspps = -1;
|
||||
rtph264pay->spspps_interval = DEFAULT_CONFIG_INTERVAL;
|
||||
rtph264pay->delta_unit = FALSE;
|
||||
|
||||
rtph264pay->adapter = gst_adapter_new ();
|
||||
}
|
||||
|
@ -704,7 +705,8 @@ gst_rtp_h264_pay_decode_nal (GstRtpH264Pay * payloader,
|
|||
|
||||
static GstFlowReturn
|
||||
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);
|
||||
|
||||
static GstFlowReturn
|
||||
gst_rtp_h264_pay_send_sps_pps (GstRTPBasePayload * basepayload,
|
||||
|
@ -721,7 +723,7 @@ gst_rtp_h264_pay_send_sps_pps (GstRTPBasePayload * basepayload,
|
|||
GST_DEBUG_OBJECT (rtph264pay, "inserting SPS in the stream");
|
||||
/* resend SPS */
|
||||
ret = gst_rtp_h264_pay_payload_nal (basepayload, gst_buffer_ref (sps_buf),
|
||||
dts, pts, FALSE);
|
||||
dts, pts, FALSE, FALSE);
|
||||
/* Not critical here; but throw a warning */
|
||||
if (ret != GST_FLOW_OK) {
|
||||
sent_all_sps_pps = FALSE;
|
||||
|
@ -735,7 +737,7 @@ gst_rtp_h264_pay_send_sps_pps (GstRTPBasePayload * basepayload,
|
|||
GST_DEBUG_OBJECT (rtph264pay, "inserting PPS in the stream");
|
||||
/* resend PPS */
|
||||
ret = gst_rtp_h264_pay_payload_nal (basepayload, gst_buffer_ref (pps_buf),
|
||||
dts, pts, FALSE);
|
||||
dts, pts, FALSE, FALSE);
|
||||
/* Not critical here; but throw a warning */
|
||||
if (ret != GST_FLOW_OK) {
|
||||
sent_all_sps_pps = FALSE;
|
||||
|
@ -749,9 +751,12 @@ gst_rtp_h264_pay_send_sps_pps (GstRTPBasePayload * basepayload,
|
|||
return ret;
|
||||
}
|
||||
|
||||
/* @delta_unit: if %FALSE the first packet sent won't have the
|
||||
* GST_BUFFER_FLAG_DELTA_UNIT flag. */
|
||||
static GstFlowReturn
|
||||
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)
|
||||
{
|
||||
GstRtpH264Pay *rtph264pay;
|
||||
GstFlowReturn ret;
|
||||
|
@ -843,6 +848,12 @@ gst_rtp_h264_pay_payload_nal (GstRTPBasePayload * basepayload,
|
|||
GST_BUFFER_PTS (outbuf) = pts;
|
||||
GST_BUFFER_DTS (outbuf) = dts;
|
||||
|
||||
if (!delta_unit)
|
||||
/* Only the first packet sent should not have the flag */
|
||||
delta_unit = TRUE;
|
||||
else
|
||||
GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DELTA_UNIT);
|
||||
|
||||
gst_rtp_buffer_unmap (&rtp);
|
||||
|
||||
/* insert payload memory block */
|
||||
|
@ -909,6 +920,12 @@ gst_rtp_h264_pay_payload_nal (GstRTPBasePayload * basepayload,
|
|||
gst_buffer_copy_region (paybuf, GST_BUFFER_COPY_MEMORY, pos,
|
||||
limitedSize));
|
||||
|
||||
if (!delta_unit)
|
||||
/* Only the first packet sent should not have the flag */
|
||||
delta_unit = TRUE;
|
||||
else
|
||||
GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DELTA_UNIT);
|
||||
|
||||
/* add the buffer to the buffer list */
|
||||
gst_buffer_list_add (list, outbuf);
|
||||
|
||||
|
@ -940,6 +957,7 @@ gst_rtp_h264_pay_handle_buffer (GstRTPBasePayload * basepayload,
|
|||
gboolean avc;
|
||||
GstBuffer *paybuf = NULL;
|
||||
gsize skip;
|
||||
gboolean delayed_not_delta_unit = FALSE;
|
||||
|
||||
rtph264pay = GST_RTP_H264_PAY (basepayload);
|
||||
|
||||
|
@ -956,11 +974,23 @@ gst_rtp_h264_pay_handle_buffer (GstRTPBasePayload * basepayload,
|
|||
size = map.size;
|
||||
pts = GST_BUFFER_PTS (buffer);
|
||||
dts = GST_BUFFER_DTS (buffer);
|
||||
rtph264pay->delta_unit = GST_BUFFER_FLAG_IS_SET (buffer,
|
||||
GST_BUFFER_FLAG_DELTA_UNIT);
|
||||
GST_DEBUG_OBJECT (basepayload, "got %" G_GSIZE_FORMAT " bytes", size);
|
||||
} else {
|
||||
dts = gst_adapter_prev_dts (rtph264pay->adapter, NULL);
|
||||
pts = gst_adapter_prev_pts (rtph264pay->adapter, NULL);
|
||||
if (buffer) {
|
||||
if (!GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT)) {
|
||||
if (gst_adapter_available (rtph264pay->adapter) == 0)
|
||||
rtph264pay->delta_unit = FALSE;
|
||||
else
|
||||
/* This buffer contains a key frame but the adapter isn't empty. So
|
||||
* we'll purge it first by sending a first packet and then the second
|
||||
* one won't have the DELTA_UNIT flag. */
|
||||
delayed_not_delta_unit = TRUE;
|
||||
}
|
||||
|
||||
if (!GST_CLOCK_TIME_IS_VALID (dts))
|
||||
dts = GST_BUFFER_DTS (buffer);
|
||||
if (!GST_CLOCK_TIME_IS_VALID (pts))
|
||||
|
@ -1024,7 +1054,12 @@ gst_rtp_h264_pay_handle_buffer (GstRTPBasePayload * basepayload,
|
|||
nal_len);
|
||||
ret =
|
||||
gst_rtp_h264_pay_payload_nal (basepayload, paybuf, dts, pts,
|
||||
end_of_au);
|
||||
end_of_au, rtph264pay->delta_unit);
|
||||
|
||||
if (!rtph264pay->delta_unit)
|
||||
/* Only the first outgoing packet doesn't have the DELTA_UNIT flag */
|
||||
rtph264pay->delta_unit = TRUE;
|
||||
|
||||
if (ret != GST_FLOW_OK)
|
||||
break;
|
||||
|
||||
|
@ -1155,7 +1190,16 @@ gst_rtp_h264_pay_handle_buffer (GstRTPBasePayload * basepayload,
|
|||
/* put the data in one or more RTP packets */
|
||||
ret =
|
||||
gst_rtp_h264_pay_payload_nal (basepayload, paybuf, dts, pts,
|
||||
end_of_au);
|
||||
end_of_au, rtph264pay->delta_unit);
|
||||
|
||||
if (delayed_not_delta_unit) {
|
||||
rtph264pay->delta_unit = FALSE;
|
||||
delayed_not_delta_unit = FALSE;
|
||||
} else {
|
||||
/* Only the first outgoing packet doesn't have the DELTA_UNIT flag */
|
||||
rtph264pay->delta_unit = TRUE;
|
||||
}
|
||||
|
||||
if (ret != GST_FLOW_OK) {
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -74,6 +74,9 @@ struct _GstRtpH264Pay
|
|||
guint spspps_interval;
|
||||
gboolean send_spspps;
|
||||
GstClockTime last_spspps;
|
||||
|
||||
/* TRUE if the next NALU processed should have the DELTA_UNIT flag */
|
||||
gboolean delta_unit;
|
||||
};
|
||||
|
||||
struct _GstRtpH264PayClass
|
||||
|
|
Loading…
Reference in a new issue