neonhttpsrc: port to 1.0

This commit is contained in:
Tim-Philipp Müller 2013-05-12 18:28:18 +01:00
parent e5288a2464
commit ca3a83a60d
3 changed files with 67 additions and 97 deletions

View file

@ -346,7 +346,7 @@ GST_PLUGINS_NONPORTED=" cdxaparse \
linsys vcd \ linsys vcd \
apexsink cdaudio dc1394 dirac directfb \ apexsink cdaudio dc1394 dirac directfb \
gsettings \ gsettings \
musepack musicbrainz nas neon ofa openal sdl sndfile timidity \ musepack musicbrainz nas ofa openal sdl sndfile timidity \
directdraw direct3d9 acm wininet \ directdraw direct3d9 acm wininet \
xvid lv2 teletextdec sndio osx_video quicktime" xvid lv2 teletextdec sndio osx_video quicktime"
AC_SUBST(GST_PLUGINS_NONPORTED) AC_SUBST(GST_PLUGINS_NONPORTED)

View file

@ -49,7 +49,7 @@ static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
#define HTTP_DEFAULT_HOST "localhost" #define HTTP_DEFAULT_HOST "localhost"
/* default properties */ /* default properties */
#define DEFAULT_LOCATION "http://"HTTP_DEFAULT_HOST":"G_STRINGIFY(HTTP_DEFAULT_PORT) #define DEFAULT_LOCATION "http://" HTTP_DEFAULT_HOST ":" G_STRINGIFY(HTTP_DEFAULT_PORT)
#define DEFAULT_PROXY "" #define DEFAULT_PROXY ""
#define DEFAULT_USER_AGENT "GStreamer neonhttpsrc" #define DEFAULT_USER_AGENT "GStreamer neonhttpsrc"
#define DEFAULT_AUTOMATIC_REDIRECT TRUE #define DEFAULT_AUTOMATIC_REDIRECT TRUE
@ -82,8 +82,8 @@ static void gst_neonhttp_src_set_property (GObject * object, guint prop_id,
static void gst_neonhttp_src_get_property (GObject * object, guint prop_id, static void gst_neonhttp_src_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec); GValue * value, GParamSpec * pspec);
static GstFlowReturn gst_neonhttp_src_create (GstPushSrc * psrc, static GstFlowReturn gst_neonhttp_src_fill (GstPushSrc * psrc,
GstBuffer ** outbuf); GstBuffer * outbuf);
static gboolean gst_neonhttp_src_start (GstBaseSrc * bsrc); static gboolean gst_neonhttp_src_start (GstBaseSrc * bsrc);
static gboolean gst_neonhttp_src_stop (GstBaseSrc * bsrc); static gboolean gst_neonhttp_src_stop (GstBaseSrc * bsrc);
static gboolean gst_neonhttp_src_get_size (GstBaseSrc * bsrc, guint64 * size); static gboolean gst_neonhttp_src_get_size (GstBaseSrc * bsrc, guint64 * size);
@ -95,7 +95,7 @@ static gboolean gst_neonhttp_src_query (GstBaseSrc * bsrc, GstQuery * query);
static gboolean gst_neonhttp_src_set_proxy (GstNeonhttpSrc * src, static gboolean gst_neonhttp_src_set_proxy (GstNeonhttpSrc * src,
const gchar * uri); const gchar * uri);
static gboolean gst_neonhttp_src_set_location (GstNeonhttpSrc * src, static gboolean gst_neonhttp_src_set_location (GstNeonhttpSrc * src,
const gchar * uri); const gchar * uri, GError ** err);
static gint gst_neonhttp_src_send_request_and_redirect (GstNeonhttpSrc * src, static gint gst_neonhttp_src_send_request_and_redirect (GstNeonhttpSrc * src,
ne_session ** ses, ne_request ** req, gint64 offset, gboolean do_redir); ne_session ** ses, ne_request ** req, gint64 offset, gboolean do_redir);
static gint gst_neonhttp_src_request_dispatch (GstNeonhttpSrc * src, static gint gst_neonhttp_src_request_dispatch (GstNeonhttpSrc * src,
@ -104,48 +104,21 @@ static void gst_neonhttp_src_close_session (GstNeonhttpSrc * src);
static gchar *gst_neonhttp_src_unicodify (const gchar * str); static gchar *gst_neonhttp_src_unicodify (const gchar * str);
static void oom_callback (void); static void oom_callback (void);
static void #define parent_class gst_neonhttp_src_parent_class
_urihandler_init (GType type) G_DEFINE_TYPE_WITH_CODE (GstNeonhttpSrc, gst_neonhttp_src, GST_TYPE_PUSH_SRC,
{ G_IMPLEMENT_INTERFACE (GST_TYPE_URI_HANDLER,
static const GInterfaceInfo urihandler_info = { gst_neonhttp_src_uri_handler_init));
gst_neonhttp_src_uri_handler_init,
NULL,
NULL
};
g_type_add_interface_static (type, GST_TYPE_URI_HANDLER, &urihandler_info);
GST_DEBUG_CATEGORY_INIT (neonhttpsrc_debug, "neonhttpsrc", 0,
"NEON HTTP src");
}
GST_BOILERPLATE_FULL (GstNeonhttpSrc, gst_neonhttp_src, GstPushSrc,
GST_TYPE_PUSH_SRC, _urihandler_init);
static void
gst_neonhttp_src_base_init (gpointer g_class)
{
GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
gst_element_class_add_pad_template (element_class,
gst_static_pad_template_get (&srctemplate));
gst_element_class_set_static_metadata (element_class, "HTTP client source",
"Source/Network",
"Receive data as a client over the network via HTTP using NEON",
"Edgard Lima <edgard.lima@indt.org.br>, "
"Rosfran Borges <rosfran.borges@indt.org.br>, "
"Andre Moreira Magalhaes <andre.magalhaes@indt.org.br>");
}
static void static void
gst_neonhttp_src_class_init (GstNeonhttpSrcClass * klass) gst_neonhttp_src_class_init (GstNeonhttpSrcClass * klass)
{ {
GObjectClass *gobject_class; GObjectClass *gobject_class;
GstElementClass *element_class;
GstBaseSrcClass *gstbasesrc_class; GstBaseSrcClass *gstbasesrc_class;
GstPushSrcClass *gstpushsrc_class; GstPushSrcClass *gstpushsrc_class;
gobject_class = (GObjectClass *) klass; gobject_class = (GObjectClass *) klass;
element_class = (GstElementClass *) klass;
gstbasesrc_class = (GstBaseSrcClass *) klass; gstbasesrc_class = (GstBaseSrcClass *) klass;
gstpushsrc_class = (GstPushSrcClass *) klass; gstpushsrc_class = (GstPushSrcClass *) klass;
@ -238,14 +211,24 @@ gst_neonhttp_src_class_init (GstNeonhttpSrcClass * klass)
gstbasesrc_class->do_seek = GST_DEBUG_FUNCPTR (gst_neonhttp_src_do_seek); gstbasesrc_class->do_seek = GST_DEBUG_FUNCPTR (gst_neonhttp_src_do_seek);
gstbasesrc_class->query = GST_DEBUG_FUNCPTR (gst_neonhttp_src_query); gstbasesrc_class->query = GST_DEBUG_FUNCPTR (gst_neonhttp_src_query);
gstpushsrc_class->create = GST_DEBUG_FUNCPTR (gst_neonhttp_src_create); gstpushsrc_class->fill = GST_DEBUG_FUNCPTR (gst_neonhttp_src_fill);
GST_DEBUG_CATEGORY_INIT (neonhttpsrc_debug, "neonhttpsrc", 0, GST_DEBUG_CATEGORY_INIT (neonhttpsrc_debug, "neonhttpsrc", 0,
"NEON HTTP Client Source"); "NEON HTTP Client Source");
gst_element_class_add_pad_template (element_class,
gst_static_pad_template_get (&srctemplate));
gst_element_class_set_static_metadata (element_class, "HTTP client source",
"Source/Network",
"Receive data as a client over the network via HTTP using NEON",
"Edgard Lima <edgard.lima@indt.org.br>, "
"Rosfran Borges <rosfran.borges@indt.org.br>, "
"Andre Moreira Magalhaes <andre.magalhaes@indt.org.br>");
} }
static void static void
gst_neonhttp_src_init (GstNeonhttpSrc * src, GstNeonhttpSrcClass * g_class) gst_neonhttp_src_init (GstNeonhttpSrc * src)
{ {
const gchar *str; const gchar *str;
@ -265,11 +248,9 @@ gst_neonhttp_src_init (GstNeonhttpSrc * src, GstNeonhttpSrcClass * g_class)
memset (&src->uri, 0, sizeof (src->uri)); memset (&src->uri, 0, sizeof (src->uri));
memset (&src->proxy, 0, sizeof (src->proxy)); memset (&src->proxy, 0, sizeof (src->proxy));
src->content_size = -1; src->content_size = -1;
src->icy_caps = NULL;
src->icy_metaint = 0;
src->seekable = TRUE; src->seekable = TRUE;
gst_neonhttp_src_set_location (src, DEFAULT_LOCATION); gst_neonhttp_src_set_location (src, DEFAULT_LOCATION, NULL);
/* configure proxy */ /* configure proxy */
str = g_getenv ("http_proxy"); str = g_getenv ("http_proxy");
@ -297,11 +278,6 @@ gst_neonhttp_src_dispose (GObject * gobject)
src->cookies = NULL; src->cookies = NULL;
} }
if (src->icy_caps) {
gst_caps_unref (src->icy_caps);
src->icy_caps = NULL;
}
if (src->request) { if (src->request) {
ne_request_destroy (src->request); ne_request_destroy (src->request);
src->request = NULL; src->request = NULL;
@ -356,7 +332,7 @@ gst_neonhttp_src_set_property (GObject * object, guint prop_id,
GST_WARNING ("location property cannot be NULL"); GST_WARNING ("location property cannot be NULL");
goto done; goto done;
} }
if (!gst_neonhttp_src_set_location (src, location)) { if (!gst_neonhttp_src_set_location (src, location, NULL)) {
GST_WARNING ("badly formated location"); GST_WARNING ("badly formated location");
goto done; goto done;
} }
@ -471,51 +447,38 @@ oom_callback (void)
} }
static GstFlowReturn static GstFlowReturn
gst_neonhttp_src_create (GstPushSrc * psrc, GstBuffer ** outbuf) gst_neonhttp_src_fill (GstPushSrc * psrc, GstBuffer * outbuf)
{ {
GstNeonhttpSrc *src; GstNeonhttpSrc *src;
GstBaseSrc *basesrc;
GstFlowReturn ret;
gint read; gint read;
src = GST_NEONHTTP_SRC (psrc); src = GST_NEONHTTP_SRC (psrc);
basesrc = GST_BASE_SRC_CAST (psrc);
/* The caller should know the number of bytes and not read beyond EOS. */ /* The caller should know the number of bytes and not read beyond EOS. */
if (G_UNLIKELY (src->eos)) if (G_UNLIKELY (src->eos))
goto eos; goto eos;
/* Create the buffer. */ read = gst_neonhttp_src_request_dispatch (src, outbuf);
ret = gst_pad_alloc_buffer (GST_BASE_SRC_PAD (basesrc),
basesrc->segment.last_stop, basesrc->blocksize,
src->icy_caps ? src->icy_caps :
GST_PAD_CAPS (GST_BASE_SRC_PAD (basesrc)), outbuf);
if (G_UNLIKELY (ret != GST_FLOW_OK))
goto done;
read = gst_neonhttp_src_request_dispatch (src, *outbuf);
if (G_UNLIKELY (read < 0)) if (G_UNLIKELY (read < 0))
goto read_error; goto read_error;
GST_LOG_OBJECT (src, "returning %u bytes", GST_BUFFER_SIZE (*outbuf)); GST_LOG_OBJECT (src, "returning %" G_GSIZE_FORMAT " bytes, "
"offset %" G_GUINT64_FORMAT, gst_buffer_get_size (outbuf),
GST_BUFFER_OFFSET (outbuf));
done: return GST_FLOW_OK;
return ret;
/* ERRORS */ /* ERRORS */
eos: eos:
{ {
GST_DEBUG_OBJECT (src, "EOS reached"); GST_DEBUG_OBJECT (src, "EOS reached");
return GST_FLOW_UNEXPECTED; return GST_FLOW_EOS;
} }
read_error: read_error:
{ {
GST_ELEMENT_ERROR (src, RESOURCE, READ, GST_ELEMENT_ERROR (src, RESOURCE, READ,
(NULL), ("Could not read any bytes (%i, %s)", read, (NULL), ("Could not read any bytes (%i, %s)", read,
ne_get_error (src->session))); ne_get_error (src->session)));
gst_buffer_unref (*outbuf);
*outbuf = NULL;
return GST_FLOW_ERROR; return GST_FLOW_ERROR;
} }
} }
@ -562,18 +525,16 @@ gst_neonhttp_src_start (GstBaseSrc * bsrc)
if (TRUE) { if (TRUE) {
/* Icecast stuff */ /* Icecast stuff */
const gchar *str_value; const gchar *str_value;
gint gint_value; gint icy_metaint;
str_value = ne_get_response_header (src->request, "icy-metaint"); str_value = ne_get_response_header (src->request, "icy-metaint");
if (str_value) { if (str_value) {
if (sscanf (str_value, "%d", &gint_value) == 1) { if (sscanf (str_value, "%d", &icy_metaint) == 1) {
if (src->icy_caps) { GstCaps *icy_caps;
gst_caps_unref (src->icy_caps);
src->icy_caps = NULL; icy_caps = gst_caps_new_simple ("application/x-icy",
} "metadata-interval", G_TYPE_INT, icy_metaint, NULL);
src->icy_metaint = gint_value; gst_base_src_set_caps (GST_BASE_SRC (src), icy_caps);
src->icy_caps = gst_caps_new_simple ("application/x-icy",
"metadata-interval", G_TYPE_INT, src->icy_metaint, NULL);
} }
} }
@ -658,11 +619,6 @@ gst_neonhttp_src_stop (GstBaseSrc * bsrc)
src->iradio_url = NULL; src->iradio_url = NULL;
} }
if (src->icy_caps) {
gst_caps_unref (src->icy_caps);
src->icy_caps = NULL;
}
src->eos = FALSE; src->eos = FALSE;
src->content_size = -1; src->content_size = -1;
src->read_position = 0; src->read_position = 0;
@ -754,7 +710,8 @@ gst_neonhttp_src_query (GstBaseSrc * bsrc, GstQuery * query)
} }
static gboolean static gboolean
gst_neonhttp_src_set_location (GstNeonhttpSrc * src, const gchar * uri) gst_neonhttp_src_set_location (GstNeonhttpSrc * src, const gchar * uri,
GError ** err)
{ {
ne_uri_free (&src->uri); ne_uri_free (&src->uri);
if (src->location) { if (src->location) {
@ -934,7 +891,7 @@ gst_neonhttp_src_send_request_and_redirect (GstNeonhttpSrc * src,
redir = ne_get_response_header (request, "Location"); redir = ne_get_response_header (request, "Location");
if (redir != NULL) { if (redir != NULL) {
ne_uri_free (&src->uri); ne_uri_free (&src->uri);
gst_neonhttp_src_set_location (src, redir); gst_neonhttp_src_set_location (src, redir, NULL);
GST_LOG_OBJECT (src, "Got HTTP Status Code %d", http_status); GST_LOG_OBJECT (src, "Got HTTP Status Code %d", http_status);
GST_LOG_OBJECT (src, "Using 'Location' header [%s]", src->uri.host); GST_LOG_OBJECT (src, "Using 'Location' header [%s]", src->uri.host);
} }
@ -984,18 +941,24 @@ gst_neonhttp_src_send_request_and_redirect (GstNeonhttpSrc * src,
static gint static gint
gst_neonhttp_src_request_dispatch (GstNeonhttpSrc * src, GstBuffer * outbuf) gst_neonhttp_src_request_dispatch (GstNeonhttpSrc * src, GstBuffer * outbuf)
{ {
GstMapInfo map = GST_MAP_INFO_INIT;
gint ret; gint ret;
gint read = 0; gint read = 0;
gint sizetoread = GST_BUFFER_SIZE (outbuf); gint sizetoread;
/* Loop sending the request: /* Loop sending the request:
* Retry whilst authentication fails and we supply it. */ * Retry whilst authentication fails and we supply it. */
ssize_t len = 0; ssize_t len = 0;
if (!gst_buffer_map (outbuf, &map, GST_MAP_WRITE))
return -1;
sizetoread = map.size;
while (sizetoread > 0) { while (sizetoread > 0) {
len = ne_read_response_block (src->request, len = ne_read_response_block (src->request, (gchar *) map.data + read,
(gchar *) GST_BUFFER_DATA (outbuf) + read, sizetoread); sizetoread);
if (len > 0) { if (len > 0) {
read += len; read += len;
sizetoread -= len; sizetoread -= len;
@ -1005,7 +968,8 @@ gst_neonhttp_src_request_dispatch (GstNeonhttpSrc * src, GstBuffer * outbuf)
} }
GST_BUFFER_SIZE (outbuf) = read; gst_buffer_set_size (outbuf, read);
GST_BUFFER_OFFSET (outbuf) = src->read_position;
if (len < 0) { if (len < 0) {
read = -2; read = -2;
@ -1026,6 +990,9 @@ gst_neonhttp_src_request_dispatch (GstNeonhttpSrc * src, GstBuffer * outbuf)
src->read_position += read; src->read_position += read;
done: done:
gst_buffer_unmap (outbuf, &map);
return read; return read;
} }
@ -1081,33 +1048,35 @@ gst_neonhttp_src_unicodify (const gchar * str)
/* GstURIHandler Interface */ /* GstURIHandler Interface */
static guint static guint
gst_neonhttp_src_uri_get_type (void) gst_neonhttp_src_uri_get_type (GType type)
{ {
return GST_URI_SRC; return GST_URI_SRC;
} }
static const gchar *const * static const gchar *const *
gst_neonhttp_src_uri_get_protocols (void) gst_neonhttp_src_uri_get_protocols (GType type)
{ {
static const gchar *protocols[] = { "http", "https", NULL }; static const gchar *protocols[] = { "http", "https", NULL };
return protocols; return protocols;
} }
static const gchar * static gchar *
gst_neonhttp_src_uri_get_uri (GstURIHandler * handler) gst_neonhttp_src_uri_get_uri (GstURIHandler * handler)
{ {
GstNeonhttpSrc *src = GST_NEONHTTP_SRC (handler); GstNeonhttpSrc *src = GST_NEONHTTP_SRC (handler);
return src->location; /* FIXME: make thread-safe */
return g_strdup (src->location);
} }
static gboolean static gboolean
gst_neonhttp_src_uri_set_uri (GstURIHandler * handler, const gchar * uri) gst_neonhttp_src_uri_set_uri (GstURIHandler * handler, const gchar * uri,
GError ** error)
{ {
GstNeonhttpSrc *src = GST_NEONHTTP_SRC (handler); GstNeonhttpSrc *src = GST_NEONHTTP_SRC (handler);
return gst_neonhttp_src_set_location (src, uri); return gst_neonhttp_src_set_location (src, uri, error);
} }
static void static void
@ -1129,6 +1098,9 @@ gst_neonhttp_src_uri_handler_init (gpointer g_iface, gpointer iface_data)
static gboolean static gboolean
plugin_init (GstPlugin * plugin) plugin_init (GstPlugin * plugin)
{ {
GST_DEBUG_CATEGORY_INIT (neonhttpsrc_debug, "neonhttpsrc", 0,
"NEON HTTP src");
return gst_element_register (plugin, "neonhttpsrc", GST_RANK_NONE, return gst_element_register (plugin, "neonhttpsrc", GST_RANK_NONE,
GST_TYPE_NEONHTTP_SRC); GST_TYPE_NEONHTTP_SRC);
} }

View file

@ -62,8 +62,6 @@ struct _GstNeonhttpSrc {
gchar *iradio_name; gchar *iradio_name;
gchar *iradio_genre; gchar *iradio_genre;
gchar *iradio_url; gchar *iradio_url;
GstCaps *icy_caps;
gint icy_metaint;
/* enable Neon HTTP redirects (HTTP 302 status code) */ /* enable Neon HTTP redirects (HTTP 302 status code) */
gboolean automatic_redirect; gboolean automatic_redirect;