summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/demuxers/Makefile.am7
-rw-r--r--src/demuxers/demux_mpeg.c276
-rw-r--r--src/demuxers/demux_mpeg_block.c4
3 files changed, 237 insertions, 50 deletions
diff --git a/src/demuxers/Makefile.am b/src/demuxers/Makefile.am
index c386289a6..18028e01f 100644
--- a/src/demuxers/Makefile.am
+++ b/src/demuxers/Makefile.am
@@ -37,6 +37,7 @@ endif
lib_LTLIBRARIES = $(asf_module) xineplug_dmx_avi.la\
xineplug_dmx_mpeg_block.la \
+ xineplug_dmx_mpeg.la \
xineplug_dmx_mpeg_audio.la \
xineplug_dmx_film.la \
xineplug_dmx_qt.la \
@@ -59,9 +60,9 @@ xineplug_dmx_mpeg_block_la_SOURCES = demux_mpeg_block.c
xineplug_dmx_mpeg_block_la_LIBADD = $(top_builddir)/src/xine-engine/libxine.la
xineplug_dmx_mpeg_block_la_LDFLAGS = -avoid-version -module
-#xineplug_dmx_mpeg_la_SOURCES = demux_mpeg.c
-#xineplug_dmx_mpeg_la_LIBADD = $(top_builddir)/src/xine-engine/libxine.la
-#xineplug_dmx_mpeg_la_LDFLAGS = -avoid-version -module
+xineplug_dmx_mpeg_la_SOURCES = demux_mpeg.c
+xineplug_dmx_mpeg_la_LIBADD = $(top_builddir)/src/xine-engine/libxine.la
+xineplug_dmx_mpeg_la_LDFLAGS = -avoid-version -module
xineplug_dmx_mpeg_audio_la_SOURCES = demux_mpgaudio.c
xineplug_dmx_mpeg_audio_la_LIBADD = -lm $(top_builddir)/src/xine-engine/libxine.la
diff --git a/src/demuxers/demux_mpeg.c b/src/demuxers/demux_mpeg.c
index 7054923ec..aef586222 100644
--- a/src/demuxers/demux_mpeg.c
+++ b/src/demuxers/demux_mpeg.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_mpeg.c,v 1.81 2002/10/12 17:11:58 jkeil Exp $
+ * $Id: demux_mpeg.c,v 1.82 2002/10/23 10:08:48 jkeil Exp $
*
* demultiplexer for mpeg 1/2 program streams
* reads streams of variable blocksizes
@@ -57,13 +57,10 @@ typedef struct demux_mpeg_s {
demux_plugin_t demux_plugin;
- xine_t *xine;
-
- config_values_t *config;
-
fifo_buffer_t *audio_fifo;
fifo_buffer_t *video_fifo;
+ xine_stream_t *stream;
input_plugin_t *input;
pthread_t thread;
@@ -85,6 +82,16 @@ typedef struct demux_mpeg_s {
} demux_mpeg_t;
+typedef struct {
+
+ demux_class_t demux_class;
+
+ /* class-wide, global variables here */
+
+ xine_t *xine;
+ config_values_t *config;
+} demux_mpeg_class_t;
+
/*
* borrow a little knowledge from the Quicktime demuxer
*/
@@ -238,10 +245,10 @@ static void check_newpts( demux_mpeg_t *this, int64_t pts, int video )
(this->send_newpts || (this->last_pts[video] && abs(diff)>WRAP_THRESHOLD) ) ) {
if (this->buf_flag_seek) {
- xine_demux_control_newpts(this->xine, pts, BUF_FLAG_SEEK);
+ xine_demux_control_newpts(this->stream, pts, BUF_FLAG_SEEK);
this->buf_flag_seek = 0;
} else {
- xine_demux_control_newpts(this->xine, pts, 0);
+ xine_demux_control_newpts(this->stream, pts, 0);
}
this->send_newpts = 0;
this->last_pts[1-video] = 0;
@@ -791,7 +798,7 @@ static void *demux_mpeg_loop (void *this_gen) {
} while( this->status == DEMUX_OK );
if (this->send_end_buffers) {
- xine_demux_control_end(this->xine, BUF_FLAG_END_STREAM);
+ xine_demux_control_end(this->stream, BUF_FLAG_END_STREAM);
}
printf ("demux_mpeg: demux thread finished (status: %d, buf:%x)\n",
@@ -824,9 +831,9 @@ static void demux_mpeg_stop (demux_plugin_t *this_gen) {
pthread_mutex_unlock( &this->mutex );
pthread_join (this->thread, &p);
- xine_demux_flush_engine(this->xine);
+ xine_demux_flush_engine(this->stream);
- xine_demux_control_end(this->xine, BUF_FLAG_END_USER);
+ xine_demux_control_end(this->stream, BUF_FLAG_END_USER);
}
static int demux_mpeg_get_status (demux_plugin_t *this_gen) {
@@ -835,17 +842,19 @@ static int demux_mpeg_get_status (demux_plugin_t *this_gen) {
return (this->thread_running?DEMUX_OK:DEMUX_FINISHED);
}
-static int demux_mpeg_send_headers (demux_mpeg_t *this) {
+static void demux_mpeg_send_headers (demux_plugin_t *this_gen) {
+
+ demux_mpeg_t *this = (demux_mpeg_t *) this_gen;
pthread_mutex_lock( &this->mutex );
- this->video_fifo = this->xine->video_fifo;
- this->audio_fifo = this->xine->audio_fifo;
+ this->video_fifo = this->stream->video_fifo;
+ this->audio_fifo = this->stream->audio_fifo;
this->rate = 0; /* fixme */
this->last_pts[0] = 0;
this->last_pts[1] = 0;
- xine_demux_control_start(this->xine);
+ xine_demux_control_start(this->stream);
if ((this->input->get_capabilities (this->input) & INPUT_CAP_PREVIEW) != 0 ) {
@@ -872,11 +881,9 @@ static int demux_mpeg_send_headers (demux_mpeg_t *this) {
/* printf ("demux_mpeg: rate %d\n", this->rate); */
}
- xine_demux_control_headers_done (this->xine);
+ xine_demux_control_headers_done (this->stream);
pthread_mutex_unlock (&this->mutex);
-
- return DEMUX_CAN_HANDLE;
}
static int demux_mpeg_start (demux_plugin_t *this_gen,
@@ -919,7 +926,7 @@ static int demux_mpeg_start (demux_plugin_t *this_gen,
}
else {
this->buf_flag_seek = 1;
- xine_demux_flush_engine(this->xine);
+ xine_demux_flush_engine(this->stream);
}
/* this->status is saved because we can be interrupted between
@@ -937,6 +944,7 @@ static int demux_mpeg_seek (demux_plugin_t *this_gen,
return demux_mpeg_start (this_gen, start_pos, start_time);
}
+#if 0
static int demux_mpeg_open(demux_plugin_t *this_gen,
input_plugin_t *input, int stage) {
@@ -1120,15 +1128,7 @@ static int demux_mpeg_open(demux_plugin_t *this_gen,
return DEMUX_CANNOT_HANDLE;
}
-
-static char *demux_mpeg_get_id(void) {
- return "MPEG";
-}
-
-static char *demux_mpeg_get_mimetypes(void) {
- return "video/mpeg: mpeg, mpg, mpe: MPEG animation;"
- "video/x-mpeg: mpeg, mpg, mpe: MPEG animation;";
-}
+#endif
static void demux_mpeg_dispose (demux_plugin_t *this) {
free (this);
@@ -1145,38 +1145,224 @@ static int demux_mpeg_get_stream_length (demux_plugin_t *this_gen) {
}
-static void *init_demuxer_plugin (xine_t *xine, void *data) {
-
- demux_mpeg_t *this;
+static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *stream,
+ input_plugin_t *input) {
+ demux_mpeg_t *this;
+ config_values_t *config = ((demux_mpeg_class_t *) class_gen)->config;
this = xine_xmalloc (sizeof (demux_mpeg_t));
- this->config = xine->config;
- this->xine = xine;
+ this->stream = stream;
+ this->input = input;
/* Calling register_string() configure valid mrls in configfile */
- (void*) this->config->register_string(this->config, "mrl.mrls_mpeg", VALID_MRLS,
- _("valid mrls for mpeg demuxer"),
- NULL, 20, NULL, NULL);
- (void*) this->config->register_string(this->config,
- "mrl.ends_mpeg", VALID_ENDS,
- _("valid mrls ending for mpeg demuxer"),
- NULL, 20, NULL, NULL);
-
- this->demux_plugin.open = demux_mpeg_open;
+ (void*) config->register_string(config, "mrl.mrls_mpeg", VALID_MRLS,
+ _("valid mrls for mpeg demuxer"),
+ NULL, 20, NULL, NULL);
+ (void*) config->register_string(config,
+ "mrl.ends_mpeg", VALID_ENDS,
+ _("valid mrls ending for mpeg demuxer"),
+ NULL, 20, NULL, NULL);
+
+ this->demux_plugin.send_headers = demux_mpeg_send_headers;
this->demux_plugin.start = demux_mpeg_start;
this->demux_plugin.seek = demux_mpeg_seek;
this->demux_plugin.stop = demux_mpeg_stop;
this->demux_plugin.dispose = demux_mpeg_dispose;
this->demux_plugin.get_status = demux_mpeg_get_status;
- this->demux_plugin.get_identifier = demux_mpeg_get_id;
this->demux_plugin.get_stream_length = demux_mpeg_get_stream_length;
- this->demux_plugin.get_mimetypes = demux_mpeg_get_mimetypes;
+ this->demux_plugin.demux_class = class_gen;
this->status = DEMUX_FINISHED;
- this->xine = xine;
pthread_mutex_init( &this->mutex, NULL );
+
+ switch (stream->content_detection_method) {
+
+ case XINE_DEMUX_CONTENT_STRATEGY: {
+ uint8_t buf[4096];
+ off_t mdat_atom_offset = -1;
+ int64_t mdat_atom_size = -1;
+ unsigned int fourcc_tag;
+ int i, j;
+ int ok = 0;
+
+ if ((input->get_capabilities(input) & INPUT_CAP_SEEKABLE) == 0
+ || input->get_blocksize(input)) {
+ free (this);
+ return NULL;
+ }
+
+ input->seek(input, 0, SEEK_SET);
+ if (input->read(input, buf, 16) == 16) {
+
+ if(!buf[0] && !buf[1] && (buf[2] == 0x01))
+
+ switch(buf[3]) {
+ case 0xba:
+ if((buf[4] & 0xf0) == 0x20) {
+ uint32_t pckbuf ;
+
+ pckbuf = read_bytes (this, 1);
+ if ((pckbuf>>4) != 4) {
+ ok = 1;
+ break;
+ }
+ }
+ break;
+#if 0
+ case 0xe0:
+ if((buf[6] & 0xc0) != 0x80) {
+ uint32_t pckbuf ;
+
+ pckbuf = read_bytes (this, 1);
+ if ((pckbuf>>4) != 4) {
+ ok = 1;
+ break;
+ }
+ }
+ break;
+#endif
+ }
+ }
+
+ if (ok)
+ break;
+
+ /* special case for MPEG streams hidden inside QT files; check
+ * is there is an mdat atom */
+ find_mdat_atom(input, &mdat_atom_offset, &mdat_atom_size);
+ if (mdat_atom_offset != -1) {
+ /* seek to the start of the mdat data, which might be in different
+ * depending on the size type of the atom */
+ if (mdat_atom_size == 1)
+ input->seek(input, mdat_atom_offset + 16, SEEK_SET);
+ else
+ input->seek(input, mdat_atom_offset + 8, SEEK_SET);
+
+ /* go through the same MPEG detection song and dance */
+ if (input->read(input, buf, 6)) {
+ if (!buf[0] && !buf[1] && buf[2] == 0x01) {
+ switch (buf[3]) {
+ case 0xba:
+ if ((buf[4] & 0xf0) == 0x20) {
+ uint32_t pckbuf ;
+
+ pckbuf = read_bytes (this, 1);
+ if ((pckbuf>>4) != 4) {
+ ok = 1;
+ }
+ }
+ break;
+ }
+ }
+ }
+ if (ok)
+ break;
+
+ free (this);
+ return NULL;
+ }
+
+ /* special case for MPEG streams with a RIFF header */
+ fourcc_tag = BE_32(&buf[0]);
+ if (fourcc_tag == RIFF_TAG) {
+ fourcc_tag = BE_32(&buf[8]);
+ /* disregard the RIFF file if it is certainly a better known
+ * format like AVI or WAVE */
+ if ((fourcc_tag == WAVE_TAG) ||
+ (fourcc_tag == AVI_TAG))
+ return DEMUX_CANNOT_HANDLE;
+
+ /* Iterate through first n kilobytes of RIFF file searching for
+ * MPEG video marker. No, it's not a very efficient approach, but
+ * if execution has reached this special case, this is currently
+ * the best chance for detecting the file automatically. Also,
+ * be extra lazy and do not bother skipping over the data
+ * header. */
+ for (i = 0; i < RIFF_CHECK_KILOBYTES && !ok; i++) {
+ if (input->read(input, buf, 1024) != 1024)
+ break;
+ for (j = 0; j < 1024 - 4; j++) {
+ if (BE_32(&buf[j]) == MPEG_MARKER) {
+ ok = 1;
+ break;
+ }
+ }
+ }
+ if (ok)
+ break;
+ }
+ free (this);
+ return NULL;
+ }
+
+ case XINE_DEMUX_EXTENSION_STRATEGY: {
+ char *ending, *mrl;
+
+ mrl = input->get_mrl (input);
+
+ ending = strrchr(mrl, '.');
+
+ if (!ending) {
+ free (this);
+ return NULL;
+ }
+
+ if (strncasecmp(ending, ".MPEG", 4)) {
+ free (this);
+ return NULL;
+ }
+ }
+ break;
+
+ default:
+ free (this);
+ return NULL;
+ }
+
+ return &this->demux_plugin;
+}
+
+static char *get_description (demux_class_t *this_gen) {
+ return "Mpeg-1 demux plugin";
+}
+
+static char *get_identifier (demux_class_t *this_gen) {
+ return "MPEG";
+}
+
+static char *get_extensions (demux_class_t *this_gen) {
+ return "mpeg";
+}
+
+static char *get_mimetypes (demux_class_t *this_gen) {
+ return "video/mpeg: mpeg, mpg, mpe: MPEG animation;"
+ "video/x-mpeg: mpeg, mpg, mpe: MPEG animation;";
+}
+
+static void class_dispose (demux_class_t *this_gen) {
+
+ demux_mpeg_class_t *this = (demux_mpeg_class_t *) this_gen;
+
+ free (this);
+ }
+
+static void *init_plugin (xine_t *xine, void *data) {
+
+ demux_mpeg_class_t *this;
+
+ this = xine_xmalloc (sizeof (demux_mpeg_class_t));
+ this->config = xine->config;
+ this->xine = xine;
+
+ this->demux_class.open_plugin = open_plugin;
+ this->demux_class.get_description = get_description;
+ this->demux_class.get_identifier = get_identifier;
+ this->demux_class.get_mimetypes = get_mimetypes;
+ this->demux_class.get_extensions = get_extensions;
+ this->demux_class.dispose = class_dispose;
+
return this;
}
@@ -1186,6 +1372,6 @@ static void *init_demuxer_plugin (xine_t *xine, void *data) {
plugin_info_t xine_plugin_info[] = {
/* type, API, "name", version, special_info, init_function */
- { PLUGIN_DEMUX, 11, "mpeg", XINE_VERSION_CODE, NULL, init_demuxer_plugin },
+ { PLUGIN_DEMUX, 14, "mpeg", XINE_VERSION_CODE, NULL, init_plugin },
{ PLUGIN_NONE, 0, "", 0, NULL, NULL }
};
diff --git a/src/demuxers/demux_mpeg_block.c b/src/demuxers/demux_mpeg_block.c
index 3b1210d66..e8eabe480 100644
--- a/src/demuxers/demux_mpeg_block.c
+++ b/src/demuxers/demux_mpeg_block.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_mpeg_block.c,v 1.123 2002/10/22 07:36:05 jcdutton Exp $
+ * $Id: demux_mpeg_block.c,v 1.124 2002/10/23 10:08:48 jkeil Exp $
*
* demultiplexer for mpeg 1/2 program streams
*
@@ -1093,7 +1093,7 @@ static void demux_mpeg_block_accept_input (demux_mpeg_block_t *this,
static int demux_mpeg_block_get_stream_length (demux_plugin_t *this_gen) {
demux_mpeg_block_t *this = (demux_mpeg_block_t *) this_gen;
- /*
+ /*
* find input plugin
*/