rtponviftimestamp: implement support for the T flag
authorMathieu Duponchelle <mathieu@centricular.com>
Mon, 5 Nov 2018 19:32:03 +0000 (20:32 +0100)
committerMathieu Duponchelle <mduponchelle1@gmail.com>
Fri, 5 Apr 2019 00:28:48 +0000 (00:28 +0000)
https://www.onvif.org/specs/stream/ONVIF-Streaming-Spec.pdf

6.3 RTP header extension

gst/onvif/gstrtponviftimestamp.c
gst/onvif/gstrtponviftimestamp.h

index 81b57db..b7a7e8e 100644 (file)
@@ -35,6 +35,7 @@
 #define DEFAULT_NTP_OFFSET GST_CLOCK_TIME_NONE
 #define DEFAULT_CSEQ 0
 #define DEFAULT_SET_E_BIT FALSE
+#define DEFAULT_SET_T_BIT FALSE
 
 GST_DEBUG_CATEGORY_STATIC (rtponviftimestamp_debug);
 #define GST_CAT_DEFAULT (rtponviftimestamp_debug)
@@ -69,6 +70,7 @@ enum
   PROP_NTP_OFFSET,
   PROP_CSEQ,
   PROP_SET_E_BIT,
+  PROP_SET_T_BIT,
 };
 
 /*static guint gst_rtp_onvif_timestamp_signals[LAST_SIGNAL] = { 0 }; */
@@ -91,6 +93,9 @@ gst_rtp_onvif_timestamp_get_property (GObject * object,
     case PROP_SET_E_BIT:
       g_value_set_boolean (value, self->prop_set_e_bit);
       break;
+    case PROP_SET_T_BIT:
+      g_value_set_boolean (value, self->prop_set_t_bit);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -113,6 +118,9 @@ gst_rtp_onvif_timestamp_set_property (GObject * object,
     case PROP_SET_E_BIT:
       self->prop_set_e_bit = g_value_get_boolean (value);
       break;
+    case PROP_SET_T_BIT:
+      self->prop_set_t_bit = g_value_get_boolean (value);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -191,6 +199,7 @@ gst_rtp_onvif_timestamp_change_state (GstElement * element,
           GST_TIME_ARGS (self->ntp_offset));
       self->set_d_bit = TRUE;
       self->set_e_bit = FALSE;
+      self->set_t_bit = FALSE;
       break;
     default:
       break;
@@ -256,6 +265,12 @@ gst_rtp_onvif_timestamp_class_init (GstRtpOnvifTimestampClass * klass)
           "extension. This increases latency by one packet",
           DEFAULT_SET_E_BIT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
+  g_object_class_install_property (gobject_class, PROP_SET_T_BIT,
+      g_param_spec_boolean ("set-t-bit", "Set 'T' bit",
+          "If the element should set the 'T' bit as defined in the ONVIF RTP "
+          "extension. This increases latency by one packet",
+          DEFAULT_SET_T_BIT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
   /* register pads */
   gst_element_class_add_static_pad_template (gstelement_class,
       &sink_template_factory);
@@ -333,8 +348,11 @@ gst_rtp_onvif_timestamp_sink_event (GstPad * pad, GstObject * parent,
     case GST_EVENT_EOS:
     {
       GstFlowReturn res;
+
       /* Push pending buffers, if any */
       self->set_e_bit = TRUE;
+      if (self->prop_set_t_bit)
+        self->set_t_bit = TRUE;
       res = send_cached_buffer_and_events (self);
       if (res != GST_FLOW_OK) {
         drop = TRUE;
@@ -347,6 +365,7 @@ gst_rtp_onvif_timestamp_sink_event (GstPad * pad, GstObject * parent,
       purge_cached_buffer_and_events (self);
       self->set_d_bit = TRUE;
       self->set_e_bit = FALSE;
+      self->set_t_bit = FALSE;
       gst_segment_init (&self->segment, GST_FORMAT_UNDEFINED);
       break;
     default:
@@ -418,6 +437,7 @@ gst_rtp_onvif_timestamp_init (GstRtpOnvifTimestamp * self)
 
   self->prop_ntp_offset = DEFAULT_NTP_OFFSET;
   self->prop_set_e_bit = DEFAULT_SET_E_BIT;
+  self->prop_set_t_bit = DEFAULT_SET_T_BIT;
 
   gst_segment_init (&self->segment, GST_FORMAT_UNDEFINED);
 
@@ -527,7 +547,7 @@ handle_buffer (GstRtpOnvifTimestamp * self, GstBuffer * buf)
 
   GST_WRITE_UINT64_BE (data, time);
 
-  /* The next byte is composed of: C E D mbz (5 bits) */
+  /* The next byte is composed of: C E D T mbz (4 bits) */
 
   /* Set C if the buffer does *not* have the DELTA_UNIT flag as it means
    * that's a key frame (or 'clean point'). */
@@ -550,6 +570,13 @@ handle_buffer (GstRtpOnvifTimestamp * self, GstBuffer * buf)
     self->set_d_bit = FALSE;
   }
 
+  /* Set T if we have received EOS */
+  if (self->set_t_bit) {
+    GST_DEBUG_OBJECT (self, "set T flag");
+    field |= (1 << 4);
+    self->set_t_bit = FALSE;
+  }
+
   GST_WRITE_UINT8 (data + 8, field);
 
   /* CSeq (low-order byte) */
@@ -581,7 +608,7 @@ gst_rtp_onvif_timestamp_chain (GstPad * pad, GstObject * parent,
   GstRtpOnvifTimestamp *self = GST_RTP_ONVIF_TIMESTAMP (parent);
   GstFlowReturn result = GST_FLOW_OK;
 
-  if (!self->prop_set_e_bit) {
+  if (!self->prop_set_e_bit && !self->prop_set_t_bit) {
     /* Modify and push this buffer right away */
     return handle_and_push_buffer (self, buf);
   }
@@ -620,7 +647,7 @@ gst_rtp_onvif_timestamp_chain_list (GstPad * pad, GstObject * parent,
   GstRtpOnvifTimestamp *self = GST_RTP_ONVIF_TIMESTAMP (parent);
   GstFlowReturn result = GST_FLOW_OK;
 
-  if (!self->prop_set_e_bit) {
+  if (!self->prop_set_e_bit && !self->prop_set_t_bit) {
     return handle_and_push_buffer_list (self, list);
   }
 
index 1fb3199..21a0f65 100644 (file)
@@ -51,6 +51,7 @@ struct _GstRtpOnvifTimestamp {
   GstClockTime prop_ntp_offset;
   guint prop_cseq;
   gboolean prop_set_e_bit;
+  gboolean prop_set_t_bit;
 
   /* currently used ntp-offset
    *(can be changed runtime with a GstNtpOffset event)
@@ -59,6 +60,7 @@ struct _GstRtpOnvifTimestamp {
   /* a GstNtpOffset event might mark the stream as discontinued */
   gboolean set_d_bit;
   gboolean set_e_bit;
+  gboolean set_t_bit;
 
   GstSegment segment;
   /* Buffer waiting to be handled, only used if prop_set_e_bit is TRUE */