[adaptive] add patches for dash and hls (sync with mobile) 47/105047/1
authorEunhae Choi <eunhae1.choi@samsung.com>
Tue, 13 Dec 2016 12:37:12 +0000 (21:37 +0900)
committereunhae choi <eunhae1.choi@samsung.com>
Thu, 15 Dec 2016 07:52:08 +0000 (23:52 -0800)
Change-Id: I09ed0be0eb390337c87b0fa73a4591b05e7a6818
(cherry picked from commit 33c221cb95e50f454725a4e5b6b27a4f2733165c)

17 files changed:
ext/dash/gstdashdemux.c
ext/dash/gstdashdemux.h
ext/dash/gstmpdparser.c
ext/dash/gstmpdparser.h
ext/hls/gsthlsdemux.c
ext/hls/gsthlsdemux.h
ext/hls/m3u8.c
ext/hls/m3u8.h
gst-libs/gst/adaptivedemux/gstadaptivedemux.c
gst-libs/gst/adaptivedemux/gstadaptivedemux.h
gst-libs/gst/uridownloader/gsturidownloader.c
gst-libs/gst/uridownloader/gsturidownloader.h
gst/mpegtsdemux/mpegtspacketizer.c
gst/mpegtsdemux/mpegtspacketizer.h
gst/mpegtsdemux/tsdemux.c
gst/mpegtsdemux/tsdemux.h
packaging/gst-plugins-bad.spec

index 20d6764..641aa64 100644 (file)
@@ -190,6 +190,12 @@ enum
 #define DEFAULT_BANDWIDTH_USAGE         0.8     /* 0 to 1     */
 #define DEFAULT_MAX_BITRATE        24000000     /* in bit/s  */
 
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+#define SEEK_UPDATES_PLAY_POSITION(r, start_type, stop_type) \
+  ((r >= 0 && start_type != GST_SEEK_TYPE_NONE) || \
+   (r < 0 && stop_type != GST_SEEK_TYPE_NONE))
+#endif
+
 /* Clock drift compensation for live streams */
 #define SLOW_CLOCK_UPDATE_INTERVAL  (1000000 * 30 * 60) /* 30 minutes */
 #define FAST_CLOCK_UPDATE_INTERVAL  (1000000 * 30)      /* 30 seconds */
@@ -244,8 +250,16 @@ gst_dash_demux_stream_get_fragment_waiting_time (GstAdaptiveDemuxStream *
     stream);
 static void gst_dash_demux_advance_period (GstAdaptiveDemux * demux);
 static gboolean gst_dash_demux_has_next_period (GstAdaptiveDemux * demux);
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+static gboolean
+gst_dash_demux_stream_fragment_start (GstAdaptiveDemux * demux,
+    GstAdaptiveDemuxStream * stream);
+static GstFlowReturn gst_dash_demux_data_received (GstAdaptiveDemux * demux,
+    GstAdaptiveDemuxStream * stream, GstBuffer * buffer);
+#else
 static GstFlowReturn gst_dash_demux_data_received (GstAdaptiveDemux * demux,
     GstAdaptiveDemuxStream * stream);
+#endif
 static GstFlowReturn
 gst_dash_demux_stream_fragment_finished (GstAdaptiveDemux * demux,
     GstAdaptiveDemuxStream * stream);
@@ -267,6 +281,9 @@ static GDateTime *gst_dash_demux_get_server_now_utc (GstDashDemux * demux);
 #define SIDX(s) (&(s)->sidx_parser.sidx)
 #define SIDX_ENTRY(s,i) (&(SIDX(s)->entries[(i)]))
 #define SIDX_CURRENT_ENTRY(s) SIDX_ENTRY(s, SIDX(s)->entry_index)
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+#define SIDX_ENTRY_COUNT(s) (SIDX(s)->entries_count)
+#endif
 
 static void gst_dash_demux_send_content_protection_event (gpointer cp_data,
     gpointer stream);
@@ -421,6 +438,9 @@ gst_dash_demux_class_init (GstDashDemuxClass * klass)
       gst_dash_demux_get_presentation_offset;
   gstadaptivedemux_class->get_period_start_time =
       gst_dash_demux_get_period_start_time;
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+  gstadaptivedemux_class->start_fragment = gst_dash_demux_stream_fragment_start;
+#endif
 
   gstadaptivedemux_class->finish_fragment =
       gst_dash_demux_stream_fragment_finished;
@@ -541,6 +561,13 @@ gst_dash_demux_setup_all_streams (GstDashDemux * demux)
 
     srcpad = gst_dash_demux_create_pad (demux, active_stream);
     caps = gst_dash_demux_get_input_caps (demux, active_stream);
+
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+    caps = gst_caps_make_writable (caps);
+    gst_caps_set_simple (caps,"adaptive_stream", G_TYPE_BOOLEAN, TRUE, "dash_stream", G_TYPE_BOOLEAN, TRUE, NULL);
+    GST_LOG_OBJECT(demux, "*** modified caps for dash streaming = %" GST_PTR_FORMAT, caps);
+#endif
+
     GST_LOG_OBJECT (demux, "Creating stream %d %" GST_PTR_FORMAT, i, caps);
 
     if (active_stream->cur_adapt_set) {
@@ -581,6 +608,10 @@ gst_dash_demux_setup_all_streams (GstDashDemux * demux)
     }
 
     gst_isoff_sidx_parser_init (&stream->sidx_parser);
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+    if (gst_mpd_client_has_isoff_ondemand_profile (demux->client))
+      stream->sidx_adapter = gst_adapter_new ();
+#endif
   }
 
   return TRUE;
@@ -968,7 +999,13 @@ gst_dash_demux_stream_update_fragment_info (GstAdaptiveDemuxStream * stream)
         &fragment);
 
     stream->fragment.uri = fragment.uri;
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+    int entry_count = SIDX_ENTRY_COUNT(dashstream);
+    GST_DEBUG_OBJECT(stream, "dashstream sidx entries_count=%d \n", entry_count);
+    if (isombff && entry_count > 0 && dashstream->sidx_index > 0 && dashstream->sidx_index <= entry_count) {
+#else
     if (isombff && dashstream->sidx_index != 0) {
+#endif
       GstSidxBoxEntry *entry = SIDX_CURRENT_ENTRY (dashstream);
       stream->fragment.range_start =
           dashstream->sidx_base_offset + entry->offset;
@@ -981,6 +1018,9 @@ gst_dash_demux_stream_update_fragment_info (GstAdaptiveDemuxStream * stream)
         stream->fragment.range_end = fragment.range_end;
       }
     } else {
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+      GST_DEBUG_OBJECT(stream, "sidx entries_count=%d  sidx_index=%d\n", dashstream->sidx_parser.sidx.entries_count, dashstream->sidx_index);
+#endif
       stream->fragment.timestamp = fragment.timestamp;
       stream->fragment.duration = fragment.duration;
       stream->fragment.range_start =
@@ -1008,10 +1048,12 @@ gst_dash_demux_stream_sidx_seek (GstDashDemuxStream * dashstream,
   }
   sidx->entry_index = i;
   dashstream->sidx_index = i;
+#ifndef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
   if (i < sidx->entries_count)
     dashstream->sidx_current_remaining = sidx->entries[i].size;
   else
     dashstream->sidx_current_remaining = 0;
+#endif
 }
 
 static GstFlowReturn
@@ -1076,10 +1118,11 @@ gst_dash_demux_stream_advance_subfragment (GstAdaptiveDemuxStream * stream)
   GST_DEBUG_OBJECT (stream->pad, "New sidx index: %d / %d. "
       "Finished fragment: %d", sidx->entry_index, sidx->entries_count,
       fragment_finished);
-
+#ifndef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
   if (!fragment_finished) {
     dashstream->sidx_current_remaining = sidx->entries[sidx->entry_index].size;
   }
+#endif
   return !fragment_finished;
 }
 
@@ -1098,6 +1141,18 @@ gst_dash_demux_stream_has_next_fragment (GstAdaptiveDemuxStream * stream)
       dashstream->active_stream, stream->demux->segment.rate > 0.0);
 }
 
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+static void
+gst_dash_demux_clear_pending_stream_data (GstDashDemux * dashdemux,
+    GstDashDemuxStream * dashstream)
+{
+  gst_isoff_sidx_parser_clear (&dashstream->sidx_parser);
+  gst_isoff_sidx_parser_init (&dashstream->sidx_parser);
+  if (dashstream->sidx_adapter)
+    gst_adapter_clear (dashstream->sidx_adapter);
+}
+#endif
+
 static GstFlowReturn
 gst_dash_demux_stream_advance_fragment (GstAdaptiveDemuxStream * stream)
 {
@@ -1110,7 +1165,9 @@ gst_dash_demux_stream_advance_fragment (GstAdaptiveDemuxStream * stream)
     if (gst_dash_demux_stream_advance_subfragment (stream))
       return GST_FLOW_OK;
   }
-
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+  gst_dash_demux_clear_pending_stream_data (dashdemux, dashstream);
+#endif
   return gst_mpd_client_advance_segment (dashdemux->client,
       dashstream->active_stream, stream->demux->segment.rate > 0.0);
 }
@@ -1166,6 +1223,16 @@ gst_dash_demux_stream_select_bitrate (GstAdaptiveDemuxStream * stream,
     }
   }
 
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+  if (ret) {
+    gst_dash_demux_clear_pending_stream_data (demux, dashstream);
+    if (gst_mpd_client_has_isoff_ondemand_profile (demux->client)) {
+      /* store our current position to change to the same one in a different
+       * representation if needed */
+      dashstream->sidx_index = SIDX (dashstream)->entry_index;
+    }
+  }
+ #else
   if (gst_mpd_client_has_isoff_ondemand_profile (demux->client)) {
 
     /* store our current position to change to the same one in a different
@@ -1178,6 +1245,7 @@ gst_dash_demux_stream_select_bitrate (GstAdaptiveDemuxStream * stream,
       gst_isoff_sidx_parser_init (&dashstream->sidx_parser);
     }
   }
+#endif
 
 end:
   return ret;
@@ -1203,11 +1271,25 @@ gst_dash_demux_seek (GstAdaptiveDemux * demux, GstEvent * seek)
       &stop_type, &stop);
 
   /* TODO check if start-type/stop-type is SET */
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+  if (!SEEK_UPDATES_PLAY_POSITION (rate, start_type, stop_type)) {
+    /* nothing to do if we don't have to update the current position */
+    return TRUE;
+  }
+#endif
+
   if (demux->segment.rate > 0.0)
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+    target_pos = (GstClockTime) start;
+#else
     target_pos = (GstClockTime) demux->segment.start;
+#endif
   else
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+    target_pos = (GstClockTime) stop;
+#else
     target_pos = (GstClockTime) demux->segment.stop;
-
+#endif
   /* select the requested Period in the Media Presentation */
   if (!gst_mpd_client_setup_media_presentation (dashdemux->client, target_pos,
           -1, NULL))
@@ -1252,8 +1334,12 @@ gst_dash_demux_seek (GstAdaptiveDemux * demux, GstEvent * seek)
     GstDashDemuxStream *dashstream = iter->data;
 
     if (flags & GST_SEEK_FLAG_FLUSH) {
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+       gst_dash_demux_clear_pending_stream_data (dashdemux, dashstream);
+#else
       gst_isoff_sidx_parser_clear (&dashstream->sidx_parser);
       gst_isoff_sidx_parser_init (&dashstream->sidx_parser);
+#endif
     }
     gst_dash_demux_stream_seek (iter->data, target_pos);
   }
@@ -1457,6 +1543,20 @@ _gst_buffer_split (GstBuffer * buffer, gint offset, gsize size)
   return newbuf;
 }
 
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+static gboolean
+gst_dash_demux_stream_fragment_start (GstAdaptiveDemux * demux,
+    GstAdaptiveDemuxStream * stream)
+{
+  GstDashDemuxStream *dashstream = (GstDashDemuxStream *) stream;
+
+  dashstream->sidx_index_header_or_data = 0;
+  dashstream->sidx_current_offset = -1;
+
+  return TRUE;
+}
+#endif
+
 static GstFlowReturn
 gst_dash_demux_stream_fragment_finished (GstAdaptiveDemux * demux,
     GstAdaptiveDemuxStream * stream)
@@ -1479,27 +1579,80 @@ gst_dash_demux_stream_fragment_finished (GstAdaptiveDemux * demux,
       stream->fragment.duration);
 }
 
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+static GstFlowReturn
+gst_dash_demux_data_received (GstAdaptiveDemux * demux,
+    GstAdaptiveDemuxStream * stream, GstBuffer * buffer)
+#else
 static GstFlowReturn
 gst_dash_demux_data_received (GstAdaptiveDemux * demux,
     GstAdaptiveDemuxStream * stream)
+#endif
 {
   GstDashDemuxStream *dash_stream = (GstDashDemuxStream *) stream;
   GstDashDemux *dashdemux = GST_DASH_DEMUX_CAST (demux);
   GstFlowReturn ret = GST_FLOW_OK;
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+  guint index_header_or_data;
+#else
   GstBuffer *buffer;
   gsize available;
+#endif
 
   if (!gst_mpd_client_has_isoff_ondemand_profile (dashdemux->client))
-    return GST_ADAPTIVE_DEMUX_CLASS (parent_class)->data_received (demux,
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+       return gst_adaptive_demux_stream_push_buffer (stream, buffer);
+#else
+       return GST_ADAPTIVE_DEMUX_CLASS (parent_class)->data_received (demux,
         stream);
+#endif
+
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+  if (stream->downloading_index)
+    index_header_or_data = 1;
+  else if (stream->downloading_header)
+    index_header_or_data = 2;
+  else
+    index_header_or_data = 3;
+
+  if (dash_stream->sidx_index_header_or_data != index_header_or_data) {
+    /* Clear pending data */
+    if (gst_adapter_available (dash_stream->sidx_adapter) != 0)
+      GST_ERROR_OBJECT (stream->pad,
+          "Had pending SIDX data after switch between index/header/data");
+    gst_adapter_clear (dash_stream->sidx_adapter);
+    dash_stream->sidx_index_header_or_data = index_header_or_data;
+    dash_stream->sidx_current_offset = -1;
+  }
+
+  if (dash_stream->sidx_current_offset == -1)
+    dash_stream->sidx_current_offset =
+        GST_BUFFER_OFFSET_IS_VALID (buffer) ? GST_BUFFER_OFFSET (buffer) : 0;
+
+  gst_adapter_push (dash_stream->sidx_adapter, buffer);
+  buffer = NULL;
+#endif
+
 
   if (stream->downloading_index) {
     GstIsoffParserResult res;
     guint consumed;
-
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+    gsize available;
+    available = gst_adapter_available (dash_stream->sidx_adapter);
+    buffer = gst_adapter_take_buffer (dash_stream->sidx_adapter, available);
+#else
     available = gst_adapter_available (stream->adapter);
     buffer = gst_adapter_take_buffer (stream->adapter, available);
+#endif
 
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+    if (buffer == NULL)
+    {
+       GST_ERROR_OBJECT (demux, "buffer data is NULL");
+       return GST_FLOW_OK;
+    }
+#endif
     if (dash_stream->sidx_parser.status != GST_ISOFF_SIDX_PARSER_FINISHED) {
       res =
           gst_isoff_sidx_parser_add_buffer (&dash_stream->sidx_parser, buffer,
@@ -1518,24 +1671,54 @@ gst_dash_demux_data_received (GstAdaptiveDemux * demux,
           } else {
             SIDX (dash_stream)->entry_index = dash_stream->sidx_index;
           }
+#ifndef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
           dash_stream->sidx_current_remaining =
               SIDX_CURRENT_ENTRY (dash_stream)->size;
+#endif
         } else if (consumed < available) {
           GstBuffer *pending;
           /* we still need to keep some data around for the next parsing round
            * so just push what was already processed by the parser */
           pending = _gst_buffer_split (buffer, consumed, -1);
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+          gst_adapter_push (dash_stream->sidx_adapter, pending);
+#else
           gst_adapter_push (stream->adapter, pending);
+#endif
         }
       }
     }
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+    GST_BUFFER_OFFSET (buffer) = dash_stream->sidx_current_offset;
+    GST_BUFFER_OFFSET_END (buffer) =
+        GST_BUFFER_OFFSET (buffer) + gst_buffer_get_size (buffer);
+    dash_stream->sidx_current_offset = GST_BUFFER_OFFSET_END (buffer);
+#endif
     ret = gst_adaptive_demux_stream_push_buffer (stream, buffer);
   } else if (dash_stream->sidx_parser.status == GST_ISOFF_SIDX_PARSER_FINISHED) {
-
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+    gsize available;
+    while (ret == GST_FLOW_OK
+        && ((available = gst_adapter_available (dash_stream->sidx_adapter)) > 0)) {
+#else
     while (ret == GST_FLOW_OK
         && ((available = gst_adapter_available (stream->adapter)) > 0)) {
+#endif
       gboolean advance = FALSE;
-
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+      guint64 sidx_end_offset =
+          dash_stream->sidx_base_offset +
+          SIDX_CURRENT_ENTRY (dash_stream)->offset +
+          SIDX_CURRENT_ENTRY (dash_stream)->size;
+       if (dash_stream->sidx_current_offset + available < sidx_end_offset){
+        buffer = gst_adapter_take_buffer (dash_stream->sidx_adapter, available);
+       } else {
+        buffer =
+            gst_adapter_take_buffer (dash_stream->sidx_adapter,
+            sidx_end_offset - dash_stream->sidx_current_offset);
+        advance = TRUE;
+      }
+#else
       if (available < dash_stream->sidx_current_remaining) {
         buffer = gst_adapter_take_buffer (stream->adapter, available);
         dash_stream->sidx_current_remaining -= available;
@@ -1546,6 +1729,17 @@ gst_dash_demux_data_received (GstAdaptiveDemux * demux,
         dash_stream->sidx_current_remaining = 0;
         advance = TRUE;
       }
+#endif
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+      if (buffer == NULL) {
+        GST_ERROR_OBJECT (demux, "buffer data is NULL");
+        return GST_FLOW_OK;
+      }
+      GST_BUFFER_OFFSET (buffer) = dash_stream->sidx_current_offset;
+      GST_BUFFER_OFFSET_END (buffer) =
+          GST_BUFFER_OFFSET (buffer) + gst_buffer_get_size (buffer);
+      dash_stream->sidx_current_offset = GST_BUFFER_OFFSET_END (buffer);
+#endif
       ret = gst_adaptive_demux_stream_push_buffer (stream, buffer);
       if (advance) {
         GstFlowReturn new_ret;
@@ -1560,10 +1754,22 @@ gst_dash_demux_data_received (GstAdaptiveDemux * demux,
     }
   } else {
     /* this should be the main header, just push it all */
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+    buffer = gst_adapter_take_buffer (dash_stream->sidx_adapter,
+        gst_adapter_available (dash_stream->sidx_adapter));
+
+    GST_BUFFER_OFFSET (buffer) = dash_stream->sidx_current_offset;
+    GST_BUFFER_OFFSET_END (buffer) =
+        GST_BUFFER_OFFSET (buffer) + gst_buffer_get_size (buffer);
+    dash_stream->sidx_current_offset = GST_BUFFER_OFFSET_END (buffer);
+
+    ret = gst_adaptive_demux_stream_push_buffer (stream, buffer);
+#else
     ret =
         gst_adaptive_demux_stream_push_buffer (stream,
         gst_adapter_take_buffer (stream->adapter,
             gst_adapter_available (stream->adapter)));
+#endif
   }
 
   return ret;
@@ -1575,6 +1781,10 @@ gst_dash_demux_stream_free (GstAdaptiveDemuxStream * stream)
   GstDashDemuxStream *dash_stream = (GstDashDemuxStream *) stream;
 
   gst_isoff_sidx_parser_clear (&dash_stream->sidx_parser);
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+  if (dash_stream->sidx_adapter)
+    g_object_unref (dash_stream->sidx_adapter);
+#endif
 }
 
 static GstDashDemuxClockDrift *
@@ -1686,7 +1896,7 @@ struct Rfc822TimeZone
 
 /*
  Parse an RFC822 (section 5) date-time from the Date: field in the
- HTTP response. 
+ HTTP response.
  See https://tools.ietf.org/html/rfc822#section-5
 */
 static GstDateTime *
@@ -1912,10 +2122,15 @@ gst_dash_demux_poll_clock_drift (GstDashDemux * demux)
     if (method == GST_MPD_UTCTIMING_TYPE_HTTP_HEAD) {
       range_start = -1;
     }
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+  download = gst_uri_downloader_fetch_uri (GST_ADAPTIVE_DEMUX_CAST
+        (demux)->downloader, urls[clock_drift->selected_url], NULL, NULL, NULL, DEFAULT_ADAPTIVE_RETRY,DEFAULT_ADAPTIVE_TIMEOUT,TRUE, FALSE, TRUE, NULL);
+#else
     download =
         gst_uri_downloader_fetch_uri_with_range (GST_ADAPTIVE_DEMUX_CAST
         (demux)->downloader, urls[clock_drift->selected_url], NULL, TRUE, TRUE,
         TRUE, range_start, range_end, NULL);
+#endif
     if (download) {
       if (method == GST_MPD_UTCTIMING_TYPE_HTTP_HEAD && download->headers) {
         value = gst_dash_demux_parse_http_head (clock_drift, download);
index ca2af31..931ad94 100644 (file)
@@ -67,11 +67,22 @@ struct _GstDashDemuxStream
   GstMediaFragmentInfo current_fragment;
 
   /* index parsing */
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+  GstAdapter *sidx_adapter;
+#endif
   GstSidxParser sidx_parser;
+#ifndef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
   gsize sidx_current_remaining;
+#endif
   gint sidx_index;
   gint64 sidx_base_offset;
   GstClockTime pending_seek_ts;
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+  /* sidx offset tracking */
+  guint64 sidx_current_offset;
+  /* index = 1, header = 2, data = 3 */
+  guint sidx_index_header_or_data;
+#endif
 };
 
 /**
index 80dc0df..72084e2 100644 (file)
@@ -2253,9 +2253,14 @@ gst_mpd_client_fetch_external_segment_list (GstMpdClient * client,
   gst_uri_unref (base_uri);
   gst_uri_unref (uri);
 
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+  download = gst_uri_downloader_fetch_uri (client->downloader,
+      uri_string, client->mpd_uri, NULL, NULL, DEFAULT_ADAPTIVE_RETRY,DEFAULT_ADAPTIVE_TIMEOUT,TRUE, FALSE, TRUE, &err);
+#else
   download =
       gst_uri_downloader_fetch_uri (client->downloader,
       uri_string, client->mpd_uri, TRUE, FALSE, TRUE, &err);
+#endif
   g_free (uri_string);
 
   if (!download) {
@@ -3849,10 +3854,14 @@ gst_mpd_client_fetch_external_period (GstMpdClient * client,
   uri_string = gst_uri_to_string (uri);
   gst_uri_unref (base_uri);
   gst_uri_unref (uri);
-
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+  download = gst_uri_downloader_fetch_uri (client->downloader,
+      uri_string, client->mpd_uri, NULL, NULL, DEFAULT_ADAPTIVE_RETRY,DEFAULT_ADAPTIVE_TIMEOUT,TRUE, FALSE, TRUE, &err);
+#else
   download =
       gst_uri_downloader_fetch_uri (client->downloader,
       uri_string, client->mpd_uri, TRUE, FALSE, TRUE, &err);
+#endif
   g_free (uri_string);
 
   if (!download) {
@@ -4180,9 +4189,15 @@ gst_mpd_client_fetch_external_adaptation_set (GstMpdClient * client,
   gst_uri_unref (base_uri);
   gst_uri_unref (uri);
 
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+  download = gst_uri_downloader_fetch_uri (client->downloader,
+      uri_string, client->mpd_uri, NULL, NULL, DEFAULT_ADAPTIVE_RETRY,DEFAULT_ADAPTIVE_TIMEOUT,TRUE, FALSE, TRUE, &err);
+#else
   download =
       gst_uri_downloader_fetch_uri (client->downloader,
       uri_string, client->mpd_uri, TRUE, FALSE, TRUE, &err);
+#endif
+
   g_free (uri_string);
 
   if (!download) {
@@ -4462,14 +4477,21 @@ gst_mpd_client_add_time_difference (GstDateTime * t1, gint64 usecs)
   GDateTime *gdt2;
   GstDateTime *rv;
 
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+  g_return_val_if_fail (t1 != NULL, NULL);
+  gdt = gst_date_time_to_g_date_time (t1);
+  g_return_val_if_fail (gdt != NULL, NULL);
+  gdt2 = g_date_time_add (gdt, usecs);
+  g_return_val_if_fail (gdt2 != NULL, NULL);
+#else
   g_assert (t1 != NULL);
   gdt = gst_date_time_to_g_date_time (t1);
   g_assert (gdt != NULL);
   gdt2 = g_date_time_add (gdt, usecs);
   g_assert (gdt2 != NULL);
+#endif
   g_date_time_unref (gdt);
   rv = gst_date_time_new_from_g_date_time (gdt2);
-
   /* Don't g_date_time_unref(gdt2) because gst_date_time_new_from_g_date_time takes
    * ownership of the GDateTime pointer.
    */
@@ -4503,6 +4525,9 @@ gst_mpd_client_get_last_fragment_timestamp_end (GstMpdClient * client,
   GST_DEBUG ("Stream index: %i", stream_idx);
   stream = g_list_nth_data (client->active_streams, stream_idx);
   g_return_val_if_fail (stream != NULL, 0);
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+  g_return_val_if_fail (stream->segments != NULL, 0);
+#endif
 
   segment_idx = gst_mpd_client_get_segments_counts (client, stream) - 1;
   currentChunk = g_ptr_array_index (stream->segments, segment_idx);
index 36569b5..d82a983 100644 (file)
@@ -67,6 +67,11 @@ typedef struct _GstMultSegmentBaseType    GstMultSegmentBaseType;
 #define GST_MPD_CLIENT_LOCK(c) g_mutex_lock (&c->lock);
 #define GST_MPD_CLIENT_UNLOCK(c) g_mutex_unlock (&c->lock);
 
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+#define DEFAULT_ADAPTIVE_RETRY -1
+#define DEFAULT_ADAPTIVE_TIMEOUT -1
+#endif
+
 typedef enum
 {
   GST_STREAM_UNKNOWN,
index ab53aed..c084615 100644 (file)
@@ -107,8 +107,13 @@ gst_hls_demux_start_fragment (GstAdaptiveDemux * demux,
     GstAdaptiveDemuxStream * stream);
 static GstFlowReturn gst_hls_demux_finish_fragment (GstAdaptiveDemux * demux,
     GstAdaptiveDemuxStream * stream);
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+static GstFlowReturn gst_hls_demux_data_received (GstAdaptiveDemux * demux,
+    GstAdaptiveDemuxStream * stream, GstBuffer * buffer);
+#else
 static GstFlowReturn gst_hls_demux_data_received (GstAdaptiveDemux * demux,
     GstAdaptiveDemuxStream * stream);
+#endif
 static gboolean gst_hls_demux_stream_has_next_fragment (GstAdaptiveDemuxStream *
     stream);
 static GstFlowReturn gst_hls_demux_advance_fragment (GstAdaptiveDemuxStream *
@@ -130,6 +135,9 @@ gst_hls_demux_dispose (GObject * obj)
   GstHLSDemux *demux = GST_HLS_DEMUX (obj);
 
   gst_hls_demux_reset (GST_ADAPTIVE_DEMUX_CAST (demux));
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+  g_object_unref (demux->pending_encrypted_data);
+#endif
   gst_m3u8_client_free (demux->client);
 
   G_OBJECT_CLASS (parent_class)->dispose (obj);
@@ -202,6 +210,9 @@ static void
 gst_hls_demux_init (GstHLSDemux * demux)
 {
   demux->do_typefind = TRUE;
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+  demux->pending_encrypted_data = gst_adapter_new ();
+#endif
 }
 
 static void
@@ -296,6 +307,18 @@ gst_hls_demux_get_bitrate (GstHLSDemux * hlsdemux)
   return 0;
 }
 
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+static void
+gst_hls_demux_clear_pending_data (GstHLSDemux * hlsdemux)
+{
+  gst_hls_demux_decrypt_end (hlsdemux);
+  gst_adapter_clear (hlsdemux->pending_encrypted_data);
+  gst_buffer_replace (&hlsdemux->pending_decrypted_buffer, NULL);
+  gst_buffer_replace (&hlsdemux->pending_typefind_buffer, NULL);
+  hlsdemux->current_offset = -1;
+}
+#endif
+
 static gboolean
 gst_hls_demux_seek (GstAdaptiveDemux * demux, GstEvent * seek)
 {
@@ -318,7 +341,11 @@ gst_hls_demux_seek (GstAdaptiveDemux * demux, GstEvent * seek)
 
   /* properly cleanup pending decryption status */
   if (flags & GST_SEEK_FLAG_FLUSH) {
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+    gst_hls_demux_clear_pending_data (hlsdemux);
+#else
     gst_hls_demux_decrypt_end (hlsdemux);
+#endif
   }
 
   /* Use I-frame variants for trick modes */
@@ -411,6 +438,9 @@ gst_hls_demux_setup_streams (GstAdaptiveDemux * demux)
   GstHLSDemux *hlsdemux = GST_HLS_DEMUX_CAST (demux);
 
   /* only 1 output supported */
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+  gst_hls_demux_clear_pending_data (hlsdemux);
+#endif
   gst_adaptive_demux_stream_new (demux, gst_hls_demux_create_pad (hlsdemux));
 
   hlsdemux->reset_pts = TRUE;
@@ -509,12 +539,21 @@ gst_hls_demux_start_fragment (GstAdaptiveDemux * demux,
       hlsdemux->key_fragment = NULL;
 
       GST_INFO_OBJECT (demux, "Fetching key %s", hlsdemux->current_key);
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+      key_fragment =
+          gst_uri_downloader_fetch_uri (demux->downloader,
+          hlsdemux->current_key, hlsdemux->client->main ?
+          hlsdemux->client->main->uri : NULL, demux->user_agent, demux->cookies, DEFAULT_ADAPTIVE_RETRY,DEFAULT_ADAPTIVE_TIMEOUT,FALSE, FALSE,
+          hlsdemux->client->current ? hlsdemux->client->current->
+          allowcache : TRUE, &err);
+#else
       key_fragment =
           gst_uri_downloader_fetch_uri (demux->downloader,
           hlsdemux->current_key, hlsdemux->client->main ?
           hlsdemux->client->main->uri : NULL, FALSE, FALSE,
           hlsdemux->client->current ? hlsdemux->client->current->
           allowcache : TRUE, &err);
+#endif
       if (key_fragment == NULL)
         goto key_failed;
       hlsdemux->key_url = g_strdup (hlsdemux->current_key);
@@ -530,6 +569,9 @@ gst_hls_demux_start_fragment (GstAdaptiveDemux * demux,
     gst_buffer_unref (key_buffer);
     g_object_unref (key_fragment);
   }
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+  gst_hls_demux_clear_pending_data (hlsdemux);
+#endif
 
   return TRUE;
 
@@ -551,6 +593,12 @@ gst_hls_demux_handle_buffer (GstAdaptiveDemux * demux,
     guint buffer_size;
     GstTypeFindProbability prob = GST_TYPE_FIND_NONE;
 
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+    if (hlsdemux->pending_typefind_buffer)
+      buffer = gst_buffer_append (hlsdemux->pending_typefind_buffer, buffer);
+    hlsdemux->pending_typefind_buffer = NULL;
+#endif
+
     gst_buffer_map (buffer, &info, GST_MAP_READ);
     buffer_size = info.size;
 
@@ -572,11 +620,15 @@ gst_hls_demux_handle_buffer (GstAdaptiveDemux * demux,
         gst_buffer_unref (buffer);
         return GST_FLOW_NOT_NEGOTIATED;
       } else {
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+       hlsdemux->pending_typefind_buffer = buffer;
+#else
         if (hlsdemux->pending_buffer)
           hlsdemux->pending_buffer =
               gst_buffer_append (buffer, hlsdemux->pending_buffer);
         else
           hlsdemux->pending_buffer = buffer;
+#endif
         return GST_FLOW_OK;
       }
     }
@@ -594,9 +646,20 @@ gst_hls_demux_handle_buffer (GstAdaptiveDemux * demux,
 #endif
     hlsdemux->do_typefind = FALSE;
   }
-
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+  g_assert (hlsdemux->pending_typefind_buffer == NULL);
+  if (buffer) {
+    buffer = gst_buffer_make_writable (buffer);
+    GST_BUFFER_OFFSET (buffer) = hlsdemux->current_offset;
+    hlsdemux->current_offset += gst_buffer_get_size (buffer);
+    GST_BUFFER_OFFSET_END (buffer) = hlsdemux->current_offset;
+    return gst_adaptive_demux_stream_push_buffer (stream, buffer);
+  }
+#else
   if (buffer)
     return gst_adaptive_demux_stream_push_buffer (stream, buffer);
+#endif
+
   return GST_FLOW_OK;
 }
 
@@ -610,66 +673,125 @@ gst_hls_demux_finish_fragment (GstAdaptiveDemux * demux,
   if (hlsdemux->current_key)
     gst_hls_demux_decrypt_end (hlsdemux);
 
+#ifndef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
   /* ideally this should be empty, but this eos might have been
    * caused by an error on the source element */
   GST_DEBUG_OBJECT (demux, "Data still on the adapter when EOS was received"
       ": %" G_GSIZE_FORMAT, gst_adapter_available (stream->adapter));
   gst_adapter_clear (stream->adapter);
+#endif
 
   if (stream->last_ret == GST_FLOW_OK) {
-    if (hlsdemux->pending_buffer) {
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+    if (hlsdemux->pending_decrypted_buffer)
+#else
+    if (hlsdemux->pending_buffer)
+#endif
+    {
       if (hlsdemux->current_key) {
         GstMapInfo info;
         gssize unpadded_size;
-
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+        /* Handle pkcs7 unpadding here */
+        gst_buffer_map (hlsdemux->pending_decrypted_buffer, &info, GST_MAP_READ);
+        unpadded_size = info.size - info.data[info.size - 1];
+        gst_buffer_unmap (hlsdemux->pending_decrypted_buffer, &info);
+        gst_buffer_resize (hlsdemux->pending_decrypted_buffer, 0, unpadded_size);
+#else
         /* Handle pkcs7 unpadding here */
         gst_buffer_map (hlsdemux->pending_buffer, &info, GST_MAP_READ);
         unpadded_size = info.size - info.data[info.size - 1];
         gst_buffer_unmap (hlsdemux->pending_buffer, &info);
 
         gst_buffer_resize (hlsdemux->pending_buffer, 0, unpadded_size);
+#endif
       }
-
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+      ret =
+          gst_hls_demux_handle_buffer (demux, stream, hlsdemux->pending_decrypted_buffer,
+          TRUE);
+      hlsdemux->pending_decrypted_buffer = NULL;
+#else
       ret =
           gst_hls_demux_handle_buffer (demux, stream, hlsdemux->pending_buffer,
           TRUE);
       hlsdemux->pending_buffer = NULL;
+#endif
     }
-  } else {
+  }
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+  gst_hls_demux_clear_pending_data (hlsdemux);
+#else
+  else {
     if (hlsdemux->pending_buffer)
       gst_buffer_unref (hlsdemux->pending_buffer);
     hlsdemux->pending_buffer = NULL;
   }
-
+#endif
+  GST_WARNING_OBJECT (hlsdemux, "gst_hls_demux_handle_buffer return : %d",ret);
   if (ret == GST_FLOW_OK || ret == GST_FLOW_NOT_LINKED)
     return gst_adaptive_demux_stream_advance_fragment (demux, stream,
         stream->fragment.duration);
   return ret;
 }
 
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+static GstFlowReturn
+gst_hls_demux_data_received (GstAdaptiveDemux * demux,
+    GstAdaptiveDemuxStream * stream, GstBuffer * buffer)
+#else
 static GstFlowReturn
 gst_hls_demux_data_received (GstAdaptiveDemux * demux,
     GstAdaptiveDemuxStream * stream)
+#endif
 {
   GstHLSDemux *hlsdemux = GST_HLS_DEMUX_CAST (demux);
+#ifndef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
   gsize available;
   GstBuffer *buffer = NULL;
 
   available = gst_adapter_available (stream->adapter);
+#endif
+
+#ifndef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+  if (hlsdemux->current_offset == -1)
+    hlsdemux->current_offset =
+        GST_BUFFER_OFFSET_IS_VALID (buffer) ? GST_BUFFER_OFFSET (buffer) : 0;
+#endif
 
   /* Is it encrypted? */
   if (hlsdemux->current_key) {
     GError *err = NULL;
     GstBuffer *tmp_buffer;
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+    gsize size;
+    gst_adapter_push (hlsdemux->pending_encrypted_data, buffer);
+    size = gst_adapter_available (hlsdemux->pending_encrypted_data);
+#endif
 
     /* must be a multiple of 16 */
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+    size = size & (~0xF);
+#else
     available = available & (~0xF);
+#endif
 
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+    if (size == 0) {
+      return GST_FLOW_OK;
+    }
+#else
     if (available == 0) {
       return GST_FLOW_OK;
     }
+#endif
+
 
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+    buffer = gst_adapter_take_buffer (hlsdemux->pending_encrypted_data, size);
+#else
     buffer = gst_adapter_take_buffer (stream->adapter, available);
+#endif
     buffer = gst_hls_demux_decrypt_fragment (hlsdemux, buffer, &err);
     if (buffer == NULL) {
       GST_ELEMENT_ERROR (demux, STREAM, DECODE, ("Failed to decrypt buffer"),
@@ -678,15 +800,24 @@ gst_hls_demux_data_received (GstAdaptiveDemux * demux,
       return GST_FLOW_ERROR;
     }
 
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+    tmp_buffer = hlsdemux->pending_decrypted_buffer;
+    hlsdemux->pending_decrypted_buffer = buffer;
+    buffer = tmp_buffer;
+#else
     tmp_buffer = hlsdemux->pending_buffer;
     hlsdemux->pending_buffer = buffer;
     buffer = tmp_buffer;
-  } else {
+#endif
+  }
+  else {
+#ifndef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
     buffer = gst_adapter_take_buffer (stream->adapter, available);
     if (hlsdemux->pending_buffer) {
       buffer = gst_buffer_append (hlsdemux->pending_buffer, buffer);
       hlsdemux->pending_buffer = NULL;
     }
+#endif
   }
 
   return gst_hls_demux_handle_buffer (demux, stream, buffer, FALSE);
@@ -808,9 +939,13 @@ gst_hls_demux_reset (GstAdaptiveDemux * ademux)
   demux->client = gst_m3u8_client_new ("", NULL);
 
   demux->srcpad_counter = 0;
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+  gst_hls_demux_clear_pending_data (demux);
+#else
   if (demux->pending_buffer)
     gst_buffer_unref (demux->pending_buffer);
   demux->pending_buffer = NULL;
+#endif
   if (demux->current_key) {
     g_free (demux->current_key);
     demux->current_key = NULL;
@@ -871,12 +1006,27 @@ gst_hls_demux_update_playlist (GstHLSDemux * demux, gboolean update,
   gboolean main_checked = FALSE, updated = FALSE;
   gchar *uri, *main_uri;
 
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+//[prasenjit.c]Sometimes for Errornous Clips , when Server changes the playlist abruptly , the URI does not remain valid anymore.
+//Adding one error check condition to handle the cases.
+  if ((!demux->client->current)||(!demux->client->main)) {
+    GST_WARNING_OBJECT (demux, "Invalid m3u8 instance in playlist .. no update possible !!!");
+    return FALSE;
+  }
+#endif
+
 retry:
   uri = gst_m3u8_client_get_current_uri (demux->client);
   main_uri = gst_m3u8_client_get_uri (demux->client);
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+  download =
+      gst_uri_downloader_fetch_uri (adaptive_demux->downloader, uri, main_uri, adaptive_demux->user_agent, adaptive_demux->cookies,PLAYLIST_ADAPTIVE_RETRY,PLAYLIST_ADAPTIVE_TIMEOUT,
+      TRUE, TRUE, TRUE, err);
+#else
   download =
       gst_uri_downloader_fetch_uri (adaptive_demux->downloader, uri, main_uri,
       TRUE, TRUE, TRUE, err);
+#endif
   g_free (main_uri);
   if (download == NULL) {
     if (!adaptive_demux->cancelled && update && !main_checked
@@ -887,9 +1037,15 @@ retry:
       GST_INFO_OBJECT (demux,
           "Updating playlist %s failed, attempt to refresh variant playlist %s",
           uri, main_uri);
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+      download =
+          gst_uri_downloader_fetch_uri (adaptive_demux->downloader,
+          main_uri, NULL, adaptive_demux->user_agent, adaptive_demux->cookies, PLAYLIST_ADAPTIVE_RETRY,PLAYLIST_ADAPTIVE_TIMEOUT,TRUE, TRUE, TRUE, &err2);
+#else
       download =
           gst_uri_downloader_fetch_uri (adaptive_demux->downloader,
           main_uri, NULL, TRUE, TRUE, TRUE, &err2);
+#endif
       g_free (main_uri);
       g_clear_error (&err2);
       if (download != NULL) {
@@ -1096,6 +1252,10 @@ retry_failover_protection:
   old_bandwidth = GST_M3U8 (previous_variant->data)->bandwidth;
   new_bandwidth = GST_M3U8 (current_variant->data)->bandwidth;
 
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+  GST_INFO_OBJECT (demux, "Previous Stream Codec = %s , Codec_Count = %d", GST_M3U8 (previous_variant->data)->codecs,GST_M3U8 (previous_variant->data)->codec_count);
+  GST_INFO_OBJECT (demux, "Current Stream Codec = %s , Codec_Count = %d", GST_M3U8 (current_variant->data)->codecs,GST_M3U8 (current_variant->data)->codec_count);
+#endif
   /* Don't do anything else if the playlist is the same */
   if (new_bandwidth == old_bandwidth) {
     GST_M3U8_CLIENT_UNLOCK (demux->client);
@@ -1110,7 +1270,13 @@ retry_failover_protection:
   GST_INFO_OBJECT (demux, "Client was on %dbps, max allowed is %dbps, switching"
       " to bitrate %dbps", old_bandwidth, max_bitrate, new_bandwidth);
   stream->discont = TRUE;
-
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+  if (GST_M3U8 (previous_variant->data)->codec_count > GST_M3U8 (current_variant->data)->codec_count)
+  {
+       GST_WARNING_OBJECT (demux, "Temporary patch for disabling stream switch in case New Variant has lesser streams than current variant !!");
+       goto playlist_switch_back;
+  }
+#endif
   if (gst_hls_demux_update_playlist (demux, FALSE, NULL)) {
     gchar *uri;
     gchar *main_uri;
@@ -1127,9 +1293,16 @@ retry_failover_protection:
     if (changed)
       *changed = TRUE;
   } else {
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+playlist_switch_back:
+    GST_INFO_OBJECT (demux, "Unable to update playlist. Switching back");
+
+    GList *failover = NULL;
+#else
     GList *failover = NULL;
 
     GST_INFO_OBJECT (demux, "Unable to update playlist. Switching back");
+#endif
     GST_M3U8_CLIENT_LOCK (demux->client);
 
     failover = g_list_previous (current_variant);
index c81b716..8238963 100644 (file)
@@ -88,10 +88,18 @@ struct _GstHLSDemux
 #endif
   gchar *current_key;
   guint8 *current_iv;
-  GstBuffer *pending_buffer; /* decryption scenario:
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+  GstAdapter *pending_encrypted_data;  /* for chunking data into 16 byte multiples for decryption */
+  GstBuffer *pending_decrypted_buffer; /* last decrypted buffer for pkcs7 unpadding.
+                                          We only know that it is the last at EOS */
+  GstBuffer *pending_typefind_buffer; /* for collecting data until typefind succeeds */
+  guint64 current_offset;              /* offset we're currently at */
+#else
+  GstBuffer *pending_buffer;  /*decryption scenario:
                               * the last buffer can only be pushed when
                               * resized, so need to store and wait for
                               * EOS to know it is the last */
+#endif
 
   gboolean reset_pts;
 };
index 4265f97..523c25c 100644 (file)
@@ -549,6 +549,9 @@ gst_m3u8_update (GstM3U8Client * client, GstM3U8 * self, gchar * data,
         new_list = gst_m3u8_new ();
         new_list->parent = self;
         new_list->iframe = iframe;
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+        new_list->codec_count = 0;
+#endif
         data = data + (iframe ? 26 : 18);
         while (data && parse_attributes (&data, &a, &v)) {
           if (g_str_equal (a, "BANDWIDTH")) {
@@ -560,6 +563,26 @@ gst_m3u8_update (GstM3U8Client * client, GstM3U8 * self, gchar * data,
           } else if (g_str_equal (a, "CODECS")) {
             g_free (new_list->codecs);
             new_list->codecs = g_strdup (v);
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+            gchar *temp_codec_str = NULL;
+            gchar *temp_codec_ptr = NULL;
+
+            temp_codec_str = g_strdup (new_list->codecs);
+            GST_DEBUG ("CODECS : %s",new_list->codecs);
+            new_list->codec_count = 1;
+            temp_codec_ptr = temp_codec_str;
+            while(temp_codec_str != NULL)
+            {
+              temp_codec_str = strchr (temp_codec_str, ',');
+              if (temp_codec_str)
+              {
+                new_list->codec_count++;
+                temp_codec_str = temp_codec_str + 1;
+              }
+            }
+            g_free(temp_codec_ptr);
+            GST_DEBUG ("CODEC COUNT : %d",new_list->codec_count);
+#endif
           } else if (g_str_equal (a, "RESOLUTION")) {
             if (!int_from_string (v, &v, &new_list->width))
               GST_WARNING ("Error while reading RESOLUTION width");
@@ -855,16 +878,34 @@ gst_m3u8_client_update (GstM3U8Client * self, gchar * data)
   }
 
   if (m3u8->files && self->sequence == -1) {
+#ifndef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+    self->current_file = g_list_first (m3u8->files);
+#endif
     if (GST_M3U8_CLIENT_IS_LIVE (self)) {
       /* for live streams, start GST_M3U8_LIVE_MIN_FRAGMENT_DISTANCE from
          the end of the playlist. See section 6.3.3 of HLS draft */
       gint pos =
           g_list_length (m3u8->files) - GST_M3U8_LIVE_MIN_FRAGMENT_DISTANCE;
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+/*[shweta.agg] While playing live video in hotstar, Video is starting from beginning.Setting current_file to nth fragment for live streams.
+    https://cgit.freedesktop.org/gstreamer/gst-plugins-bad/commit/ext/hls/m3u8.c?id=22456ce0328a8d06a12997979a143a0103867a49
+*/
       self->current_file = g_list_nth (m3u8->files, pos >= 0 ? pos : 0);
+#else
+      self->sequence =
+          GST_M3U8_MEDIA_FILE (g_list_nth_data (m3u8->files,
+              pos >= 0 ? pos : 0))->sequence;
+#endif
     } else {
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
       self->current_file = g_list_first (m3u8->files);
+#else
+      self->sequence = GST_M3U8_MEDIA_FILE (self->current_file->data)->sequence;
+#endif
     }
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
     self->sequence = GST_M3U8_MEDIA_FILE (self->current_file->data)->sequence;
+#endif
     self->sequence_position = 0;
     GST_DEBUG ("Setting first sequence at %u", (guint) self->sequence);
   }
@@ -1177,7 +1218,7 @@ gst_m3u8_client_advance_fragment (GstM3U8Client * client, gboolean forward)
     }
   }
   if (client->current_file) {
-    /* Store duration of the fragment we're using to update the position 
+    /* Store duration of the fragment we're using to update the position
      * the next time we advance */
     client->current_file_duration =
         GST_M3U8_MEDIA_FILE (client->current_file->data)->duration;
index 7b09de1..9f1e4aa 100644 (file)
@@ -64,6 +64,9 @@ struct _GstM3U8
   gint bandwidth;
   gint program_id;
   gchar *codecs;
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+  gint codec_count;
+#endif
   gint width;
   gint height;
   gboolean iframe;
index 91ac6c5..f965a5a 100644 (file)
@@ -88,7 +88,9 @@ GST_DEBUG_CATEGORY (adaptivedemux_debug);
 #define DEFAULT_LOOKBACK_FRAGMENTS 3
 #define DEFAULT_CONNECTION_SPEED 0
 #define DEFAULT_BITRATE_LIMIT 0.8
-
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+#define MAX_DASH_DOWNLOAD_ERROR_COUNT 200
+#endif
 enum
 {
   PROP_0,
@@ -187,9 +189,15 @@ static GstFlowReturn gst_adaptive_demux_combine_flows (GstAdaptiveDemux *
 static void
 gst_adaptive_demux_stream_fragment_download_finish (GstAdaptiveDemuxStream *
     stream, GstFlowReturn ret, GError * err);
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+static GstFlowReturn
+gst_adaptive_demux_stream_data_received_default (GstAdaptiveDemux * demux,
+    GstAdaptiveDemuxStream * stream, GstBuffer * buffer);
+#else
 static GstFlowReturn
 gst_adaptive_demux_stream_data_received_default (GstAdaptiveDemux * demux,
     GstAdaptiveDemuxStream * stream);
+#endif
 static GstFlowReturn
 gst_adaptive_demux_stream_finish_fragment_default (GstAdaptiveDemux * demux,
     GstAdaptiveDemuxStream * stream);
@@ -365,6 +373,11 @@ gst_adaptive_demux_init (GstAdaptiveDemux * demux,
   demux->num_lookback_fragments = DEFAULT_LOOKBACK_FRAGMENTS;
   demux->bitrate_limit = DEFAULT_BITRATE_LIMIT;
   demux->connection_speed = DEFAULT_CONNECTION_SPEED;
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+  demux->is_dashstreaming = FALSE;
+  demux->dash_error_count = 0;
+  demux->dash_newest_segment = NULL;
+#endif
 
   gst_element_add_pad (GST_ELEMENT (demux), demux->sinkpad);
 }
@@ -410,6 +423,38 @@ gst_adaptive_demux_change_state (GstElement * element,
   return result;
 }
 
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+static gboolean
+gst_adaptive_demux_check_http_header (GQuark field_id, const GValue * value,
+    gpointer data)
+{
+  GstAdaptiveDemux *demux = GST_ADAPTIVE_DEMUX_CAST (data);
+
+  if (value && g_ascii_strcasecmp (g_quark_to_string (field_id), "User-Agent") == 0) {
+    if (demux->user_agent)
+      g_free (demux->user_agent);
+    demux->user_agent = g_value_dup_string (value);
+    GST_INFO_OBJECT (demux, "User-Agent : %s", (demux->user_agent) ? (demux->user_agent) : NULL);
+  }
+
+  if (value && g_ascii_strcasecmp (g_quark_to_string (field_id), "Set-Cookie") == 0) {
+    guint i = 0;
+    gchar **cookies = (gchar **) g_malloc0 ((gst_value_array_get_size (value) + 1) * sizeof (gchar *));
+
+    for (i = 0; i < gst_value_array_get_size (value); i++) {
+      GST_INFO_OBJECT (demux, "Cookie : %s", g_value_get_string (gst_value_array_get_value (value, i)));
+      cookies[i] = g_value_dup_string (gst_value_array_get_value (value, i));
+    }
+    cookies[i] = NULL;
+    if (demux->cookies)
+      g_strfreev (demux->cookies);
+    demux->cookies = g_strdupv (cookies);
+    g_strfreev (cookies);
+  }
+  return TRUE;
+}
+#endif
+
 static gboolean
 gst_adaptive_demux_sink_event (GstPad * pad, GstObject * parent,
     GstEvent * event)
@@ -460,7 +505,7 @@ gst_adaptive_demux_sink_event (GstPad * pad, GstObject * parent,
           demux->manifest_base_uri = redirect_uri;
         }
 
-        GST_DEBUG_OBJECT (demux, "Fetched manifest at URI: %s (base: %s)",
+        GST_WARNING_OBJECT (demux, "Fetched manifest at URI: %s (base: %s)",
             demux->manifest_uri, GST_STR_NULL (demux->manifest_base_uri));
       } else {
         GST_WARNING_OBJECT (demux, "Upstream URI query failed.");
@@ -537,6 +582,32 @@ gst_adaptive_demux_sink_event (GstPad * pad, GstObject * parent,
       /* Swallow newsegments, we'll push our own */
       gst_event_unref (event);
       return TRUE;
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+    case GST_EVENT_CUSTOM_DOWNSTREAM_STICKY:{
+      const GstStructure *structure;
+      GstStructure *req_headers = NULL;
+      GstStructure *res_headers = NULL;
+
+      structure = gst_event_get_structure (event);
+      if (gst_structure_has_name (structure, "http-headers")) {
+        if (gst_structure_has_field (structure, "request-headers")) {
+          gst_structure_get (structure, "request-headers", GST_TYPE_STRUCTURE,
+              &req_headers, NULL);
+          gst_structure_foreach (req_headers,
+              gst_adaptive_demux_check_http_header, demux);
+          gst_structure_free(req_headers);
+        }
+        if (gst_structure_has_field (structure, "response-headers")) {
+          gst_structure_get (structure, "response-headers", GST_TYPE_STRUCTURE,
+              &res_headers, NULL);
+          gst_structure_foreach (res_headers,
+              gst_adaptive_demux_check_http_header, demux);
+          gst_structure_free(res_headers);
+        }
+      }
+      break;
+    }
+#endif
     default:
       break;
   }
@@ -584,11 +655,25 @@ gst_adaptive_demux_reset (GstAdaptiveDemux * demux)
     demux->priv->old_streams = NULL;
   }
 
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+  if (demux->dash_newest_segment) {
+    g_free (demux->dash_newest_segment);
+    demux->dash_newest_segment = NULL;
+  }
+#endif
+
   g_free (demux->manifest_uri);
   g_free (demux->manifest_base_uri);
   demux->manifest_uri = NULL;
   demux->manifest_base_uri = NULL;
-
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+  if (demux->user_agent)
+    g_free (demux->user_agent);
+  if (demux->cookies)
+    g_strfreev (demux->cookies);
+  demux->user_agent = NULL;
+  demux->cookies = NULL;
+#endif
   gst_adapter_clear (demux->priv->input_adapter);
   demux->priv->have_manifest = FALSE;
 
@@ -616,6 +701,13 @@ gst_adaptive_demux_handle_message (GstBin * bin, GstMessage * msg)
       for (iter = demux->streams; iter; iter = g_list_next (iter)) {
         stream = iter->data;
         if (GST_OBJECT_CAST (stream->src) == GST_MESSAGE_SRC (msg)) {
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+          gchar *caps_str = NULL;
+          GstCaps *pad_caps = NULL;
+          pad_caps     = gst_pad_get_current_caps(stream->pad);
+          if (pad_caps)
+            caps_str = gst_caps_to_string (pad_caps);
+#endif
           gst_message_parse_error (msg, &err, &debug);
 
           GST_WARNING_OBJECT (GST_ADAPTIVE_DEMUX_STREAM_PAD (stream),
@@ -629,10 +721,97 @@ gst_adaptive_demux_handle_message (GstBin * bin, GstMessage * msg)
             err->message = new_error;
           }
 
-          /* error, but ask to retry */
-          gst_adaptive_demux_stream_fragment_download_finish (stream,
-              GST_FLOW_CUSTOM_ERROR, err);
-
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+          if ((caps_str) && (strstr(caps_str,"dash_stream")) && (gst_adaptive_demux_is_live (demux))) {
+            if (demux->dash_error_count < MAX_DASH_DOWNLOAD_ERROR_COUNT) {
+              if (strstr(err->message,"Not Found")) {
+                char tmp_current_fragment[100] = {0,};
+                char tmp_newest_fragment[100] = {0,};
+                char tmp_intermediate_url[1000]={0,};
+                char *s1 = NULL , *s2 = NULL;
+                int index1=0, index2=0;
+                gboolean bRet = TRUE;
+
+                if (demux->dash_newest_segment) {
+                  g_free (demux->dash_newest_segment);
+                  demux->dash_newest_segment = NULL;
+                }
+
+                if (stream->fragment.uri) {
+                  s1 = strrchr(stream->fragment.uri, '/');
+                  index1 = (int)(s1 - stream->fragment.uri);
+                  index2 = (int)strlen(stream->fragment.uri);
+                  s1++;
+                  strncpy(tmp_current_fragment, s1, index2-index1-1);
+                  tmp_current_fragment[index2-index1-1]='\0';
+                }
+
+                s1 = s2 = NULL;
+                s1 = strstr(err->message,"Dash-Newest-Segment");
+                if (s1) {
+                  s1 = s1 + 20;
+                  s2 = strrchr(s1,',');
+                  index1 = (int)strlen(s1);
+                  index2 = (int)strlen(s2);
+                  strncpy(tmp_intermediate_url, s1, index1-index2);
+                  tmp_intermediate_url[index1-index2] = '\0';
+
+                  if (strcmp(tmp_intermediate_url,"(NULL)") != 0) {
+                    s1 = s2 = NULL;
+                    s1 = strrchr(tmp_intermediate_url, '/');
+                    index1 = (int)(s1 - tmp_intermediate_url);
+                    index2 = (int)strlen(tmp_intermediate_url);
+                    s1++;
+                    strncpy(tmp_newest_fragment, s1, index2-index1-1);
+                    tmp_newest_fragment[index2-index1-1]='\0';
+                  } else {
+                    GST_WARNING_OBJECT (demux, "Dash-Newest-Segment Not Available !!\n");
+                  }
+                }
+
+                if ((tmp_current_fragment)&&(tmp_newest_fragment)) {
+                  if (g_ascii_strcasecmp(tmp_newest_fragment,tmp_current_fragment) <= 0) {
+                    GST_DEBUG_OBJECT (demux, "newest fragment less than current fragment");
+                    bRet = FALSE;
+                  } else {
+                    GST_DEBUG_OBJECT (demux, "newest fragment more than current fragment");
+                    bRet = TRUE;
+                  }
+                }
+
+                demux->dash_newest_segment = g_strdup(tmp_newest_fragment);
+                demux->dash_error_count++;
+
+                if (bRet)
+                {
+                  GST_DEBUG_OBJECT (demux, "Advancing the Fragment \n");
+                  GstAdaptiveDemuxClass *klass;
+                  GstFlowReturn ret;
+                  klass = GST_ADAPTIVE_DEMUX_GET_CLASS (stream->demux);
+                  ret = klass->finish_fragment (stream->demux, stream);
+                  gst_adaptive_demux_stream_fragment_download_finish (stream, ret, NULL);
+                } else {
+                  GST_DEBUG_OBJECT (demux, "retry: Not advancing the fragment \n");
+                  gst_adaptive_demux_stream_fragment_download_finish (stream, GST_FLOW_OK, NULL);
+                }
+              } else {
+                GST_DEBUG_OBJECT (demux, "retry");
+                gst_adaptive_demux_stream_fragment_download_finish (stream, GST_FLOW_OK, NULL);
+              }
+            } else {
+              GST_DEBUG_OBJECT (demux, "error count reached MAX .. posting Error and stopping the task");
+              gst_adaptive_demux_stream_fragment_download_finish (stream, GST_FLOW_EOS, err);
+            }
+          } else
+#endif
+          {
+            /* error, but ask to retry */
+            gst_adaptive_demux_stream_fragment_download_finish (stream,GST_FLOW_CUSTOM_ERROR, err);
+          }
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+          gst_caps_unref (pad_caps);
+          g_free (caps_str);
+#endif
           g_error_free (err);
           g_free (debug);
           break;
@@ -938,6 +1117,10 @@ GstAdaptiveDemuxStream *
 gst_adaptive_demux_stream_new (GstAdaptiveDemux * demux, GstPad * pad)
 {
   GstAdaptiveDemuxStream *stream;
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+  gchar *factory_name = NULL;
+  GstElementFactory *factory = NULL;
+#endif
 
   stream = g_malloc0 (demux->stream_struct_size);
 
@@ -962,7 +1145,21 @@ gst_adaptive_demux_stream_new (GstAdaptiveDemux * demux, GstPad * pad)
   gst_segment_init (&stream->segment, GST_FORMAT_TIME);
   g_cond_init (&stream->fragment_download_cond);
   g_mutex_init (&stream->fragment_download_lock);
+
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+  factory = gst_element_get_factory(demux);
+  factory_name = GST_OBJECT_NAME(factory);
+  GST_DEBUG_OBJECT (demux,"Plugin Factory Name: %s", factory_name);
+
+  if (!demux->is_dashstreaming && g_strrstr(factory_name, "dashdemux")){
+       demux->is_dashstreaming = TRUE;
+       g_mutex_init (&demux->UC_download_lock);
+       GST_DEBUG_OBJECT (demux,"Enabling Flag is_dashstreaming !!!");
+  }
+#endif
+#ifndef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
   stream->adapter = gst_adapter_new ();
+#endif
 
   demux->next_streams = g_list_append (demux->next_streams, stream);
 
@@ -1021,6 +1218,13 @@ gst_adaptive_demux_stream_free (GstAdaptiveDemuxStream * stream)
   g_cond_clear (&stream->fragment_download_cond);
   g_mutex_clear (&stream->fragment_download_lock);
 
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+  if (demux->is_dashstreaming){
+    demux->is_dashstreaming = FALSE;
+    g_mutex_clear (&demux->UC_download_lock);
+  }
+#endif
+
   g_free (stream->fragment_bitrates);
 
   if (stream->pad) {
@@ -1030,7 +1234,9 @@ gst_adaptive_demux_stream_free (GstAdaptiveDemuxStream * stream)
   if (stream->pending_caps)
     gst_caps_unref (stream->pending_caps);
 
+#ifndef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
   g_object_unref (stream->adapter);
+#endif
 
   g_free (stream);
 }
@@ -1416,7 +1622,9 @@ gst_adaptive_demux_stop_tasks (GstAdaptiveDemux * demux)
     gst_task_join (stream->download_task);
     stream->download_error_count = 0;
     stream->need_header = TRUE;
+#ifndef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
     gst_adapter_clear (stream->adapter);
+#endif
   }
   gst_task_join (demux->priv->updates_task);
 }
@@ -1727,14 +1935,22 @@ gst_adaptive_demux_stream_finish_fragment_default (GstAdaptiveDemux * demux,
       stream->fragment.duration);
 }
 
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+static GstFlowReturn
+gst_adaptive_demux_stream_data_received_default (GstAdaptiveDemux * demux,
+    GstAdaptiveDemuxStream * stream, GstBuffer * buffer)
+#else
 static GstFlowReturn
 gst_adaptive_demux_stream_data_received_default (GstAdaptiveDemux * demux,
     GstAdaptiveDemuxStream * stream)
+#endif
 {
+#ifndef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
   GstBuffer *buffer;
 
   buffer = gst_adapter_take_buffer (stream->adapter,
       gst_adapter_available (stream->adapter));
+#endif
   return gst_adaptive_demux_stream_push_buffer (stream, buffer);
 }
 
@@ -1788,14 +2004,26 @@ _src_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
   stream->fragment_total_time +=
       g_get_monotonic_time () - stream->download_chunk_start_time;
 
+#ifndef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
   gst_adapter_push (stream->adapter, buffer);
+#endif
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+  demux->dash_error_count = 0;
+#endif
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+  GST_DEBUG_OBJECT (stream->pad, "Received buffer of size %" G_GSIZE_FORMAT,
+      gst_buffer_get_size (buffer));
+  ret = klass->data_received (demux, stream, buffer);
+#else
   GST_DEBUG_OBJECT (stream->pad, "Received buffer of size %" G_GSIZE_FORMAT
       ". Now %" G_GSIZE_FORMAT " on adapter", gst_buffer_get_size (buffer),
       gst_adapter_available (stream->adapter));
   ret = klass->data_received (demux, stream);
+#endif
   stream->download_chunk_start_time = g_get_monotonic_time ();
 
   if (ret != GST_FLOW_OK) {
+    GST_WARNING_OBJECT (stream->pad, "data_received return = %d",ret);
     if (ret < GST_FLOW_EOS) {
       GST_ELEMENT_ERROR (demux, STREAM, FAILED, (NULL),
           ("stream stopped, reason %s", gst_flow_get_name (ret)));
@@ -1849,9 +2077,56 @@ _src_event (GstPad * pad, GstObject * parent, GstEvent * event)
       GstAdaptiveDemuxClass *klass;
       GstFlowReturn ret;
 
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+      char tmp_current_fragment[100] = {0,};
+      char *s1 = NULL ;
+      int index1=0, index2=0;
+      gboolean bRet = TRUE;
+      gchar *caps_str = NULL;
+      GstCaps *pad_caps = NULL;
+      pad_caps = gst_pad_get_current_caps(stream->pad);
+      if (pad_caps)
+        caps_str = gst_caps_to_string (pad_caps);
+
+      if ((caps_str)&&(strstr(caps_str,"dash_stream")) &&
+          (gst_adaptive_demux_is_live (stream->demux))&&(stream->demux->dash_error_count > 0)) {
+
+        GST_DEBUG_OBJECT (stream->demux, "_src_event fragment comparison for Dash stream !!!\n");
+        if (stream->fragment.uri) {
+          s1 = strrchr(stream->fragment.uri, '/');
+          index1 = (int)(s1 - stream->fragment.uri);
+          index2 = (int)strlen(stream->fragment.uri);
+          s1++;
+          strncpy(tmp_current_fragment, s1, index2-index1-1);
+          tmp_current_fragment[index2-index1-1]='\0';
+        }
+        if ((tmp_current_fragment)&&(stream->demux->dash_newest_segment)) {
+          if (g_ascii_strcasecmp(stream->demux->dash_newest_segment,tmp_current_fragment) <= 0) {
+            GST_DEBUG_OBJECT (stream->demux, "newest fragment less than current fragment");
+            bRet = FALSE;
+          } else {
+            GST_DEBUG_OBJECT (stream->demux, "newest fragment more than current fragment");
+            bRet = TRUE;
+          }
+        }
+      }
+
+      if (bRet) {
+         klass = GST_ADAPTIVE_DEMUX_GET_CLASS (stream->demux);
+         ret = klass->finish_fragment (stream->demux, stream);
+         gst_adaptive_demux_stream_fragment_download_finish (stream, ret, NULL);
+      } else {
+         GST_DEBUG_OBJECT (stream->demux, "retry: Not advancing the fragment from src_event !!");
+         gst_adaptive_demux_stream_fragment_download_finish (stream, GST_FLOW_OK, NULL);
+      }
+
+      gst_caps_unref (pad_caps);
+      g_free (caps_str);
+#else
       klass = GST_ADAPTIVE_DEMUX_GET_CLASS (stream->demux);
       ret = klass->finish_fragment (stream->demux, stream);
       gst_adaptive_demux_stream_fragment_download_finish (stream, ret, NULL);
+#endif
       break;
     }
     default:
@@ -2008,6 +2283,23 @@ gst_adaptive_demux_stream_update_source (GstAdaptiveDemuxStream * stream,
       g_object_set (stream->src, "compress", FALSE, NULL);
     if (g_object_class_find_property (gobject_class, "keep-alive"))
       g_object_set (stream->src, "keep-alive", TRUE, NULL);
+
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+    if (demux->is_dashstreaming){
+      g_mutex_lock (&demux->UC_download_lock);
+      GST_DEBUG_OBJECT (demux, "DashDemux Case: Locking UC_download_lock !!!");
+    }
+    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);
+    if (demux->is_dashstreaming){
+      g_mutex_unlock (&demux->UC_download_lock);
+      GST_DEBUG_OBJECT (demux, "DashDemux Case: Unlocking UC_download_lock !!!");
+    }
+#endif
     if (g_object_class_find_property (gobject_class, "extra-headers")) {
       if (referer || refresh || !allow_cache) {
         GstStructure *extra_headers = gst_structure_new_empty ("headers");
@@ -2370,7 +2662,14 @@ gst_adaptive_demux_stream_download_loop (GstAdaptiveDemuxStream * stream)
           gst_adaptive_demux_stream_get_fragment_waiting_time (demux, stream);
       GST_MANIFEST_UNLOCK (demux);
       if (wait_time > 0)
+      {
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+        gint64 end_time = g_get_monotonic_time () + wait_time / GST_USECOND;
+        GST_DEBUG_OBJECT (stream->pad, "Download waiting for %" GST_TIME_FORMAT,
+            GST_TIME_ARGS (wait_time));
+#endif
         gst_adaptive_demux_stream_download_wait (stream, wait_time);
+      }
     } else {
       GST_MANIFEST_UNLOCK (demux);
     }
@@ -2561,7 +2860,7 @@ gst_adaptive_demux_updates_loop (GstAdaptiveDemux * demux)
     GstFlowReturn ret = GST_FLOW_OK;
 
     /* Wait here until we should do the next update or we're cancelled */
-    GST_DEBUG_OBJECT (demux, "Wait for next playlist update");
+    GST_DEBUG_OBJECT (demux, "Wait for next playlist update : next_update=%" GST_TIME_FORMAT,GST_TIME_ARGS(demux->priv->next_update));
 
     g_mutex_lock (&demux->priv->updates_timed_lock);
     if (demux->priv->stop_updates_task) {
@@ -2734,6 +3033,9 @@ gst_adaptive_demux_stream_advance_fragment_unlocked (GstAdaptiveDemux * demux,
 
   if (gst_adaptive_demux_is_live (demux)
       || gst_adaptive_demux_stream_has_next_fragment (demux, stream)) {
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+    demux->dash_error_count = 0;
+#endif
     ret = klass->stream_advance_fragment (stream);
   } else {
     ret = GST_FLOW_EOS;
@@ -2746,7 +3048,9 @@ gst_adaptive_demux_stream_advance_fragment_unlocked (GstAdaptiveDemux * demux,
     if (gst_adaptive_demux_stream_select_bitrate (demux, stream,
             gst_adaptive_demux_stream_update_current_bitrate (demux, stream))) {
       stream->need_header = TRUE;
+#ifndef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
       gst_adapter_clear (stream->adapter);
+#endif
       ret = (GstFlowReturn) GST_ADAPTIVE_DEMUX_FLOW_SWITCH;
     }
 
@@ -2812,9 +3116,13 @@ gst_adaptive_demux_update_manifest_default (GstAdaptiveDemux * demux)
   GstFragment *download;
   GstBuffer *buffer;
   GstFlowReturn ret;
-
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+  download = gst_uri_downloader_fetch_uri (demux->downloader,
+      demux->manifest_uri, NULL, demux->user_agent, demux->cookies, PLAYLIST_ADAPTIVE_RETRY,PLAYLIST_ADAPTIVE_TIMEOUT,TRUE, TRUE, TRUE, NULL);
+#else
   download = gst_uri_downloader_fetch_uri (demux->downloader,
       demux->manifest_uri, NULL, TRUE, TRUE, TRUE, NULL);
+#endif
   if (download) {
     GST_MANIFEST_LOCK (demux);
     g_free (demux->manifest_uri);
index f617c64..0ebb759 100644 (file)
@@ -85,6 +85,13 @@ G_BEGIN_DECLS
   g_clear_error (&err); \
 } G_STMT_END
 
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+#define DEFAULT_ADAPTIVE_RETRY -1
+#define DEFAULT_ADAPTIVE_TIMEOUT -1
+#define PLAYLIST_ADAPTIVE_RETRY 3
+#define PLAYLIST_ADAPTIVE_TIMEOUT 2
+#endif
+
 typedef struct _GstAdaptiveDemuxStreamFragment GstAdaptiveDemuxStreamFragment;
 typedef struct _GstAdaptiveDemuxStream GstAdaptiveDemuxStream;
 typedef struct _GstAdaptiveDemux GstAdaptiveDemux;
@@ -126,7 +133,9 @@ struct _GstAdaptiveDemuxStream
 #endif
   GstSegment segment;
 
+#ifndef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
   GstAdapter *adapter;
+#endif
 
   GstCaps *pending_caps;
   GstEvent *pending_segment;
@@ -206,7 +215,13 @@ struct _GstAdaptiveDemux
 
   gchar *manifest_uri;
   gchar *manifest_base_uri;
-
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+  gchar *user_agent;
+  gchar **cookies;
+  gboolean is_dashstreaming;
+  /* Lock for updating User Agent & Cookies */
+  GMutex UC_download_lock;
+#endif
   /* Properties */
   guint num_lookback_fragments;
   gfloat bitrate_limit;         /* limit of the available bitrate to use */
@@ -217,6 +232,10 @@ struct _GstAdaptiveDemux
 
   /* < private > */
   GstAdaptiveDemuxPrivate *priv;
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+  guint dash_error_count;
+  gchar *dash_newest_segment;
+#endif
 };
 
 /**
@@ -387,6 +406,20 @@ struct _GstAdaptiveDemuxClass
    * also push any pending data before moving to the next fragment.
    */
   GstFlowReturn (*finish_fragment) (GstAdaptiveDemux * demux, GstAdaptiveDemuxStream * stream);
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+  /**
+   * data_received:
+   * @demux: #GstAdaptiveDemux
+   * @stream: #GstAdaptiveDemuxStream
+   * @buffer: #GstBuffer
+   *
+   * Notifies the subclass that a fragment chunk was downloaded. The subclass
+   * can look at the data and modify/push data as desired.
+   *
+   * Returns: #GST_FLOW_OK if successful, #GST_FLOW_ERROR in case of error.
+   */
+  GstFlowReturn (*data_received) (GstAdaptiveDemux * demux, GstAdaptiveDemuxStream * stream, GstBuffer * buffer);
+#else
   /**
    * data_received:
    * @demux: #GstAdaptiveDemux
@@ -398,6 +431,7 @@ struct _GstAdaptiveDemuxClass
    * Returns: #GST_FLOW_OK if successful, #GST_FLOW_ERROR in case of error.
    */
   GstFlowReturn (*data_received) (GstAdaptiveDemux * demux, GstAdaptiveDemuxStream * stream);
+#endif
 
   /**
    * get_live_seek_range:
index 72e5e79..3b755c3 100644 (file)
@@ -346,10 +346,17 @@ gst_uri_downloader_set_range (GstUriDownloader * downloader,
   return TRUE;
 }
 
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+static gboolean
+gst_uri_downloader_set_uri (GstUriDownloader * downloader, const gchar * uri,
+    const gchar * referer, gchar* user_agent, gchar** cookies, gint max_retry , gint timeout , gboolean compress, gboolean refresh,
+    gboolean allow_cache)
+#else
 static gboolean
 gst_uri_downloader_set_uri (GstUriDownloader * downloader, const gchar * uri,
     const gchar * referer, gboolean compress, gboolean refresh,
     gboolean allow_cache)
+#endif
 {
   GstPad *pad;
   GObjectClass *gobject_class;
@@ -404,6 +411,17 @@ gst_uri_downloader_set_uri (GstUriDownloader * downloader, const gchar * uri,
     g_object_set (downloader->priv->urisrc, "compress", compress, NULL);
   if (g_object_class_find_property (gobject_class, "keep-alive"))
     g_object_set (downloader->priv->urisrc, "keep-alive", TRUE, NULL);
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+  if (user_agent && g_object_class_find_property (gobject_class, "user-agent"))
+    g_object_set (downloader->priv->urisrc, "user-agent", user_agent, NULL);
+  if (cookies && g_object_class_find_property (gobject_class, "cookies"))
+    g_object_set (downloader->priv->urisrc, "cookies", cookies, NULL);
+
+  if ((max_retry != -1)&&(g_object_class_find_property (gobject_class, "retries")))
+    g_object_set (downloader->priv->urisrc, "retries", max_retry, NULL);
+  if ((timeout != -1)&&(g_object_class_find_property (gobject_class, "timeout")))
+    g_object_set (downloader->priv->urisrc, "timeout", timeout, NULL);
+#endif
   if (g_object_class_find_property (gobject_class, "extra-headers")) {
     if (referer || refresh || !allow_cache) {
       GstStructure *extra_headers = gst_structure_new_empty ("headers");
@@ -459,6 +477,16 @@ gst_uri_downloader_set_method (GstUriDownloader * downloader,
   return FALSE;
 }
 
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+GstFragment *
+gst_uri_downloader_fetch_uri (GstUriDownloader * downloader,
+    const gchar * uri, const gchar * referer, gchar* user_agent, gchar** cookies, gint max_retry , gint timeout , gboolean compress,
+    gboolean refresh, gboolean allow_cache, GError ** err)
+{
+  return gst_uri_downloader_fetch_uri_with_range (downloader, uri,
+      referer, user_agent, cookies, max_retry,timeout,compress, refresh, allow_cache, 0, -1, err);
+}
+#else
 GstFragment *
 gst_uri_downloader_fetch_uri (GstUriDownloader * downloader,
     const gchar * uri, const gchar * referer, gboolean compress,
@@ -467,7 +495,7 @@ gst_uri_downloader_fetch_uri (GstUriDownloader * downloader,
   return gst_uri_downloader_fetch_uri_with_range (downloader, uri,
       referer, compress, refresh, allow_cache, 0, -1, err);
 }
-
+#endif
 /**
  * gst_uri_downloader_fetch_uri_with_range:
  * @downloader: the #GstUriDownloader
@@ -477,11 +505,19 @@ gst_uri_downloader_fetch_uri (GstUriDownloader * downloader,
  *
  * Returns the downloaded #GstFragment
  */
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+GstFragment *
+gst_uri_downloader_fetch_uri_with_range (GstUriDownloader *
+    downloader, const gchar * uri, const gchar * referer, gchar* user_agent, gchar** cookies, gint max_retry , gint timeout , gboolean compress,
+    gboolean refresh, gboolean allow_cache,
+    gint64 range_start, gint64 range_end, GError ** err)
+#else
 GstFragment *
 gst_uri_downloader_fetch_uri_with_range (GstUriDownloader *
     downloader, const gchar * uri, const gchar * referer, gboolean compress,
     gboolean refresh, gboolean allow_cache,
     gint64 range_start, gint64 range_end, GError ** err)
+#endif
 {
   GstStateChangeReturn ret;
   GstFragment *download = NULL;
@@ -497,13 +533,19 @@ gst_uri_downloader_fetch_uri_with_range (GstUriDownloader *
     GST_DEBUG_OBJECT (downloader, "Cancelled, aborting fetch");
     goto quit;
   }
-
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+  if (!gst_uri_downloader_set_uri (downloader, uri, referer, user_agent, cookies, max_retry , timeout ,compress, refresh,
+          allow_cache)) {
+    GST_WARNING_OBJECT (downloader, "Failed to set URI");
+    goto quit;
+  }
+#else
   if (!gst_uri_downloader_set_uri (downloader, uri, referer, compress, refresh,
           allow_cache)) {
     GST_WARNING_OBJECT (downloader, "Failed to set URI");
     goto quit;
   }
-
+#endif
   gst_bus_set_flushing (downloader->priv->bus, FALSE);
   if (downloader->priv->download)
     g_object_unref (downloader->priv->download);
index 80b8a3e..b8d20e7 100644 (file)
@@ -61,8 +61,13 @@ struct _GstUriDownloaderClass
 GType gst_uri_downloader_get_type (void);
 
 GstUriDownloader * gst_uri_downloader_new (void);
+#ifdef TIZEN_FEATURE_ADAPTIVE_MODIFICATION
+GstFragment * gst_uri_downloader_fetch_uri (GstUriDownloader * downloader, const gchar * uri, const gchar * referer, gchar* user_agent, gchar** cookies, gint max_retry , gint timeout , gboolean compress, gboolean refresh, gboolean allow_cache, GError ** err);
+GstFragment * gst_uri_downloader_fetch_uri_with_range (GstUriDownloader * downloader, const gchar * uri, const gchar * referer, gchar* user_agent, gchar** cookies, gint max_retry , gint timeout , gboolean compress, gboolean refresh, gboolean allow_cache, gint64 range_start, gint64 range_end, GError ** err);
+#else
 GstFragment * gst_uri_downloader_fetch_uri (GstUriDownloader * downloader, const gchar * uri, const gchar * referer, gboolean compress, gboolean refresh, gboolean allow_cache, GError ** err);
 GstFragment * gst_uri_downloader_fetch_uri_with_range (GstUriDownloader * downloader, const gchar * uri, const gchar * referer, gboolean compress, gboolean refresh, gboolean allow_cache, gint64 range_start, gint64 range_end, GError ** err);
+#endif
 void gst_uri_downloader_reset (GstUriDownloader *downloader);
 void gst_uri_downloader_cancel (GstUriDownloader *downloader);
 void gst_uri_downloader_free (GstUriDownloader *downloader);
index 7765afa..0c7d60a 100644 (file)
@@ -273,6 +273,8 @@ mpegts_packetizer_init (MpegTSPacketizer2 * packetizer)
   packetizer->refoffset = -1;
   packetizer->last_in_time = GST_CLOCK_TIME_NONE;
 #ifdef TIZEN_FEATURE_TSDEMUX_MODIFICATION
+  packetizer->ra_base_time = GST_CLOCK_TIME_NONE;
+  packetizer->is_random_access = FALSE;
   packetizer->is_non_pcr_live_feed = FALSE;
   packetizer->non_pcr_base_time = GST_CLOCK_TIME_NONE;
   packetizer->last_live_pts = GST_CLOCK_TIME_NONE;
@@ -403,12 +405,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);
@@ -450,12 +466,57 @@ mpegts_packetizer_parse_adaptation_field_control (MpegTSPacketizer2 *
     }
   }
 #endif
+
+#ifdef TIZEN_FEATURE_TSDEMUX_MODIFICATION
+/* Random Access indicator */
+  if (afcflags & MPEGTS_AFC_RANDOM_ACCES_FLAGS) {
+    GST_DEBUG ("Random access flag enabled: 0x40");
+       packetizer->is_random_access = TRUE;
+  }
+/*
+[prasenjit.c] For Jio Beats Audio-Only HLS Contents , PCR flags are not getting set.
+As a result , when DRC switch happens , Base Offset not getting updated resulting in timestamp mismatch.
+Currently have checked for adaptation control flags and if PCR is not getting set along with other flags , Skew calculation is done based on last_in_time.
+*/
+  if ((afcflags != 0x00)&&(!(afcflags & MPEGTS_AFC_PCR_FLAG)))
+  {
+       MpegTSPCR *pcrtable = NULL;
+       pcrtable = get_pcr_table (packetizer, packet->pid);
+       GST_DEBUG ("last_in_time %" GST_TIME_FORMAT " base_pcrtime:%" GST_TIME_FORMAT
+        " base_time:%" GST_TIME_FORMAT " pcroffset:%" GST_TIME_FORMAT " skew:%" GST_TIME_FORMAT " last_pcrtime:%" GST_TIME_FORMAT ,
+               GST_TIME_ARGS (packetizer->last_in_time),
+               GST_TIME_ARGS (pcrtable->base_pcrtime),
+               GST_TIME_ARGS (pcrtable->base_time),
+               GST_TIME_ARGS (pcrtable->pcroffset),
+               GST_TIME_ARGS (pcrtable->skew),
+               GST_TIME_ARGS (pcrtable->last_pcrtime));
+
+/*
+[prasenjit.c] For Hotstar Live Streams , PCR flags comes intermittently. This code was causing skew calculation getting done for those streams , causing invalid timestamps to get passed to Decoder.
+Blocked the code for Live Streams.
+Additionally , if Skew calculation is already done via this logic , need to disable RA flag to avoid base_time double recalculation.
+*/
+         if (((!GST_CLOCK_TIME_IS_VALID (pcrtable->base_time))||(!GST_CLOCK_TIME_IS_VALID (pcrtable->base_pcrtime)))&&(!packetizer->is_live_stream))
+         {
+               GST_WARNING ("PCR Flag is not set. Need to Reset the TS Basetime properly (disabling RA flag if enabled) !!!");
+               packet->pcr = packetizer->last_in_time;
+               calculate_skew (packetizer, pcrtable, packet->pcr,packetizer->last_in_time);
+               packetizer->is_random_access = FALSE;
+         }
+  }
+  else if ((afcflags == 0x00)&&(!(afcflags & MPEGTS_AFC_PCR_FLAG))&&(packetizer->is_live_stream))
+  {
+         GST_DEBUG ("Non-PCR Live Stream Case !!");
+         packetizer->is_non_pcr_live_feed = TRUE;
+  }
+#else
 #ifdef TIZEN_FEATURE_TSDEMUX_MODIFICATION
   if ((afcflags == 0x00) && (!(afcflags & MPEGTS_AFC_PCR_FLAG)) && (packetizer->is_live_stream)) {
     GST_DEBUG ("Non-PCR Live Stream Case !!");
     packetizer->is_non_pcr_live_feed = TRUE;
   }
 #endif
+#endif
 
   return TRUE;
 }
@@ -596,6 +657,8 @@ mpegts_packetizer_clear (MpegTSPacketizer2 * packetizer)
   packetizer->map_offset = 0;
   packetizer->last_in_time = GST_CLOCK_TIME_NONE;
 #ifdef TIZEN_FEATURE_TSDEMUX_MODIFICATION
+  packetizer->ra_base_time = GST_CLOCK_TIME_NONE;
+  packetizer->is_random_access = FALSE;
   packetizer->is_live_stream = FALSE;
 #endif
 
@@ -1000,6 +1063,9 @@ mpegts_packetizer_push_section (MpegTSPacketizer2 * packetizer,
       GST_LOG
           ("PID 0x%04x PUSI and pointer == 0, skipping straight to section_start parsing",
           packet->pid);
+#ifdef TIZEN_FEATURE_TSDEMUX_MODIFICATION
+      mpegts_packetizer_clear_section (stream);
+#endif
       goto section_start;
     }
   }
@@ -1548,8 +1614,20 @@ no_skew:
   pcr->prev_in_time = time;
   pcr->prev_send_diff = send_diff;
 
+#ifdef TIZEN_FEATURE_TSDEMUX_MODIFICATION
+    GST_DEBUG (" gstpcrtime %" GST_TIME_FORMAT " base_pcrtime:%" GST_TIME_FORMAT
+        " base_time:%" GST_TIME_FORMAT " pcroffset:%" GST_TIME_FORMAT " out_time:%" GST_TIME_FORMAT"skew:%" GST_TIME_FORMAT " last_pcrtime:%" GST_TIME_FORMAT ,
+        GST_TIME_ARGS (gstpcrtime),
+        GST_TIME_ARGS (pcr->base_pcrtime),
+        GST_TIME_ARGS (pcr->base_time),
+        GST_TIME_ARGS (pcr->pcroffset),
+        GST_TIME_ARGS (out_time),
+        GST_TIME_ARGS (pcr->skew),
+        GST_TIME_ARGS (pcr->last_pcrtime));
+#else
   GST_DEBUG ("skew %" G_GINT64_FORMAT ", out %" GST_TIME_FORMAT,
       pcr->skew, GST_TIME_ARGS (out_time));
+#endif
 
   return out_time;
 }
@@ -1681,6 +1759,12 @@ _reevaluate_group_pcr_offset (MpegTSPCR * pcrtable, PCROffsetGroup * group)
         GST_DEBUG ("Wraparound prev-cur (guess_offset:%" GST_TIME_FORMAT
             ") bitrate:%" G_GUINT64_FORMAT,
             GST_TIME_ARGS (PCRTIME_TO_GSTTIME (guess_offset)), lastbr);
+#ifdef TIZEN_FEATURE_TSDEMUX_MODIFICATION
+        if(prevbr == 0) {
+          GST_ERROR ("Division by zero error, prevbr is 0");
+          continue;
+        }
+#endif
         diffprev = (float) 100.0 *(ABSDIFF (prevbr, lastbr)) / (float) prevbr;
         GST_DEBUG ("Difference with previous bitrate:%f", diffprev);
         if (diffprev < 10.0) {
@@ -2211,6 +2295,18 @@ mpegts_packetizer_pts_to_ts (MpegTSPacketizer2 * packetizer,
   /* Use clock skew if present */
   if (packetizer->calculate_skew
       && GST_CLOCK_TIME_IS_VALID (pcrtable->base_time)) {
+#ifdef TIZEN_FEATURE_TSDEMUX_MODIFICATION
+    res = pts + pcrtable->pcroffset;
+    GST_DEBUG ("pts %" GST_TIME_FORMAT " base_pcrtime:%" GST_TIME_FORMAT
+        " base_time:%" GST_TIME_FORMAT " pcroffset:%" GST_TIME_FORMAT " res:%" GST_TIME_FORMAT"skew:%" GST_TIME_FORMAT " last_pcrtime:%" GST_TIME_FORMAT ,
+        GST_TIME_ARGS (pts),
+        GST_TIME_ARGS (pcrtable->base_pcrtime),
+        GST_TIME_ARGS (pcrtable->base_time),
+        GST_TIME_ARGS (pcrtable->pcroffset),
+        GST_TIME_ARGS (res),
+        GST_TIME_ARGS (pcrtable->skew),
+        GST_TIME_ARGS (pcrtable->last_pcrtime));
+#else
     GST_DEBUG ("pts %" GST_TIME_FORMAT " base_pcrtime:%" GST_TIME_FORMAT
         " base_time:%" GST_TIME_FORMAT " pcroffset:%" GST_TIME_FORMAT,
         GST_TIME_ARGS (pts),
@@ -2218,6 +2314,7 @@ mpegts_packetizer_pts_to_ts (MpegTSPacketizer2 * packetizer,
         GST_TIME_ARGS (pcrtable->base_time),
         GST_TIME_ARGS (pcrtable->pcroffset));
     res = pts + pcrtable->pcroffset;
+#endif
 
     /* Don't return anything if we differ too much against last seen PCR */
     /* FIXME : Ideally we want to figure out whether we have a wraparound or
@@ -2225,6 +2322,40 @@ 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
      */
+     /*
+       * [prasenjit.c] 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
+     GstClockTime 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 (ABSDIFF (res, pcrtable->last_pcrtime) > 15 * GST_SECOND))
       res = GST_CLOCK_TIME_NONE;
     else {
@@ -2234,6 +2365,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;
@@ -2301,8 +2433,17 @@ mpegts_packetizer_pts_to_ts (MpegTSPacketizer2 * packetizer,
         GST_DEBUG ("Using group !");
         refpcr = group->first_pcr;
         refpcroffset = group->pcr_offset;
+#ifdef TIZEN_FEATURE_TSDEMUX_MODIFICATION
+        if (pts < PCRTIME_TO_GSTTIME (refpcr)) {
+          if (PCRTIME_TO_GSTTIME (refpcr) - pts > GST_SECOND)
+            pts += PCR_GST_MAX_VALUE;
+          else
+            refpcr = G_MAXINT64;
+        }
+#else
         if (pts < refpcr)
           refpcr -= PCR_MAX_VALUE;
+#endif
       }
     }
     if (refpcr != G_MAXINT64)
@@ -2312,7 +2453,11 @@ mpegts_packetizer_pts_to_ts (MpegTSPacketizer2 * packetizer,
       GST_WARNING ("No groups, can't calculate timestamp");
   }
 #ifdef TIZEN_FEATURE_TSDEMUX_MODIFICATION
-  else if ((packetizer->is_non_pcr_live_feed) && (GST_CLOCK_TIME_IS_VALID(pts))) {
+  else if(packetizer->is_random_access){
+       if(!GST_CLOCK_TIME_IS_VALID (packetizer->ra_base_time))
+               packetizer->ra_base_time = pts;
+       res = pts - packetizer->ra_base_time;
+  } else if ((packetizer->is_non_pcr_live_feed) && (GST_CLOCK_TIME_IS_VALID(pts))) {
     /*
     [prasenjit.c] For Live Youtube Channels , PCR flag does not come.
     Due to this , base offset of the content pts values are not obtained , so playback does not work.
index af90268..88a1d5f 100644 (file)
@@ -278,6 +278,9 @@ struct _MpegTSPacketizer2 {
   /* Last inputted timestamp */
   GstClockTime last_in_time;
 #ifdef TIZEN_FEATURE_TSDEMUX_MODIFICATION
+  /* Random Access flag handling*/
+  GstClockTime ra_base_time;
+  gboolean is_random_access;
   gboolean is_live_stream;
   gboolean is_non_pcr_live_feed;
   GstClockTime non_pcr_base_time;
index 659a2fa..498d33f 100644 (file)
@@ -410,6 +410,11 @@ gst_ts_demux_reset (MpegTSBase * base)
   demux->group_id = G_MAXUINT;
 
   demux->last_seek_offset = -1;
+
+#ifdef TIZEN_FEATURE_TSDEMUX_MODIFICATION
+  demux->has_video = FALSE;
+  demux->video_keyframe_found = FALSE;
+#endif
 #ifdef TIZEN_FEATURE_AVOID_PAD_SWITCHING
   gst_ts_demux_remove_old_streams (demux, FALSE);
 #endif
@@ -696,6 +701,11 @@ scan_keyframe_h264 (TSDemuxStream * stream, const guint8 * data,
             GST_DEBUG_OBJECT (stream->pad, "Found keyframe at: %u",
                 unit.sc_offset);
             frame_unit = unit;
+
+#ifdef TIZEN_FEATURE_TSDEMUX_MODIFICATION
+            GstTSDemux *demux = GST_TS_DEMUX(gst_pad_get_parent(stream->pad));
+            demux->video_keyframe_found = TRUE;
+#endif
           }
         }
 
@@ -860,6 +870,11 @@ gst_ts_demux_do_seek (MpegTSBase * base, GstEvent * event)
   demux->last_seek_offset = base->seek_offset;
   demux->rate = rate;
   res = GST_FLOW_OK;
+#ifdef TIZEN_FEATURE_TSDEMUX_MODIFICATION
+  demux->video_keyframe_found = FALSE;
+#endif
+
+  GST_DEBUG("seek_offset = %"G_GUINT64_FORMAT, base->seek_offset);
 
   gst_segment_do_seek (&demux->segment, rate, format, flags, start_type,
       start, stop_type, stop, NULL);
@@ -1083,9 +1098,7 @@ static GstPad *
 create_pad_for_stream (MpegTSBase * base, MpegTSBaseStream * bstream,
     MpegTSBaseProgram * program)
 {
-#ifndef TIZEN_FEATURE_AVOID_PAD_SWITCHING
   GstTSDemux *demux = GST_TS_DEMUX (base);
-#endif
   TSDemuxStream *stream = (TSDemuxStream *) bstream;
   gchar *name = NULL;
   GstCaps *caps = NULL;
@@ -1452,6 +1465,16 @@ done:
     gst_pad_push_event (pad, event);
     g_free (stream_id);
 #endif
+
+//caps modification done for both audio and video streams by adding adaptive_streaming flag.
+//This flag will be used by parser / decoder to identify whether the stream is a HLS stream or not for their processing.
+#ifdef TIZEN_FEATURE_TSDEMUX_MODIFICATION
+    caps = gst_caps_make_writable (caps);
+    gst_caps_set_simple (caps,"adaptive_stream", G_TYPE_BOOLEAN, TRUE, "hls_stream", G_TYPE_BOOLEAN, TRUE, NULL);
+    GST_DEBUG("*** modified caps for hls streaming = %" GST_PTR_FORMAT,
+        caps);
+#endif
+
     gst_pad_set_caps (pad, caps);
     if (!stream->taglist)
       stream->taglist = gst_tag_list_new_empty ();
@@ -1461,6 +1484,15 @@ done:
     gst_pad_set_event_function (pad, gst_ts_demux_srcpad_event);
   }
 
+#ifdef TIZEN_FEATURE_TSDEMUX_MODIFICATION
+    /* Push pending tags */
+    if (stream->taglist) {
+      /* post now, send event on pad later */
+      GST_DEBUG_OBJECT (stream->pad, "Posting tags %" GST_PTR_FORMAT, stream->taglist);
+       gst_element_post_message (GST_ELEMENT_CAST (demux), gst_message_new_tag (GST_OBJECT_CAST (demux), gst_tag_list_copy (stream->taglist)));
+    }
+#endif
+
   if (name)
     g_free (name);
   if (template)
@@ -1509,6 +1541,9 @@ gst_ts_demux_stream_added (MpegTSBase * base, MpegTSBaseStream * bstream,
         && bstream->stream_type == GST_MPEGTS_STREAM_TYPE_VIDEO_H264) {
       stream->scan_function =
           (GstTsDemuxKeyFrameScanFunction) scan_keyframe_h264;
+#ifdef TIZEN_FEATURE_TSDEMUX_MODIFICATION
+      demux->has_video = TRUE;
+#endif
     } else {
       stream->scan_function = NULL;
     }
@@ -2270,6 +2305,14 @@ calculate_and_push_newsegment (GstTSDemux * demux, TSDemuxStream * stream)
       demux->segment.time = firstts;
       demux->segment.rate = demux->rate;
       demux->segment.base = base;
+#ifdef TIZEN_FEATURE_TSDEMUX_MODIFICATION
+      /*Modification : when first program using firstts, but if seek,
+                gst_ts_demux_do_seek() already set the segment*/
+      if(demux->reset_segment)
+      {
+        demux->reset_segment = FALSE;
+      }
+#endif
     }
   } else if (demux->segment.start < firstts) {
     /* Take into account the offset to the first buffer timestamp */
@@ -2414,8 +2457,15 @@ gst_ts_demux_push_pending_data (GstTSDemux * demux, TSDemuxStream * stream)
   if (stream->needs_keyframe) {
     MpegTSBase *base = (MpegTSBase *) demux;
 
+#ifdef TIZEN_FEATURE_TSDEMUX_MODIFICATION
+    /*FIXME : for seek case, only when ts stream has video and also video stream had found the key_frame, then push the stream*/
+    if ((gst_ts_demux_adjust_seek_offset_for_keyframe (stream, stream->data,
+                stream->current_size) && (demux->has_video ? demux->video_keyframe_found : TRUE) ) || demux->last_seek_offset == 0)
+#else
     if ((gst_ts_demux_adjust_seek_offset_for_keyframe (stream, stream->data,
-                stream->current_size)) || demux->last_seek_offset == 0) {
+                stream->current_size) ) || demux->last_seek_offset == 0)
+#endif
+    {
       GST_DEBUG_OBJECT (stream->pad,
           "Got Keyframe, ready to go at %" GST_TIME_FORMAT,
           GST_TIME_ARGS (stream->pts));
@@ -2424,13 +2474,24 @@ gst_ts_demux_push_pending_data (GstTSDemux * demux, TSDemuxStream * stream)
       stream->seeked_dts = stream->dts;
       stream->needs_keyframe = FALSE;
     } else {
-      base->seek_offset = demux->last_seek_offset - 200 * base->packetsize;
-      if (demux->last_seek_offset < 200 * (guint64)base->packetsize)
-        base->seek_offset = 0;
-      demux->last_seek_offset = base->seek_offset;
-      mpegts_packetizer_flush (base->packetizer, FALSE);
-      base->mode = BASE_MODE_SEEKING;
+#ifdef TIZEN_FEATURE_TSDEMUX_MODIFICATION
+      /*Modification : fix seek performance issue, when found one non-keyframe,
+                 need to combine the left packets to a complete frame and check if it is Keyframe */
+      if(base->seek_offset - demux->last_seek_offset > 100 * base->packetsize)
+      {
+        base->seek_offset = demux->last_seek_offset - 100 * base->packetsize;
 
+#else
+        base->seek_offset = demux->last_seek_offset - 200 * base->packetsize;
+#endif
+        if (demux->last_seek_offset < 200 * base->packetsize)
+          base->seek_offset = 0;
+        demux->last_seek_offset = base->seek_offset;
+        mpegts_packetizer_flush (base->packetizer, FALSE);
+        base->mode = BASE_MODE_SEEKING;
+#ifdef TIZEN_FEATURE_TSDEMUX_MODIFICATION
+      }
+#endif
       stream->continuity_counter = CONTINUITY_UNSET;
       res = GST_FLOW_REWINDING;
       g_free (stream->data);
index c951fd7..820a26f 100644 (file)
@@ -88,6 +88,11 @@ struct _GstTSDemux
 
   /* Used when seeking for a keyframe to go backward in the stream */
   guint64 last_seek_offset;
+
+#ifdef TIZEN_FEATURE_TSDEMUX_MODIFICATION
+  gboolean video_keyframe_found;
+  gboolean has_video;
+#endif
 };
 
 struct _GstTSDemuxClass
index 22312dc..860f7b0 100644 (file)
@@ -4,7 +4,7 @@
 
 Name:           gst-plugins-bad
 Version:        1.6.1
-Release:        9
+Release:        10
 Summary:        GStreamer Streaming-Media Framework Plug-Ins
 License:        LGPL-2.0+
 Group:          Multimedia/Framework
@@ -79,7 +79,13 @@ processing capabilities can be added simply by installing new plug-ins.
 %build
 export V=1
 NOCONFIGURE=1 ./autogen.sh
-export CFLAGS+=" -Wall -g -fPIC -DTIZEN_FEATURE_WLSINK_ENHANCEMENT -DTIZEN_FEATURE_AVOID_PAD_SWITCHING -DTIZEN_FEATURE_ADAPTIVE_MODIFICATION -DTIZEN_FEATURE_TSDEMUX_MODIFICATION -DTIZEN_FEATURE_UPSTREAM"
+export CFLAGS+=" -Wall -g -fPIC\
+  -DTIZEN_FEATURE_WLSINK_ENHANCEMENT\
+  -DTIZEN_FEATURE_AVOID_PAD_SWITCHING\
+  -DTIZEN_FEATURE_ADAPTIVE_MODIFICATION\
+  -DTIZEN_FEATURE_TSDEMUX_MODIFICATION\
+  -DTIZEN_FEATURE_UPSTREAM"
+
 %configure\
        --disable-static\
        --disable-examples\
@@ -119,7 +125,6 @@ export CFLAGS+=" -Wall -g -fPIC -DTIZEN_FEATURE_WLSINK_ENHANCEMENT -DTIZEN_FEATU
        --disable-adpcmenc\
        --disable-aiff\
        --disable-asfmux\
-       --disable-audiomixer\
        --disable-compositor\
        --disable-audiovisualizers\
        --disable-bayer\
@@ -263,6 +268,7 @@ rm -rf $RPM_BUILD_ROOT
 #%{_libdir}/gstreamer-%{gst_branch}/libgstvideofiltersbad.so
 #%{_libdir}/gstreamer-%{gst_branch}/libgstyadif.so
 #%{_libdir}/gstreamer-%{gst_branch}/libgstuvch264.so
+%{_libdir}/gstreamer-%{gst_branch}/libgstaudiomixer.so
 
 %if %{with wayland}
 %{_libdir}/libgstwayland-%{gst_branch}.so.0*