summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMike Melanson <mike@multimedia.cx>2002-08-04 21:45:10 +0000
committerMike Melanson <mike@multimedia.cx>2002-08-04 21:45:10 +0000
commit303ea22a561d75f6e113adc5202758d5dcad1c62 (patch)
tree4224b65ebf9d941a1f93f44b0d29aab4a66e53d5 /src
parentff2f102663a27c9f78d0dc3baa7745f6bae47c7e (diff)
downloadxine-lib-303ea22a561d75f6e113adc5202758d5dcad1c62.tar.gz
xine-lib-303ea22a561d75f6e113adc5202758d5dcad1c62.tar.bz2
add support for finding MPEG streams within Quicktime files
CVS patchset: 2390 CVS date: 2002/08/04 21:45:10
Diffstat (limited to 'src')
-rw-r--r--src/demuxers/demux_mpeg.c136
1 files changed, 122 insertions, 14 deletions
diff --git a/src/demuxers/demux_mpeg.c b/src/demuxers/demux_mpeg.c
index 698cfaa82..45bbf235f 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.68 2002/07/20 08:04:55 tmattern Exp $
+ * $Id: demux_mpeg.c,v 1.69 2002/08/04 21:45:10 tmmm Exp $
*
* demultiplexer for mpeg 1/2 program streams
* reads streams of variable blocksizes
@@ -84,6 +84,80 @@ typedef struct demux_mpeg_s {
} demux_mpeg_t;
+/*
+ * borrow a little knowledge from the Quicktime demuxer
+ */
+#include "bswap.h"
+
+#define BE_16(x) (be2me_16(*(uint16_t *)(x)))
+#define BE_32(x) (be2me_32(*(uint32_t *)(x)))
+#define QT_ATOM( ch0, ch1, ch2, ch3 ) \
+ ( (long)(unsigned char)(ch3) | ( (long)(unsigned char)(ch2) << 8 ) | \
+ ( (long)(unsigned char)(ch1) << 16 ) | ( (long)(unsigned char)(ch0) << 24 ) )
+
+#define MDAT_ATOM QT_ATOM('m', 'd', 'a', 't')
+#define ATOM_PREAMBLE_SIZE 8
+
+/*
+ * 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
+ * atom (that means the offset * of the 4-byte length preceding the
+ * characters 'mdat')
+ * *mdat_size contains the 4-byte size preceding the mdat characters in
+ * the atom. Note that this will be 1 in the case of a 64-bit atom.
+ * Both mdat_offset and mdat_size are set to -1 if not mdat atom was
+ * found.
+ *
+ * Note: Do not count on the input stream being positioned anywhere in
+ * particular when this function is finished.
+ */
+static void find_mdat_atom(input_plugin_t *input, off_t *mdat_offset,
+ int64_t *mdat_size) {
+
+ off_t atom_size;
+ unsigned int atom;
+ unsigned char atom_preamble[ATOM_PREAMBLE_SIZE];
+
+ /* init the passed variables */
+ *mdat_offset = *mdat_size = -1;
+
+ /* take it from the top */
+ if (input->seek(input, 0, SEEK_SET) != 0)
+ return;
+
+ /* traverse through the input */
+ while (*mdat_offset == -1) {
+ if (input->read(input, atom_preamble, ATOM_PREAMBLE_SIZE) !=
+ ATOM_PREAMBLE_SIZE)
+ break;
+
+ atom_size = BE_32(&atom_preamble[0]);
+ atom = BE_32(&atom_preamble[4]);
+
+ if (atom == MDAT_ATOM) {
+ *mdat_offset = input->get_current_pos(input) - ATOM_PREAMBLE_SIZE;
+ *mdat_size = atom_size;
+ break;
+ }
+
+ /* 64-bit length special case */
+ if (atom_size == 1) {
+ if (input->read(input, atom_preamble, ATOM_PREAMBLE_SIZE) !=
+ ATOM_PREAMBLE_SIZE)
+ break;
+
+ atom_size = BE_32(&atom_preamble[0]);
+ atom_size <<= 32;
+ atom_size |= BE_32(&atom_preamble[4]);
+ atom_size -= ATOM_PREAMBLE_SIZE * 2;
+ } else
+ atom_size -= ATOM_PREAMBLE_SIZE;
+
+
+ input->seek(input, atom_size, SEEK_CUR);
+ }
+}
+
static uint32_t read_bytes (demux_mpeg_t *this, int n) {
uint32_t res;
@@ -831,6 +905,8 @@ static int demux_mpeg_open(demux_plugin_t *this_gen,
input_plugin_t *input, int stage) {
demux_mpeg_t *this = (demux_mpeg_t *) this_gen;
+ off_t mdat_atom_offset = -1;
+ int64_t mdat_atom_size = -1;
this->input = input;
@@ -847,22 +923,20 @@ static int demux_mpeg_open(demux_plugin_t *this_gen,
if(input->read(input, buf, 6)) {
- if(buf[0] || buf[1] || (buf[2] != 0x01))
- return DEMUX_CANNOT_HANDLE;
-
- switch(buf[3]) {
+ if(!buf[0] && !buf[1] && (buf[2] == 0x01))
+ switch(buf[3]) {
- case 0xba:
- if((buf[4] & 0xf0) == 0x20) {
- uint32_t pckbuf ;
+ 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;
+ pckbuf = read_bytes (this, 1);
+ if ((pckbuf>>4) != 4) {
+ this->input = input;
+ return DEMUX_CAN_HANDLE;
+ }
}
- }
- break;
+ break;
#if 0
case 0xe0:
if((buf[6] & 0xc0) != 0x80) {
@@ -877,6 +951,40 @@ static int demux_mpeg_open(demux_plugin_t *this_gen,
break;
#endif
}
+
+ /* 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);
+
+ /* 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;
+ }
+ }
}
}
return DEMUX_CANNOT_HANDLE;