Merge the tizen patch and fix build err based on 1.12.2
[platform/upstream/gst-plugins-good.git] / ext / soup / gstsouphttpsrc.c
index 2d08e13..f6b8fb4 100644 (file)
@@ -447,6 +447,17 @@ gst_soup_http_src_reset (GstSoupHTTPSrc * src)
   src->reduce_blocksize_count = 0;
   src->increase_blocksize_count = 0;
 
+#ifdef TIZEN_FEATURE_SOUP_MODIFICATION
+  if (src->dash_oldest_segment) {
+    g_free (src->dash_oldest_segment);
+    src->dash_oldest_segment = NULL;
+  }
+  if (src->dash_newest_segment) {
+    g_free (src->dash_newest_segment);
+    src->dash_newest_segment = NULL;
+  }
+#endif
+
   g_cancellable_reset (src->cancellable);
   if (src->input_stream) {
     g_object_unref (src->input_stream);
@@ -491,13 +502,19 @@ gst_soup_http_src_init (GstSoupHTTPSrc * src)
   src->max_retries = DEFAULT_RETRIES;
   src->method = DEFAULT_SOUP_METHOD;
   src->minimum_blocksize = gst_base_src_get_blocksize (GST_BASE_SRC_CAST (src));
+#ifdef TIZEN_FEATURE_SOUP_MODIFICATION
+  src->dash_oldest_segment = NULL;
+  src->dash_newest_segment = NULL;
+#endif
   proxy = g_getenv ("http_proxy");
   if (!gst_soup_http_src_set_proxy (src, proxy)) {
     GST_WARNING_OBJECT (src,
         "The proxy in the http_proxy env var (\"%s\") cannot be parsed.",
         proxy);
   }
-
+#ifdef TIZEN_FEATURE_SOUP_MODIFICATION
+  src->cookie_jar  = NULL;
+#endif
   gst_base_src_set_automatic_eos (GST_BASE_SRC (src), FALSE);
 
   gst_soup_http_src_reset (src);
@@ -599,8 +616,29 @@ gst_soup_http_src_set_property (GObject * object, guint prop_id,
       break;
     }
     case PROP_COOKIES:
+#ifdef TIZEN_FEATURE_SOUP_MODIFICATION
+    {
+      char **array;
+      SoupURI *base_uri;
+      g_strfreev (src->cookies);
+      src->cookies = g_strdupv (g_value_get_boxed (value));
+
+      if (src->cookie_jar && ((array = src->cookies) != NULL)) {
+        base_uri = soup_uri_new (src->location);
+        GST_INFO_OBJECT (src, "request to set cookies...");
+        while (*array != NULL) {
+          soup_cookie_jar_add_cookie (src->cookie_jar,
+              soup_cookie_parse (*array++, base_uri));
+        }
+        soup_uri_free (base_uri);
+      } else {
+        GST_INFO_OBJECT (src, "set cookies after session creation");
+      }
+    }
+#else
       g_strfreev (src->cookies);
       src->cookies = g_strdupv (g_value_get_boxed (value));
+#endif
       break;
     case PROP_IS_LIVE:
       gst_base_src_set_live (GST_BASE_SRC (src), g_value_get_boolean (value));
@@ -702,7 +740,26 @@ gst_soup_http_src_get_property (GObject * object, guint prop_id,
       }
       break;
     case PROP_COOKIES:
-      g_value_set_boxed (value, g_strdupv (src->cookies));
+#ifdef TIZEN_FEATURE_SOUP_MODIFICATION
+    {
+        GSList *cookie_list, *c;
+        gchar **cookies, **array;
+
+        cookies = NULL;
+        if ((src->cookie_jar) &&
+            ((cookie_list = soup_cookie_jar_all_cookies (src->cookie_jar)) != NULL)) {
+          cookies = g_new0 (gchar *, g_slist_length(cookie_list) + 1);
+          array = cookies;
+          for (c = cookie_list; c; c = c->next) {
+            *array++ = soup_cookie_to_set_cookie_header ((SoupCookie *)(c->data));
+          }
+          soup_cookies_free (cookie_list);
+        }
+        g_value_set_boxed (value, cookies);
+    }
+#else
+        g_value_set_boxed (value, g_strdupv (src->cookies));
+#endif
       break;
     case PROP_IS_LIVE:
       g_value_set_boolean (value, gst_base_src_is_live (GST_BASE_SRC (src)));
@@ -789,7 +846,14 @@ gst_soup_http_src_add_range_header (GstSoupHTTPSrc * src, guint64 offset,
   gint rc;
 
   soup_message_headers_remove (src->msg->request_headers, "Range");
-  if (offset || stop_offset != -1) {
+
+/* This changes are needed to enable Seekable Contents from server.
+   We have observed that , for few specific networks ( VODAFONE ) , without theabove headers ,
+   Youtube is sending non-seekable contents to the Client. */
+#ifndef TIZEN_FEATURE_SOUP_MODIFICATION
+  if (offset || stop_offset != -1)
+#endif
+  {
     if (stop_offset != -1) {
       g_assert (offset != stop_offset);
 
@@ -798,12 +862,13 @@ gst_soup_http_src_add_range_header (GstSoupHTTPSrc * src, guint64 offset,
           stop_offset);
     } else {
       rc = g_snprintf (buf, sizeof (buf), "bytes=%" G_GUINT64_FORMAT "-",
-          offset);
+                offset);
     }
     if (rc > sizeof (buf) || rc < 0)
       return FALSE;
     soup_message_headers_append (src->msg->request_headers, "Range", buf);
   }
+
   src->read_position = offset;
   return TRUE;
 }
@@ -837,6 +902,35 @@ _append_extra_header (GQuark field_id, const GValue * value, gpointer user_data)
   soup_message_headers_append (src->msg->request_headers, field_name,
       field_content);
 
+#ifdef TIZEN_FEATURE_SOUP_MODIFICATION
+  if (!g_ascii_strcasecmp(field_name, "Cookie")) {
+    SoupURI *uri = NULL;
+    SoupCookie *cookie_parsed = NULL;
+    gchar *saveptr = NULL;
+
+    if (strlen(field_content) > 0) {
+      gchar *tmp_field = NULL;
+
+      uri = soup_uri_new (src->location);
+
+      tmp_field = strtok_r (field_content, ";", &saveptr);
+
+      while (tmp_field != NULL) {
+        GST_DEBUG_OBJECT (src, "field_content = %s", tmp_field);
+
+        cookie_parsed = soup_cookie_parse(tmp_field, uri);
+        GST_DEBUG_OBJECT (src, "cookie parsed = %p", cookie_parsed);
+
+        if (src->cookie_jar)
+          soup_cookie_jar_add_cookie (src->cookie_jar, cookie_parsed);
+
+        tmp_field = strtok_r (NULL, ";", &saveptr);
+      }
+      soup_uri_free (uri);
+    }
+  }
+#endif
+
   g_free (field_content);
 
   return TRUE;
@@ -903,15 +997,15 @@ gst_soup_http_src_session_open (GstSoupHTTPSrc * src)
       src->session =
           soup_session_new_with_options (SOUP_SESSION_USER_AGENT,
           src->user_agent, SOUP_SESSION_TIMEOUT, src->timeout,
-          SOUP_SESSION_SSL_STRICT, src->ssl_strict,
-          SOUP_SESSION_TLS_INTERACTION, src->tls_interaction, NULL);
+          SOUP_SESSION_SSL_STRICT, src->ssl_strict, NULL);
+//          SOUP_SESSION_TLS_INTERACTION, src->tls_interaction, NULL);
     } else {
       src->session =
           soup_session_new_with_options (SOUP_SESSION_PROXY_URI, src->proxy,
           SOUP_SESSION_TIMEOUT, src->timeout,
           SOUP_SESSION_SSL_STRICT, src->ssl_strict,
-          SOUP_SESSION_USER_AGENT, src->user_agent,
-          SOUP_SESSION_TLS_INTERACTION, src->tls_interaction, NULL);
+          SOUP_SESSION_USER_AGENT, src->user_agent, NULL);
+//          SOUP_SESSION_TLS_INTERACTION, src->tls_interaction, NULL);
     }
 
     if (!src->session) {
@@ -920,6 +1014,28 @@ gst_soup_http_src_session_open (GstSoupHTTPSrc * src)
       return FALSE;
     }
 
+#ifdef TIZEN_FEATURE_SOUP_MODIFICATION
+    {
+      char **array = NULL;
+      SoupURI *base_uri;
+      SoupCookie *soup_cookie = NULL;
+
+      soup_session_add_feature_by_type (src->session, SOUP_TYPE_COOKIE_JAR);
+      src->cookie_jar = SOUP_COOKIE_JAR (soup_session_get_feature (src->session, SOUP_TYPE_COOKIE_JAR));
+      if ((array = src->cookies) != NULL) {
+        base_uri = soup_uri_new (src->location);
+        while (*array != NULL) {
+          soup_cookie = soup_cookie_parse (*array++, base_uri);
+          if (soup_cookie != NULL) {
+            GST_INFO_OBJECT (src, "adding cookies..");
+            soup_cookie_jar_add_cookie (src->cookie_jar, soup_cookie);
+          }
+        }
+        soup_uri_free (base_uri);
+      }
+    }
+#endif
+
     g_signal_connect (src->session, "authenticate",
         G_CALLBACK (gst_soup_http_src_authenticate_cb), src);
 
@@ -958,6 +1074,14 @@ gst_soup_http_src_session_close (GstSoupHTTPSrc * src)
   }
 
   if (src->session) {
+#ifdef TIZEN_FEATURE_SOUP_MODIFICATION
+/* When Playback is ongoing and Browser is moved to background ( Pressing Menu or Home Key ), The Session gets destroyed.
+   But the cookie_jar property remains unfreed. This results in garbage pointer and causes crash.
+   Removing the cookie_jar feature during close session of browser to handle the issue. */
+    GST_DEBUG_OBJECT (src, "Removing Cookie Jar instance");
+    soup_session_remove_feature_by_type(src->session, SOUP_TYPE_COOKIE_JAR);
+    src->cookie_jar = NULL;
+#endif
     soup_session_abort (src->session);
     g_object_unref (src->session);
     src->session = NULL;
@@ -1018,6 +1142,56 @@ insert_http_header (const gchar * name, const gchar * value, gpointer user_data)
   }
 }
 
+#ifdef TIZEN_FEATURE_SOUP_MODIFICATION
+static void
+gst_soup_http_src_headers_foreach (const gchar * name, const gchar * val,
+    gpointer src)
+{
+  GST_INFO_OBJECT (src, " %s: %s", name, val);
+
+  if (g_ascii_strcasecmp (name, "Set-Cookie") == 0)
+  {
+    if (val)
+    {
+      gboolean bret = FALSE;
+      GstStructure *s = NULL;
+      GstSoupHTTPSrc * tmp = src;
+      SoupURI *uri;
+
+      uri =  soup_uri_new (tmp->location);
+
+      /* post current bandwith & uri to application */
+      s = gst_structure_new ("cookies",
+            "updated-cookie", G_TYPE_STRING, val,
+            "updated-url", G_TYPE_STRING, tmp->location, NULL);
+      bret = gst_element_post_message (GST_ELEMENT_CAST (src), gst_message_new_element (GST_OBJECT_CAST (src), s));
+      soup_cookie_jar_set_cookie (tmp->cookie_jar,  uri, val);
+      soup_uri_free (uri);
+
+      GST_INFO_OBJECT (src, "request url [%s], posted cookies [%s] msg and returned = %d", tmp->location, val, bret);
+    }
+  }
+  else if (g_ascii_strcasecmp (name, "Dash-Oldest-Segment") == 0)
+  {
+    if (val)
+    {
+      GstSoupHTTPSrc * tmp = src;
+      tmp->dash_oldest_segment = g_strdup (val);
+      GST_INFO_OBJECT (src, "Dash-Oldest-Segment set as %s ", tmp->dash_oldest_segment);
+    }
+  }
+  else if (g_ascii_strcasecmp (name, "Dash-Newest-Segment") == 0)
+  {
+    if (val)
+    {
+      GstSoupHTTPSrc * tmp = src;
+      tmp->dash_newest_segment = g_strdup (val);
+      GST_INFO_OBJECT (src, "Dash-Newest-Segment set as %s ", tmp->dash_newest_segment);
+    }
+  }
+}
+#endif
+
 static GstFlowReturn
 gst_soup_http_src_got_headers (GstSoupHTTPSrc * src, SoupMessage * msg)
 {
@@ -1029,9 +1203,15 @@ gst_soup_http_src_got_headers (GstSoupHTTPSrc * src, SoupMessage * msg)
   GstEvent *http_headers_event;
   GstStructure *http_headers, *headers;
   const gchar *accept_ranges;
+#ifdef TIZEN_FEATURE_SOUP_MODIFICATION
+  gint64 start = 0, stop = 0, total = 0;
+#endif
 
-  GST_INFO_OBJECT (src, "got headers");
-
+  GST_INFO_OBJECT (src, "got headers : %d", msg->status_code);
+#ifdef TIZEN_FEATURE_SOUP_MODIFICATION
+  soup_message_headers_foreach (msg->response_headers,
+      gst_soup_http_src_headers_foreach, src);
+#endif
   if (msg->status_code == SOUP_STATUS_PROXY_AUTHENTICATION_REQUIRED &&
       src->proxy_id && src->proxy_pw) {
     /* wait for authenticate callback */
@@ -1072,8 +1252,27 @@ gst_soup_http_src_got_headers (GstSoupHTTPSrc * src, SoupMessage * msg)
   /* Parse Content-Length. */
   if (soup_message_headers_get_encoding (msg->response_headers) ==
       SOUP_ENCODING_CONTENT_LENGTH) {
-    newsize = src->request_position +
-        soup_message_headers_get_content_length (msg->response_headers);
+#ifdef TIZEN_FEATURE_SOUP_MODIFICATION
+      if (msg->status_code == SOUP_STATUS_PARTIAL_CONTENT) {
+        newsize = src->request_position +
+            soup_message_headers_get_content_length (msg->response_headers);
+      } else {
+        if (soup_message_headers_get_content_range(msg->response_headers, &start, &stop, &total) && (total > 0)) {
+          GST_DEBUG_OBJECT (src, "get range header : %" G_GINT64_FORMAT
+                                  "~%" G_GINT64_FORMAT"/%"G_GINT64_FORMAT, start, stop, total);
+          newsize = (guint64)total;
+        } else {
+          if ((src->have_size) && (src->content_size <= src->request_position)) {
+            newsize = src->content_size;
+          } else {
+            newsize = soup_message_headers_get_content_length (msg->response_headers);
+          }
+        }
+      }
+#else
+      newsize = src->request_position +
+          soup_message_headers_get_content_length (msg->response_headers);
+#endif
     if (!src->have_size || (src->content_size != newsize)) {
       src->content_size = newsize;
       src->have_size = TRUE;
@@ -1096,6 +1295,15 @@ gst_soup_http_src_got_headers (GstSoupHTTPSrc * src, SoupMessage * msg)
     if (g_ascii_strcasecmp (accept_ranges, "none") == 0)
       src->seekable = FALSE;
   }
+#ifdef TIZEN_FEATURE_SOUP_MODIFICATION
+  /* The Range request header is always included.
+   * @ref gst_soup_http_src_add_range_header() */
+  else if ((msg->status_code == SOUP_STATUS_OK) &&
+    (soup_message_headers_get_content_range(msg->response_headers, &start, &stop, &total) == FALSE)) {
+    GST_DEBUG_OBJECT (src, "there is no accept range header");
+    src->seekable = FALSE;
+  }
+#endif
 
   /* Icecast stuff */
   tag_list = gst_tag_list_new_empty ();
@@ -1312,12 +1520,22 @@ gst_soup_http_src_parse_status (SoupMessage * msg, GstSoupHTTPSrc * src)
     /* when content_size is unknown and we have just finished receiving
      * a body message, requests that go beyond the content limits will result
      * in an error. Here we convert those to EOS */
+#ifdef TIZEN_FEATURE_SOUP_MODIFICATION
+    if (msg->status_code == SOUP_STATUS_REQUESTED_RANGE_NOT_SATISFIABLE &&
+        ((src->have_body && !src->have_size) ||
+         (src->have_size && src->request_position >= src->content_size))) {
+      GST_DEBUG_OBJECT (src, "Requested range out of limits and received full "
+          "body, returning EOS");
+      return GST_FLOW_EOS;
+    }
+#else
     if (msg->status_code == SOUP_STATUS_REQUESTED_RANGE_NOT_SATISFIABLE &&
         src->have_body && !src->have_size) {
       GST_DEBUG_OBJECT (src, "Requested range out of limits and received full "
           "body, returning EOS");
       return GST_FLOW_EOS;
     }
+#endif
 
     /* FIXME: reason_phrase is not translated and not suitable for user
      * error dialog according to libsoup documentation.
@@ -1370,6 +1588,35 @@ gst_soup_http_src_build_message (GstSoupHTTPSrc * src, const gchar * method)
     soup_message_headers_append (src->msg->request_headers, "icy-metadata",
         "1");
   }
+
+#ifdef TIZEN_FEATURE_SOUP_MODIFICATION
+/* This changes are needed to enable Seekable Contents from server.
+   We have observed that , for few specific networks ( VODAFONE ) , without theabove headers ,
+   Youtube is sending non-seekable contents to the Client. */
+  soup_message_headers_append (src->msg->request_headers, "Accept-Ranges","bytes");
+
+  if (src->cookie_jar) {
+    GSList *cookie_list, *c;
+    gchar *header;
+
+    SoupURI *uri = NULL;
+    SoupCookie *cookie;
+    uri = soup_uri_new (src->location);
+
+    if ((cookie_list = soup_cookie_jar_all_cookies (src->cookie_jar)) != NULL) {
+      for (c = cookie_list; c; c = c->next) {
+        cookie = (SoupCookie *)c->data;
+        if (soup_cookie_applies_to_uri(cookie, uri)) {
+          header = soup_cookie_to_cookie_header (cookie);
+          soup_message_headers_append (src->msg->request_headers, "Cookie", header);
+          g_free (header);
+        }
+      }
+    }
+    soup_cookies_free (cookie_list);
+    soup_uri_free (uri);
+  }
+#else
   if (src->cookies) {
     gchar **cookie;
 
@@ -1378,6 +1625,7 @@ gst_soup_http_src_build_message (GstSoupHTTPSrc * src, const gchar * method)
           *cookie);
     }
   }
+#endif
 
   soup_message_set_flags (src->msg, SOUP_MESSAGE_OVERWRITE_CHUNKS |
       (src->automatic_redirect ? 0 : SOUP_MESSAGE_NO_REDIRECT));
@@ -1392,6 +1640,11 @@ gst_soup_http_src_build_message (GstSoupHTTPSrc * src, const gchar * method)
 
   gst_soup_http_src_add_extra_headers (src);
 
+#ifdef TIZEN_FEATURE_SOUP_MODIFICATION
+  soup_message_headers_foreach (src->msg->request_headers,
+      gst_soup_http_src_headers_foreach, src);
+#endif
+
   return TRUE;
 }
 
@@ -1472,8 +1725,14 @@ gst_soup_http_src_do_request (GstSoupHTTPSrc * src, const gchar * method)
   ret = gst_soup_http_src_send_message (src);
 
   /* Check if Range header was respected. */
+#ifdef TIZEN_FEATURE_SOUP_MODIFICATION
+  if (ret == GST_FLOW_OK && src->request_position > 0 &&
+      (src->msg->status_code != SOUP_STATUS_PARTIAL_CONTENT) &&
+         (src->request_position < src->content_size)) {
+#else
   if (ret == GST_FLOW_OK && src->request_position > 0 &&
       src->msg->status_code != SOUP_STATUS_PARTIAL_CONTENT) {
+#endif
     src->seekable = FALSE;
     GST_ELEMENT_ERROR_WITH_DETAILS (src, RESOURCE, SEEK,
         (_("Server does not support seeking.")),
@@ -1714,6 +1973,16 @@ gst_soup_http_src_start (GstBaseSrc * bsrc)
 
   GST_DEBUG_OBJECT (src, "start(\"%s\")", src->location);
 
+#ifdef TIZEN_FEATURE_SOUP_MODIFICATION
+  if (src->dash_oldest_segment) {
+    g_free (src->dash_oldest_segment);
+    src->dash_oldest_segment = NULL;
+  }
+  if (src->dash_newest_segment) {
+    g_free (src->dash_newest_segment);
+    src->dash_newest_segment = NULL;
+  }
+#endif
   return gst_soup_http_src_session_open (src);
 }
 
@@ -1902,9 +2171,18 @@ gst_soup_http_src_query (GstBaseSrc * bsrc, GstQuery * query)
 
   switch (GST_QUERY_TYPE (query)) {
     case GST_QUERY_SCHEDULING:
+
       gst_query_parse_scheduling (query, &flags, &minsize, &maxsize, &align);
       flags |= GST_SCHEDULING_FLAG_BANDWIDTH_LIMITED;
+
+#ifdef TIZEN_FEATURE_SOUP_MODIFICATION
+      if (gst_soup_http_src_is_seekable(bsrc)) {
+          GST_DEBUG_OBJECT (src, "set seekable flag");
+          flags |= GST_SCHEDULING_FLAG_SEEKABLE;
+      }
+#endif
       gst_query_set_scheduling (query, flags, minsize, maxsize, align);
+
       break;
     default:
       break;