mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-04 07:26:33 +00:00
souphttpsrc: add support for keep-alive sessions
https://bugzilla.gnome.org/show_bug.cgi?id=699926
This commit is contained in:
parent
106bc2b17b
commit
4d80d3fad9
2 changed files with 90 additions and 37 deletions
|
@ -108,17 +108,20 @@ enum
|
||||||
PROP_TIMEOUT,
|
PROP_TIMEOUT,
|
||||||
PROP_EXTRA_HEADERS,
|
PROP_EXTRA_HEADERS,
|
||||||
PROP_SOUP_LOG_LEVEL,
|
PROP_SOUP_LOG_LEVEL,
|
||||||
PROP_COMPRESS
|
PROP_COMPRESS,
|
||||||
|
PROP_KEEP_ALIVE
|
||||||
};
|
};
|
||||||
|
|
||||||
#define DEFAULT_USER_AGENT "GStreamer souphttpsrc "
|
#define DEFAULT_USER_AGENT "GStreamer souphttpsrc "
|
||||||
#define DEFAULT_IRADIO_MODE TRUE
|
#define DEFAULT_IRADIO_MODE TRUE
|
||||||
#define DEFAULT_SOUP_LOG_LEVEL SOUP_LOGGER_LOG_NONE
|
#define DEFAULT_SOUP_LOG_LEVEL SOUP_LOGGER_LOG_NONE
|
||||||
#define DEFAULT_COMPRESS FALSE
|
#define DEFAULT_COMPRESS FALSE
|
||||||
|
#define DEFAULT_KEEP_ALIVE FALSE
|
||||||
|
|
||||||
static void gst_soup_http_src_uri_handler_init (gpointer g_iface,
|
static void gst_soup_http_src_uri_handler_init (gpointer g_iface,
|
||||||
gpointer iface_data);
|
gpointer iface_data);
|
||||||
static void gst_soup_http_src_finalize (GObject * gobject);
|
static void gst_soup_http_src_finalize (GObject * gobject);
|
||||||
|
static void gst_soup_http_src_dispose (GObject * gobject);
|
||||||
|
|
||||||
static void gst_soup_http_src_set_property (GObject * object, guint prop_id,
|
static void gst_soup_http_src_set_property (GObject * object, guint prop_id,
|
||||||
const GValue * value, GParamSpec * pspec);
|
const GValue * value, GParamSpec * pspec);
|
||||||
|
@ -191,6 +194,7 @@ gst_soup_http_src_class_init (GstSoupHTTPSrcClass * klass)
|
||||||
gobject_class->set_property = gst_soup_http_src_set_property;
|
gobject_class->set_property = gst_soup_http_src_set_property;
|
||||||
gobject_class->get_property = gst_soup_http_src_get_property;
|
gobject_class->get_property = gst_soup_http_src_get_property;
|
||||||
gobject_class->finalize = gst_soup_http_src_finalize;
|
gobject_class->finalize = gst_soup_http_src_finalize;
|
||||||
|
gobject_class->dispose = gst_soup_http_src_dispose;
|
||||||
|
|
||||||
g_object_class_install_property (gobject_class,
|
g_object_class_install_property (gobject_class,
|
||||||
PROP_LOCATION,
|
PROP_LOCATION,
|
||||||
|
@ -248,6 +252,7 @@ gst_soup_http_src_class_init (GstSoupHTTPSrcClass * klass)
|
||||||
"Enable internet radio mode (ask server to send shoutcast/icecast "
|
"Enable internet radio mode (ask server to send shoutcast/icecast "
|
||||||
"metadata interleaved with the actual stream data)",
|
"metadata interleaved with the actual stream data)",
|
||||||
DEFAULT_IRADIO_MODE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
DEFAULT_IRADIO_MODE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GstSoupHTTPSrc::http-log-level:
|
* GstSoupHTTPSrc::http-log-level:
|
||||||
*
|
*
|
||||||
|
@ -277,6 +282,20 @@ gst_soup_http_src_class_init (GstSoupHTTPSrcClass * klass)
|
||||||
"Allow compressed content encodings",
|
"Allow compressed content encodings",
|
||||||
DEFAULT_COMPRESS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
DEFAULT_COMPRESS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GstSoupHTTPSrc::keep-alive:
|
||||||
|
*
|
||||||
|
* If set to %TRUE, souphttpsrc will keep alive connections when being
|
||||||
|
* set to READY state and only will close connections when connecting
|
||||||
|
* to a different server or when going to NULL state..
|
||||||
|
*
|
||||||
|
* Since: 1.4
|
||||||
|
*/
|
||||||
|
g_object_class_install_property (gobject_class, PROP_KEEP_ALIVE,
|
||||||
|
g_param_spec_boolean ("keep-alive", "keep-alive",
|
||||||
|
"Use HTTP persistent connections", DEFAULT_KEEP_ALIVE,
|
||||||
|
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||||
|
|
||||||
gst_element_class_add_pad_template (gstelement_class,
|
gst_element_class_add_pad_template (gstelement_class,
|
||||||
gst_static_pad_template_get (&srctemplate));
|
gst_static_pad_template_get (&srctemplate));
|
||||||
|
|
||||||
|
@ -357,6 +376,18 @@ gst_soup_http_src_init (GstSoupHTTPSrc * src)
|
||||||
gst_soup_http_src_reset (src);
|
gst_soup_http_src_reset (src);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_soup_http_src_dispose (GObject * gobject)
|
||||||
|
{
|
||||||
|
GstSoupHTTPSrc *src = GST_SOUP_HTTP_SRC (gobject);
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (src, "dispose");
|
||||||
|
|
||||||
|
gst_soup_http_src_session_close (src);
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (parent_class)->dispose (gobject);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_soup_http_src_finalize (GObject * gobject)
|
gst_soup_http_src_finalize (GObject * gobject)
|
||||||
{
|
{
|
||||||
|
@ -478,6 +509,9 @@ gst_soup_http_src_set_property (GObject * object, guint prop_id,
|
||||||
case PROP_COMPRESS:
|
case PROP_COMPRESS:
|
||||||
src->compress = g_value_get_boolean (value);
|
src->compress = g_value_get_boolean (value);
|
||||||
break;
|
break;
|
||||||
|
case PROP_KEEP_ALIVE:
|
||||||
|
src->keep_alive = g_value_get_boolean (value);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
|
@ -545,6 +579,9 @@ gst_soup_http_src_get_property (GObject * object, guint prop_id,
|
||||||
case PROP_COMPRESS:
|
case PROP_COMPRESS:
|
||||||
g_value_set_boolean (value, src->compress);
|
g_value_set_boolean (value, src->compress);
|
||||||
break;
|
break;
|
||||||
|
case PROP_KEEP_ALIVE:
|
||||||
|
g_value_set_boolean (value, src->keep_alive);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
break;
|
break;
|
||||||
|
@ -707,9 +744,11 @@ gst_soup_http_src_session_open (GstSoupHTTPSrc * src)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
src->context = g_main_context_new ();
|
if (!src->context)
|
||||||
|
src->context = g_main_context_new ();
|
||||||
|
|
||||||
src->loop = g_main_loop_new (src->context, TRUE);
|
if (!src->loop)
|
||||||
|
src->loop = g_main_loop_new (src->context, TRUE);
|
||||||
if (!src->loop) {
|
if (!src->loop) {
|
||||||
GST_ELEMENT_ERROR (src, LIBRARY, INIT,
|
GST_ELEMENT_ERROR (src, LIBRARY, INIT,
|
||||||
(NULL), ("Failed to start GMainLoop"));
|
(NULL), ("Failed to start GMainLoop"));
|
||||||
|
@ -717,36 +756,43 @@ gst_soup_http_src_session_open (GstSoupHTTPSrc * src)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (src, "Creating session");
|
|
||||||
if (src->proxy == NULL) {
|
|
||||||
src->session =
|
|
||||||
soup_session_async_new_with_options (SOUP_SESSION_ASYNC_CONTEXT,
|
|
||||||
src->context, SOUP_SESSION_USER_AGENT, src->user_agent,
|
|
||||||
SOUP_SESSION_TIMEOUT, src->timeout,
|
|
||||||
SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_PROXY_RESOLVER_DEFAULT,
|
|
||||||
NULL);
|
|
||||||
} else {
|
|
||||||
src->session =
|
|
||||||
soup_session_async_new_with_options (SOUP_SESSION_ASYNC_CONTEXT,
|
|
||||||
src->context, SOUP_SESSION_PROXY_URI, src->proxy,
|
|
||||||
SOUP_SESSION_TIMEOUT, src->timeout,
|
|
||||||
SOUP_SESSION_USER_AGENT, src->user_agent, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!src->session) {
|
if (!src->session) {
|
||||||
GST_ELEMENT_ERROR (src, LIBRARY, INIT,
|
GST_DEBUG_OBJECT (src, "Creating session");
|
||||||
(NULL), ("Failed to create async session"));
|
if (src->proxy == NULL) {
|
||||||
return FALSE;
|
src->session =
|
||||||
|
soup_session_async_new_with_options (SOUP_SESSION_ASYNC_CONTEXT,
|
||||||
|
src->context, SOUP_SESSION_USER_AGENT, src->user_agent,
|
||||||
|
SOUP_SESSION_TIMEOUT, src->timeout,
|
||||||
|
SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_PROXY_RESOLVER_DEFAULT,
|
||||||
|
NULL);
|
||||||
|
} else {
|
||||||
|
src->session =
|
||||||
|
soup_session_async_new_with_options (SOUP_SESSION_ASYNC_CONTEXT,
|
||||||
|
src->context, SOUP_SESSION_PROXY_URI, src->proxy,
|
||||||
|
SOUP_SESSION_TIMEOUT, src->timeout,
|
||||||
|
SOUP_SESSION_USER_AGENT, src->user_agent, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!src->session) {
|
||||||
|
GST_ELEMENT_ERROR (src, LIBRARY, INIT,
|
||||||
|
(NULL), ("Failed to create async session"));
|
||||||
|
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));
|
||||||
|
} else {
|
||||||
|
GST_DEBUG_OBJECT (src, "Re-using session");
|
||||||
}
|
}
|
||||||
|
|
||||||
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->compress)
|
if (src->compress)
|
||||||
soup_session_add_feature_by_type (src->session, SOUP_TYPE_CONTENT_DECODER);
|
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;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
@ -760,6 +806,12 @@ gst_soup_http_src_session_close (GstSoupHTTPSrc * src)
|
||||||
src->session = NULL;
|
src->session = NULL;
|
||||||
src->msg = NULL;
|
src->msg = NULL;
|
||||||
}
|
}
|
||||||
|
if (src->loop) {
|
||||||
|
g_main_loop_unref (src->loop);
|
||||||
|
g_main_context_unref (src->context);
|
||||||
|
src->loop = NULL;
|
||||||
|
src->context = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -1263,8 +1315,10 @@ gst_soup_http_src_build_message (GstSoupHTTPSrc * src, const gchar * method)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
src->session_io_status = GST_SOUP_HTTP_SRC_SESSION_IO_STATUS_IDLE;
|
src->session_io_status = GST_SOUP_HTTP_SRC_SESSION_IO_STATUS_IDLE;
|
||||||
soup_message_headers_append (src->msg->request_headers, "Connection",
|
if (!src->keep_alive) {
|
||||||
"close");
|
soup_message_headers_append (src->msg->request_headers, "Connection",
|
||||||
|
"close");
|
||||||
|
}
|
||||||
if (src->iradio_mode) {
|
if (src->iradio_mode) {
|
||||||
soup_message_headers_append (src->msg->request_headers, "icy-metadata",
|
soup_message_headers_append (src->msg->request_headers, "icy-metadata",
|
||||||
"1");
|
"1");
|
||||||
|
@ -1396,13 +1450,11 @@ gst_soup_http_src_stop (GstBaseSrc * bsrc)
|
||||||
|
|
||||||
src = GST_SOUP_HTTP_SRC (bsrc);
|
src = GST_SOUP_HTTP_SRC (bsrc);
|
||||||
GST_DEBUG_OBJECT (src, "stop()");
|
GST_DEBUG_OBJECT (src, "stop()");
|
||||||
gst_soup_http_src_session_close (src);
|
if (src->keep_alive)
|
||||||
if (src->loop) {
|
gst_soup_http_src_cancel_message (src);
|
||||||
g_main_loop_unref (src->loop);
|
else
|
||||||
g_main_context_unref (src->context);
|
gst_soup_http_src_session_close (src);
|
||||||
src->loop = NULL;
|
|
||||||
src->context = NULL;
|
|
||||||
}
|
|
||||||
if (src->extra_headers) {
|
if (src->extra_headers) {
|
||||||
gst_structure_free (src->extra_headers);
|
gst_structure_free (src->extra_headers);
|
||||||
src->extra_headers = NULL;
|
src->extra_headers = NULL;
|
||||||
|
|
|
@ -83,6 +83,7 @@ struct _GstSoupHTTPSrc {
|
||||||
* decide if an out of range request should be
|
* decide if an out of range request should be
|
||||||
* handled as an error or EOS when the content
|
* handled as an error or EOS when the content
|
||||||
* size is unknown */
|
* size is unknown */
|
||||||
|
gboolean keep_alive; /* Use keep-alive sessions */
|
||||||
|
|
||||||
/* Shoutcast/icecast metadata extraction handling. */
|
/* Shoutcast/icecast metadata extraction handling. */
|
||||||
gboolean iradio_mode;
|
gboolean iradio_mode;
|
||||||
|
|
Loading…
Reference in a new issue