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 \
apexsink cdaudio dc1394 dirac directfb \
gsettings \
musepack musicbrainz nas neon ofa openal sdl sndfile timidity \
musepack musicbrainz nas ofa openal sdl sndfile timidity \
directdraw direct3d9 acm wininet \
xvid lv2 teletextdec sndio osx_video quicktime"
AC_SUBST(GST_PLUGINS_NONPORTED)

View file

@ -49,7 +49,7 @@ static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
#define HTTP_DEFAULT_HOST "localhost"
/* 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_USER_AGENT "GStreamer neonhttpsrc"
#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,
GValue * value, GParamSpec * pspec);
static GstFlowReturn gst_neonhttp_src_create (GstPushSrc * psrc,
GstBuffer ** outbuf);
static GstFlowReturn gst_neonhttp_src_fill (GstPushSrc * psrc,
GstBuffer * outbuf);
static gboolean gst_neonhttp_src_start (GstBaseSrc * bsrc);
static gboolean gst_neonhttp_src_stop (GstBaseSrc * bsrc);
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,
const gchar * uri);
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,
ne_session ** ses, ne_request ** req, gint64 offset, gboolean do_redir);
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 void oom_callback (void);
static void
_urihandler_init (GType type)
{
static const GInterfaceInfo urihandler_info = {
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>");
}
#define parent_class gst_neonhttp_src_parent_class
G_DEFINE_TYPE_WITH_CODE (GstNeonhttpSrc, gst_neonhttp_src, GST_TYPE_PUSH_SRC,
G_IMPLEMENT_INTERFACE (GST_TYPE_URI_HANDLER,
gst_neonhttp_src_uri_handler_init));
static void
gst_neonhttp_src_class_init (GstNeonhttpSrcClass * klass)
{
GObjectClass *gobject_class;
GstElementClass *element_class;
GstBaseSrcClass *gstbasesrc_class;
GstPushSrcClass *gstpushsrc_class;
gobject_class = (GObjectClass *) klass;
element_class = (GstElementClass *) klass;
gstbasesrc_class = (GstBaseSrcClass *) 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->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,
"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
gst_neonhttp_src_init (GstNeonhttpSrc * src, GstNeonhttpSrcClass * g_class)
gst_neonhttp_src_init (GstNeonhttpSrc * src)
{
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->proxy, 0, sizeof (src->proxy));
src->content_size = -1;
src->icy_caps = NULL;
src->icy_metaint = 0;
src->seekable = TRUE;
gst_neonhttp_src_set_location (src, DEFAULT_LOCATION);
gst_neonhttp_src_set_location (src, DEFAULT_LOCATION, NULL);
/* configure proxy */
str = g_getenv ("http_proxy");
@ -297,11 +278,6 @@ gst_neonhttp_src_dispose (GObject * gobject)
src->cookies = NULL;
}
if (src->icy_caps) {
gst_caps_unref (src->icy_caps);
src->icy_caps = NULL;
}
if (src->request) {
ne_request_destroy (src->request);
src->request = NULL;
@ -356,7 +332,7 @@ gst_neonhttp_src_set_property (GObject * object, guint prop_id,
GST_WARNING ("location property cannot be NULL");
goto done;
}
if (!gst_neonhttp_src_set_location (src, location)) {
if (!gst_neonhttp_src_set_location (src, location, NULL)) {
GST_WARNING ("badly formated location");
goto done;
}
@ -471,51 +447,38 @@ oom_callback (void)
}
static GstFlowReturn
gst_neonhttp_src_create (GstPushSrc * psrc, GstBuffer ** outbuf)
gst_neonhttp_src_fill (GstPushSrc * psrc, GstBuffer * outbuf)
{
GstNeonhttpSrc *src;
GstBaseSrc *basesrc;
GstFlowReturn ret;
gint read;
src = GST_NEONHTTP_SRC (psrc);
basesrc = GST_BASE_SRC_CAST (psrc);
/* The caller should know the number of bytes and not read beyond EOS. */
if (G_UNLIKELY (src->eos))
goto eos;
/* Create the buffer. */
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);
read = gst_neonhttp_src_request_dispatch (src, outbuf);
if (G_UNLIKELY (read < 0))
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 ret;
return GST_FLOW_OK;
/* ERRORS */
eos:
{
GST_DEBUG_OBJECT (src, "EOS reached");
return GST_FLOW_UNEXPECTED;
return GST_FLOW_EOS;
}
read_error:
{
GST_ELEMENT_ERROR (src, RESOURCE, READ,
(NULL), ("Could not read any bytes (%i, %s)", read,
ne_get_error (src->session)));
gst_buffer_unref (*outbuf);
*outbuf = NULL;
return GST_FLOW_ERROR;
}
}
@ -562,18 +525,16 @@ gst_neonhttp_src_start (GstBaseSrc * bsrc)
if (TRUE) {
/* Icecast stuff */
const gchar *str_value;
gint gint_value;
gint icy_metaint;
str_value = ne_get_response_header (src->request, "icy-metaint");
if (str_value) {
if (sscanf (str_value, "%d", &gint_value) == 1) {
if (src->icy_caps) {
gst_caps_unref (src->icy_caps);
src->icy_caps = NULL;
}
src->icy_metaint = gint_value;
src->icy_caps = gst_caps_new_simple ("application/x-icy",
"metadata-interval", G_TYPE_INT, src->icy_metaint, NULL);
if (sscanf (str_value, "%d", &icy_metaint) == 1) {
GstCaps *icy_caps;
icy_caps = gst_caps_new_simple ("application/x-icy",
"metadata-interval", G_TYPE_INT, icy_metaint, NULL);
gst_base_src_set_caps (GST_BASE_SRC (src), icy_caps);
}
}
@ -658,11 +619,6 @@ gst_neonhttp_src_stop (GstBaseSrc * bsrc)
src->iradio_url = NULL;
}
if (src->icy_caps) {
gst_caps_unref (src->icy_caps);
src->icy_caps = NULL;
}
src->eos = FALSE;
src->content_size = -1;
src->read_position = 0;
@ -754,7 +710,8 @@ gst_neonhttp_src_query (GstBaseSrc * bsrc, GstQuery * query)
}
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);
if (src->location) {
@ -934,7 +891,7 @@ gst_neonhttp_src_send_request_and_redirect (GstNeonhttpSrc * src,
redir = ne_get_response_header (request, "Location");
if (redir != NULL) {
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, "Using 'Location' header [%s]", src->uri.host);
}
@ -984,18 +941,24 @@ gst_neonhttp_src_send_request_and_redirect (GstNeonhttpSrc * src,
static gint
gst_neonhttp_src_request_dispatch (GstNeonhttpSrc * src, GstBuffer * outbuf)
{
GstMapInfo map = GST_MAP_INFO_INIT;
gint ret;
gint read = 0;
gint sizetoread = GST_BUFFER_SIZE (outbuf);
gint sizetoread;
/* Loop sending the request:
* Retry whilst authentication fails and we supply it. */
ssize_t len = 0;
if (!gst_buffer_map (outbuf, &map, GST_MAP_WRITE))
return -1;
sizetoread = map.size;
while (sizetoread > 0) {
len = ne_read_response_block (src->request,
(gchar *) GST_BUFFER_DATA (outbuf) + read, sizetoread);
len = ne_read_response_block (src->request, (gchar *) map.data + read,
sizetoread);
if (len > 0) {
read += 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) {
read = -2;
@ -1026,6 +990,9 @@ gst_neonhttp_src_request_dispatch (GstNeonhttpSrc * src, GstBuffer * outbuf)
src->read_position += read;
done:
gst_buffer_unmap (outbuf, &map);
return read;
}
@ -1081,33 +1048,35 @@ gst_neonhttp_src_unicodify (const gchar * str)
/* GstURIHandler Interface */
static guint
gst_neonhttp_src_uri_get_type (void)
gst_neonhttp_src_uri_get_type (GType type)
{
return GST_URI_SRC;
}
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 };
return protocols;
}
static const gchar *
static gchar *
gst_neonhttp_src_uri_get_uri (GstURIHandler * handler)
{
GstNeonhttpSrc *src = GST_NEONHTTP_SRC (handler);
return src->location;
/* FIXME: make thread-safe */
return g_strdup (src->location);
}
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);
return gst_neonhttp_src_set_location (src, uri);
return gst_neonhttp_src_set_location (src, uri, error);
}
static void
@ -1129,6 +1098,9 @@ gst_neonhttp_src_uri_handler_init (gpointer g_iface, gpointer iface_data)
static gboolean
plugin_init (GstPlugin * plugin)
{
GST_DEBUG_CATEGORY_INIT (neonhttpsrc_debug, "neonhttpsrc", 0,
"NEON HTTP src");
return gst_element_register (plugin, "neonhttpsrc", GST_RANK_NONE,
GST_TYPE_NEONHTTP_SRC);
}

View file

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