summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormosu <mosu@b3059339-0415-0410-9bf9-f77b7e298cf2>2003-07-11 20:24:20 +0000
committermosu <mosu@b3059339-0415-0410-9bf9-f77b7e298cf2>2003-07-11 20:24:20 +0000
commit0723498eef370f68ef22dfaaeda5dcd1b9d6c788 (patch)
tree34f847b0c9cf6a3ea4e0fb097f44543b13c7c3fc
parent6ab50ab057f758e13b6cea952cbea8ec07222a4f (diff)
downloadmpv-0723498eef370f68ef22dfaaeda5dcd1b9d6c788.tar.bz2
mpv-0723498eef370f68ef22dfaaeda5dcd1b9d6c788.tar.xz
Necessary changes for the upcoming libebml/libmatroska 0.5.0. Implemented support for RealAudio and RealVideo inside Matroska.
git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@10411 b3059339-0415-0410-9bf9-f77b7e298cf2
-rwxr-xr-xconfigure34
-rw-r--r--libmpdemux/demux_mkv.cpp718
-rw-r--r--libmpdemux/matroska.h9
3 files changed, 561 insertions, 200 deletions
diff --git a/configure b/configure
index f3c1efdb88..6dcbe9bb37 100755
--- a/configure
+++ b/configure
@@ -4169,35 +4169,40 @@ fi
echores "$_theora"
-echocheck "Matroska support"
+echocheck "Matroska support (0.5.0 or later)"
if test "$_matroska" != no ; then
_matroska=no
+ _TMPC=$TMPC
+ TMPC=${TMPC}pp
cat > $TMPC << EOF
-#include <EbmlConfig.h>
+#include <ebml/EbmlVersion.h>
+#include <matroska/KaxVersion.h>
+
+#if LIBEBML_VERSION < 000500
+#error libebml is too old
+#endif
+
+#if LIBMATROSKA_VERSION < 000500
+#error libmatroska is too old
+#endif
+
int main(void) { return 0; }
EOF
- cc_check -lmatroska -lebml && _matroska=yes
+ cc_check -lmatroska -lebml -lstdc++ && _matroska=yes
if test "$_matroska" = no ; then
_saved_inc_extra=$_inc_extra
- _inc_extra="$_inc_extra -I/usr/include/ebml -I/usr/include/matroska"
- cc_check -lmatroska -lebml && _matroska=yes
+ _inc_extra="$_inc_extra -I/usr/local/include"
+ cc_check -lmatroska -lebml -lstdc++ && _matroska=yes
if test "$_matroska" = no ; then
- _inc_extra="$_saved_inc_extra -I/usr/local/include/ebml -I/usr/local/include/matroska"
- cc_check -lmatroska -lebml && _matroska=yes
- if test "$_matroska" = no ; then
- _inc_extra=$_saved_inc_extra
- fi
+ _inc_extra=$_saved_inc_extra
fi
fi
+ TMPC=$_TMPC
fi
if test "$_matroska" = yes ; then
_def_matroska='#define HAVE_MATROSKA 1'
_inputmodules="matroska $_inputmodules"
_ld_matroska="-lmatroska -lebml -lstdc++"
- case $cc_version in
- 2.*) _def_matroska_gcc2="#define LIBEBML_GCC2" ;;
- *) _def_matroska_gcc2="/*#define LIBEBML_GCC2*/" ;;
- esac
else
_def_matroska='#undef HAVE_MATROSKA'
_noinputmodules="matroska $_noinputmodules"
@@ -5870,7 +5875,6 @@ $_def_theora
/* enable Matroska support */
$_def_matroska
-$_def_matroska_gcc2
/* enable FAAD (AAC) support */
$_def_faad
diff --git a/libmpdemux/demux_mkv.cpp b/libmpdemux/demux_mkv.cpp
index 7e8bfd047b..37e5aa92f9 100644
--- a/libmpdemux/demux_mkv.cpp
+++ b/libmpdemux/demux_mkv.cpp
@@ -22,32 +22,32 @@ extern "C" {
#include <iostream>
#include <cassert>
#include <typeinfo>
-
-#include "EbmlHead.h"
-#include "EbmlSubHead.h"
-#include "EbmlStream.h"
-#include "EbmlContexts.h"
-#include "EbmlVersion.h"
-#include "FileKax.h"
-
-#include "KaxAttachements.h"
-#include "KaxBlock.h"
-#include "KaxBlockData.h"
-#include "KaxChapters.h"
-#include "KaxCluster.h"
-#include "KaxClusterData.h"
-#include "KaxContexts.h"
-#include "KaxCues.h"
-#include "KaxCuesData.h"
-#include "KaxInfo.h"
-#include "KaxInfoData.h"
-#include "KaxSeekHead.h"
-#include "KaxSegment.h"
-#include "KaxTracks.h"
-#include "KaxTrackAudio.h"
-#include "KaxTrackVideo.h"
-
-#include "StdIOCallback.h"
+#include <vector>
+
+#include <ebml/EbmlHead.h>
+#include <ebml/EbmlSubHead.h>
+#include <ebml/EbmlStream.h>
+#include <ebml/EbmlContexts.h>
+#include <ebml/EbmlVersion.h>
+#include <ebml/StdIOCallback.h>
+
+#include <matroska/KaxAttachements.h>
+#include <matroska/KaxBlock.h>
+#include <matroska/KaxBlockData.h>
+#include <matroska/KaxChapters.h>
+#include <matroska/KaxCluster.h>
+#include <matroska/KaxClusterData.h>
+#include <matroska/KaxContexts.h>
+#include <matroska/KaxCues.h>
+#include <matroska/KaxCuesData.h>
+#include <matroska/KaxInfo.h>
+#include <matroska/KaxInfoData.h>
+#include <matroska/KaxSeekHead.h>
+#include <matroska/KaxSegment.h>
+#include <matroska/KaxTracks.h>
+#include <matroska/KaxTrackAudio.h>
+#include <matroska/KaxTrackVideo.h>
+#include <matroska/FileKax.h>
#include "matroska.h"
@@ -58,6 +58,10 @@ using namespace std;
#define LIBEBML_VERSION 000000
#endif // LIBEBML_VERSION
+#if LIBEBML_VERSION < 000500
+#error libebml version too old - need at least 0.5.0
+#endif
+
// for e.g. "-slang ger"
extern char *dvdsub_lang;
extern char *audio_lang;
@@ -153,10 +157,16 @@ typedef struct mkv_track {
void *private_data;
unsigned int private_size;
+ // For Vorbis audio
unsigned char *headers[3];
uint32_t header_sizes[3];
int ok;
+
+ // Stuff for RealMedia packet assembly
+ bool realmedia;
+ demux_packet_t *rm_dp;
+ int rm_seqnum;
} mkv_track_t;
typedef struct mkv_demuxer {
@@ -189,6 +199,79 @@ typedef struct mkv_demuxer {
int64_t skip_to_timecode;
} mkv_demuxer_t;
+typedef struct {
+ uint32_t chunks; // number of chunks
+ uint32_t timestamp; // timestamp from packet header
+ uint32_t len; // length of actual data
+ uint32_t chunktab; // offset to chunk offset array
+} dp_hdr_t;
+
+#pragma pack(push,2)
+
+typedef struct {
+ uint32_t size;
+ uint32_t fourcc1;
+ uint32_t fourcc2;
+ uint16_t width;
+ uint16_t height;
+ uint16_t bpp;
+ uint32_t unknown1;
+ uint32_t fps;
+ uint32_t type1;
+ uint32_t type2;
+} real_video_props_t;
+
+typedef struct {
+ uint32_t fourcc1; // '.', 'r', 'a', 0xfd
+ uint16_t version1; // 4 or 5
+ uint16_t unknown1; // 00 000
+ uint32_t fourcc2; // .ra4 or .ra5
+ uint32_t unknown2; // ???
+ uint16_t version2; // 4 or 5
+ uint32_t header_size; // == 0x4e
+ uint16_t flavor; // codec flavor id
+ uint32_t coded_frame_size; // coded frame size
+ uint32_t unknown3; // big number
+ uint32_t unknown4; // bigger number
+ uint32_t unknown5; // yet another number
+ uint16_t sub_packet_h;
+ uint16_t frame_size;
+ uint16_t sub_packet_size;
+ uint16_t unknown6; // 00 00
+ uint16_t sample_rate;
+ uint16_t unknown8; // 0
+ uint16_t sample_size;
+ uint16_t channels;
+} real_audio_v4_props_t;
+
+typedef struct {
+ uint32_t fourcc1; // '.', 'r', 'a', 0xfd
+ uint16_t version1; // 4 or 5
+ uint16_t unknown1; // 00 000
+ uint32_t fourcc2; // .ra4 or .ra5
+ uint32_t unknown2; // ???
+ uint16_t version2; // 4 or 5
+ uint32_t header_size; // == 0x4e
+ uint16_t flavor; // codec flavor id
+ uint32_t coded_frame_size; // coded frame size
+ uint32_t unknown3; // big number
+ uint32_t unknown4; // bigger number
+ uint32_t unknown5; // yet another number
+ uint16_t sub_packet_h;
+ uint16_t frame_size;
+ uint16_t sub_packet_size;
+ uint16_t unknown6; // 00 00
+ uint8_t unknown7[6]; // 0, srate, 0
+ uint16_t sample_rate;
+ uint16_t unknown8; // 0
+ uint16_t sample_size;
+ uint16_t channels;
+ uint32_t genr; // "genr"
+ uint32_t fourcc3; // fourcc
+} real_audio_v5_props_t;
+
+#pragma pack(pop)
+
static uint16_t get_uint16(const void *buf) {
uint16_t ret;
unsigned char *tmp;
@@ -215,6 +298,63 @@ static uint32_t get_uint32(const void *buf) {
return ret;
}
+static uint16_t get_uint16_be(const void *buf) {
+ uint16_t ret;
+ unsigned char *tmp;
+
+ tmp = (unsigned char *) buf;
+
+ ret = tmp[0] & 0xff;
+ ret = (ret << 8) + (tmp[1] & 0xff);
+
+ return ret;
+}
+
+static uint32_t get_uint32_be(const void *buf) {
+ uint32_t ret;
+ unsigned char *tmp;
+
+ tmp = (unsigned char *) buf;
+
+ ret = tmp[0] & 0xff;
+ ret = (ret << 8) + (tmp[1] & 0xff);
+ ret = (ret << 8) + (tmp[2] & 0xff);
+ ret = (ret << 8) + (tmp[3] & 0xff);
+
+ return ret;
+}
+
+unsigned char read_char(unsigned char *p, int &pos, int size) {
+ if ((pos + 1) > size)
+ throw exception();
+ pos++;
+ return p[pos - 1];
+}
+
+unsigned short read_word(unsigned char *p, int &pos, int size) {
+ unsigned short v;
+
+ if ((pos + 2) > size)
+ throw exception();
+ v = p[pos];
+ v = (v << 8) | (p[pos + 1] & 0xff);
+ pos += 2;
+ return v;
+}
+
+unsigned int read_dword(unsigned char *p, int &pos, int size) {
+ unsigned int v;
+
+ if ((pos + 4) > size)
+ throw exception();
+ v = p[pos];
+ v = (v << 8) | (p[pos + 1] & 0xff);
+ v = (v << 8) | (p[pos + 2] & 0xff);
+ v = (v << 8) | (p[pos + 3] & 0xff);
+ pos += 4;
+ return v;
+}
+
static void handle_subtitles(demuxer_t *d, KaxBlock *block, int64_t duration) {
mkv_demuxer_t *mkv_d = (mkv_demuxer_t *)d->priv;
int len, line, state;
@@ -375,18 +515,7 @@ static int check_track_information(mkv_demuxer_t *d) {
}
memcpy(t->v_fourcc, &bih->biCompression, 4);
-
- if (t->v_frate == 0.0) {
- mp_msg(MSGT_DEMUX, MSGL_WARN, "[mkv] ERROR: (MS compatibility "
- "mode, track %u) "
- "No VideoFrameRate element was found.\n", t->tnum);
- continue;
- }
}
- } else {
- mp_msg(MSGT_DEMUX, MSGL_WARN, "[mkv] Native CodecIDs for video "
- "tracks are not supported yet (track %u).\n", t->tnum);
- continue;
}
if (t->v_width == 0) {
@@ -521,9 +650,21 @@ static int check_track_information(mkv_demuxer_t *d) {
t->header_sizes[0] - t->header_sizes[1];
t->a_formattag = 0xFFFE;
+ } else if (t->private_size >= sizeof(real_audio_v4_props_t)) {
+ if (!strcmp(t->codec_id, MKV_A_REAL28))
+ t->a_formattag = mmioFOURCC('2', '8', '_', '8');
+ else if (!strcmp(t->codec_id, MKV_A_REALATRC))
+ t->a_formattag = mmioFOURCC('a', 't', 'r', 'c');
+ else if (!strcmp(t->codec_id, MKV_A_REALCOOK))
+ t->a_formattag = mmioFOURCC('c', 'o', 'o', 'k');
+ else if (!strcmp(t->codec_id, MKV_A_REALDNET))
+ t->a_formattag = mmioFOURCC('d', 'n', 'e', 't');
+ else if (!strcmp(t->codec_id, MKV_A_REALSIPR))
+ t->a_formattag = mmioFOURCC('s', 'i', 'p', 'r');
} else {
mp_msg(MSGT_DEMUX, MSGL_WARN, "[mkv] Unknown/unsupported audio "
- "codec ID '%s' for track %u.\n", t->codec_id, t->tnum);
+ "codec ID '%s' for track %u or missing/faulty private "
+ "codec data.\n", t->codec_id, t->tnum);
continue;
}
}
@@ -645,6 +786,9 @@ static void add_cluster_position(mkv_demuxer_t *mkv_d, int64_t position) {
mkv_d->num_cluster_pos = 0;
}
+#define fits_parent(l, p) (l->GetElementPosition() < \
+ (p->GetElementPosition() + p->ElementSize()))
+
static int parse_cues(mkv_demuxer_t *mkv_d) {
EbmlElement *l1 = NULL, *l2 = NULL, *l3 = NULL, *l4 = NULL, *l5 = NULL;
EbmlStream *es;
@@ -676,7 +820,9 @@ static int parse_cues(mkv_demuxer_t *mkv_d) {
l2 = es->FindNextElement(l1->Generic().Context, upper_lvl_el, 0xFFFFFFFFL,
true, 1);
while (l2 != NULL) {
- if (upper_lvl_el != 0)
+ if (upper_lvl_el > 0)
+ break;
+ if ((upper_lvl_el < 0) && !fits_parent(l2, l1))
break;
if (EbmlId(*l2) == KaxCuePoint::ClassInfos.GlobalId) {
@@ -687,7 +833,9 @@ static int parse_cues(mkv_demuxer_t *mkv_d) {
l3 = es->FindNextElement(l2->Generic().Context, upper_lvl_el,
0xFFFFFFFFL, true, 1);
while (l3 != NULL) {
- if (upper_lvl_el != 0)
+ if (upper_lvl_el > 0)
+ break;
+ if ((upper_lvl_el < 0) && !fits_parent(l3, l2))
break;
if (EbmlId(*l3) == KaxCueTime::ClassInfos.GlobalId) {
@@ -706,7 +854,9 @@ static int parse_cues(mkv_demuxer_t *mkv_d) {
l4 = es->FindNextElement(l3->Generic().Context, upper_lvl_el,
0xFFFFFFFFL, true, 1);
while (l4 != NULL) {
- if (upper_lvl_el != 0)
+ if (upper_lvl_el > 0)
+ break;
+ if ((upper_lvl_el < 0) && !fits_parent(l4, l3))
break;
if (EbmlId(*l4) == KaxCueTrack::ClassInfos.GlobalId) {
@@ -755,7 +905,9 @@ static int parse_cues(mkv_demuxer_t *mkv_d) {
l5 = es->FindNextElement(l4->Generic().Context, upper_lvl_el,
0xFFFFFFFFL, true, 1);
while (l5 != NULL) {
- if (upper_lvl_el != 0)
+ if (upper_lvl_el > 0)
+ break;
+ if ((upper_lvl_el < 0) && !fits_parent(l5, l4))
break;
if (EbmlId(*l5) == KaxCueRefTime::ClassInfos.GlobalId) {
@@ -789,21 +941,21 @@ static int parse_cues(mkv_demuxer_t *mkv_d) {
mp_msg(MSGT_DEMUX, MSGL_DBG2, "[mkv] | + found cue ref "
"codec state: %llu\n", uint64(cue_rcs));
- } else {
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "[mkv] | + unknown "
- "element, level 5: %s\n", typeid(*l5).name());
+ } else
+ upper_lvl_el = 0;
+
+ if (upper_lvl_el == 0) {
+ l5->SkipData(static_cast<EbmlStream &>(*es),
+ l5->Generic().Context);
+ delete l5;
+ l5 = es->FindNextElement(l4->Generic().Context,
+ upper_lvl_el, 0xFFFFFFFFL, true);
}
- l5->SkipData(static_cast<EbmlStream &>(*es),
- l5->Generic().Context);
- delete l5;
- l5 = es->FindNextElement(l4->Generic().Context,
- upper_lvl_el, 0xFFFFFFFFL, true, 1);
} // while (l5 != NULL)
} else
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "[mkv] | + unknown element, "
- "level 4: %s\n", typeid(*l4).name());
+ upper_lvl_el = 0;
if (upper_lvl_el > 0) { // we're coming from l5
upper_lvl_el--;
@@ -812,13 +964,17 @@ static int parse_cues(mkv_demuxer_t *mkv_d) {
if (upper_lvl_el > 0)
break;
- } else {
+ } else if (upper_lvl_el == 0) {
l4->SkipData(static_cast<EbmlStream &>(*es),
l4->Generic().Context);
delete l4;
l4 = es->FindNextElement(l3->Generic().Context, upper_lvl_el,
0xFFFFFFFFL, true, 1);
+ } else {
+ delete l4;
+ l4 = l5;
}
+
} // while (l4 != NULL)
} else
@@ -832,13 +988,17 @@ static int parse_cues(mkv_demuxer_t *mkv_d) {
if (upper_lvl_el > 0)
break;
- } else {
+ } else if (upper_lvl_el == 0) {
l3->SkipData(static_cast<EbmlStream &>(*es),
l3->Generic().Context);
delete l3;
l3 = es->FindNextElement(l2->Generic().Context, upper_lvl_el,
0xFFFFFFFFL, true, 1);
+ } else {
+ delete l3;
+ l3 = l4;
}
+
} // while (l3 != NULL)
// Three elements must have been found in order for this to be a
@@ -854,8 +1014,7 @@ static int parse_cues(mkv_demuxer_t *mkv_d) {
(elements_found & 8) ? 0 : 1);
} else
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "[mkv] | + unknown element, level 2: "
- "%s\n", typeid(*l2).name());
+ upper_lvl_el = 0;
if (upper_lvl_el > 0) { // we're coming from l3
upper_lvl_el--;
@@ -864,13 +1023,17 @@ static int parse_cues(mkv_demuxer_t *mkv_d) {
if (upper_lvl_el > 0)
break;
- } else {
+ } else if (upper_lvl_el == 0) {
l2->SkipData(static_cast<EbmlStream &>(*es),
l2->Generic().Context);
delete l2;
l2 = es->FindNextElement(l1->Generic().Context, upper_lvl_el,
0xFFFFFFFFL, true, 1);
+ } else {
+ delete l2;
+ l2 = l3;
}
+
} // while (l2 != NULL)
// Debug: dump the index
@@ -890,6 +1053,10 @@ static int parse_cues(mkv_demuxer_t *mkv_d) {
return 1;
}
+
+
+extern "C" void print_wave_header(WAVEFORMATEX *h);
+
extern "C" int demux_mkv_open(demuxer_t *demuxer) {
unsigned char signature[4];
stream_t *s;
@@ -977,7 +1144,9 @@ extern "C" int demux_mkv_open(demuxer_t *demuxer) {
l1 = es->FindNextElement(l0->Generic().Context, upper_lvl_el, 0xFFFFFFFFL,
true, 1);
while (l1 != NULL) {
- if ((upper_lvl_el != 0) || exit_loop)
+ if ((upper_lvl_el > 0) || exit_loop)
+ break;
+ if ((upper_lvl_el < 0) && !fits_parent(l1, l0))
break;
if (EbmlId(*l1) == KaxInfo::ClassInfos.GlobalId) {
@@ -987,7 +1156,9 @@ extern "C" int demux_mkv_open(demuxer_t *demuxer) {
l2 = es->FindNextElement(l1->Generic().Context, upper_lvl_el,
0xFFFFFFFFL, true, 1);
while (l2 != NULL) {
- if ((upper_lvl_el != 0) || exit_loop)
+ if ((upper_lvl_el > 0) || exit_loop)
+ break;
+ if ((upper_lvl_el < 0) && !fits_parent(l2, l1))
break;
if (EbmlId(*l2) == KaxTimecodeScale::ClassInfos.GlobalId) {
@@ -1005,14 +1176,15 @@ extern "C" int demux_mkv_open(demuxer_t *demuxer) {
mkv_d->duration);
} else
- mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + unknown element@2: %s\n",
- typeid(*l2).name());
+ upper_lvl_el = 0;
- l2->SkipData(static_cast<EbmlStream &>(*es),
- l2->Generic().Context);
- delete l2;
- l2 = es->FindNextElement(l1->Generic().Context, upper_lvl_el,
- 0xFFFFFFFFL, true, 1);
+ if (upper_lvl_el == 0) {
+ l2->SkipData(static_cast<EbmlStream &>(*es),
+ l2->Generic().Context);
+ delete l2;
+ l2 = es->FindNextElement(l1->Generic().Context, upper_lvl_el,
+ 0xFFFFFFFFL, true, 1);
+ }
}
} else if (EbmlId(*l1) == KaxTracks::ClassInfos.GlobalId) {
@@ -1023,7 +1195,9 @@ extern "C" int demux_mkv_open(demuxer_t *demuxer) {
l2 = es->FindNextElement(l1->Generic().Context, upper_lvl_el,
0xFFFFFFFFL, true, 1);
while (l2 != NULL) {
- if ((upper_lvl_el != 0) || exit_loop)
+ if ((upper_lvl_el > 0) || exit_loop)
+ break;
+ if ((upper_lvl_el < 0) && !fits_parent(l2, l1))
break;
if (EbmlId(*l2) == KaxTrackEntry::ClassInfos.GlobalId) {
@@ -1037,7 +1211,9 @@ extern "C" int demux_mkv_open(demuxer_t *demuxer) {
l3 = es->FindNextElement(l2->Generic().Context, upper_lvl_el,
0xFFFFFFFFL, true, 1);
while (l3 != NULL) {
- if (upper_lvl_el != 0)
+ if (upper_lvl_el > 0)
+ break;
+ if ((upper_lvl_el < 0) && !fits_parent(l3, l2))
break;
// Now evaluate the data belonging to this track
@@ -1058,17 +1234,20 @@ extern "C" int demux_mkv_open(demuxer_t *demuxer) {
mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + Track UID: %u\n",
uint32(tuid));
-#if LIBEBML_VERSION >= 000404
} else if (EbmlId(*l3) ==
KaxTrackDefaultDuration::ClassInfos.GlobalId) {
KaxTrackDefaultDuration &def_duration =
*static_cast<KaxTrackDefaultDuration *>(l3);
def_duration.ReadData(es->I_O());
- track->v_frate = 1000000000.0 / (float)uint64(def_duration);
- mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + Default duration: "
- "%.3fms ( = %.3f fps)\n", (float)uint64(def_duration) /
- 1000000.0, track->v_frate);
-#endif // LIBEBML_VERSION
+ if (uint64(def_duration) == 0)
+ mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + Default duration: 0");
+ else {
+ track->v_frate = 1000000000.0 / (float)uint64(def_duration);
+ mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + Default duration: "
+ "%.3fms ( = %.3f fps)\n",
+ (float)uint64(def_duration) / 1000000.0,
+ track->v_frate);
+ }
} else if (EbmlId(*l3) == KaxTrackType::ClassInfos.GlobalId) {
KaxTrackType &ttype = *static_cast<KaxTrackType *>(l3);
@@ -1099,7 +1278,9 @@ extern "C" int demux_mkv_open(demuxer_t *demuxer) {
l4 = es->FindNextElement(l3->Generic().Context, upper_lvl_el,
0xFFFFFFFFL, true, 1);
while (l4 != NULL) {
- if (upper_lvl_el != 0)
+ if (upper_lvl_el > 0)
+ break;
+ if ((upper_lvl_el < 0) && !fits_parent(l4, l3))
break;
if (EbmlId(*l4) ==
@@ -1130,14 +1311,16 @@ extern "C" int demux_mkv_open(demuxer_t *demuxer) {
track->a_bps);
} else
- mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + unknown "
- "element@4: %s\n", typeid(*l4).name());
-
- l4->SkipData(static_cast<EbmlStream &>(*es),
- l4->Generic().Context);
- delete l4;
- l4 = es->FindNextElement(l3->Generic().Context, upper_lvl_el,
- 0xFFFFFFFFL, true, 1);
+ upper_lvl_el = 0;
+
+ if (upper_lvl_el == 0) {
+ l4->SkipData(static_cast<EbmlStream &>(*es),
+ l4->Generic().Context);
+ delete l4;
+ l4 = es->FindNextElement(l3->Generic().Context,
+ upper_lvl_el, 0xFFFFFFFFL, true);
+ }
+
} // while (l4 != NULL)
} else if (EbmlId(*l3) == KaxTrackVideo::ClassInfos.GlobalId) {
@@ -1145,7 +1328,9 @@ extern "C" int demux_mkv_open(demuxer_t *demuxer) {
l4 = es->FindNextElement(l3->Generic().Context, upper_lvl_el,
0xFFFFFFFFL, true, 1);
while (l4 != NULL) {
- if (upper_lvl_el != 0)
+ if (upper_lvl_el > 0)
+ break;
+ if ((upper_lvl_el < 0) && !fits_parent(l4, l3))
break;
if (EbmlId(*l4) == KaxVideoPixelWidth::ClassInfos.GlobalId) {
@@ -1194,28 +1379,24 @@ extern "C" int demux_mkv_open(demuxer_t *demuxer) {
float(framerate));
} else
- mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + unknown "
- "element@4: %s\n", typeid(*l4).name());
-
- l4->SkipData(static_cast<EbmlStream &>(*es),
- l4->Generic().Context);
- delete l4;
- l4 = es->FindNextElement(l3->Generic().Context, upper_lvl_el,
- 0xFFFFFFFFL, true, 1);
+ upper_lvl_el = 0;
+
+ if (upper_lvl_el == 0) {
+ l4->SkipData(static_cast<EbmlStream &>(*es),
+ l4->Generic().Context);
+ delete l4;
+ l4 = es->FindNextElement(l3->Generic().Context,
+ upper_lvl_el, 0xFFFFFFFFL, true);
+ }
+
} // while (l4 != NULL)
} else if (EbmlId(*l3) == KaxCodecID::ClassInfos.GlobalId) {
KaxCodecID &codec_id = *static_cast<KaxCodecID*>(l3);
codec_id.ReadData(es->I_O());
-#if LIBEBML_VERSION >= 000404
mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + Codec ID: %s\n",
string(codec_id).c_str());
track->codec_id = strdup(string(codec_id).c_str());
-#else
- mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + Codec ID: %s\n",
- &binary(codec_id));
- track->codec_id = strdup((char *)&binary(codec_id));
-#endif // LIBEBML_VERSION
} else if (EbmlId(*l3) == KaxCodecPrivate::ClassInfos.GlobalId) {
KaxCodecPrivate &c_priv = *static_cast<KaxCodecPrivate*>(l3);
@@ -1251,14 +1432,8 @@ extern "C" int demux_mkv_open(demuxer_t *demuxer) {
free(track->language);
track->language = strdup(string(language).c_str());
- } else if ((!(EbmlId(*l3) ==
- KaxTrackFlagLacing::ClassInfos.GlobalId)) &&
- (!(EbmlId(*l3) ==
- KaxTrackMinCache::ClassInfos.GlobalId)) &&
- (!(EbmlId(*l3) ==
- KaxTrackMaxCache::ClassInfos.GlobalId)))
- mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + unknown element@3: "
- "%s\n", typeid(*l3).name());
+ } else
+ upper_lvl_el = 0;
if (upper_lvl_el > 0) { // we're coming from l4
upper_lvl_el--;
@@ -1266,13 +1441,17 @@ extern "C" int demux_mkv_open(demuxer_t *demuxer) {
l3 = l4;
if (upper_lvl_el > 0)
break;
- } else {
+ } else if (upper_lvl_el == 0) {
l3->SkipData(static_cast<EbmlStream &>(*es),
l3->Generic().Context);
delete l3;
l3 = es->FindNextElement(l2->Generic().Context, upper_lvl_el,
0xFFFFFFFFL, true, 1);
+ } else {
+ delete l3;
+ l3 = l4;
}
+
} // while (l3 != NULL)
} else
@@ -1284,13 +1463,17 @@ extern "C" int demux_mkv_open(demuxer_t *demuxer) {
l2 = l3;
if (upper_lvl_el > 0)
break;
- } else {
+ } else if (upper_lvl_el == 0) {
l2->SkipData(static_cast<EbmlStream &>(*es),
l2->Generic().Context);
delete l2;
l2 = es->FindNextElement(l1->Generic().Context, upper_lvl_el,
0xFFFFFFFFL, true, 1);
+ } else {
+ delete l2;
+ l2 = l3;
}
+
} // while (l2 != NULL)
} else if (EbmlId(*l1) == KaxSeekHead::ClassInfos.GlobalId) {
@@ -1299,7 +1482,9 @@ extern "C" int demux_mkv_open(demuxer_t *demuxer) {
l2 = es->FindNextElement(l1->Generic().Context, upper_lvl_el,
0xFFFFFFFFL, true, 1);
while (l2 != NULL) {
- if (upper_lvl_el != 0)
+ if (upper_lvl_el > 0)
+ break;
+ if ((upper_lvl_el < 0) && !fits_parent(l2, l1))
break;
if (EbmlId(*l2) == KaxSeek::ClassInfos.GlobalId) {
@@ -1311,7 +1496,9 @@ extern "C" int demux_mkv_open(demuxer_t *demuxer) {
l3 = es->FindNextElement(l2->Generic().Context, upper_lvl_el,
0xFFFFFFFFL, true, 1);
while (l3 != NULL) {
- if (upper_lvl_el != 0)
+ if (upper_lvl_el > 0)
+ break;
+ if ((upper_lvl_el < 0) && !fits_parent(l3, l2))
break;
if (EbmlId(*l3) == KaxSeekID::ClassInfos.GlobalId) {
@@ -1354,14 +1541,16 @@ extern "C" int demux_mkv_open(demuxer_t *demuxer) {
seek_pos = uint64(kax_seek_pos);
} else
- mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + unknown element, "
- "level 3: %s\n", typeid(*l3).name());
+ upper_lvl_el = 0;
+
+ if (upper_lvl_el == 0) {
+ l3->SkipData(static_cast<EbmlStream &>(*es),
+ l3->Generic().Context);
+ delete l3;
+ l3 = es->FindNextElement(l2->Generic().Context, upper_lvl_el,
+ 0xFFFFFFFFL, true, 1);
+ }
- l3->SkipData(static_cast<EbmlStream &>(*es),
- l3->Generic().Context);
- delete l3;
- l3 = es->FindNextElement(l2->Generic().Context, upper_lvl_el,
- 0xFFFFFFFFL, true, 1);
} // while (l3 != NULL)
if (!mkv_d->cues_found && (seek_pos > 0) &&
@@ -1369,8 +1558,7 @@ extern "C" int demux_mkv_open(demuxer_t *demuxer) {
cues_pos = mkv_d->segment->GetGlobalPosition(seek_pos);
} else
- mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + unknown element, level 2: "
- "%s\n", typeid(*l2).name());
+ upper_lvl_el = 0;
if (upper_lvl_el > 0) { // we're coming from l3
upper_lvl_el--;
@@ -1379,13 +1567,17 @@ extern "C" int demux_mkv_open(demuxer_t *demuxer) {
if (upper_lvl_el > 0)
break;
- } else {
+ } else if (upper_lvl_el == 0) {
l2->SkipData(static_cast<EbmlStream &>(*es),
l2->Generic().Context);
delete l2;
l2 = es->FindNextElement(l1->Generic().Context, upper_lvl_el,
0xFFFFFFFFL, true, 1);
+ } else {
+ delete l2;
+ l2 = l3;
}
+
} // while (l2 != NULL)
} else if ((EbmlId(*l1) == KaxCues::ClassInfos.GlobalId) &&
@@ -1405,8 +1597,7 @@ extern "C" int demux_mkv_open(demuxer_t *demuxer) {
exit_loop = 1;
} else
- mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] |+ unknown element@1: %s\n",
- typeid(*l1).name());
+ upper_lvl_el = 0;
if (exit_loop) // we've found the first cluster, so get out
break;
@@ -1417,12 +1608,16 @@ extern "C" int demux_mkv_open(demuxer_t *demuxer) {
l1 = l2;
if (upper_lvl_el > 0)
break;
- } else {
+ } else if (upper_lvl_el == 0) {
l1->SkipData(static_cast<EbmlStream &>(*es), l1->Generic().Context);
delete l1;
l1 = es->FindNextElement(l0->Generic().Context, upper_lvl_el,
- 0xFFFFFFFFL, true, 1);
+ 0xFFFFFFFFL, true);
+ } else {
+ delete l1;
+ l1 = l2;
}
+
} // while (l1 != NULL)
if (!exit_loop) {
@@ -1443,8 +1638,6 @@ extern "C" int demux_mkv_open(demuxer_t *demuxer) {
mkv_d->first_tc = 0;
stream_seek(s, l1->GetElementPosition());
- mp_msg(MSGT_DEMUX, MSGL_ERR, "[mkv] First tc: %lld\n", mkv_d->first_tc);
-
// If we have found an entry for the cues in the meta seek data but no
// cues at the front of the file then read them now. This way the
// timecode scale will have been initialized correctly.
@@ -1489,35 +1682,88 @@ extern "C" int demux_mkv_open(demuxer_t *demuxer) {
track = find_track_by_num(mkv_d, demuxer->video->id, NULL);
if (track) {
- if (track->ms_compat) { // MS compatibility mode
- BITMAPINFOHEADER *src, *dst;
- mp_msg(MSGT_DEMUX, MSGL_INFO, "[mkv] Will play video track %u\n",
- track->tnum);
- sh_v = new_sh_video(demuxer, track->tnum);
- sh_v->bih = (BITMAPINFOHEADER *)calloc(1, track->private_size);
- if (sh_v->bih == NULL) {
- free_mkv_demuxer(mkv_d);
- return 0;
- }
+ BITMAPINFOHEADER *bih;
- dst = sh_v->bih;
+ bih = (BITMAPINFOHEADER *)calloc(1, track->private_size);
+ if (bih == NULL) {
+ free_mkv_demuxer(mkv_d);
+ return 0;
+ }
+
+ if (track->ms_compat) { // MS compatibility mode
+ BITMAPINFOHEADER *src;
src = (BITMAPINFOHEADER *)track->private_data;
- dst->biSize = get_uint32(&src->biSize);
- dst->biWidth = get_uint32(&src->biWidth);
- dst->biHeight = get_uint32(&src->biHeight);
- dst->biPlanes = get_uint16(&src->biPlanes);
- dst->biBitCount = get_uint16(&src->biBitCount);
- dst->biCompression = get_uint32(&src->biCompression);
- dst->biSizeImage = get_uint32(&src->biSizeImage);
- dst->biXPelsPerMeter = get_uint32(&src->biXPelsPerMeter);
- dst->biYPelsPerMeter = get_uint32(&src->biYPelsPerMeter);
- dst->biClrUsed = get_uint32(&src->biClrUsed);
- dst->biClrImportant = get_uint32(&src->biClrImportant);
- memcpy((char *)dst + sizeof(BITMAPINFOHEADER),
+ bih->biSize = get_uint32(&src->biSize);
+ bih->biWidth = get_uint32(&src->biWidth);
+ bih->biHeight = get_uint32(&src->biHeight);
+ bih->biPlanes = get_uint16(&src->biPlanes);
+ bih->biBitCount = get_uint16(&src->biBitCount);
+ bih->biCompression = get_uint32(&src->biCompression);
+ bih->biSizeImage = get_uint32(&src->biSizeImage);
+ bih->biXPelsPerMeter = get_uint32(&src->biXPelsPerMeter);
+ bih->biYPelsPerMeter = get_uint32(&src->biYPelsPerMeter);
+ bih->biClrUsed = get_uint32(&src->biClrUsed);
+ bih->biClrImportant = get_uint32(&src->biClrImportant);
+ memcpy((char *)bih + sizeof(BITMAPINFOHEADER),
(char *)src + sizeof(BITMAPINFOHEADER),
track->private_size - sizeof(BITMAPINFOHEADER));
+ } else {
+ bih->biSize = sizeof(BITMAPINFOHEADER);
+ bih->biWidth = track->v_width;
+ bih->biHeight = track->v_height;
+ bih->biBitCount = 24;
+ bih->biSizeImage = bih->biWidth * bih->biHeight * bih->biBitCount / 8;
+
+ if ((track->private_size >= sizeof(real_video_props_t)) &&
+ (!strcmp(track->codec_id, MKV_V_REALV10) ||
+ !strcmp(track->codec_id, MKV_V_REALV20) ||
+ !strcmp(track->codec_id, MKV_V_REALV30) ||
+ !strcmp(track->codec_id, MKV_V_REALV40))) {
+ unsigned char *dst, *src;
+ real_video_props_t *rvp;
+ uint32_t type2;
+
+ rvp = (real_video_props_t *)track->private_data;
+ src = (unsigned char *)(rvp + 1);
+
+ bih = (BITMAPINFOHEADER *)realloc(bih, sizeof(BITMAPINFOHEADER) + 12);
+ bih->biSize += 12;
+ type2 = get_uint32_be(&rvp-&