summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiguel Freitas <miguelfreitas@users.sourceforge.net>2003-01-29 02:33:35 +0000
committerMiguel Freitas <miguelfreitas@users.sourceforge.net>2003-01-29 02:33:35 +0000
commit58f833f31e88bebac909db5fc433cd4e19f1837d (patch)
tree6acdcee6ee4746866467feeca299707e24e0fc69
parent89378a497899c211d530ce64077a3e8128044d1d (diff)
downloadxine-lib-58f833f31e88bebac909db5fc433cd4e19f1837d.tar.gz
xine-lib-58f833f31e88bebac909db5fc433cd4e19f1837d.tar.bz2
- preliminary support for reference streams parsing at xine-lib (they
are sent to gui using a new event) - function to return demux from mime type string (used by xine-plugin) - very simple parser for ram files at demux_real CVS patchset: 4030 CVS date: 2003/01/29 02:33:35
-rw-r--r--include/xine.h.in28
-rw-r--r--src/demuxers/demux_asf.c8
-rw-r--r--src/demuxers/demux_real.c158
-rw-r--r--src/xine-engine/load_plugins.c49
4 files changed, 219 insertions, 24 deletions
diff --git a/include/xine.h.in b/include/xine.h.in
index 6fa89c39a..f195c70cc 100644
--- a/include/xine.h.in
+++ b/include/xine.h.in
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
- * $Id: xine.h.in,v 1.57 2003/01/18 15:29:19 miguelfreitas Exp $
+ * $Id: xine.h.in,v 1.58 2003/01/29 02:33:35 miguelfreitas Exp $
*
* public xine-lib (libxine) interface and documentation
*
@@ -819,6 +819,11 @@ char *xine_get_file_extensions (xine_t *self);
* the pointer returned can be free()ed when no longer used */
char *xine_get_mime_types (xine_t *self);
+/* get the demuxer identifier that handles a given mime type
+ *
+ * the pointer returned can be free()ed when no longer used
+ * returns NULL if no demuxer is available to handle this. */
+char *xine_get_demux_for_mime_type (xine_t *self, const char *mime_type);
/* get a description string for an input plugin */
const char *xine_get_input_plugin_description (xine_t *self,
@@ -1141,6 +1146,7 @@ void xine_config_reset (xine_t *self);
#define XINE_EVENT_AUDIO_LEVEL 6 /* report current audio level (l/r) */
#define XINE_EVENT_QUIT 7 /* last event sent when stream is disposed */
#define XINE_EVENT_PROGRESS 8 /* index creation/network connections */
+#define XINE_EVENT_MRL_REFERENCE 9 /* demuxer->frontend: MRL reference(s) for the real stream */
/* input events coming from frontend */
#define XINE_EVENT_INPUT_MOUSE_BUTTON 101
@@ -1231,6 +1237,26 @@ typedef struct {
int percent;
} xine_progress_data_t;
+/*
+ * mrl reference data is sent by demuxers when a reference stream is found.
+ * this stream just contains pointers (urls) to the real data, which are
+ * passed to frontend using this event type. (examples: .asx, .mov and .ram)
+ *
+ * ideally, frontends should add these mrls to a "hierarchical playlist".
+ * that is, instead of the original file, the ones provided here should be
+ * played instead. on pratice, just using a simple playlist should work.
+ *
+ * mrl references should be played in the same order they are received, just
+ * after the current stream finishes.
+ * alternative playlists may be provided and should be used in case of
+ * failure of the primary playlist.
+ */
+typedef struct {
+ int alternative; /* alternative playlist number, usually 0 */
+ char mrl[1]; /* might (will) be longer */
+} xine_mrl_reference_data_t;
+
+
/* opaque xine_event_queue_t */
typedef struct xine_event_queue_s xine_event_queue_t;
diff --git a/src/demuxers/demux_asf.c b/src/demuxers/demux_asf.c
index d941df984..c20452847 100644
--- a/src/demuxers/demux_asf.c
+++ b/src/demuxers/demux_asf.c
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
- * $Id: demux_asf.c,v 1.101 2003/01/26 17:38:41 tmattern Exp $
+ * $Id: demux_asf.c,v 1.102 2003/01/29 02:33:35 miguelfreitas Exp $
*
* demultiplexer for asf streams
*
@@ -1565,13 +1565,15 @@ static char *get_identifier (demux_class_t *this_gen) {
}
static char *get_extensions (demux_class_t *this_gen) {
- return "asf wmv wma";
+ return "asf asx wmv wma";
}
static char *get_mimetypes (demux_class_t *this_gen) {
return "video/x-ms-asf: asf: ASF video;"
"video/x-ms-wmv: wmv: WMV video;"
- "application/vnd.ms-asf: asf: ASF video;";
+ "application/vnd.ms-asf: asf: ASF video;"
+ "application/x-mplayer2: asf,asx,asp: mplayer2;"
+ "video/x-ms-asf-plugin: asf,asx,asp: mms animation;";
}
static void class_dispose (demux_class_t *this_gen) {
diff --git a/src/demuxers/demux_real.c b/src/demuxers/demux_real.c
index f40849e6a..f0d082071 100644
--- a/src/demuxers/demux_real.c
+++ b/src/demuxers/demux_real.c
@@ -28,7 +28,7 @@
*
* Based on FFmpeg's libav/rm.c.
*
- * $Id: demux_real.c,v 1.37 2003/01/23 16:12:13 miguelfreitas Exp $
+ * $Id: demux_real.c,v 1.38 2003/01/29 02:33:36 miguelfreitas Exp $
*/
#ifdef HAVE_CONFIG_H
@@ -40,6 +40,7 @@
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
+#include <ctype.h>
#include "xine_internal.h"
#include "xineutils.h"
@@ -121,6 +122,7 @@ typedef struct {
int fragment_size; /* video sub-demux */
+ int reference_mode;
} demux_real_t ;
typedef struct {
@@ -593,6 +595,77 @@ static void real_parse_headers (demux_real_t *this) {
}
}
+
+/* very naive approach for parsing ram files. it will extract known
+ * mrls directly so it should work for simple smil files too.
+ * no attempt is made to support smil features:
+ * http://service.real.com/help/library/guides/production/htmfiles/smil.htm
+ */
+static int demux_real_parse_references( demux_real_t *this) {
+
+ char *buf = NULL;
+ int buf_size = 0;
+ int buf_used = 0;
+ int len, i, j;
+ int alternative = 0;
+ xine_mrl_reference_data_t *data;
+ xine_event_t uevent;
+
+
+ /* read file to memory.
+ * warning: dumb code, but hopefuly ok since reference file is small */
+ do {
+ buf_size += 1024;
+ buf = realloc(buf, buf_size+1);
+
+ len = this->input->read(this->input, &buf[buf_used], buf_size-buf_used);
+
+ if( len > 0 )
+ buf_used += len;
+
+ /* 50k of reference file? no way. something must be wrong */
+ if( buf_used > 50*1024 )
+ break;
+ } while( len > 0 );
+
+ if(buf_used)
+ buf[buf_used] = '\0';
+
+ for(i=0;i<buf_used;i++) {
+
+ /* "--stop--" is used to have pnm alternative for old real clients
+ * new real clients will stop processing the file and thus use
+ * rtsp protocol.
+ */
+ if( !strncmp(&buf[i],"--stop--",8) )
+ alternative++;
+
+ if( !strncmp(&buf[i],"pnm://",6) || !strncmp(&buf[i],"rtsp://",7) ) {
+ for(j=i; buf[j] && buf[j] != '"' && !isspace(buf[j]); j++ )
+ ;
+ j--;
+ buf[j]='\0';
+ printf("demux_real: ref=%s\n", &buf[i]);
+
+ uevent.type = XINE_EVENT_MRL_REFERENCE;
+ uevent.stream = this->stream;
+ uevent.data_length = strlen(&buf[i])+sizeof(xine_mrl_reference_data_t);
+ data = malloc(uevent.data_length);
+ uevent.data = data;
+ strcpy(data->mrl, &buf[i]);
+ data->alternative = alternative;
+ xine_event_send(this->stream, &uevent);
+
+ i = j;
+ }
+ }
+
+ free(buf);
+
+ this->status = DEMUX_FINISHED;
+ return this->status;
+}
+
/* redefine abs as macro to handle 64-bit diffs.
i guess llabs may not be available everywhere */
#define abs(x) ( ((x)<0) ? -(x) : (x) )
@@ -654,6 +727,9 @@ static int demux_real_send_chunk(demux_plugin_t *this_gen) {
int64_t pts;
off_t offset;
+ if(this->reference_mode)
+ return demux_real_parse_references(this);
+
/* load a header from wherever the stream happens to be pointing */
if ( (size=this->input->read(this->input, header, DATA_PACKET_HEADER_SIZE)) !=
DATA_PACKET_HEADER_SIZE) {
@@ -876,7 +952,7 @@ static int demux_real_send_chunk(demux_plugin_t *this_gen) {
n = this->input->read (this->input, buf->content, size);
- if (n<size) {
+ if (n<size || size < 0) {
printf ("demux_real: read error 44\n");
buf->free_buffer(buf);
@@ -967,8 +1043,12 @@ static void demux_real_send_headers(demux_plugin_t *this_gen) {
this->video_stream_num = -1;
this->audio_stream_num = -1;
- real_parse_headers (this);
-
+ if( !this->reference_mode ) {
+ real_parse_headers (this);
+ } else {
+ if ((this->input->get_capabilities (this->input) & INPUT_CAP_SEEKABLE) != 0)
+ this->input->seek (this->input, 0, SEEK_SET);
+ }
}
static int demux_real_seek (demux_plugin_t *this_gen,
@@ -1023,6 +1103,26 @@ static int demux_real_get_optional_data(demux_plugin_t *this_gen,
return DEMUX_OPTIONAL_UNSUPPORTED;
}
+/* help function to discover stream type. returns:
+ * 0 if not known.
+ * 1 if normal stream.
+ * 2 if reference stream.
+ */
+static int real_check_stream_type(uint8_t *buf, int len)
+{
+ if ((buf[0] == 0x2e)
+ && (buf[1] == 'R')
+ && (buf[2] == 'M')
+ && (buf[3] == 'F'))
+ return 1;
+
+ buf[len] = '\0';
+ if( strstr(buf,"pnm://") || strstr(buf,"rtsp://") || strstr(buf,"<smil>") )
+ return 2;
+
+ return 0;
+}
+
static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *stream,
input_plugin_t *input_gen) {
@@ -1033,46 +1133,40 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str
case METHOD_BY_CONTENT:
{
- uint8_t buf[4096];
+ uint8_t buf[4096], len;
if ((input->get_capabilities(input) & INPUT_CAP_SEEKABLE) != 0) {
input->seek(input, 0, SEEK_SET);
- if (input->read(input, buf, 4)) {
+ if ((len = input->read(input, buf, 1024))) {
#ifdef LOG
printf ("demux_real: input seekable, read 4 bytes: %02x %02x %02x %02x\n",
buf[0], buf[1], buf[2], buf[3]);
#endif
- if ((buf[0] != 0x2e)
- || (buf[1] != 'R')
- || (buf[2] != 'M')
- || (buf[3] != 'F'))
+ if (!real_check_stream_type(buf,len))
return NULL;
} else
return NULL;
- } else if (input->get_optional_data (input, buf, INPUT_OPTIONAL_DATA_PREVIEW)) {
+ } else if ((len = input->get_optional_data (input, buf, INPUT_OPTIONAL_DATA_PREVIEW))) {
#ifdef LOG
printf ("demux_real: input provides preview, read 4 bytes: %02x %02x %02x %02x\n",
buf[0], buf[1], buf[2], buf[3]);
#endif
- if ((buf[0] != 0x2e)
- || (buf[1] != 'R')
- || (buf[2] != 'M')
- || (buf[3] != 'F'))
+ if (!real_check_stream_type(buf,len))
return NULL;
} else
return NULL;
}
-
+#ifdef LOG
printf ("demux_real: by content accepted.\n");
-
+#endif
break;
case METHOD_BY_EXTENSION: {
@@ -1118,6 +1212,32 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str
this->stream = stream;
this->input = input;
+
+ /* discover stream type */
+ {
+ uint8_t buf[4096], len;
+
+ this->reference_mode = 0;
+ if ((len = input->get_capabilities(input) & INPUT_CAP_SEEKABLE) != 0) {
+
+ input->seek(input, 0, SEEK_SET);
+
+ if ((len = input->read(input, buf, 1024))) {
+ if (real_check_stream_type(buf,len) == 2)
+ this->reference_mode = 1;
+ }
+
+ } else if ((len = input->get_optional_data (input, buf, INPUT_OPTIONAL_DATA_PREVIEW))) {
+
+ if (real_check_stream_type(buf,len) == 2)
+ this->reference_mode = 1;
+ }
+
+ if(this->reference_mode)
+ printf("demux_real: reference stream detected\n");
+ }
+
+
this->demux_plugin.send_headers = demux_real_send_headers;
this->demux_plugin.send_chunk = demux_real_send_chunk;
this->demux_plugin.seek = demux_real_seek;
@@ -1132,7 +1252,6 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str
strncpy (this->last_mrl, input->get_mrl (input), 1024);
-
return &this->demux_plugin;
}
@@ -1149,7 +1268,8 @@ static char *get_extensions (demux_class_t *this_gen) {
}
static char *get_mimetypes (demux_class_t *this_gen) {
- return "audio/x-pn-realaudio: ra, rm, ram: Real Media File;";
+ return "audio/x-pn-realaudio: ra, rm, ram: Real Media file;"
+ "audio/x-pn-realaudio-plugin: rpm: Real Media plugin file;";
}
static void class_dispose (demux_class_t *this_gen) {
diff --git a/src/xine-engine/load_plugins.c b/src/xine-engine/load_plugins.c
index cdffd4570..d89548894 100644
--- a/src/xine-engine/load_plugins.c
+++ b/src/xine-engine/load_plugins.c
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
- * $Id: load_plugins.c,v 1.138 2003/01/18 20:35:24 f1rmb Exp $
+ * $Id: load_plugins.c,v 1.139 2003/01/29 02:33:36 miguelfreitas Exp $
*
*
* Load input/demux/audio_out/video_out/codec plugins
@@ -37,6 +37,7 @@
#include <string.h>
#include <errno.h>
#include <stdlib.h>
+#include <ctype.h>
#include <signal.h>
#include "xine_internal.h"
@@ -2011,6 +2012,52 @@ char *xine_get_mime_types (xine_t *self) {
}
+/* get the demuxer identifier that handles a given mime type
+ *
+ * the pointer returned can be free()ed when no longer used
+ * returns NULL if no demuxer is available to handle this. */
+char *xine_get_demux_for_mime_type (xine_t *self, const char *mime_type) {
+
+ plugin_catalog_t *catalog = self->plugin_catalog;
+ plugin_node_t *node;
+ char *id = NULL;
+ char *mime_arg, *mime_demux;
+ char *s;
+
+ /* create a copy and convert to lower case */
+ mime_arg = strdup(mime_type);
+ for(s=mime_arg; *s; s++)
+ *s = tolower(*s);
+
+ pthread_mutex_lock (&catalog->lock);
+
+ node = xine_list_first_content (catalog->demux);
+ while (node && !id) {
+ demux_class_t *cls = (demux_class_t *)node->plugin_class;
+
+ s = cls->get_mimetypes (cls);
+ if (s) {
+ mime_demux = strdup(s);
+
+ for(s=mime_demux; *s; s++)
+ *s = tolower(*s);
+
+ if( strstr(mime_demux, mime_arg) )
+ id = strdup(node->info->id);
+
+ free(mime_demux);
+ }
+ node = xine_list_next_content (catalog->demux);
+ }
+
+ pthread_mutex_unlock (&catalog->lock);
+
+ free(mime_arg);
+
+ return id;
+}
+
+
static void dispose_plugin_list (xine_list_t *list) {
plugin_node_t *node;