summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/demuxers/demux_mpeg.c89
1 files changed, 66 insertions, 23 deletions
diff --git a/src/demuxers/demux_mpeg.c b/src/demuxers/demux_mpeg.c
index 06bf6a364..d846143d5 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.70 2002/08/06 01:59:22 tmmm Exp $
+ * $Id: demux_mpeg.c,v 1.71 2002/08/07 03:13:37 tmmm Exp $
*
* demultiplexer for mpeg 1/2 program streams
* reads streams of variable blocksizes
@@ -106,6 +106,19 @@ typedef struct demux_mpeg_s {
#define ATOM_PREAMBLE_SIZE 8
+/* a little something for dealing with RIFF headers */
+
+#define FOURCC_TAG(ch0, ch1, ch2, ch3) QT_ATOM(ch0, ch1, ch2, ch3)
+
+#define RIFF_TAG FOURCC_TAG('R', 'I', 'F', 'F')
+#define WAVE_TAG FOURCC_TAG('W', 'A', 'V', 'E')
+#define AVI_TAG FOURCC_TAG('A', 'V', 'I', ' ')
+
+/* arbitrary number of initial file bytes to check for an MPEG marker */
+#define RIFF_CHECK_KILOBYTES 1024
+
+#define MPEG_MARKER FOURCC_TAG( 0x00, 0x00, 0x01, 0xBA )
+
/*
* This function traverses a file and looks for a mdat atom. Upon exit:
* *mdat_offset contains the file offset of the beginning of the mdat
@@ -925,6 +938,8 @@ static int demux_mpeg_open(demux_plugin_t *this_gen,
demux_mpeg_t *this = (demux_mpeg_t *) this_gen;
off_t mdat_atom_offset = -1;
int64_t mdat_atom_size = -1;
+ unsigned int fourcc_tag;
+ int i, j;
this->input = input;
@@ -939,7 +954,7 @@ static int demux_mpeg_open(demux_plugin_t *this_gen,
if(input->get_blocksize(input))
return DEMUX_CANNOT_HANDLE;
- if(input->read(input, buf, 6)) {
+ if(input->read(input, buf, 16) == 16) {
if(!buf[0] && !buf[1] && (buf[2] == 0x01))
switch(buf[3]) {
@@ -973,34 +988,62 @@ static int demux_mpeg_open(demux_plugin_t *this_gen,
/* 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)
- return DEMUX_CANNOT_HANDLE;
-
- /* 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);
+ 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))
+ return DEMUX_CANNOT_HANDLE;
+
+ switch(buf[3]) {
+
+ case 0xba:
+ if((buf[4] & 0xf0) == 0x20) {
+ uint32_t pckbuf ;
+
+ pckbuf = read_bytes (this, 1);
+ if ((pckbuf>>4) != 4) {
+ this->input = input;
+ return DEMUX_CAN_HANDLE;
+ }
+ }
+ break;
+ }
+ }
+ }
- /* go through the same MPEG detection song and dance */
- if(input->read(input, buf, 6)) {
- if(buf[0] || buf[1] || (buf[2] != 0x01))
+ /* 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;
- switch(buf[3]) {
-
- case 0xba:
- if((buf[4] & 0xf0) == 0x20) {
- uint32_t pckbuf ;
-
- pckbuf = read_bytes (this, 1);
- if ((pckbuf>>4) != 4) {
+ /* 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; i++) {
+ if (input->read(input, buf, 1024) != 1024)
+ return DEMUX_CANNOT_HANDLE;
+
+ for (j = 0; j < 1024 - 4; j++) {
+ if (BE_32(&buf[j]) == MPEG_MARKER) {
this->input = input;
return DEMUX_CAN_HANDLE;
}
}
- break;
}
}
}