diff options
author | mosu <mosu@b3059339-0415-0410-9bf9-f77b7e298cf2> | 2003-07-11 20:24:20 +0000 |
---|---|---|
committer | mosu <mosu@b3059339-0415-0410-9bf9-f77b7e298cf2> | 2003-07-11 20:24:20 +0000 |
commit | 0723498eef370f68ef22dfaaeda5dcd1b9d6c788 (patch) | |
tree | 34f847b0c9cf6a3ea4e0fb097f44543b13c7c3fc /libmpdemux | |
parent | 6ab50ab057f758e13b6cea952cbea8ec07222a4f (diff) | |
download | mpv-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
Diffstat (limited to 'libmpdemux')
-rw-r--r-- | libmpdemux/demux_mkv.cpp | 718 | ||||
-rw-r--r-- | libmpdemux/matroska.h | 9 |
2 files changed, 542 insertions, 185 deletions
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->type2); + if ((type2 == 0x10003000) || (type2 == 0x100030001)) + bih->biCompression = mmioFOURCC('R', 'V', '1', '3'); + else + bih->biCompression = mmioFOURCC('R', 'V', track->codec_id[9], '0'); + dst = (unsigned char *)(bih + 1); + ((unsigned int *)dst)[0] = get_uint32_be(&rvp->type1); + ((unsigned int *)dst)[1] = type2; + + if ((bih->biCompression <= 0x30335652) && + (type2 >= 0x20200002)) { + // read secondary WxH for the cmsg24[] (see vd_realvid.c) + ((unsigned short *)(bih + 1))[4] = 4 * (unsigned short)src[0]; + ((unsigned short *)(bih + 1))[5] = 4 * (unsigned short)src[1]; + } else + memset(&dst[8], 0, 4); + track->realmedia = true; + + } else { + mp_msg(MSGT_DEMUX, MSGL_WARN, "[mkv] Unknown/unsupported CodecID " + "(%s) or missing/bad CodecPrivate data (track %u).\n", + track->codec_id, track->tnum); + demuxer->video->id = -2; + } + } + + if (demuxer->video->id != -2) { + 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 = bih; sh_v->format = sh_v->bih->biCompression; + if (track->v_frate == 0.0) + track->v_frate = 25.0; sh_v->fps = track->v_frate; sh_v->frametime = 1 / track->v_frate; sh_v->disp_w = track->v_width; @@ -1530,11 +1776,9 @@ extern "C" int demux_mkv_open(demuxer_t *demuxer) { sh_v->ds = demuxer->video; mkv_d->video = track; - } else { - mp_msg(MSGT_DEMUX, MSGL_WARN, "[mkv] Native CodecIDs not supported at " - "the moment (track %u).\n", track->tnum); - demuxer->video->id = -2; - } + } else + free(bih); + } else { mp_msg(MSGT_DEMUX, MSGL_INFO, "[mkv] No video track found/w |