summaryrefslogtreecommitdiffstats
path: root/libmpdemux/demux_mkv.cpp
diff options
context:
space:
mode:
authormosu <mosu@b3059339-0415-0410-9bf9-f77b7e298cf2>2003-08-17 09:26:01 +0000
committermosu <mosu@b3059339-0415-0410-9bf9-f77b7e298cf2>2003-08-17 09:26:01 +0000
commita6267718f92541b140507805bba708e0c48288f5 (patch)
treed73dbf364f055e763566150006b0be9c2c219910 /libmpdemux/demux_mkv.cpp
parent8b653cc824384ae6da4d5475fa4247c5042b1a8b (diff)
downloadmpv-a6267718f92541b140507805bba708e0c48288f5.tar.bz2
mpv-a6267718f92541b140507805bba708e0c48288f5.tar.xz
Big reorganization. Relies on libmatroska's Read() function and then processes units in memory. Also some fixes for handling of global elements which re-enable playback of files created with the latest VDubMod.
git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@10638 b3059339-0415-0410-9bf9-f77b7e298cf2
Diffstat (limited to 'libmpdemux/demux_mkv.cpp')
-rw-r--r--libmpdemux/demux_mkv.cpp1155
1 files changed, 421 insertions, 734 deletions
diff --git a/libmpdemux/demux_mkv.cpp b/libmpdemux/demux_mkv.cpp
index e50325eda6..775250ea27 100644
--- a/libmpdemux/demux_mkv.cpp
+++ b/libmpdemux/demux_mkv.cpp
@@ -47,11 +47,13 @@ extern "C" {
#include <matroska/KaxTracks.h>
#include <matroska/KaxTrackAudio.h>
#include <matroska/KaxTrackVideo.h>
+#include <matroska/KaxTrackEntryData.h>
#include <matroska/FileKax.h>
#include "matroska.h"
-using namespace LIBMATROSKA_NAMESPACE;
+using namespace libebml;
+using namespace libmatroska;
using namespace std;
#ifndef LIBEBML_VERSION
@@ -796,13 +798,24 @@ 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()))
+#define in_parent(p) (mkv_d->in->getFilePointer() < \
+ (p->GetElementPosition() + p->ElementSize()))
+#define FINDFIRST(p, c) (static_cast<c *> \
+ (((EbmlMaster *)p)->FindFirstElt(c::ClassInfos, false)))
+#define FINDNEXT(p, c, e) (static_cast<c *> \
+ (((EbmlMaster *)p)->FindNextElt(*e, false)))
static int parse_cues(mkv_demuxer_t *mkv_d) {
- EbmlElement *l1 = NULL, *l2 = NULL, *l3 = NULL, *l4 = NULL, *l5 = NULL;
+ EbmlElement *l2 = NULL;
EbmlStream *es;
- int upper_lvl_el, elements_found, i, k;
+ KaxCues *cues;
+ KaxCuePoint *cpoint;
+ KaxCueTime *ctime;
+ KaxCueClusterPosition *ccpos;
+ KaxCueTrack *ctrack;
+ KaxCueTrackPositions *ctrackpos;
+ KaxCueReference *cref;
+ int upper_lvl_el, i, k;
uint64_t tc_scale, filepos = 0, timecode = 0;
uint32_t tnum = 0;
mkv_index_entry_t *entry;
@@ -813,238 +826,72 @@ static int parse_cues(mkv_demuxer_t *mkv_d) {
mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] /---- [ parsing cues ] -----------\n");
- l1 = es->FindNextElement(mkv_d->segment->Generic().Context, upper_lvl_el,
- 0xFFFFFFFFL, true, 1);
- if (l1 == NULL)
+ cues = (KaxCues *)es->FindNextElement(mkv_d->segment->Generic().Context,
+ upper_lvl_el, 0xFFFFFFFFL, true, 1);
+ if (cues == NULL)
return 0;
- if (!(EbmlId(*l1) == KaxCues::ClassInfos.GlobalId)) {
+ if (!(EbmlId(*cues) == KaxCues::ClassInfos.GlobalId)) {
mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] No KaxCues element found but but %s.\n"
- "[mkv] \\---- [ parsing cues ] -----------\n", typeid(*l1).name());
+ "[mkv] \\---- [ parsing cues ] -----------\n",
+ cues->Generic().DebugName);
return 0;
}
mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] |+ found cues\n");
- l2 = es->FindNextElement(l1->Generic().Context, upper_lvl_el, 0xFFFFFFFFL,
- true, 1);
- while (l2 != NULL) {
- if (upper_lvl_el > 0)
- break;
- if ((upper_lvl_el < 0) && !fits_parent(l2, l1))
- break;
-
- if (EbmlId(*l2) == KaxCuePoint::ClassInfos.GlobalId) {
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "[mkv] | + found cue point\n");
+ cues->Read(*es, KaxCues::ClassInfos.Context, upper_lvl_el, l2, true);
- elements_found = 0;
+ cpoint = FINDFIRST(cues, KaxCuePoint);
- l3 = es->FindNextElement(l2->Generic().Context, upper_lvl_el,
- 0xFFFFFFFFL, true, 1);
- while (l3 != NULL) {
- if (upper_lvl_el > 0)
- break;
- if ((upper_lvl_el < 0) && !fits_parent(l3, l2))
- break;
+ while (cpoint != NULL) {
+ mp_msg(MSGT_DEMUX, MSGL_DBG2, "[mkv] | + found cue point\n");
- if (EbmlId(*l3) == KaxCueTime::ClassInfos.GlobalId) {
- KaxCueTime &cue_time = *static_cast<KaxCueTime *>(l3);
- cue_time.ReadData(es->I_O());
- timecode = uint64(cue_time) * tc_scale / 1000000 - mkv_d->first_tc;
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "[mkv] | + found cue time: %.3fs\n",
- (float)timecode / 1000.0);
- elements_found |= 1;
-
- } else if (EbmlId(*l3) ==
- KaxCueTrackPositions::ClassInfos.GlobalId) {
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "[mkv] | + found cue track "
- "positions\n");
-
- l4 = es->FindNextElement(l3->Generic().Context, upper_lvl_el,
- 0xFFFFFFFFL, true, 1);
- while (l4 != NULL) {
- if (upper_lvl_el > 0)
- break;
- if ((upper_lvl_el < 0) && !fits_parent(l4, l3))
- break;
-
- if (EbmlId(*l4) == KaxCueTrack::ClassInfos.GlobalId) {
- KaxCueTrack &cue_track = *static_cast<KaxCueTrack *>(l4);
- cue_track.ReadData(es->I_O());
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "[mkv] | + found cue track: "
- "%u\n", uint32(cue_track));
-
- tnum = uint32(cue_track);
- elements_found |= 2;
-
- } else if (EbmlId(*l4) ==
- KaxCueClusterPosition::ClassInfos.GlobalId) {
- KaxCueClusterPosition &cue_cp =
- *static_cast<KaxCueClusterPosition *>(l4);
- cue_cp.ReadData(es->I_O());
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "[mkv] | + found cue cluster "
- "position: %llu\n", uint64(cue_cp));
-
- filepos = mkv_d->segment->GetGlobalPosition(uint64_t(cue_cp));
- elements_found |= 4;
-
- } else if (EbmlId(*l4) ==
- KaxCueBlockNumber::ClassInfos.GlobalId) {
- KaxCueBlockNumber &cue_bn =
- *static_cast<KaxCueBlockNumber *>(l4);
- cue_bn.ReadData(es->I_O());
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "[mkv] | + found cue block "
- "number: %llu\n", uint64(cue_bn));
-
- } else if (EbmlId(*l4) ==
- KaxCueCodecState::ClassInfos.GlobalId) {
- KaxCueCodecState &cue_cs =
- *static_cast<KaxCueCodecState *>(l4);
- cue_cs.ReadData(es->I_O());
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "[mkv] | + found cue codec "
- "state: %llu\n", uint64(cue_cs));
-
- } else if (EbmlId(*l4) ==
- KaxCueReference::ClassInfos.GlobalId) {
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "[mkv] | + found cue "
- "reference\n");
-
- elements_found |= 8;
-
- l5 = es->FindNextElement(l4->Generic().Context, upper_lvl_el,
- 0xFFFFFFFFL, true, 1);
- while (l5 != NULL) {
- if (upper_lvl_el > 0)
- break;
- if ((upper_lvl_el < 0) && !fits_parent(l5, l4))
- break;
-
- if (EbmlId(*l5) == KaxCueRefTime::ClassInfos.GlobalId) {
- KaxCueRefTime &cue_rt =
- *static_cast<KaxCueRefTime *>(l5);
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "[mkv] | + found cue ref "
- "time: %.3fs\n", ((float)uint64(cue_rt)) * tc_scale /
- 1000000000.0);
-
- } else if (EbmlId(*l5) ==
- KaxCueRefCluster::ClassInfos.GlobalId) {
- KaxCueRefCluster &cue_rc =
- *static_cast<KaxCueRefCluster *>(l5);
- cue_rc.ReadData(es->I_O());
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "[mkv] | + found cue ref "
- "cluster: %llu\n", uint64(cue_rc));
-
- } else if (EbmlId(*l5) ==
- KaxCueRefNumber::ClassInfos.GlobalId) {
- KaxCueRefNumber &cue_rn =
- *static_cast<KaxCueRefNumber *>(l5);
- cue_rn.ReadData(es->I_O());
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "[mkv] | + found cue ref "
- "number: %llu\n", uint64(cue_rn));
-
- } else if (EbmlId(*l5) ==
- KaxCueRefCodecState::ClassInfos.GlobalId) {
- KaxCueRefCodecState &cue_rcs =
- *static_cast<KaxCueRefCodecState *>(l5);
- cue_rcs.ReadData(es->I_O());
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "[mkv] | + found cue ref "
- "codec state: %llu\n", uint64(cue_rcs));
-
- } 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);
- }
-
- } // while (l5 != NULL)
-
- } else
- upper_lvl_el = 0;
-
- if (upper_lvl_el > 0) { // we're coming from l5
- upper_lvl_el--;
- delete l4;
- l4 = l5;
- if (upper_lvl_el > 0)
- break;
-
- } 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)
+ ctime = FINDFIRST(cpoint, KaxCueTime);
+ if (ctime == NULL) {
+ cpoint = FINDNEXT(cues, KaxCuePoint, cpoint);
+ continue;
+ }
+
+ timecode = uint64(*ctime) * tc_scale / 1000000 - mkv_d->first_tc;
+ mp_msg(MSGT_DEMUX, MSGL_DBG2, "[mkv] | + found cue time: %.3fs\n",
+ (float)timecode / 1000.0);
- } else
- mp_msg(MSGT_DEMUX, MSGL_DBG2, "[mkv] | + unknown element, level 3: "
- "%s\n", typeid(*l3).name());
-
- if (upper_lvl_el > 0) { // we're coming from l4
- upper_lvl_el--;
- delete l3;
- l3 = l4;
- if (upper_lvl_el > 0)
- break;
+ ctrackpos = FINDFIRST(cpoint, KaxCueTrackPositions);
- } 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 (ctrackpos != NULL) {
+ ctrack = FINDFIRST(ctrackpos, KaxCueTrack);
- } // while (l3 != NULL)
+ if (ctrack == NULL) {
+ ctrackpos = FINDNEXT(cpoint, KaxCueTrackPositions, ctrackpos);
+ continue;
+ }
- // Three elements must have been found in order for this to be a
- // correct entry:
- // 1: cue time (timecode)
- // 2: cue track (tnum)
- // 4: cue cluster position (filepos)
- // If 8 is also set, then there was a reference element, and the
- // current block is not an I frame. If 8 is not set then this is
- // an I frame.
- if ((elements_found & 7) == 7)
- add_index_entry(mkv_d, tnum, filepos, timecode,
- (elements_found & 8) ? 0 : 1);
+ tnum = uint32(*ctrack);
+ mp_msg(MSGT_DEMUX, MSGL_DBG2, "[mkv] | + found cue track: %u\n", tnum);
- } else
- upper_lvl_el = 0;
+ ccpos = FINDFIRST(ctrackpos, KaxCueClusterPosition);
+ if (ccpos == NULL) {
+ ctrackpos = FINDNEXT(cpoint, KaxCueTrackPositions, ctrackpos);
+ continue;
+ }
- if (upper_lvl_el > 0) { // we're coming from l3
- upper_lvl_el--;
- delete l2;
- l2 = l3;
- if (upper_lvl_el > 0)
- break;
+ filepos = mkv_d->segment->GetGlobalPosition(uint64_t(*ccpos));
+ mp_msg(MSGT_DEMUX, MSGL_DBG2, "[mkv] | + found cue cluster "
+ "position: %llu\n", filepos);
- } 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;
+ cref = FINDFIRST(ctrackpos, KaxCueReference);
+ add_index_entry(mkv_d, tnum, filepos, timecode,
+ cref == NULL ? 1 : 0);
+
+ ctrackpos = FINDNEXT(cpoint, KaxCueTrackPositions, ctrackpos);
}
- } // while (l2 != NULL)
+ cpoint = FINDNEXT(cues, KaxCuePoint, cpoint);
+ }
+
+ delete cues;
// Debug: dump the index
for (i = 0; i < mkv_d->num_indexes; i++) {
@@ -1063,8 +910,6 @@ 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) {
@@ -1074,7 +919,7 @@ extern "C" int demux_mkv_open(demuxer_t *demuxer) {
mkv_demuxer_t *mkv_d;
int upper_lvl_el, exit_loop, i;
// Elements for different levels
- EbmlElement *l0 = NULL, *l1 = NULL, *l2 = NULL, *l3 = NULL, *l4 = NULL;
+ EbmlElement *l0 = NULL, *l1 = NULL, *l2 = NULL;
EbmlStream *es;
mkv_track_t *track;
sh_audio_t *sh_a;
@@ -1083,7 +928,7 @@ extern "C" int demux_mkv_open(demuxer_t *demuxer) {
int seek_element_is_cue;
#ifdef USE_ICONV
- subcp_open();
+ subcp_open();
#endif
s = demuxer->stream;
@@ -1119,7 +964,7 @@ extern "C" int demux_mkv_open(demuxer_t *demuxer) {
es = mkv_d->es;
// Find the EbmlHead element. Must be the first one.
- l0 = es->FindNextID(EbmlHead::ClassInfos, 0xFFFFFFFFL);
+ l0 = es->FindNextID(EbmlHead::ClassInfos, 0xFFFFFFFFFFFFFFFFL);
if (l0 == NULL) {
mp_msg(MSGT_DEMUX, MSGL_ERR, "[mkv] no head found\n");
free_mkv_demuxer(mkv_d);
@@ -1131,7 +976,7 @@ extern "C" int demux_mkv_open(demuxer_t *demuxer) {
mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] Found the head...\n");
// Next element must be a segment
- l0 = es->FindNextID(KaxSegment::ClassInfos, 0xFFFFFFFFL);
+ l0 = es->FindNextID(KaxSegment::ClassInfos, 0xFFFFFFFFFFFFFFFFL);
if (l0 == NULL) {
mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] but no segment :(\n");
free_mkv_demuxer(mkv_d);
@@ -1153,442 +998,296 @@ extern "C" int demux_mkv_open(demuxer_t *demuxer) {
// We've got our segment, so let's find the tracks
l1 = es->FindNextElement(l0->Generic().Context, upper_lvl_el, 0xFFFFFFFFL,
true, 1);
- while (l1 != NULL) {
- if ((upper_lvl_el > 0) || exit_loop)
- break;
- if ((upper_lvl_el < 0) && !fits_parent(l1, l0))
- break;
+ while ((l1 != NULL) && (upper_lvl_el <= 0)) {
if (EbmlId(*l1) == KaxInfo::ClassInfos.GlobalId) {
// General info about this Matroska file
- mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] |+ segment information...\n");
-
- l2 = es->FindNextElement(l1->Generic().Context, upper_lvl_el,
- 0xFFFFFFFFL, true, 1);
- while (l2 != NULL) {
- if ((upper_lvl_el > 0) || exit_loop)
- break;
- if ((upper_lvl_el < 0) && !fits_parent(l2, l1))
- break;
+ KaxTimecodeScale *ktc_scale;
+ KaxDuration *kduration;
- if (EbmlId(*l2) == KaxTimecodeScale::ClassInfos.GlobalId) {
- KaxTimecodeScale &tc_scale = *static_cast<KaxTimecodeScale *>(l2);
- tc_scale.ReadData(es->I_O());
- mkv_d->tc_scale = uint64(tc_scale);
- mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + timecode scale: %llu\n",
- mkv_d->tc_scale);
+ mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] |+ segment information...\n");
- } else if (EbmlId(*l2) == KaxDuration::ClassInfos.GlobalId) {
- KaxDuration &duration = *static_cast<KaxDuration *>(l2);
- duration.ReadData(es->I_O());
- mkv_d->duration = float(duration) * mkv_d->tc_scale / 1000000000.0;
- mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + duration: %.3fs\n",
- mkv_d->duration);
+ l1->Read(*es, KaxInfo::ClassInfos.Context, upper_lvl_el, l2, true);
- } else
- upper_lvl_el = 0;
+ ktc_scale = FINDFIRST(l1, KaxTimecodeScale);
+ if (ktc_scale != NULL) {
+ mkv_d->tc_scale = uint64(*ktc_scale);
+ mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + timecode scale: %llu\n",
+ mkv_d->tc_scale);
+ } else
+ mkv_d->tc_scale = MKVD_TIMECODESCALE;
- 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);
- }
+ kduration = FINDFIRST(l1, KaxDuration);
+ if (kduration != NULL) {
+ mkv_d->duration = float(*kduration) * mkv_d->tc_scale / 1000000000.0;
+ mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + duration: %.3fs\n",
+ mkv_d->duration);
}
+ l1->SkipData(*es, l1->Generic().Context);
+
} else if (EbmlId(*l1) == KaxTracks::ClassInfos.GlobalId) {
// Yep, we've found our KaxTracks element. Now find all tracks
// contained in this segment.
+
+ KaxTrackEntry *ktentry;
+
mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] |+ segment tracks...\n");
-
- l2 = es->FindNextElement(l1->Generic().Context, upper_lvl_el,
- 0xFFFFFFFFL, true, 1);
- while (l2 != NULL) {
- if ((upper_lvl_el > 0) || exit_loop)
- break;
- if ((upper_lvl_el < 0) && !fits_parent(l2, l1))
- break;
-
- if (EbmlId(*l2) == KaxTrackEntry::ClassInfos.GlobalId) {
- // We actually found a track entry :) We're happy now.
- mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + a track...\n");
-
- track = new_mkv_track(mkv_d);
- if (track == NULL)
- return 0;
+
+ l1->Read(*es, KaxTracks::ClassInfos.Context, upper_lvl_el, l2, true);
+
+ ktentry = FINDFIRST(l1, KaxTrackEntry);
+ while (ktentry != NULL) {
+ // We actually found a track entry :) We're happy now.
+
+ KaxTrackNumber *ktnum;
+ KaxTrackDefaultDuration *kdefdur;
+ KaxTrackType *kttype;
+ KaxTrackAudio *ktaudio;
+ KaxTrackVideo *ktvideo;
+ KaxCodecID *kcodecid;
+ KaxCodecPrivate *kcodecpriv;
+ KaxTrackFlagDefault *ktfdefault;
+ KaxTrackLanguage *ktlanguage;
+
+ mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + a track...\n");
- l3 = es->FindNextElement(l2->Generic().Context, upper_lvl_el,
- 0xFFFFFFFFL, true, 1);
- while (l3 != NULL) {
- if (upper_lvl_el > 0)
+ track = new_mkv_track(mkv_d);
+ if (track == NULL)
+ return 0;
+
+ ktnum = FINDFIRST(ktentry, KaxTrackNumber);
+ if (ktnum != NULL) {
+ mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + Track number: %u\n",
+ uint32(*ktnum));
+ track->tnum = uint32(*ktnum);
+ if (find_track_by_num(mkv_d, track->tnum, track) != NULL)
+ mp_msg(MSGT_DEMUX, MSGL_WARN, "[mkv] | + WARNING: There's "
+ "more than one track with the number %u.\n",
+ track->tnum);
+ }
+
+ kdefdur = FINDFIRST(ktentry, KaxTrackDefaultDuration);
+ if (kdefdur != NULL) {
+ if (uint64(*kdefdur) == 0)
+ mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + Default duration: 0");
+ else {
+ track->v_frate = 1000000000.0 / (float)uint64(*kdefdur);
+ mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + Default duration: "
+ "%.3fms ( = %.3f fps)\n",
+ (float)uint64(*kdefdur) / 1000000.0, track->v_frate);
+ }
+ }
+
+ kttype = FINDFIRST(ktentry, KaxTrackType);
+ if (kttype != NULL) {
+ mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + Track type: ");
+
+ switch (uint8(*kttype)) {
+ case track_audio:
+ mp_msg(MSGT_DEMUX, MSGL_V, "Audio\n");
+ track->type = 'a';
break;
- if ((upper_lvl_el < 0) && !fits_parent(l3, l2))
+ case track_video:
+ mp_msg(MSGT_DEMUX, MSGL_V, "Video\n");
+ track->type = 'v';
break;
-
- // Now evaluate the data belonging to this track
- if (EbmlId(*l3) == KaxTrackNumber::ClassInfos.GlobalId) {
- KaxTrackNumber &tnum = *static_cast<KaxTrackNumber *>(l3);
- tnum.ReadData(es->I_O());
- mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + Track number: %u\n",
- uint32(tnum));
- track->tnum = uint32(tnum);
- if (find_track_by_num(mkv_d, track->tnum, track) != NULL)
- mp_msg(MSGT_DEMUX, MSGL_WARN, "[mkv] | + WARNING: There's "
- "more than one track with the number %u.\n",
- track->tnum);
-
- } else if (EbmlId(*l3) == KaxTrackUID::ClassInfos.GlobalId) {
- KaxTrackUID &tuid = *static_cast<KaxTrackUID *>(l3);
- tuid.ReadData(es->I_O());
- mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + Track UID: %u\n",
- uint32(tuid));
-
- } else if (EbmlId(*l3) ==
- KaxTrackDefaultDuration::ClassInfos.GlobalId) {
- KaxTrackDefaultDuration &def_duration =
- *static_cast<KaxTrackDefaultDuration *>(l3);
- def_duration.ReadData(es->I_O());
- 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);
- }
+ case track_subtitle:
+ mp_msg(MSGT_DEMUX, MSGL_V, "Subtitle\n");
+ track->type = 's';
+ break;
+ default:
+ mp_msg(MSGT_DEMUX, MSGL_V, "unknown\n");
+ track->type = '?';
+ break;
+ }
+ }
- } else if (EbmlId(*l3) == KaxTrackType::ClassInfos.GlobalId) {
- KaxTrackType &ttype = *static_cast<KaxTrackType *>(l3);
- ttype.ReadData(es->I_O());
- mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + Track type: ");
-
- switch (uint8(ttype)) {
- case track_audio:
- mp_msg(MSGT_DEMUX, MSGL_V, "Audio\n");
- track->type = 'a';
- break;
- case track_video:
- mp_msg(MSGT_DEMUX, MSGL_V, "Video\n");
- track->type = 'v';
- break;
- case track_subtitle:
- mp_msg(MSGT_DEMUX, MSGL_V, "Subtitle\n");
- track->type = 's';
- break;
- default:
- mp_msg(MSGT_DEMUX, MSGL_V, "unknown\n");
- track->type = '?';
- break;
- }
+ ktaudio = FINDFIRST(ktentry, KaxTrackAudio);
+ if (ktaudio != NULL) {
+ KaxAudioSamplingFreq *ka_sfreq;
+ KaxAudioChannels *ka_channels;
+ KaxAudioBitDepth *ka_bitdepth;
- } else if (EbmlId(*l3) == KaxTrackAudio::ClassInfos.GlobalId) {
- mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + Audio track\n");
- l4 = es->FindNextElement(l3->Generic().Context, upper_lvl_el,
- 0xFFFFFFFFL, true, 1);
- while (l4 != NULL) {
- if (upper_lvl_el > 0)
- break;
- if ((upper_lvl_el < 0) && !fits_parent(l4, l3))
- break;
-
- if (EbmlId(*l4) ==
- KaxAudioSamplingFreq::ClassInfos.GlobalId) {
- KaxAudioSamplingFreq &freq =
- *static_cast<KaxAudioSamplingFreq*>(l4);
- freq.ReadData(es->I_O());
- track->a_sfreq = float(freq);
- mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + Sampling "
- "frequency: %f\n", track->a_sfreq);
-
- } else if (EbmlId(*l4) ==
- KaxAudioChannels::ClassInfos.GlobalId) {
- KaxAudioChannels &channels =
- *static_cast<KaxAudioChannels*>(l4);
- channels.ReadData(es->I_O());
- track->a_channels = uint8(channels);
- mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + Channels: %u\n",
- track->a_channels);
-
- } else if (EbmlId(*l4) ==
- KaxAudioBitDepth::ClassInfos.GlobalId) {
- KaxAudioBitDepth &bps =
- *static_cast<KaxAudioBitDepth*>(l4);
- bps.ReadData(es->I_O());
- track->a_bps = uint8(bps);
- mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + Bit depth: %u\n",
- track->a_bps);
-
- } else
- 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);
- }
+ mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + Audio track\n");
- } // while (l4 != NULL)
-
- } else if (EbmlId(*l3) == KaxTrackVideo::ClassInfos.GlobalId) {
- mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + Video track\n");
- l4 = es->FindNextElement(l3->Generic().Context, upper_lvl_el,
- 0xFFFFFFFFL, true, 1);
- while (l4 != NULL) {
- if (upper_lvl_el > 0)
- break;
- if ((upper_lvl_el < 0) && !fits_parent(l4, l3))
- break;
-
- if (EbmlId(*l4) == KaxVideoPixelWidth::ClassInfos.GlobalId) {
- KaxVideoPixelWidth &width =
- *static_cast<KaxVideoPixelWidth *>(l4);
- width.ReadData(es->I_O());
- track->v_width = uint16(width);
- mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + Pixel width: %u\n",
- track->v_width);
-
- } else if (EbmlId(*l4) ==
- KaxVideoPixelHeight::ClassInfos.GlobalId) {
- KaxVideoPixelHeight &height =
- *static_cast<KaxVideoPixelHeight *>(l4);
- height.ReadData(es->I_O());
- track->v_height = uint16(height);
- mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + Pixel height: "
- "%u\n", track->v_height);
-
- } else if (EbmlId(*l4) ==
- KaxVideoDisplayWidth::ClassInfos.GlobalId) {
- KaxVideoDisplayWidth &width =
- *static_cast<KaxVideoDisplayWidth *>(l4);
- width.ReadData(es->I_O());
- track->v_dwidth = uint16(width);
- mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + Display width: "
- "%u\n", track->v_dwidth);
-
- } else if (EbmlId(*l4) ==
- KaxVideoDisplayHeight::ClassInfos.GlobalId) {
- KaxVideoDisplayHeight &height =
- *static_cast<KaxVideoDisplayHeight *>(l4);
- height.ReadData(es->I_O());
- track->v_dheight = uint16(height);
- mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + Display height: "
- "%u\n", track->v_dheight);
-
- } else if (EbmlId(*l4) ==
- KaxVideoFrameRate::ClassInfos.GlobalId) {
- // For older files.
- KaxVideoFrameRate &framerate =
- *static_cast<KaxVideoFrameRate *>(l4);
- framerate.ReadData(es->I_O());
- track->v_frate = float(framerate);
- mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + Frame rate: %f\n",
- float(framerate));
-
- } else
- 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);
- }
+ ka_sfreq = FINDFIRST(ktaudio, KaxAudioSamplingFreq);
+ if (ka_sfreq != NULL) {
+ track->a_sfreq = float(*ka_sfreq);
+ mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + Sampling "
+ "frequency: %f\n", track->a_sfreq);
+ } else
+ track->a_sfreq = 8000.0;
- } // while (l4 != NULL)
-
- } else if (EbmlId(*l3) == KaxCodecID::ClassInfos.GlobalId) {
- KaxCodecID &codec_id = *static_cast<KaxCodecID*>(l3);
- codec_id.ReadData(es->I_O());
- 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 if (EbmlId(*l3) == KaxCodecPrivate::ClassInfos.GlobalId) {
- KaxCodecPrivate &c_priv = *static_cast<KaxCodecPrivate*>(l3);
- c_priv.ReadData(es->I_O());
- mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + CodecPrivate, length "
- "%llu\n", c_priv.GetSize());
- track->private_size = c_priv.GetSize();
- if (track->private_size > 0) {
- track->private_data = malloc(track->private_size);
- if (track->private_data == NULL)
- return 0;
- memcpy(track->private_data, c_priv.GetBuffer(),
- track->private_size);
- }
+ ka_channels = FINDFIRST(ktaudio, KaxAudioChannels);
+ if (ka_channels != NULL) {
+ track->a_channels = uint8(*ka_channels);
+ mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + Channels: %u\n",
+ track->a_channels);
+ } else
+ track->a_channels = 1;
- } else if (EbmlId(*l3) ==
- KaxTrackFlagDefault::ClassInfos.GlobalId) {
- KaxTrackFlagDefault &f_default =
- *static_cast<KaxTrackFlagDefault *>(l3);
- f_default.ReadData(es->I_O());
- track->default_track = uint32(f_default);
- mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + Default flag: %u\n",
- track->default_track);
-
- } else if (EbmlId(*l3) ==
- KaxTrackLanguage::ClassInfos.GlobalId) {
- KaxTrackLanguage &language =
- *static_cast<KaxTrackLanguage *>(l3);
- language.ReadData(es->I_O());
- mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + Language: %s\n",
- string(language).c_str());
- if (track->language != NULL)
- free(track->language);
- track->language = strdup(string(language).c_str());
+ ka_bitdepth = FINDFIRST(ktaudio, KaxAudioBitDepth);
+ if (ka_bitdepth != NULL) {
+ track->a_bps = uint8(*ka_bitdepth);
+ mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + Bit depth: %u\n",
+ track->a_bps);
+ }
- } else
- upper_lvl_el = 0;
-
- if (upper_lvl_el > 0) { // we're coming from l4
- upper_lvl_el--;
- delete l3;
- l3 = l4;
- if (upper_lvl_el > 0)
- break;
- } 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)
+ ktvideo = FINDFIRST(ktentry, KaxTrackVideo);
+ if (ktvideo != NULL) {
+ KaxVideoPixelWidth *kv_pwidth;
+ KaxVideoPixelHeight *kv_pheight;
+ KaxVideoDisplayWidth *kv_dwidth;
+ KaxVideoDisplayHeight *kv_dheight;
+ KaxVideoFrameRate *kv_frate;
+
+ kv_pwidth = FINDFIRST(ktvideo, KaxVideoPixelWidth);
+ if (kv_pwidth != NULL) {
+ track->v_width = uint16(*kv_pwidth);
+ mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + Pixel width: %u\n",
+ track->v_width);
+ }
- } else
- mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + unknown element@2: %s\n",
- typeid(*l2).name());
- if (upper_lvl_el > 0) { // we're coming from l3
- upper_lvl_el--;
- delete l2;
- l2 = l3;
- if (upper_lvl_el > 0)
- break;
- } 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;
- }
+ kv_pheight = FINDFIRST(ktvideo, KaxVideoPixelHeight);
+ if (kv_pheight != NULL) {
+ track->v_height = uint16(*kv_pheight);
+ mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + Pixel height: %u\n",
+ track->v_height);
+ }
- } // while (l2 != NULL)
+ kv_dwidth = FINDFIRST(ktvideo, KaxVideoDisplayWidth);
+ if (kv_dwidth != NULL) {
+ track->v_dwidth = uint16(*kv_dwidth);
+ mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + Display width: %u\n",
+ track->v_dwidth);
+ }
- } else if (EbmlId(*l1) == KaxSeekHead::ClassInfos.GlobalId) {
- mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] |+ found seek head\n");
+ kv_dheight = FINDFIRST(ktvideo, KaxVideoDisplayHeight);
+ if (kv_dheight != NULL) {
+ track->v_dheight = uint16(*kv_dheight);
+ mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + Display height: %u\n",
+ track->v_dheight);
+ }
- l2 = es->FindNextElement(l1->Generic().Context, upper_lvl_el,
- 0xFFFFFFFFL, true, 1);
- while (l2 != NULL) {
- if (upper_lvl_el > 0)
- brea