GST_DEBUG_CATEGORY_STATIC (souphttpsrc_debug);
#define GST_CAT_DEFAULT souphttpsrc_debug
+#define GST_SOUP_SESSION_CONTEXT "gst.soup.session"
+
static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
GST_PAD_SRC,
GST_PAD_ALWAYS,
#define DEFAULT_IRADIO_MODE TRUE
#define DEFAULT_SOUP_LOG_LEVEL SOUP_LOGGER_LOG_HEADERS
#define DEFAULT_COMPRESS FALSE
-#define DEFAULT_KEEP_ALIVE FALSE
+#define DEFAULT_KEEP_ALIVE TRUE
#define DEFAULT_SSL_STRICT TRUE
#define DEFAULT_SSL_CA_FILE NULL
#define DEFAULT_SSL_USE_SYSTEM_CA_FILE TRUE
#define REDUCE_BLOCKSIZE_LIMIT 0.20
#define REDUCE_BLOCKSIZE_COUNT 2
#define REDUCE_BLOCKSIZE_FACTOR 0.5
+#define GROW_TIME_LIMIT (1 * GST_SECOND)
+
+#ifdef TIZEN_FEATURE_SOUP_MODIFICATION
+#define DLNA_OP_TIMED_SEEK 0x02
+#define DLNA_OP_BYTE_SEEK 0x01
+#endif
static void gst_soup_http_src_uri_handler_init (gpointer g_iface,
gpointer iface_data);
static GstStateChangeReturn gst_soup_http_src_change_state (GstElement *
element, GstStateChange transition);
+static void gst_soup_http_src_set_context (GstElement * element,
+ GstContext * context);
static GstFlowReturn gst_soup_http_src_create (GstPushSrc * psrc,
GstBuffer ** outbuf);
static gboolean gst_soup_http_src_start (GstBaseSrc * bsrc);
"Wouter Cloetens <wouter@mind.be>");
gstelement_class->change_state =
GST_DEBUG_FUNCPTR (gst_soup_http_src_change_state);
+ gstelement_class->set_context =
+ GST_DEBUG_FUNCPTR (gst_soup_http_src_set_context);
gstbasesrc_class->start = GST_DEBUG_FUNCPTR (gst_soup_http_src_start);
gstbasesrc_class->stop = GST_DEBUG_FUNCPTR (gst_soup_http_src_stop);
src->reduce_blocksize_count = 0;
src->increase_blocksize_count = 0;
+ src->last_socket_read_time = 0;
#ifdef TIZEN_FEATURE_SOUP_MODIFICATION
if (src->dash_oldest_segment) {
g_free (src->dash_newest_segment);
src->dash_newest_segment = NULL;
}
+ src->dlna_opt = 0;
#endif
g_cancellable_reset (src->cancellable);
+ g_mutex_lock (&src->mutex);
if (src->input_stream) {
g_object_unref (src->input_stream);
src->input_stream = NULL;
}
+ g_mutex_unlock (&src->mutex);
gst_caps_replace (&src->src_caps, NULL);
g_free (src->iradio_name);
src->cookies = NULL;
src->iradio_mode = DEFAULT_IRADIO_MODE;
src->session = NULL;
+ src->external_session = NULL;
+ src->forced_external_session = FALSE;
src->msg = NULL;
src->timeout = DEFAULT_TIMEOUT;
src->log_level = DEFAULT_SOUP_LOG_LEVEL;
+ src->compress = DEFAULT_COMPRESS;
+ src->keep_alive = DEFAULT_KEEP_ALIVE;
src->ssl_strict = DEFAULT_SSL_STRICT;
src->ssl_use_system_ca_file = DEFAULT_SSL_USE_SYSTEM_CA_FILE;
src->tls_database = DEFAULT_TLS_DATABASE;
#ifdef TIZEN_FEATURE_SOUP_MODIFICATION
src->dash_oldest_segment = NULL;
src->dash_newest_segment = NULL;
+ src->received_total = 0;
+ src->dlna_opt = 0;
#endif
proxy = g_getenv ("http_proxy");
if (!gst_soup_http_src_set_proxy (src, proxy)) {
"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);
gst_soup_http_src_session_close (src);
+ if (src->external_session) {
+ g_object_unref (src->external_session);
+ src->external_session = NULL;
+ }
+
G_OBJECT_CLASS (parent_class)->dispose (gobject);
}
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));
g_value_set_static_string (value, "");
else {
char *proxy = soup_uri_to_string (src->proxy, FALSE);
-
g_value_set_string (value, proxy);
g_free (proxy);
}
break;
case PROP_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
+ g_value_set_boxed (value, g_strdupv (src->cookies));
break;
case PROP_IS_LIVE:
g_value_set_boolean (value, gst_base_src_is_live (GST_BASE_SRC (src)));
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;
}
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;
}
if (!src->session) {
- GST_DEBUG_OBJECT (src, "Creating session");
- if (src->proxy == NULL) {
- 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, NULL);
-// SOUP_SESSION_TLS_INTERACTION, src->tls_interaction, NULL);
+ GstQuery *query;
+ gboolean can_share = (src->timeout == DEFAULT_TIMEOUT)
+ && (src->ssl_strict == DEFAULT_SSL_STRICT)
+ && (src->tls_interaction == NULL) && (src->proxy == NULL)
+ && (src->tls_database == DEFAULT_TLS_DATABASE)
+ && (src->ssl_ca_file == DEFAULT_SSL_CA_FILE)
+ && (src->ssl_use_system_ca_file == DEFAULT_SSL_USE_SYSTEM_CA_FILE);
+
+ query = gst_query_new_context (GST_SOUP_SESSION_CONTEXT);
+ if (gst_pad_peer_query (GST_BASE_SRC_PAD (src), query)) {
+ GstContext *context;
+
+ gst_query_parse_context (query, &context);
+ gst_element_set_context (GST_ELEMENT_CAST (src), context);
} 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, NULL);
-// SOUP_SESSION_TLS_INTERACTION, src->tls_interaction, NULL);
- }
+ GstMessage *message;
- if (!src->session) {
- GST_ELEMENT_ERROR (src, LIBRARY, INIT,
- (NULL), ("Failed to create async session"));
- return FALSE;
+ message =
+ gst_message_new_need_context (GST_OBJECT_CAST (src),
+ GST_SOUP_SESSION_CONTEXT);
+ gst_element_post_message (GST_ELEMENT_CAST (src), message);
}
+ gst_query_unref (query);
+
+ GST_OBJECT_LOCK (src);
+ if (src->external_session && (can_share || src->forced_external_session)) {
+ GST_DEBUG_OBJECT (src, "Using external session %p",
+ src->external_session);
+ src->session = g_object_ref (src->external_session);
+ src->session_is_shared = TRUE;
+ } else {
+ GST_DEBUG_OBJECT (src, "Creating session (can share %d)", can_share);
+
+ /* We explicitly set User-Agent to NULL here and overwrite it per message
+ * to be able to have the same session with different User-Agents per
+ * source */
+ if (src->proxy == NULL) {
+ src->session =
+ soup_session_new_with_options (SOUP_SESSION_USER_AGENT,
+ NULL, SOUP_SESSION_TIMEOUT, src->timeout,
+ SOUP_SESSION_SSL_STRICT, src->ssl_strict,
+ 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, NULL,
+ SOUP_SESSION_TLS_INTERACTION, src->tls_interaction, NULL);
+ }
-#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);
- }
+ if (src->session) {
+ gst_soup_util_log_setup (src->session, src->log_level,
+ GST_ELEMENT (src));
+ soup_session_add_feature_by_type (src->session,
+ SOUP_TYPE_CONTENT_DECODER);
+ soup_session_add_feature_by_type (src->session, SOUP_TYPE_COOKIE_JAR);
+
+ if (can_share) {
+ GstContext *context;
+ GstMessage *message;
+ GstStructure *s;
+
+ GST_DEBUG_OBJECT (src, "Sharing session %p", src->session);
+ src->session_is_shared = TRUE;
+
+ /* Unset the limit the number of maximum allowed connection */
+ g_object_set (src->session, SOUP_SESSION_MAX_CONNS, G_MAXINT,
+ SOUP_SESSION_MAX_CONNS_PER_HOST, G_MAXINT, NULL);
+
+ context = gst_context_new (GST_SOUP_SESSION_CONTEXT, TRUE);
+ s = gst_context_writable_structure (context);
+ gst_structure_set (s, "session", SOUP_TYPE_SESSION, src->session,
+ "force", G_TYPE_BOOLEAN, FALSE, NULL);
+
+ gst_object_ref (src->session);
+ GST_OBJECT_UNLOCK (src);
+ gst_element_set_context (GST_ELEMENT_CAST (src), context);
+ message =
+ gst_message_new_have_context (GST_OBJECT_CAST (src), context);
+ gst_element_post_message (GST_ELEMENT_CAST (src), message);
+ GST_OBJECT_LOCK (src);
+ gst_object_unref (src->session);
+ } else {
+ src->session_is_shared = FALSE;
}
- soup_uri_free (base_uri);
}
}
-#endif
+
+ if (!src->session) {
+ GST_ELEMENT_ERROR (src, LIBRARY, INIT,
+ (NULL), ("Failed to create session"));
+ GST_OBJECT_UNLOCK (src);
+ return FALSE;
+ }
g_signal_connect (src->session, "authenticate",
G_CALLBACK (gst_soup_http_src_authenticate_cb), src);
- /* Set up logging */
- gst_soup_util_log_setup (src->session, src->log_level, GST_ELEMENT (src));
- if (src->tls_database)
- g_object_set (src->session, "tls-database", src->tls_database, NULL);
- else if (src->ssl_ca_file)
- g_object_set (src->session, "ssl-ca-file", src->ssl_ca_file, NULL);
- else
- g_object_set (src->session, "ssl-use-system-ca-file",
- src->ssl_use_system_ca_file, NULL);
+ if (!src->session_is_shared) {
+ if (src->tls_database)
+ g_object_set (src->session, "tls-database", src->tls_database, NULL);
+ else if (src->ssl_ca_file)
+ g_object_set (src->session, "ssl-ca-file", src->ssl_ca_file, NULL);
+ else
+ g_object_set (src->session, "ssl-use-system-ca-file",
+ src->ssl_use_system_ca_file, NULL);
+ }
+ GST_OBJECT_UNLOCK (src);
} else {
GST_DEBUG_OBJECT (src, "Re-using session");
}
- if (src->compress)
- soup_session_add_feature_by_type (src->session, SOUP_TYPE_CONTENT_DECODER);
- else
- soup_session_remove_feature_by_type (src->session,
- SOUP_TYPE_CONTENT_DECODER);
-
return TRUE;
}
}
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);
+ if (!src->session_is_shared)
+ soup_session_abort (src->session);
+ g_signal_handlers_disconnect_by_func (src->session,
+ G_CALLBACK (gst_soup_http_src_authenticate_cb), src);
g_object_unref (src->session);
src->session = NULL;
}
+
g_mutex_unlock (&src->mutex);
}
gst_soup_http_src_authenticate_cb (SoupSession * session, SoupMessage * msg,
SoupAuth * auth, gboolean retrying, GstSoupHTTPSrc * src)
{
+ /* Might be from another user of the shared session */
+ if (!GST_IS_SOUP_HTTP_SRC (src) || msg != src->msg)
+ return;
+
if (!retrying) {
/* First time authentication only, if we fail and are called again with retry true fall through */
if (msg->status_code == SOUP_STATUS_UNAUTHORIZED) {
{
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)
- {
+ 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)
- {
+ } 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);
return GST_FLOW_OK;
}
- if (msg->status_code == SOUP_STATUS_UNAUTHORIZED) {
- /* force an error */
- return gst_soup_http_src_parse_status (msg, src);
- }
-
- src->got_headers = TRUE;
- g_cond_broadcast (&src->have_headers_cond);
-
http_headers = gst_structure_new_empty ("http-headers");
- gst_structure_set (http_headers, "uri", G_TYPE_STRING, src->location, NULL);
+ gst_structure_set (http_headers, "uri", G_TYPE_STRING, src->location,
+ "http-status-code", G_TYPE_UINT, msg->status_code, NULL);
if (src->redirection_uri)
gst_structure_set (http_headers, "redirection-uri", G_TYPE_STRING,
src->redirection_uri, NULL);
headers, NULL);
gst_structure_free (headers);
+ gst_element_post_message (GST_ELEMENT_CAST (src),
+ gst_message_new_element (GST_OBJECT_CAST (src),
+ gst_structure_copy (http_headers)));
+
+ if (msg->status_code == SOUP_STATUS_UNAUTHORIZED) {
+ /* force an error */
+ gst_structure_free (http_headers);
+ return gst_soup_http_src_parse_status (msg, src);
+ }
+
+ src->got_headers = TRUE;
+ g_cond_broadcast (&src->have_headers_cond);
+
http_headers_event =
gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM_STICKY, http_headers);
gst_event_replace (&src->http_headers_event, http_headers_event);
gst_event_unref (http_headers_event);
+#ifdef TIZEN_FEATURE_SOUP_MODIFICATION
+ /* Parse DLNA OP CODE */
+ if ((value = soup_message_headers_get_one
+ (msg->response_headers, "contentFeatures.dlna.org")) != NULL) {
+ gchar **token = NULL;
+ gchar **ptr = NULL;
+
+ GST_DEBUG_OBJECT (src, "DLNA server response");
+
+ token = g_strsplit (value, ";", 0);
+ for (ptr = token ; *ptr ; ptr++) {
+ gchar *tmp = NULL;
+ gchar *op_code = NULL;
+
+ if (!strlen (*ptr))
+ continue;
+
+ tmp = g_ascii_strup (*ptr, strlen (*ptr));
+ if (!strstr (tmp, "DLNA.ORG_OP")) {
+ g_free (tmp);
+ continue;
+ }
+
+ g_free (tmp);
+
+ op_code = strchr (*ptr, '=');
+ if (op_code) {
+ op_code++;
+
+ src->dlna_opt = (atoi (op_code) / 10 << 1) | (atoi (op_code) % 10);
+ GST_DEBUG_OBJECT (src, "dlna op code: %s (0x%X)", op_code, src->dlna_opt);
+ break;
+ }
+ }
+ g_strfreev (token);
+ }
+#endif
+
/* Parse Content-Length. */
if (soup_message_headers_get_encoding (msg->response_headers) ==
SOUP_ENCODING_CONTENT_LENGTH) {
src->seekable = FALSE;
}
#ifdef TIZEN_FEATURE_SOUP_MODIFICATION
+ else if (src->dlna_opt & DLNA_OP_BYTE_SEEK) {
+ if (src->have_size) {
+ GST_DEBUG_OBJECT (src, "DLNA server is seekable");
+ src->seekable = TRUE;
+ }
+ }
/* 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)) {
+ (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;
}
("Error parsing URL."), ("URL: %s", src->location));
return FALSE;
}
+
+ /* Duplicating the defaults of libsoup here. We don't want to set a
+ * User-Agent in the session as each source might have its own User-Agent
+ * set */
+ if (!src->user_agent || !*src->user_agent) {
+ gchar *user_agent =
+ g_strdup_printf ("libsoup/%u.%u.%u", soup_get_major_version (),
+ soup_get_minor_version (), soup_get_micro_version ());
+ soup_message_headers_append (src->msg->request_headers, "User-Agent",
+ user_agent);
+ g_free (user_agent);
+ } else if (g_str_has_suffix (src->user_agent, " ")) {
+ gchar *user_agent = g_strdup_printf ("%slibsoup/%u.%u.%u", src->user_agent,
+ soup_get_major_version (),
+ soup_get_minor_version (), soup_get_micro_version ());
+ soup_message_headers_append (src->msg->request_headers, "User-Agent",
+ user_agent);
+ g_free (user_agent);
+ } else {
+ soup_message_headers_append (src->msg->request_headers, "User-Agent",
+ src->user_agent);
+ }
+
if (!src->keep_alive) {
soup_message_headers_append (src->msg->request_headers, "Connection",
"close");
}
#ifdef TIZEN_FEATURE_SOUP_MODIFICATION
-/* This changes are needed to enable Seekable Contents from server.
+ /* 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");
+#endif
- 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;
*cookie);
}
}
-#endif
+
+ if (!src->compress)
+ soup_message_disable_feature (src->msg, SOUP_TYPE_CONTENT_DECODER);
soup_message_set_flags (src->msg, SOUP_MESSAGE_OVERWRITE_CHUNKS |
(src->automatic_redirect ? 0 : SOUP_MESSAGE_NO_REDIRECT));
return TRUE;
}
+/* Lock taken */
static GstFlowReturn
gst_soup_http_src_send_message (GstSoupHTTPSrc * src)
{
GError *error = NULL;
g_return_val_if_fail (src->msg != NULL, GST_FLOW_ERROR);
+ g_assert (src->input_stream == NULL);
src->input_stream =
soup_session_send (src->session, src->msg, src->cancellable, &error);
if (src->msg && src->request_position > 0) {
gst_soup_http_src_add_range_header (src, src->request_position,
src->stop_position);
- }
+ } else if (src->msg && src->request_position == 0)
+ soup_message_headers_remove (src->msg->request_headers, "Range");
+
+ /* add_range_header() has the side effect of setting read_position to
+ * the requested position. This *needs* to be set regardless of having
+ * a message or not. Failure to do so would result in calculation being
+ * done with stale/wrong read position */
+ src->read_position = src->request_position;
if (!src->msg) {
if (!gst_soup_http_src_build_message (src, method)) {
{
guint blocksize = gst_base_src_get_blocksize (GST_BASE_SRC_CAST (src));
- GST_LOG_OBJECT (src, "Checking to update blocksize. Read:%" G_GINT64_FORMAT
- " blocksize:%u", bytes_read, blocksize);
+ gint64 time_since_last_read =
+ g_get_monotonic_time () * GST_USECOND - src->last_socket_read_time;
+
+ GST_LOG_OBJECT (src, "Checking to update blocksize. Read: %" G_GINT64_FORMAT
+ " bytes, blocksize: %u bytes, time since last read: %" GST_TIME_FORMAT,
+ bytes_read, blocksize, GST_TIME_ARGS (time_since_last_read));
- if (bytes_read >= blocksize * GROW_BLOCKSIZE_LIMIT) {
+ if (bytes_read >= blocksize * GROW_BLOCKSIZE_LIMIT
+ && time_since_last_read <= GROW_TIME_LIMIT) {
src->reduce_blocksize_count = 0;
src->increase_blocksize_count++;
gst_base_src_set_blocksize (GST_BASE_SRC_CAST (src), blocksize);
src->increase_blocksize_count = 0;
}
- } else if (bytes_read < blocksize * REDUCE_BLOCKSIZE_LIMIT) {
+ } else if (bytes_read < blocksize * REDUCE_BLOCKSIZE_LIMIT
+ || time_since_last_read > GROW_TIME_LIMIT) {
src->reduce_blocksize_count++;
src->increase_blocksize_count = 0;
GST_BUFFER_OFFSET (*outbuf) = bsrc->segment.position;
ret = GST_FLOW_OK;
gst_soup_http_src_update_position (src, read_bytes);
+#ifdef TIZEN_FEATURE_SOUP_MODIFICATION
+ src->received_total += read_bytes;
+#endif
/* Got some data, reset retry counter */
src->retry_count = 0;
gst_soup_http_src_check_update_blocksize (src, read_bytes);
+ src->last_socket_read_time = g_get_monotonic_time () * GST_USECOND;
+
/* If we're at the end of a range request, read again to let libsoup
* finalize the request. This allows to reuse the connection again later,
* otherwise we would have to cancel the message and close the connection
goto retry;
}
}
+
+ if (ret == GST_FLOW_FLUSHING) {
+ g_mutex_lock (&src->mutex);
+ src->retry_count = 0;
+ g_mutex_unlock (&src->mutex);
+ }
+
return ret;
}
src = GST_SOUP_HTTP_SRC (bsrc);
GST_DEBUG_OBJECT (src, "stop()");
- if (src->keep_alive && !src->msg)
+ if (src->keep_alive && !src->msg && !src->session_is_shared)
gst_soup_http_src_cancel_message (src);
else
gst_soup_http_src_session_close (src);
src = GST_SOUP_HTTP_SRC (element);
switch (transition) {
+#ifdef TIZEN_FEATURE_SOUP_MODIFICATION
+ case GST_STATE_CHANGE_PAUSED_TO_READY:
+ GST_WARNING_OBJECT (src, "Last read pos"
+ ": %" G_GINT64_FORMAT ", received total : %" G_GINT64_FORMAT,
+ src->read_position, src->received_total);
+ break;
+#endif
case GST_STATE_CHANGE_READY_TO_NULL:
gst_soup_http_src_session_close (src);
break;
return ret;
}
+static void
+gst_soup_http_src_set_context (GstElement * element, GstContext * context)
+{
+ GstSoupHTTPSrc *src = GST_SOUP_HTTP_SRC (element);
+
+ if (g_strcmp0 (gst_context_get_context_type (context),
+ GST_SOUP_SESSION_CONTEXT) == 0) {
+ const GstStructure *s = gst_context_get_structure (context);
+
+ GST_OBJECT_LOCK (src);
+ if (src->external_session)
+ g_object_unref (src->external_session);
+ src->external_session = NULL;
+ gst_structure_get (s, "session", SOUP_TYPE_SESSION, &src->external_session,
+ NULL);
+ src->forced_external_session = FALSE;
+ gst_structure_get (s, "force", G_TYPE_BOOLEAN,
+ &src->forced_external_session, NULL);
+
+ GST_DEBUG_OBJECT (src, "Setting external session %p (force: %d)",
+ src->external_session, src->forced_external_session);
+ GST_OBJECT_UNLOCK (src);
+ }
+
+ GST_ELEMENT_CLASS (parent_class)->set_context (element, context);
+}
+
/* Interrupt a blocking request. */
static gboolean
gst_soup_http_src_unlock (GstBaseSrc * bsrc)
switch (GST_QUERY_TYPE (query)) {
case GST_QUERY_SCHEDULING:
-
gst_query_parse_scheduling (query, &flags, &minsize, &maxsize, &align);
flags |= GST_SCHEDULING_FLAG_BANDWIDTH_LIMITED;
}
#endif
gst_query_set_scheduling (query, flags, minsize, maxsize, align);
-
break;
default:
break;
if (uri == NULL || *uri == '\0')
return TRUE;
- if (g_str_has_prefix (uri, "http://")) {
+ if (g_strstr_len (uri, -1, "://")) {
src->proxy = soup_uri_new (uri);
} else {
gchar *new_uri = g_strconcat ("http://", uri, NULL);
return (src->proxy != NULL);
}
-static guint
+static GstURIType
gst_soup_http_src_uri_get_type (GType type)
{
return GST_URI_SRC;