tsdemux: Make latency configurable
authorOlivier Crête <olivier.crete@collabora.com>
Fri, 23 Aug 2019 21:55:00 +0000 (17:55 -0400)
committerOlivier Crête <olivier.crete@collabora.com>
Tue, 27 Aug 2019 16:09:57 +0000 (12:09 -0400)
Allows for "low latency" mpeg-ts mode which is not standard, but somewhat common.
For this to work the sender has to put timestamps at a higher frequency than the spec requires.

gst/mpegtsdemux/tsdemux.c
gst/mpegtsdemux/tsdemux.h

index 082da86038ff12f1393687423bbb0abf53973585..8bc9736900f5f025f664534534235ac324b2c39a 100644 (file)
@@ -72,8 +72,8 @@
 
 #define GST_FLOW_REWINDING GST_FLOW_CUSTOM_ERROR
 
-/* latency in nsecs */
-#define TS_LATENCY (700 * GST_MSECOND)
+/* latency in msecs */
+#define DEFAULT_LATENCY (700)
 
 /* Limit PES packet collection to a maximum of 32MB
  * which is more than large enough to support an H264 frame at
@@ -289,6 +289,7 @@ enum
   PROP_0,
   PROP_PROGRAM_NUMBER,
   PROP_EMIT_STATS,
+  PROP_LATENCY,
   /* FILL ME */
 };
 
@@ -381,6 +382,12 @@ gst_ts_demux_class_init (GstTSDemuxClass * klass)
           "Emit messages for every pcr/opcr/pts/dts", FALSE,
           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
+  g_object_class_install_property (gobject_class, PROP_LATENCY,
+      g_param_spec_int ("latency", "Latency",
+          "Latency to add for smooth demuxing (in ms)", -1,
+          G_MAXINT, DEFAULT_LATENCY,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
   element_class = GST_ELEMENT_CLASS (klass);
   gst_element_class_add_pad_template (element_class,
       gst_static_pad_template_get (&video_template));
@@ -455,6 +462,7 @@ gst_ts_demux_init (GstTSDemux * demux)
   demux->flowcombiner = gst_flow_combiner_new ();
   demux->requested_program_number = -1;
   demux->program_number = -1;
+  demux->latency = DEFAULT_LATENCY;
   gst_ts_demux_reset (base);
 }
 
@@ -474,6 +482,9 @@ gst_ts_demux_set_property (GObject * object, guint prop_id,
     case PROP_EMIT_STATS:
       demux->emit_statistics = g_value_get_boolean (value);
       break;
+    case PROP_LATENCY:
+      demux->latency = g_value_get_int (value);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
   }
@@ -492,6 +503,9 @@ gst_ts_demux_get_property (GObject * object, guint prop_id,
     case PROP_EMIT_STATS:
       g_value_set_boolean (value, demux->emit_statistics);
       break;
+    case PROP_LATENCY:
+      g_value_set_int (value, demux->latency);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
   }
@@ -558,6 +572,7 @@ gst_ts_demux_srcpad_query (GstPad * pad, GstObject * parent, GstQuery * query)
       if (res) {
         GstClockTime min_lat, max_lat;
         gboolean live;
+        gint latency;
 
         /* According to H.222.0
            Annex D.0.3 (System Time Clock recovery in the decoder)
@@ -566,10 +581,13 @@ gst_ts_demux_srcpad_query (GstPad * pad, GstObject * parent, GstQuery * query)
            We can end up with an interval of up to 700ms between valid
            PTS/DTS. We therefore allow a latency of 700ms for that.
          */
+        latency = demux->latency;
+        if (latency < 0)
+          latency = 700;
         gst_query_parse_latency (query, &live, &min_lat, &max_lat);
-        min_lat += TS_LATENCY;
+        min_lat += latency * GST_MSECOND;
         if (GST_CLOCK_TIME_IS_VALID (max_lat))
-          max_lat += TS_LATENCY;
+          max_lat += latency * GST_MSECOND;
         gst_query_set_latency (query, live, min_lat, max_lat);
       }
       break;
index aa79a725582012849e52a3f5bc25df807c46c93d..931306ac6f0f42837ef4471047426d68596b0aa1 100644 (file)
@@ -76,6 +76,7 @@ struct _GstTSDemux
   gint requested_program_number; /* Required program number (ignore:-1) */
   guint program_number;
   gboolean emit_statistics;
+  gint latency; /* latency in ms */
 
   /*< private >*/
   gint program_generation; /* Incremented each time we switch program 0..15 */