adaptivedemux/mpegtsdemux: Playback Stuck during HLS Seek
authorGilbok Lee <gilbok.lee@samsung.com>
Thu, 5 Apr 2018 09:22:05 +0000 (18:22 +0900)
committerGilbok Lee <gilbok.lee@samsung.com>
Fri, 6 Apr 2018 05:18:23 +0000 (05:18 +0000)
[Problem] Screen Freeze and Playback Stuck during HLS Seek
[Cause & Measure] Issue was happening due to timestamp calculations happening
wrongly in mpegtspacketizer for VOD contents. For fixing the issue,
currently have created interface to know the stream type ( live or vod )
and depending on the type, doing timestamp calculation.

Change-Id: If2b159cf3713e762dfc71d3f7dcf5d7c7d5be43f

gst-libs/gst/adaptivedemux/gstadaptivedemux.c
gst/mpegtsdemux/mpegtsbase.c
gst/mpegtsdemux/mpegtspacketizer.c
gst/mpegtsdemux/mpegtspacketizer.h

index ae589e7..691263a 100644 (file)
@@ -3121,13 +3121,13 @@ gst_adaptive_demux_stream_update_source (GstAdaptiveDemuxStream * stream,
     if (g_object_class_find_property (gobject_class, "keep-alive"))
       g_object_set (uri_handler, "keep-alive", TRUE, NULL);
 #ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
-     if (g_object_class_find_property (gobject_class, "user-agent")
+    if (g_object_class_find_property (gobject_class, "user-agent")
         && (demux->user_agent))
       g_object_set (stream->src, "user-agent", demux->user_agent, NULL);
     if (g_object_class_find_property (gobject_class, "cookies")
         && (demux->cookies))
       g_object_set (stream->src, "cookies", demux->cookies, NULL);
- #endif
+#endif
     if (g_object_class_find_property (gobject_class, "extra-headers")) {
       if (referer || refresh || !allow_cache) {
         GstStructure *extra_headers = gst_structure_new_empty ("headers");
index 46c1e72..2625b7d 100644 (file)
@@ -1385,6 +1385,11 @@ mpegts_base_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
   gboolean hard;
   MpegTSBase *base = GST_MPEGTS_BASE (parent);
   gboolean is_sticky = GST_EVENT_IS_STICKY (event);
+#ifdef TIZEN_FEATURE_TSDEMUX_MODIFICATION
+  GstStructure *structure = NULL;
+  GstCaps *caps = NULL;
+  gboolean caps_ret = FALSE;
+#endif
 
   GST_DEBUG_OBJECT (base, "Got event %s",
       gst_event_type_get_name (GST_EVENT_TYPE (event)));
@@ -1418,6 +1423,19 @@ mpegts_base_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
       break;
     case GST_EVENT_CAPS:
       /* FIXME, do something */
+#ifdef TIZEN_FEATURE_TSDEMUX_MODIFICATION
+      if (base->packetizer) {
+        gst_event_parse_caps (event, &caps);
+        GST_DEBUG_OBJECT (base, "got caps: %" GST_PTR_FORMAT, caps);
+
+        structure = gst_caps_get_structure (caps, 0);
+        caps_ret = gst_structure_get_boolean (structure, "is_live", &base->packetizer->is_live_stream);
+        if (caps_ret == FALSE)
+          base->packetizer->is_live_stream = TRUE;
+      } else {
+        GST_DEBUG_OBJECT (base, "base->packetizer pointer is NULL !!!");
+      }
+#endif
       gst_event_unref (event);
       break;
     case GST_EVENT_FLUSH_STOP:
@@ -1470,7 +1488,13 @@ mpegts_base_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
     if (base->mode == BASE_MODE_PUSHING
         && base->segment.format == GST_FORMAT_TIME) {
       mpegts_packetizer_flush (base->packetizer, TRUE);
+#ifndef TIZEN_FEATURE_TSDEMUX_MODIFICATION
+      /* NOTE:
+       * If use decodebin3/playbin3, it will be include.
+       * commit fb36608ccd95004b3c2b38d6451c009fbad899b6
+       * mpegts: Also clear packetizer on TIME DISCONT */
       mpegts_packetizer_clear (base->packetizer);
+#endif
     } else
       mpegts_packetizer_flush (base->packetizer, FALSE);
   }
index cc46ebb..593cb23 100644 (file)
@@ -269,6 +269,9 @@ mpegts_packetizer_init (MpegTSPacketizer2 * packetizer)
   packetizer->nb_seen_offsets = 0;
   packetizer->refoffset = -1;
   packetizer->last_in_time = GST_CLOCK_TIME_NONE;
+#ifdef TIZEN_FEATURE_TSDEMUX_MODIFICATION
+  packetizer->is_live_stream = FALSE;
+#endif
   packetizer->pcr_discont_threshold = GST_SECOND;
 }
 
@@ -393,12 +396,26 @@ mpegts_packetizer_parse_adaptation_field_control (MpegTSPacketizer2 *
         GST_TIME_ARGS (PCRTIME_TO_GSTTIME (packet->pcr)), packet->offset);
 
     PACKETIZER_GROUP_LOCK (packetizer);
+#ifdef TIZEN_FEATURE_TSDEMUX_MODIFICATION
+    if (packetizer->calculate_skew
+        && GST_CLOCK_TIME_IS_VALID (packetizer->last_in_time)) {
+      pcrtable = get_pcr_table (packetizer, packet->pid);
+      if (((!GST_CLOCK_TIME_IS_VALID (pcrtable->base_time))
+              || (!GST_CLOCK_TIME_IS_VALID (pcrtable->base_pcrtime)))
+          || (packetizer->is_live_stream)) {
+        calculate_skew (packetizer, pcrtable, packet->pcr,
+            packetizer->last_in_time);
+      } else
+        GST_DEBUG (" **** skew calculation not done **** !!!");
+    }
+#else
     if (packetizer->calculate_skew
         && GST_CLOCK_TIME_IS_VALID (packetizer->last_in_time)) {
       pcrtable = get_pcr_table (packetizer, packet->pid);
       calculate_skew (packetizer, pcrtable, packet->pcr,
           packetizer->last_in_time);
     }
+#endif
     if (packetizer->calculate_offset) {
       if (!pcrtable)
         pcrtable = get_pcr_table (packetizer, packet->pid);
@@ -579,6 +596,9 @@ mpegts_packetizer_clear (MpegTSPacketizer2 * packetizer)
   packetizer->map_size = 0;
   packetizer->map_offset = 0;
   packetizer->last_in_time = GST_CLOCK_TIME_NONE;
+#ifdef TIZEN_FEATURE_TSDEMUX_MODIFICATION
+  packetizer->is_live_stream = FALSE;
+#endif
 
   pcrtable = packetizer->observations[packetizer->pcrtablelut[0x1fff]];
   if (pcrtable)
@@ -980,7 +1000,7 @@ mpegts_packetizer_push_section (MpegTSPacketizer2 * packetizer,
    *  If it is not a PUSI
    *    Accumulate the expected data and check for complete section
    *    (loop)
-   *    
+   *
    **/
 
   if (packet->payload_unit_start_indicator) {
@@ -1936,7 +1956,7 @@ record_pcr (MpegTSPacketizer2 * packetizer, MpegTSPCR * pcrtable,
     GList *tmp;
     /* No current estimator. This happens for the initial value, or after
      * discont and flushes. Figure out where we need to record this position.
-     * 
+     *
      * Possible choices:
      * 1) No groups at all:
      *    Create a new group with pcr/offset
@@ -2210,6 +2230,9 @@ mpegts_packetizer_pts_to_ts (MpegTSPacketizer2 * packetizer,
 {
   GstClockTime res = GST_CLOCK_TIME_NONE;
   MpegTSPCR *pcrtable;
+#ifdef TIZEN_FEATURE_TSDEMUX_MODIFICATION
+  GstClockTime tmp;
+#endif
 
   PACKETIZER_GROUP_LOCK (packetizer);
   pcrtable = get_pcr_table (packetizer, pcr_pid);
@@ -2237,6 +2260,32 @@ mpegts_packetizer_pts_to_ts (MpegTSPacketizer2 * packetizer,
      * That being said, this will only happen for the small interval of time
      * where PTS/DTS are wrapping just before we see the first reset/wrap PCR
      */
+    /*
+     * For some HLS Live servers (e.g tvpstream.tvp.pl ) , we observe erronous PCR values.
+     * As a result , last_pcrtime comes faulty which causes PTS values not to be calculated at all and buffers are dropped.
+     * We are currently ignoring the check for handling the erronous server PCR case.
+     */
+#ifdef TIZEN_FEATURE_TSDEMUX_MODIFICATION
+    tmp = pcrtable->base_time + pcrtable->skew;
+    if (packetizer->is_live_stream) {
+      if (G_UNLIKELY (ABSDIFF (res, pcrtable->last_pcrtime) > 15 * GST_SECOND))
+        GST_WARNING
+            ("Live Stream : Server sending erronous PCR values : Recalculating!!");
+
+      if (tmp + res > pcrtable->base_pcrtime)
+        res += tmp - pcrtable->base_pcrtime;
+      else
+        res = GST_CLOCK_TIME_NONE;
+    } else {
+      if (G_UNLIKELY (ABSDIFF (res, pcrtable->last_pcrtime) > 15 * GST_SECOND))
+        GST_WARNING
+            ("VOD Stream : Server sending erronous PCR values : Maintaining old ts value !!!");
+      else if (tmp + res > pcrtable->base_pcrtime)
+        res += tmp - pcrtable->base_pcrtime;
+      else
+        res = GST_CLOCK_TIME_NONE;
+    }
+#else
     if (G_UNLIKELY (pcr_pid != 0x1fff &&
             ABSDIFF (res, pcrtable->last_pcrtime) > 15 * GST_SECOND))
       res = GST_CLOCK_TIME_NONE;
@@ -2247,6 +2296,7 @@ mpegts_packetizer_pts_to_ts (MpegTSPacketizer2 * packetizer,
       else
         res = GST_CLOCK_TIME_NONE;
     }
+#endif
   } else if (packetizer->calculate_offset && pcrtable->groups) {
     gint64 refpcr = G_MAXINT64, refpcroffset;
     PCROffsetGroup *group = pcrtable->current->group;
index be8bf37..e4f85e2 100644 (file)
@@ -1,7 +1,7 @@
 /*
- * mpegtspacketizer.h - 
+ * mpegtspacketizer.h -
  * Copyright (C) 2007 Alessandro Decina
- * 
+ *
  * Authors:
  *   Alessandro Decina <alessandro@nnva.org>
  *
@@ -278,6 +278,10 @@ struct _MpegTSPacketizer2 {
   /* Last inputted timestamp */
   GstClockTime last_in_time;
 
+#ifdef TIZEN_FEATURE_TSDEMUX_MODIFICATION
+  gboolean is_live_stream;
+#endif
+
   /* offset to observations table */
   guint8 pcrtablelut[0x2000];
   MpegTSPCR *observations[MAX_PCR_OBS_CHANNELS];
@@ -313,8 +317,8 @@ typedef struct
 typedef struct
 {
   guint8 table_id;
-  /* the spec says sub_table_extension is the fourth and fifth byte of a 
-   * section when the section_syntax_indicator is set to a value of "1". If 
+  /* the spec says sub_table_extension is the fourth and fifth byte of a
+   * section when the section_syntax_indicator is set to a value of "1". If
    * section_syntax_indicator is 0, sub_table_extension will be set to 0 */
   guint16  subtable_extension;
   guint8   version_number;