Mercurial > mplayer.hg
changeset 10637:b6a31ca4f9a2
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.
author | mosu |
---|---|
date | Sun, 17 Aug 2003 09:26:01 +0000 |
parents | 7938ee85f355 |
children | 9d0b8330a683 |
files | libmpdemux/demux_mkv.cpp |
diffstat | 1 files changed, 431 insertions(+), 744 deletions(-) [+] |
line wrap: on
line diff
--- a/libmpdemux/demux_mkv.cpp Sun Aug 17 01:20:48 2003 +0000 +++ b/libmpdemux/demux_mkv.cpp Sun Aug 17 09:26:01 2003 +0000 @@ -47,11 +47,13 @@ #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 @@ 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 @@ 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"); - - elements_found = 0; - - 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; + cues->Read(*es, KaxCues::ClassInfos.Context, upper_lvl_el, l2, true); - 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"); + cpoint = FINDFIRST(cues, KaxCuePoint); - 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; + while (cpoint != NULL) { + mp_msg(MSGT_DEMUX, MSGL_DBG2, "[mkv] | + found cue point\n"); - } 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)); + 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 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; + ctrackpos = FINDFIRST(cpoint, KaxCueTrackPositions); - 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)); + while (ctrackpos != NULL) { + ctrack = FINDFIRST(ctrackpos, KaxCueTrack); - } 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 (ctrack == NULL) { + ctrackpos = FINDNEXT(cpoint, KaxCueTrackPositions, ctrackpos); + continue; + } - 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) + tnum = uint32(*ctrack); + mp_msg(MSGT_DEMUX, MSGL_DBG2, "[mkv] | + found cue track: %u\n", tnum); - } 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; - - } 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) + ccpos = FINDFIRST(ctrackpos, KaxCueClusterPosition); + if (ccpos == 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); - - } else - upper_lvl_el = 0; + filepos = mkv_d->segment->GetGlobalPosition(uint64_t(*ccpos)); + mp_msg(MSGT_DEMUX, MSGL_DBG2, "[mkv] | + found cue cluster " + "position: %llu\n", filepos); - 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; + 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 @@ return 1; } - - extern "C" void print_wave_header(WAVEFORMATEX *h); extern "C" int demux_mkv_open(demuxer_t *demuxer) { @@ -1074,7 +919,7 @@ 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 @@ int seek_element_is_cue; #ifdef USE_ICONV - subcp_open(); + subcp_open(); #endif s = demuxer->stream; @@ -1119,7 +964,7 @@ 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 @@ 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 @@ // 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 + KaxTimecodeScale *ktc_scale; + KaxDuration *kduration; + 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; - 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); + l1->Read(*es, KaxInfo::ClassInfos.Context, upper_lvl_el, l2, true); - } 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); + 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; - } else - upper_lvl_el = 0; + 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); + } - 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); - } - } + 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; - - 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; - - // 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); + + 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. - } 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); - } - - } 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: "); + KaxTrackNumber *ktnum; + KaxTrackDefaultDuration *kdefdur; + KaxTrackType *kttype; + KaxTrackAudio *ktaudio; + KaxTrackVideo *ktvideo; + KaxCodecID *kcodecid; + KaxCodecPrivate *kcodecpriv; + KaxTrackFlagDefault *ktfdefault; + KaxTrackLanguage *ktlanguage; - 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; - } + mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + a track...\n"); + + track = new_mkv_track(mkv_d); + if (track == NULL) + return 0; - } 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); + 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); + } - } 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); - } - - } // while (l4 != NULL) + 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); + } + } - } 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); + kttype = FINDFIRST(ktentry, KaxTrackType); + if (kttype != NULL) { + mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + Track type: "); - } 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); - } - - } // 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()); + switch (uint8(*kttype)) { + 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; + } + } - } 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); - } + ktaudio = FINDFIRST(ktentry, KaxTrackAudio); + if (ktaudio != NULL) { + KaxAudioSamplingFreq *ka_sfreq; + KaxAudioChannels *ka_channels; + KaxAudioBitDepth *ka_bitdepth; + + mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + Audio track\n"); - } 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()); - - } else - upper_lvl_el = 0; + 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; - 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) + 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 - 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; + 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); + } + } - } // while (l2 != 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); + } + + 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); + } + + 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); + } + + 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); + } + + // For older files. + kv_frate = FINDFIRST(ktvideo, KaxVideoFrameRate); + if (kv_frate != NULL) { + track->v_frate = float(*kv_frate); + mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + Frame rate: %f\n", + track->v_frate); + } + + } + + kcodecid = FINDFIRST(ktentry, KaxCodecID); + if (kcodecid != NULL) { + mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + Codec ID: %s\n", + string(*kcodecid).c_str()); + track->codec_id = strdup(string(*kcodecid).c_str()); + } + + kcodecpriv = FINDFIRST(ktentry, KaxCodecPrivate); + if (kcodecpriv != NULL) { + mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + CodecPrivate, length " + "%llu\n", kcodecpriv->GetSize()); + track->private_size = kcodecpriv->GetSize(); + if (track->private_size > 0) { + track->private_data = malloc(track->private_size); + if (track->private_data == NULL) + return 0; + memcpy(track->private_data, kcodecpriv->GetBuffer(), + track->private_size); + } + } + + ktfdefault = FINDFIRST(ktentry, KaxTrackFlagDefault); + if (ktfdefault != NULL) { + track->default_track = uint32(*ktfdefault); + mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + Default flag: %u\n", + track->default_track); + } + + ktlanguage = FINDFIRST(ktentry, KaxTrackLanguage); + if (ktlanguage != NULL) { + mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + Language: %s\n", + string(*ktlanguage).c_str()); + if (track->language != NULL) + free(track->language); + track->language = strdup(string(*ktlanguage).c_str()); + } + + ktentry = FINDNEXT(l1, KaxTrackEntry, ktentry); + } // while (ktentry != NULL) + + l1->SkipData(*es, l1->Generic().Context); } else if (EbmlId(*l1) == KaxSeekHead::ClassInfos.GlobalId) { + + KaxSeek *kseek; + KaxSeekID *ksid; + KaxSeekPosition *kspos; + mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] |+ found seek head\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; + l1->Read(*es, KaxSeekHead::ClassInfos.Context, upper_lvl_el, l2, true); + + kseek = FINDFIRST(l1, KaxSeek); - if (EbmlId(*l2) == KaxSeek::ClassInfos.GlobalId) { - mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + seek entry\n"); + while (kseek != NULL) { + mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + seek entry\n"); + + seek_element_is_cue = 0; + seek_pos = 0; - seek_pos = 0; - seek_element_is_cue = 0; + ksid = FINDFIRST(kseek, KaxSeekID); + if (ksid != NULL) { + binary *b; + int s; - 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; + b = ksid->GetBuffer(); + s = ksid->GetSize(); + EbmlId id(b, s); + + if (id == KaxCues::ClassInfos.GlobalId) + seek_element_is_cue = 1; - if (EbmlId(*l3) == KaxSeekID::ClassInfos.GlobalId) { - binary *b; - int s; - KaxSeekID &seek_id = static_cast<KaxSeekID &>(*l3); - seek_id.ReadData(es->I_O()); - b = seek_id.GetBuffer(); - s = seek_id.GetSize(); - EbmlId id(b, s); - mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + seek ID: "); - for (i = 0; i < s; i++) - mp_msg(MSGT_DEMUX, MSGL_V, "0x%02x ", - ((unsigned char *)b)[i]); - mp_msg(MSGT_DEMUX, MSGL_V, "(%s)\n", - (id == KaxInfo::ClassInfos.GlobalId) ? - "KaxInfo" : - (id == KaxCluster::ClassInfos.GlobalId) ? - "KaxCluster" : - (id == KaxTracks::ClassInfos.GlobalId) ? - "KaxTracks" : - (id == KaxCues::ClassInfos.GlobalId) ? - "KaxCues" : - (id == KaxAttachments::ClassInfos.GlobalId) ? - "KaxAttachments" : - (id == KaxChapters::ClassInfos.GlobalId) ? - "KaxChapters" : - "unknown"); + mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + seek ID: "); + for (i = 0; i < s; i++) + mp_msg(MSGT_DEMUX, MSGL_V, "0x%02x ", + ((unsigned char *)b)[i]); + mp_msg(MSGT_DEMUX, MSGL_V, "(%s)\n", + (id == KaxInfo::ClassInfos.GlobalId) ? + "KaxInfo" : + (id == KaxCluster::ClassInfos.GlobalId) ? + "KaxCluster" : + (id == KaxTracks::ClassInfos.GlobalId) ? + "KaxTracks" : + (id == KaxCues::ClassInfos.GlobalId) ? + "KaxCues" : + (id == KaxAttachments::ClassInfos.GlobalId) ? + "KaxAttachments" : + (id == KaxChapters::ClassInfos.GlobalId) ? + "KaxChapters" : + "unknown"); + } - if (id == KaxCues::ClassInfos.GlobalId) - seek_element_is_cue = 1; - - } else if (EbmlId(*l3) == KaxSeekPosition::ClassInfos.GlobalId) { - KaxSeekPosition &kax_seek_pos = - static_cast<KaxSeekPosition &>(*l3); - kax_seek_pos.ReadData(es->I_O()); - mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + seek position: %llu\n", - uint64(kax_seek_pos)); - - seek_pos = uint64(kax_seek_pos); + kspos = FINDFIRST(kseek, KaxSeekPosition); + if (kspos != NULL) { + seek_pos = uint64(*kspos); + mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] | + seek position: %llu\n", + seek_pos); + } - } else - 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); - } - - } // while (l3 != NULL) - - if (!mkv_d->cues_found && (seek_pos > 0) && - seek_element_is_cue && (s->end_pos != 0)) + if (!mkv_d->cues_found && (kspos != NULL) && + seek_element_is_cue && (s->end_pos != 0)) cues_pos = mkv_d->segment->GetGlobalPosition(seek_pos); - } else - upper_lvl_el = 0; - - if (upper_lvl_el > 0) { // we're coming from l3 - upper_lvl_el--; - delete l2; - l2 = l3; - if (upper_lvl_el > 0) - break; + kseek = FINDNEXT(l1, KaxSeek, kseek); - } 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) + } // while (kseek != NULL) } else if ((EbmlId(*l1) == KaxCues::ClassInfos.GlobalId) && !mkv_d->cues_found) { @@ -1597,7 +1296,7 @@ io.setFilePointer(l1->GetElementPosition()); mkv_d->cues_found = parse_cues(mkv_d); stream_reset(s); - io.setFilePointer(current_pos); + l1->SkipData(*es, l1->Generic().Context); } else if (EbmlId(*l1) == KaxCluster::ClassInfos.GlobalId) { mp_msg(MSGT_DEMUX, MSGL_V, "[mkv] |+ found cluster, headers are " @@ -1607,26 +1306,35 @@ exit_loop = 1; } else - upper_lvl_el = 0; + l1->SkipData(*es, l1->Generic().Context); + if (!in_parent(l0)) { + delete l1; + break; + } + + if (upper_lvl_el > 0) { + upper_lvl_el--; + if (upper_lvl_el > 0) + break; + delete l1; + l1 = l2; + continue; + + } else if (upper_lvl_el < 0) { + upper_lvl_el++; + if (upper_lvl_el < 0) + break; + + } + if (exit_loop) // we've found the first cluster, so get out break; - if (upper_lvl_el > 0) { // we're coming from l2 - upper_lvl_el--; - delete l1; - l1 = l2; - if (upper_lvl_el > 0) - break; - } 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); - } else { - delete l1; - l1 = l2; - } + l1->SkipData(*es, l1->Generic().Context); + delete l1; + l1 = es->FindNextElement(l0->Generic().Context, upper_lvl_el, + 0xFFFFFFFFL, true); } // while (l1 != NULL) @@ -1635,6 +1343,7 @@ return 0; } + current_pos = io.getFilePointer(); // Try to find the very first timecode (cluster timecode). l2 = es->FindNextElement(l1->Generic().Context, upper_lvl_el, 0xFFFFFFFFL, true, 1); @@ -1646,7 +1355,7 @@ delete l2; } else mkv_d->first_tc = 0; - stream_seek(s, l1->GetElementPosition()); + io.setFilePointer(current_pos); // 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 @@ -2140,12 +1849,12 @@ demux_packet_t *dp; demux_stream_t *ds; mkv_demuxer_t *mkv_d; - int upper_lvl_el, exit_loop, found_data, i, delete_element, elements_found; + int upper_lvl_el, exit_loop, found_data, i; // Elements for different levels EbmlElement *l0 = NULL, *l1 = NULL, *l2 = NULL, *l3 = NULL; EbmlStream *es; KaxBlock *block; - int64_t block_duration, block_ref1, block_ref2; + int64_t block_duration, block_bref, block_fref; bool use_this_block; float current_pts; @@ -2165,11 +1874,7 @@ try { // The idea is not to handle a complete KaxCluster with each call to // demux_mkv_fill_buffer because those might be rather big. - 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) == KaxCluster::ClassInfos.GlobalId) { mkv_d->cluster = (KaxCluster *)l1; @@ -2184,11 +1889,7 @@ } else 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; + while ((l2 != NULL) && (upper_lvl_el <= 0)) { // Handle at least one data packets in one call to // demux_mkv_fill_buffer - but abort if we have found that. @@ -2211,68 +1912,38 @@ } else if (EbmlId(*l2) == KaxBlockGroup::ClassInfos.GlobalId) { + KaxBlockDuration *kbdur; + KaxReferenceBlock *krefblock; + KaxBlock *kblock; + block = NULL; block_duration = -1; - block_ref1 = 0; - block_ref2 = 0; - elements_found = 0; - - l3 = es->FindNextElement(l2->Generic().Context, upper_lvl_el, - 0xFFFFFFFFL, true, 1); - while (l3 != NULL) { - delete_element = 1; - if (upper_lvl_el > 0) - break; - if ((upper_lvl_el < 0) && !fits_parent(l3, l2)) - break; + block_bref = 0; + block_fref = 0; - if (EbmlId(*l3) == KaxBlock::ClassInfos.GlobalId) { - block = static_cast<KaxBlock *>(l3); - block->ReadData(es->I_O()); - block->SetParent(*mkv_d->cluster); - delete_element = 0; - elements_found |= 1; + l2->Read(*es, KaxBlockGroup::ClassInfos.Context, upper_lvl_el, l3, + true); - } else if (EbmlId(*l3) == - KaxBlockDuration::ClassInfos.GlobalId) { - KaxBlockDuration &duration = - *static_cast<KaxBlockDuration *>(l3); - duration.ReadData(es->I_O()); - block_duration = (int64_t)uint64(duration); - elements_found |= 2; + kbdur = FINDFIRST(l2, KaxBlockDuration); + kblock = FINDFIRST(l2, KaxBlock); + if (kblock != NULL) + kblock->SetParent(*mkv_d->cluster); - } else if (EbmlId(*l3) == - KaxReferenceBlock::ClassInfos.GlobalId) { - KaxReferenceBlock &ref = - *static_cast<KaxReferenceBlock *>(l3); - ref.ReadData(es->I_O()); - if ((elements_found & 4) == 0) { - block_ref1 = int64(ref); - elements_found |= 4; - } else { - block_ref2 = int64(ref); - elements_found |= 8; - } + krefblock = FINDFIRST(l2, KaxReferenceBlock); + while (krefblock != NULL) { + if (int64(*krefblock) < 0) + block_bref = int64(*krefblock); + else + block_fref = int64(*krefblock); - } else - upper_lvl_el = 0; + krefblock = FINDNEXT(l2, KaxReferenceBlock, krefblock); + } - if (upper_lvl_el == 0) { - l3->SkipData(static_cast<EbmlStream &>(*es), - l3->Generic().Context); - if (delete_element) - delete l3; - l3 = es->FindNextElement(l2->Generic().Context, upper_lvl_el, - 0xFFFFFFFFL, true, 1); - } - - } // while (l3 != NULL) - - if (block != NULL) { + if (kblock != NULL) { // Clear the subtitles if they're obsolete now. if ((mkv_d->clear_subs_at > 0) && (mkv_d->clear_subs_at <= - (block->GlobalTimecode() / 1000000 - mkv_d->first_tc))) { + (kblock->GlobalTimecode() / 1000000 - mkv_d->first_tc))) { mkv_d->subs.lines = 0; vo_sub = &mkv_d->subs; vo_osd_changed(OSDTYPE_SUBTITLE); @@ -2281,20 +1952,20 @@ ds = NULL; if ((mkv_d->video != NULL) && - (mkv_d->video->tnum == block->TrackNum())) + (mkv_d->video->tnum == kblock->TrackNum())) ds = d->video; else if ((mkv_d->audio != NULL) && - (mkv_d->audio->tnum == block->TrackNum())) + (mkv_d->audio->tnum == kblock->TrackNum())) ds = d->audio; use_this_block = true; - current_pts = (float)(block->GlobalTimecode() / 1000000.0 - + current_pts = (float)(kblock->GlobalTimecode() / 1000000.0 - mkv_d->first_tc) / 1000.0; if (ds == d->audio) { if (mkv_d->a_skip_to_keyframe && - ((elements_found & 4) == 4)) + (block_bref != 0)) use_this_block = false; else if (mkv_d->v_skip_to_keyframe) @@ -2305,13 +1976,13 @@ else if (ds == d->video) { if (mkv_d->v_skip_to_keyframe && - ((elements_found & 4) == 4)) + (block_bref != 0)) use_this_block = false; } else if ((mkv_d->subs_track != NULL) && - (mkv_d->subs_track->tnum == block->TrackNum())) { + (mkv_d->subs_track->tnum == kblock->TrackNum())) { if (!mkv_d->v_skip_to_keyframe) - handle_subtitles(d, block, block_duration); + handle_subtitles(d, kblock, block_duration); use_this_block = false; } else @@ -2322,21 +1993,21 @@ d->filepos = mkv_d->in->getFilePointer(); mkv_d->last_filepos = d->filepos; - for (i = 0; i < (int)block->NumberFrames(); i++) { - DataBuffer &data = block->GetBuffer(i); + for (i = 0; i < (int)kblock->NumberFrames(); i++) { + DataBuffer &data = kblock->GetBuffer(i); if ((ds == d->video) && mkv_d->video->realmedia) - handle_realvideo(d, data, (elements_found & 4) == 0, + handle_realvideo(d, data, block_bref == 0, found_data); else if ((ds == d->audio) && mkv_d->audio->realmedia) - handle_realaudio(d, data, (elements_found & 4) == 0, + handle_realaudio(d, data, block_bref == 0, found_data); else { dp = new_demux_packet(data.Size()); memcpy(dp->buffer, data.Buffer(), data.Size()); - dp->flags = (elements_found & 4) == 0 ? 1 : 0; + dp->flags = block_bref == 0 ? 1 : 0; dp->pts = mkv_d->last_pts; ds_add_packet(ds, dp); found_data++; @@ -2351,54 +2022,70 @@ } delete block; - } // block != NULL + } // kblock != NULL } else - upper_lvl_el = 0; + l2->SkipData(*es, l2->Generic().Context); - if (upper_lvl_el > 0) { // we're coming from l3 + if (!in_parent(l1)) { + delete l2; + break; + } + + if (upper_lvl_el > 0) { 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; + continue; + + } else if (upper_lvl_el < 0) { + upper_lvl_el++; + if (upper_lvl_el < 0) + break; + } + l2->SkipData(*es, l2->Generic().Context); + delete l2; + l2 = es->FindNextElement(l1->Generic().Context, upper_lvl_el, + 0xFFFFFFFFL, true); + } // while (l2 != NULL) + } else if (EbmlId(*l1) == KaxCues::ClassInfos.GlobalId) return 0; else - upper_lvl_el = 0; + l1->SkipData(*es, l1->Generic().Context); + + if (!in_parent(l0)) { + delete l1; + break; + } + + if (upper_lvl_el > 0) { + upper_lvl_el--; + if (upper_lvl_el > 0) + break; + delete l1; + l1 = l2; + continue; + + } else if (upper_lvl_el < 0) { + upper_lvl_el++; + if (upper_lvl_el < 0) + break; + + } if (exit_loop) break; - if (upper_lvl_el > 0) { // we're coming from l2 - upper_lvl_el--; - delete l1; - l1 = l2; - if (upper_lvl_el > 0) - break; - } 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); - if ((l1 != NULL) && (EbmlId(*l1) == KaxCluster::ClassInfos.GlobalId)) - add_cluster_position(mkv_d, l1->GetElementPosition()); - } else { - delete l1; - l1 = l2; - } + l1->SkipData(*es, l1->Generic().Context); + delete l1; + l1 = es->FindNextElement(l0->Generic().Context, upper_lvl_el, + 0xFFFFFFFFL, true); } // while (l1 != NULL) } catch (exception ex) {