From a04544edaa13a4a137d0eef2e5f39cba8c4cd51e Mon Sep 17 00:00:00 2001 From: Moritz Bunkus Date: Sun, 10 Aug 2003 20:01:55 +0000 Subject: [PATCH] Changed how the global elements are handled by taking the parent's size into account. This re-enables processing of files produced with the latest VirtualDubMod. --- ChangeLog | 4 + src/mkvextract.cpp | 2 +- src/mkvextract.h | 2 + src/mkvextract_attachments.cpp | 38 ++--- src/mkvextract_chapters.cpp | 38 ++--- src/mkvextract_tags.cpp | 38 ++--- src/mkvextract_tracks.cpp | 282 ++++++++++++++++++++------------- 7 files changed, 238 insertions(+), 166 deletions(-) diff --git a/ChangeLog b/ChangeLog index c56254561..a63b2766f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,9 @@ 2003-08-10 Moritz Bunkus + * mkvextract: Changed how the global elements are handled by + taking the parent's size into account. This re-enables processing + of files produced with the latest VirtualDubMod. + * mkvmerge: Changed how the Matroska reader handles global elements by taking the parent's size into account. This re-enables processing of files produced with the latest VirtualDubMod. diff --git a/src/mkvextract.cpp b/src/mkvextract.cpp index ba9faee67..61738d593 100644 --- a/src/mkvextract.cpp +++ b/src/mkvextract.cpp @@ -103,7 +103,7 @@ kax_track_t *find_track(int tid) { return NULL; } -char typenames[14][20] = {"unknown", "Ogg" "AVI", "WAV", "SRT", "MP3", "AC3", +char typenames[14][20] = {"unknown", "Ogg", "AVI", "WAV", "SRT", "MP3", "AC3", "chapter", "MicroDVD", "VobSub", "Matroska", "DTS", "AAC", "SSA/ASS"}; diff --git a/src/mkvextract.h b/src/mkvextract.h index 62f7127ed..ce842e923 100644 --- a/src/mkvextract.h +++ b/src/mkvextract.h @@ -88,6 +88,8 @@ extern char typenames[14][20]; #define fits_parent(l, p) (l->GetElementPosition() < \ (p->GetElementPosition() + p->ElementSize())) +#define in_parent(p) (in->getFilePointer() < \ + (p->GetElementPosition() + p->ElementSize())) // Helper functions in mkvextract.cpp void show_element(EbmlElement *l, int level, const char *fmt, ...); diff --git a/src/mkvextract_attachments.cpp b/src/mkvextract_attachments.cpp index 6758c4b6b..d13dc0145 100644 --- a/src/mkvextract_attachments.cpp +++ b/src/mkvextract_attachments.cpp @@ -220,11 +220,7 @@ void extract_attachments(const char *file_name) { // We've got our segment, so let's find the attachments l1 = es->FindNextElement(l0->Generic().Context, upper_lvl_el, 0xFFFFFFFFL, true, 1); - while (l1 != NULL) { - if (upper_lvl_el > 0) - break; - if ((upper_lvl_el < 0) && !fits_parent(l1, l0)) - break; + while ((l1 != NULL) && (upper_lvl_el <= 0)) { if (EbmlId(*l1) == KaxAttachments::ClassInfos.GlobalId) { handle_attachments(in, es, l0, l1->GetElementPosition()); @@ -282,30 +278,36 @@ void extract_attachments(const char *file_name) { } else - upper_lvl_el = 0; + l1->SkipData(*es, l1->Generic().Context); if (done) break; - if (upper_lvl_el > 0) { // we're coming from l2 - upper_lvl_el--; + if (!in_parent(l0)) { delete l1; - l1 = l2; + break; + } + + if (upper_lvl_el > 0) { + upper_lvl_el--; if (upper_lvl_el > 0) break; - - } else if (upper_lvl_el == 0) { - l1->SkipData(*es, l1->Generic().Context); - delete l1; - upper_lvl_el = 0; - l1 = es->FindNextElement(l0->Generic().Context, upper_lvl_el, - 0xFFFFFFFFL, true, 1); - - } else { delete l1; l1 = l2; + continue; + + } else if (upper_lvl_el < 0) { + upper_lvl_el++; + if (upper_lvl_el < 0) + break; + } + l1->SkipData(*es, l1->Generic().Context); + delete l1; + l1 = es->FindNextElement(l0->Generic().Context, upper_lvl_el, + 0xFFFFFFFFL, true); + } // while (l1 != NULL) delete l0; diff --git a/src/mkvextract_chapters.cpp b/src/mkvextract_chapters.cpp index 3eec9f296..365e7023d 100644 --- a/src/mkvextract_chapters.cpp +++ b/src/mkvextract_chapters.cpp @@ -130,11 +130,7 @@ void extract_chapters(const char *file_name, bool chapter_format_simple) { // We've got our segment, so let's find the chapters l1 = es->FindNextElement(l0->Generic().Context, upper_lvl_el, 0xFFFFFFFFL, true, 1); - while (l1 != NULL) { - if (upper_lvl_el > 0) - break; - if ((upper_lvl_el < 0) && !fits_parent(l1, l0)) - break; + while ((l1 != NULL) && (upper_lvl_el <= 0)) { if (EbmlId(*l1) == KaxChapters::ClassInfos.GlobalId) { KaxChapters &chapters = *static_cast(l1); @@ -153,27 +149,33 @@ void extract_chapters(const char *file_name, bool chapter_format_simple) { write_chapters_xml(&chapters, stdout); } else - upper_lvl_el = 0; + l1->SkipData(*es, l1->Generic().Context); - if (upper_lvl_el > 0) { // we're coming from l2 - upper_lvl_el--; + if (!in_parent(l0)) { delete l1; - l1 = l2; + break; + } + + if (upper_lvl_el > 0) { + upper_lvl_el--; if (upper_lvl_el > 0) break; - - } else if (upper_lvl_el == 0) { - l1->SkipData(*es, l1->Generic().Context); - delete l1; - upper_lvl_el = 0; - l1 = es->FindNextElement(l0->Generic().Context, upper_lvl_el, - 0xFFFFFFFFL, true, 1); - - } else { delete l1; l1 = l2; + continue; + + } else if (upper_lvl_el < 0) { + upper_lvl_el++; + if (upper_lvl_el < 0) + break; + } + l1->SkipData(*es, l1->Generic().Context); + delete l1; + l1 = es->FindNextElement(l0->Generic().Context, upper_lvl_el, + 0xFFFFFFFFL, true); + } // while (l1 != NULL) delete l0; diff --git a/src/mkvextract_tags.cpp b/src/mkvextract_tags.cpp index 2041ef049..658d4c8c9 100644 --- a/src/mkvextract_tags.cpp +++ b/src/mkvextract_tags.cpp @@ -130,11 +130,7 @@ void extract_tags(const char *file_name) { // We've got our segment, so let's find the tags l1 = es->FindNextElement(l0->Generic().Context, upper_lvl_el, 0xFFFFFFFFL, true, 1); - while (l1 != NULL) { - if (upper_lvl_el > 0) - break; - if ((upper_lvl_el < 0) && !fits_parent(l1, l0)) - break; + while ((l1 != NULL) && (upper_lvl_el <= 0)) { if (EbmlId(*l1) == KaxTags::ClassInfos.GlobalId) { KaxTags &tags = *static_cast(l1); @@ -150,27 +146,33 @@ void extract_tags(const char *file_name) { write_tags_xml(tags, stdout); } else - upper_lvl_el = 0; + l1->SkipData(*es, l1->Generic().Context); - if (upper_lvl_el > 0) { // we're coming from l2 - upper_lvl_el--; + if (!in_parent(l0)) { delete l1; - l1 = l2; + break; + } + + if (upper_lvl_el > 0) { + upper_lvl_el--; if (upper_lvl_el > 0) break; - - } else if (upper_lvl_el == 0) { - l1->SkipData(*es, l1->Generic().Context); - delete l1; - upper_lvl_el = 0; - l1 = es->FindNextElement(l0->Generic().Context, upper_lvl_el, - 0xFFFFFFFFL, true, 1); - - } else { delete l1; l1 = l2; + continue; + + } else if (upper_lvl_el < 0) { + upper_lvl_el++; + if (upper_lvl_el < 0) + break; + } + l1->SkipData(*es, l1->Generic().Context); + delete l1; + l1 = es->FindNextElement(l0->Generic().Context, upper_lvl_el, + 0xFFFFFFFFL, true); + } // while (l1 != NULL) delete l0; diff --git a/src/mkvextract_tracks.cpp b/src/mkvextract_tracks.cpp index 873be47f9..b2c1afb33 100644 --- a/src/mkvextract_tracks.cpp +++ b/src/mkvextract_tracks.cpp @@ -17,6 +17,8 @@ \author Moritz Bunkus */ +// {{{ includes + #include #include #include @@ -78,6 +80,10 @@ extern "C" { using namespace libmatroska; using namespace std; +// }}} + +// {{{ FUNCTIONS flush_ogg_pages(), write_ogg_pages() + static void flush_ogg_pages(kax_track_t &track) { ogg_page page; @@ -96,6 +102,10 @@ static void write_ogg_pages(kax_track_t &track) { } } +// }}} + +// {{{ FUNCTION create_output_files() + static void create_output_files() { int i, k, offset; bool something_to_do, is_ok; @@ -333,7 +343,7 @@ static void create_output_files() { } mxprint(stderr, "Extracting track ID %lld to a %s file '%s'.\n", - tracks[i].tid, typenames[tracks[i].type - 1], + tracks[i].tid, typenames[tracks[i].type], tracks[i].out_name); if (tracks[i].type == TYPEOGM) { @@ -402,6 +412,10 @@ static void create_output_files() { } } +// }}} + +// {{{ FUNCTION handle_data() + static void handle_data(KaxBlock *block, int64_t block_duration, bool has_ref) { kax_track_t *track; @@ -619,6 +633,10 @@ static void handle_data(KaxBlock *block, int64_t block_duration, delete block; } +// }}} + +// {{{ FUNCTION close_files() + static void close_files() { int i, k; ogg_packet op; @@ -678,6 +696,10 @@ static void close_files() { } } +// }}} + +// {{{ FUNCTION extract_tracks() + bool extract_tracks(const char *file_name) { int upper_lvl_el; // Elements for different levels @@ -744,11 +766,7 @@ bool extract_tracks(const char *file_name) { // 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) - 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 @@ -757,11 +775,7 @@ bool extract_tracks(const char *file_name) { upper_lvl_el = 0; 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)) { if (EbmlId(*l2) == KaxTimecodeScale::ClassInfos.GlobalId) { KaxTimecodeScale &ktc_scale = *static_cast(l2); @@ -769,15 +783,25 @@ bool extract_tracks(const char *file_name) { tc_scale = uint64(ktc_scale); show_element(l2, 2, "Timecode scale: %llu", tc_scale); } else - upper_lvl_el = 0; - - if (upper_lvl_el == 0) { l2->SkipData(*es, l2->Generic().Context); + + if (!in_parent(l1)) { delete l2; - l2 = es->FindNextElement(l1->Generic().Context, upper_lvl_el, - 0xFFFFFFFFL, true, 1); + break; } + 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); + } } else if (EbmlId(*l1) == KaxTracks::ClassInfos.GlobalId) { @@ -788,11 +812,7 @@ bool extract_tracks(const char *file_name) { upper_lvl_el = 0; 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)) { if (EbmlId(*l2) == KaxTrackEntry::ClassInfos.GlobalId) { // We actually found a track entry :) We're happy now. @@ -805,11 +825,7 @@ bool extract_tracks(const char *file_name) { upper_lvl_el = 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; + while ((l3 != NULL) && (upper_lvl_el <= 0)) { // Now evaluate the data belonging to this track if (EbmlId(*l3) == KaxTrackNumber::ClassInfos.GlobalId) { @@ -858,11 +874,7 @@ bool extract_tracks(const char *file_name) { upper_lvl_el = 0; 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; + while ((l4 != NULL) && (upper_lvl_el <= 0)) { if (EbmlId(*l4) == KaxAudioSamplingFreq::ClassInfos.GlobalId) { @@ -892,15 +904,25 @@ bool extract_tracks(const char *file_name) { if (track != NULL) track->a_bps = uint8(bps); } else - upper_lvl_el = 0; - - if (upper_lvl_el == 0) { l4->SkipData(*es, l4->Generic().Context); + + if (!in_parent(l3)) { delete l4; - l4 = es->FindNextElement(l3->Generic().Context, - upper_lvl_el, 0xFFFFFFFFL, true); + break; } + if (upper_lvl_el < 0) { + upper_lvl_el++; + if (upper_lvl_el < 0) + break; + + } + + l4->SkipData(*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) { @@ -909,11 +931,7 @@ bool extract_tracks(const char *file_name) { upper_lvl_el = 0; 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; + while ((l4 != NULL) && (upper_lvl_el <= 0)) { if (EbmlId(*l4) == KaxVideoPixelWidth::ClassInfos.GlobalId) { KaxVideoPixelWidth &width = @@ -942,15 +960,25 @@ bool extract_tracks(const char *file_name) { track->v_fps = float(framerate); } else - upper_lvl_el = 0; - - if (upper_lvl_el == 0) { l4->SkipData(*es, l4->Generic().Context); + + if (!in_parent(l3)) { delete l4; - l4 = es->FindNextElement(l3->Generic().Context, - upper_lvl_el, 0xFFFFFFFFL, true); + break; } + if (upper_lvl_el < 0) { + upper_lvl_el++; + if (upper_lvl_el < 0) + break; + + } + + l4->SkipData(*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) { @@ -1005,48 +1033,63 @@ bool extract_tracks(const char *file_name) { track->v_fps = 1000000000.0 / (float)uint64(def_duration); } else - upper_lvl_el = 0; + l3->SkipData(*es, l3->Generic().Context); - if (upper_lvl_el > 0) { // we're coming from l4 - upper_lvl_el--; + if (!in_parent(l2)) { delete l3; - l3 = l4; + break; + } + + if (upper_lvl_el > 0) { + upper_lvl_el--; if (upper_lvl_el > 0) break; - } else if (upper_lvl_el == 0) { - l3->SkipData(*es, - l3->Generic().Context); - delete l3; - upper_lvl_el = 0; - l3 = es->FindNextElement(l2->Generic().Context, upper_lvl_el, - 0xFFFFFFFFL, true, 1); - } else { delete l3; l3 = l4; + continue; + + } else if (upper_lvl_el < 0) { + upper_lvl_el++; + if (upper_lvl_el < 0) + break; + } + l3->SkipData(*es, l3->Generic().Context); + delete l3; + l3 = es->FindNextElement(l2->Generic().Context, upper_lvl_el, + 0xFFFFFFFFL, true); + } } else - upper_lvl_el = 0; + l2->SkipData(*es, l2->Generic().Context); - if (upper_lvl_el > 0) { // we're coming from l3 - upper_lvl_el--; + if (!in_parent(l1)) { delete l2; - l2 = l3; + break; + } + + if (upper_lvl_el > 0) { + upper_lvl_el--; if (upper_lvl_el > 0) break; - } else if (upper_lvl_el == 0) { - l2->SkipData(*es, l2->Generic().Context); - delete l2; - upper_lvl_el = 0; - 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) // Headers have been parsed completely. Now create the output files @@ -1064,11 +1107,7 @@ bool extract_tracks(const char *file_name) { upper_lvl_el = 0; 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)) { if (EbmlId(*l2) == KaxClusterTimecode::ClassInfos.GlobalId) { KaxClusterTimecode &ctc = *static_cast(l2); @@ -1085,11 +1124,7 @@ bool extract_tracks(const char *file_name) { has_reference = false; l3 = es->FindNextElement(l2->Generic().Context, upper_lvl_el, 0xFFFFFFFFL, false, 1); - while (l3 != NULL) { - if (upper_lvl_el > 0) - break; - if ((upper_lvl_el < 0) && !fits_parent(l3, l2)) - break; + while ((l3 != NULL) && (upper_lvl_el <= 0)) { delete_element = true; @@ -1121,16 +1156,28 @@ bool extract_tracks(const char *file_name) { ((float)int64(reference)) * tc_scale / 1000000.0); has_reference = true; - } - - if (upper_lvl_el == 0) { + } else l3->SkipData(*es, l3->Generic().Context); + + if (!in_parent(l2)) { if (delete_element) delete l3; - l3 = es->FindNextElement(l2->Generic().Context, upper_lvl_el, - 0xFFFFFFFFL, true, 1); + break; } + if (upper_lvl_el < 0) { + upper_lvl_el++; + if (upper_lvl_el < 0) + break; + + } + + l3->SkipData(*es, l3->Generic().Context); + if (delete_element) + delete l3; + l3 = es->FindNextElement(l2->Generic().Context, upper_lvl_el, + 0xFFFFFFFFL, true); + } // while (l3 != NULL) // Now write the stuff to the file. Or not. Or get something to @@ -1138,52 +1185,63 @@ bool extract_tracks(const char *file_name) { handle_data(block, block_duration, has_reference); } else - upper_lvl_el = 0; + l2->SkipData(*es, l2->Generic().Context); - if (upper_lvl_el > 0) { // we're coming from l3 - upper_lvl_el--; + if (!in_parent(l1)) { delete l2; - l2 = l3; + break; + } + + if (upper_lvl_el > 0) { + upper_lvl_el--; if (upper_lvl_el > 0) break; - - } else if (upper_lvl_el == 0) { - l2->SkipData(*es, - l2->Generic().Context); - delete l2; - upper_lvl_el = 0; - 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 - upper_lvl_el = 0; + l1->SkipData(*es, l1->Generic().Context); - if (upper_lvl_el > 0) { // we're coming from l2 - upper_lvl_el--; + if (!in_parent(l0)) { delete l1; - l1 = l2; + break; + } + + if (upper_lvl_el > 0) { + upper_lvl_el--; if (upper_lvl_el > 0) break; - - } else if (upper_lvl_el == 0) { - l1->SkipData(*es, l1->Generic().Context); - delete l1; - upper_lvl_el = 0; - l1 = es->FindNextElement(l0->Generic().Context, upper_lvl_el, - 0xFFFFFFFFL, true, 1); - - } else { delete l1; l1 = l2; + continue; + + } else if (upper_lvl_el < 0) { + upper_lvl_el++; + if (upper_lvl_el < 0) + break; + } + l1->SkipData(*es, l1->Generic().Context); + delete l1; + l1 = es->FindNextElement(l0->Generic().Context, upper_lvl_el, + 0xFFFFFFFFL, true); + } // while (l1 != NULL) delete l0; @@ -1203,3 +1261,5 @@ bool extract_tracks(const char *file_name) { return false; } } + +// }}}