(GDestroyNotify) gst_buffer_unref);
rtph264pay->last_spspps = -1;
rtph264pay->spspps_interval = DEFAULT_CONFIG_INTERVAL;
+ rtph264pay->delta_unit = FALSE;
rtph264pay->adapter = gst_adapter_new ();
}
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,
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;
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;
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;
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 */
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);
gboolean avc;
GstBuffer *paybuf = NULL;
gsize skip;
+ gboolean delayed_not_delta_unit = FALSE;
rtph264pay = GST_RTP_H264_PAY (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))
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;
/* 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;
}