From 7325d78ee8eee3d62ad3cc408a1058db0c59bb42 Mon Sep 17 00:00:00 2001 From: Darren Salt Date: Fri, 20 Jun 2008 02:25:33 +0100 Subject: Allow input plugins to report MIME types as optional data. Implement for http. This is an input plugin API extension; ABI is unchanged. The version is not bumped (we can't bump it due to 1.2). --- src/input/input_http.c | 19 +++++++++++++++---- src/input/input_plugin.h | 5 +++++ 2 files changed, 20 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/input/input_http.c b/src/input/input_http.c index cbc2e8140..169a0d384 100644 --- a/src/input/input_http.c +++ b/src/input/input_http.c @@ -82,6 +82,8 @@ typedef struct { char auth[BUFSIZE]; char proxyauth[BUFSIZE]; + + char *mime_type; char *proto; char *user; @@ -592,17 +594,20 @@ static const char* http_plugin_get_mrl (input_plugin_t *this_gen) { } static int http_plugin_get_optional_data (input_plugin_t *this_gen, - void *data, int data_type) { + void *const data, int data_type) { + void **const ptr = (void **const) data; http_input_plugin_t *this = (http_input_plugin_t *) this_gen; switch (data_type) { case INPUT_OPTIONAL_DATA_PREVIEW: - memcpy (data, this->preview, this->preview_size); return this->preview_size; - break; + case INPUT_OPTIONAL_DATA_MIME_TYPE: + *ptr = this->mime_type; + case INPUT_OPTIONAL_DATA_DEMUX_MIME_TYPE: + return *this->mime_type ? INPUT_OPTIONAL_SUCCESS : INPUT_OPTIONAL_UNSUPPORTED; } return INPUT_OPTIONAL_UNSUPPORTED; @@ -627,6 +632,7 @@ static void http_plugin_dispose (input_plugin_t *this_gen ) { if (this->user) free(this->user); if (this->password) free(this->password); if (this->uri) free(this->uri); + if (this->mime_type) free(this->mime_type); free (this); } @@ -655,7 +661,9 @@ static int http_plugin_open (input_plugin_t *this_gen ) { int use_proxy; int proxyport; int mpegurl_redirect = 0; - + char mime_type[256]; + + mime_type[0] = 0; use_proxy = this_class->proxyhost && strlen(this_class->proxyhost); if (use_proxy) { @@ -922,6 +930,7 @@ static int http_plugin_open (input_plugin_t *this_gen ) { const char *type = this->buf + sizeof (TAG_CONTENT_TYPE) - 1; while (isspace (*type)) ++type; + sprintf (mime_type, "%.255s", type); if (!strncasecmp (type, "video/nsv", 9)) { lprintf("shoutcast nsv detected\n"); this->is_nsv = 1; @@ -993,6 +1002,8 @@ static int http_plugin_open (input_plugin_t *this_gen ) { lprintf("preview_size=%"PRId64"\n", this->preview_size); this->curpos = 0; + if (*mime_type) + this->mime_type = strdup (mime_type); return 1; } diff --git a/src/input/input_plugin.h b/src/input/input_plugin.h index 4790164d5..ff4c75b29 100644 --- a/src/input/input_plugin.h +++ b/src/input/input_plugin.h @@ -307,6 +307,11 @@ struct input_plugin_s { #define INPUT_OPTIONAL_DATA_SPULANG 3 #define INPUT_OPTIONAL_DATA_PREVIEW 7 +/* buffer is a const char **; the string is freed by the input plugin. */ +#define INPUT_OPTIONAL_DATA_MIME_TYPE 8 +/* buffer is unused; true if the demuxer should be determined by the MIME type */ +#define INPUT_OPTIONAL_DATA_DEMUX_MIME_TYPE 9 + #define MAX_MRL_ENTRIES 255 #define MAX_PREVIEW_SIZE 4096 -- cgit v1.2.3 From 3bd7a49bfcd82b129333b9433c3b9e21400b6d3c Mon Sep 17 00:00:00 2001 From: Darren Salt Date: Fri, 20 Jun 2008 02:25:33 +0100 Subject: Read the MIME type from the plugin & use it for demuxer selection (if by extn). text/plain is specifically filtered out because it could cause lots of false positives, at least with http; web servers tend to default to text/plain for unknown types. --- src/xine-engine/load_plugins.c | 64 +++++++++++++++++++++++++++++------------- 1 file changed, 44 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/src/xine-engine/load_plugins.c b/src/xine-engine/load_plugins.c index 031c94984..a71092761 100644 --- a/src/xine-engine/load_plugins.c +++ b/src/xine-engine/load_plugins.c @@ -1224,6 +1224,26 @@ void _x_free_input_plugin (xine_stream_t *stream, input_plugin_t *input) { } } +static int probe_mime_type (xine_t *self, plugin_node_t *node, const char *mime_type) +{ + /* catalog->lock is expected to be locked */ + if (node->plugin_class || _load_plugin_class(self, node, NULL)) + { + const unsigned int mime_type_len = strlen (mime_type); + demux_class_t *cls = (demux_class_t *)node->plugin_class; + const char *mime = cls->get_mimetypes (cls); + while (mime) + { + while (*mime == ';' || isspace (*mime)) + ++mime; + if (!strncasecmp (mime, mime_type, mime_type_len) && + (!mime[mime_type_len] || mime[mime_type_len] == ':' || mime[mime_type_len] == ';')) + return 1; + mime = strchr (mime, ';'); + } + } + return 0; +} static demux_plugin_t *probe_demux (xine_stream_t *stream, int method1, int method2, input_plugin_t *input) { @@ -1246,8 +1266,6 @@ static demux_plugin_t *probe_demux (xine_stream_t *stream, int method1, int meth while (methods[i] != -1 && !plugin) { int list_id, list_size; - stream->content_detection_method = methods[i]; - pthread_mutex_lock (&catalog->lock); list_size = xine_sarray_size(catalog->plugin_lists[PLUGIN_DEMUX - 1]); @@ -1259,6 +1277,25 @@ static demux_plugin_t *probe_demux (xine_stream_t *stream, int method1, int meth xprintf(stream->xine, XINE_VERBOSITY_DEBUG, "load_plugins: probing demux '%s'\n", node->info->id); if (node->plugin_class || _load_plugin_class(stream->xine, node, NULL)) { + const char *mime_type; + + /* If detecting by MRL, try the MIME type first (but not text/plain)... */ + stream->content_detection_method = METHOD_EXPLICIT; + if (methods[i] == METHOD_BY_EXTENSION && + stream->input_plugin->get_optional_data && + stream->input_plugin->get_optional_data (stream->input_plugin, NULL, INPUT_OPTIONAL_DATA_DEMUX_MIME_TYPE) != INPUT_OPTIONAL_UNSUPPORTED && + stream->input_plugin->get_optional_data (stream->input_plugin, &mime_type, INPUT_OPTIONAL_DATA_MIME_TYPE) != INPUT_OPTIONAL_UNSUPPORTED && + mime_type && strcasecmp (mime_type, "text/plain") && + probe_mime_type (stream->xine, node, mime_type) && + (plugin = ((demux_class_t *)node->plugin_class)->open_plugin (node->plugin_class, stream, input))) + { + inc_node_ref(node); + plugin->node = node; + break; + } + + /* ... then try the extension */ + stream->content_detection_method = methods[i]; if ((plugin = ((demux_class_t *)node->plugin_class)->open_plugin(node->plugin_class, stream, input))) { inc_node_ref(node); plugin->node = node; @@ -1356,6 +1393,7 @@ demux_plugin_t *_x_find_demux_plugin_last_probe(xine_stream_t *stream, const cha i = 0; while (methods[i] != -1 && !plugin) { int list_id, list_size; + const char *mime_type; stream->content_detection_method = methods[i]; @@ -2520,7 +2558,6 @@ char *xine_get_demux_for_mime_type (xine_t *self, const char *mime_type) { plugin_node_t *node; char *id = NULL; int list_id, list_size; - const size_t mime_type_len = strlen (mime_type); pthread_mutex_lock (&catalog->lock); @@ -2529,23 +2566,10 @@ char *xine_get_demux_for_mime_type (xine_t *self, const char *mime_type) { for (list_id = 0; (list_id < list_size) && !id; list_id++) { node = xine_sarray_get (catalog->plugin_lists[PLUGIN_DEMUX - 1], list_id); - if (node->plugin_class || _load_plugin_class(self, node, NULL)) { - - demux_class_t *cls = (demux_class_t *)node->plugin_class; - const char *mime = cls->get_mimetypes (cls); - while (mime) - { - while (*mime == ';' || isspace (*mime)) - ++mime; - if (!strncmp (mime, mime_type, mime_type_len) && - (!mime[mime_type_len] || mime[mime_type_len] == ':' || mime[mime_type_len] == ';')) - { - free (id); - id = strdup(node->info->id); - break; - } - mime = strchr (mime, ';'); - } + if (probe_mime_type (self, node, mime_type)) + { + free (id); + id = strdup(node->info->id); } } -- cgit v1.2.3 From e8d0ebf629763d195cdc6675f952f479bcedb6c7 Mon Sep 17 00:00:00 2001 From: Darren Salt Date: Fri, 20 Jun 2008 02:25:34 +0100 Subject: Ask the input plugin which demuxer to use. This overrides the normal content/extension detection, but can be overridden by the user. This is an input plugin API extension; ABI is unchanged. The version is not bumped (we can't bump it due to 1.2). --- src/input/input_plugin.h | 2 ++ src/xine-engine/xine.c | 21 +++++++++++++++++++++ 2 files changed, 23 insertions(+) (limited to 'src') diff --git a/src/input/input_plugin.h b/src/input/input_plugin.h index ff4c75b29..080e05476 100644 --- a/src/input/input_plugin.h +++ b/src/input/input_plugin.h @@ -311,6 +311,8 @@ struct input_plugin_s { #define INPUT_OPTIONAL_DATA_MIME_TYPE 8 /* buffer is unused; true if the demuxer should be determined by the MIME type */ #define INPUT_OPTIONAL_DATA_DEMUX_MIME_TYPE 9 +/* buffer is a const char **; the string is static or freed by the input plugin. */ +#define INPUT_OPTIONAL_DATA_DEMUXER 10 #define MAX_MRL_ENTRIES 255 #define MAX_PREVIEW_SIZE 4096 diff --git a/src/xine-engine/xine.c b/src/xine-engine/xine.c index 984b6ade9..e4e36527f 100644 --- a/src/xine-engine/xine.c +++ b/src/xine-engine/xine.c @@ -1185,6 +1185,27 @@ static int open_internal (xine_stream_t *stream, const char *mrl) { /* enable buffered input plugin (request optimizer) */ stream->input_plugin = _x_cache_plugin_get_instance(stream, 0); + /* Let the plugin request a specific demuxer (if the user hasn't). + * This overrides find-by-content & find-by-extension. + */ + if (!stream->demux_plugin) + { + char *default_demux = NULL; + stream->input_plugin->get_optional_data (stream->input_plugin, &default_demux, INPUT_OPTIONAL_DATA_DEMUXER); + if (default_demux) + { + stream->demux_plugin = _x_find_demux_plugin_by_name (stream, default_demux, stream->input_plugin); + if (stream->demux_plugin) + { + lprintf ("demux and input plugin found\n"); + _x_meta_info_set_utf8 (stream, XINE_META_INFO_SYSTEMLAYER, + stream->demux_plugin->demux_class->get_identifier (stream->demux_plugin->demux_class)); + } + else + xine_log (stream->xine, XINE_LOG_MSG, _("xine: couldn't load plugin-specified demux %s for >%s<\n"), default_demux, mrl); + } + } + if (!stream->demux_plugin) { /* -- cgit v1.2.3