Meta seek element is split into two elements. The first's located at the start of the file containing only a small number of level 1 elements. The clusters are referenced in a second meta seek element located at the end of the file. Removed the options "--meta-seek-size" and "--no-meta-seek". Added the option to disable that second meta seek entry, "--no-clusters-in-meta-seek".

This commit is contained in:
Moritz Bunkus 2003-08-23 23:27:17 +00:00
parent 98697f1958
commit c50de21f63
5 changed files with 101 additions and 99 deletions

View File

@ -1,3 +1,13 @@
2003-08-24 Moritz Bunkus <moritz@bunkus.org>
* mkvmerge: Meta seek element is split into two elements. The
first's located at the start of the file containing only a small
number of level 1 elements. The clusters are referenced in a
second meta seek element located at the end of the file. Removed
the options "--meta-seek-size" and "--no-meta-seek". Added the
option to disable that second meta seek entry,
"--no-clusters-in-meta-seek".
2003-08-22 Moritz Bunkus <moritz@bunkus.org> 2003-08-22 Moritz Bunkus <moritz@bunkus.org>
* mkvextract: Backwards compatibility: Accepts S_SSA and S_ASS as * mkvextract: Backwards compatibility: Accepts S_SSA and S_ASS as

View File

@ -59,19 +59,9 @@ data, but seeking will probably be imprecise and slower. Use this only if
you're really desperate for space or for testing purposes. See also option you're really desperate for space or for testing purposes. See also option
\fB\-\-cues\fR which can be specified for each input file. \fB\-\-cues\fR which can be specified for each input file.
.TP .TP
\fB\-\-no\-meta\-seek\fR \fB\-\-no\-clusters\-in\-meta\-seek\fR
The meta seek information is stored along with the headers at the beginning Tells \fBmkvmerge\fR not to create a meta seek element at the end of the file
of the file and points to the cue entries (the index). This allows a player containing all clusters. See also the section about \fBMATROSKA FILE LAYOUT\fR.
to quickly find the index and uses very little space. It should be left on
and only disabled for testing purposes. At the moment \fB\-\-no\-cues\fR
implies \fB\-\-no\-meta\-seek\fR.
.TP
\fB\-\-meta\-seek\-size\fR \fId\fR
Reserve \fRd\fR bytes for the meta seek information (see
\fB\-\-no\-meta\-seek). Default value is 100 bytes which should be enough.
\fBmkvmerge\fR will abort with an appropriate warning message if the space
is not enough and also provide the optimal size to use with this option.
This option is normally not needed.
.TP .TP
\fB\-\-no\-lacing\fR \fB\-\-no\-lacing\fR
Disable lacing for all tracks. This will increase the file's size, especially Disable lacing for all tracks. This will increase the file's size, especially
@ -716,6 +706,36 @@ the seconds (two digits long, range 00 - 59). \fI+TZTZ\fR is the time zone,
e.g. +0100 or -0200. An example would be 2003-07-30T19:10:16+0200. e.g. +0100 or -0200. An example would be 2003-07-30T19:10:16+0200.
.SH MATROSKA FILE LAYOUT
.LP
The Matroska file layout is quite flexible. \fBmkvmerge\fR will render a file
in a predefined way. The resulting file looks like this:
.LP
[EBML head] [segment {meta seek #1} {attachments} {chapters}
[segment information] [track information] [cluster 1] {cluster 2} ...
{cluster n} {meta seek #2} {tags}]
.LP
The elements in curly braces optional and depend on the contents and options
used. Some notes:
.TP
*
meta seek #1 includes only a small number of level 1 element, and only if
they exist: attachments, chapters, tags, meta seek #2. Older versions of
\fBmkvmerge\fR used to put the clusters into this meta seek element as well.
Therefore some imprecise guessing was necessary to reserve enough space. It
often failed. Now only the clusters are stored in meta seek #2, and meta
seek #1 refers to the meta seek element #2.
.TP
*
Attachment, chapter and tag elements are only present if they were added.
.LP
The shortest possible Matroska file would look like this:
.LP
[EBML head] [segment [segment information] [track information] [cluster 1]]
.LP
This might be the case for audio-only files.
.SH NOTES .SH NOTES
.LP .LP
What works: What works:

View File

@ -488,8 +488,8 @@ int cluster_helper_c::render() {
cluster->Render(*out, *kax_cues); cluster->Render(*out, *kax_cues);
if (kax_seekhead != NULL) if (kax_sh_cues != NULL)
kax_seekhead->IndexThis(*cluster, *kax_segment); kax_sh_cues->IndexThis(*cluster, *kax_segment);
last_cluster_tc = cluster->GlobalTimecode(); last_cluster_tc = cluster->GlobalTimecode();
} else } else

View File

@ -136,8 +136,7 @@ int max_blocks_per_cluster = 65535;
int max_ms_per_cluster = 2000; int max_ms_per_cluster = 2000;
bool write_cues = true, cue_writing_requested = false; bool write_cues = true, cue_writing_requested = false;
bool video_track_present = false; bool video_track_present = false;
bool write_meta_seek = true; bool write_meta_seek_for_clusters = true;
int64_t meta_seek_size = 0;
bool no_lacing = false, no_linking = false; bool no_lacing = false, no_linking = false;
int64_t split_after = -1; int64_t split_after = -1;
bool split_by_time = false; bool split_by_time = false;
@ -156,9 +155,9 @@ KaxInfo *kax_infos;
KaxTracks *kax_tracks; KaxTracks *kax_tracks;
KaxTrackEntry *kax_last_entry; KaxTrackEntry *kax_last_entry;
KaxCues *kax_cues; KaxCues *kax_cues;
EbmlVoid *kax_seekhead_void = NULL; EbmlVoid *kax_sh_void = NULL;
KaxDuration *kax_duration; KaxDuration *kax_duration;
KaxSeekHead *kax_seekhead = NULL; KaxSeekHead *kax_sh_main = NULL, *kax_sh_cues = NULL;
KaxTags *kax_tags = NULL; KaxTags *kax_tags = NULL;
KaxAttachments *kax_as = NULL; KaxAttachments *kax_as = NULL;
KaxChapters *kax_chapters = NULL; KaxChapters *kax_chapters = NULL;
@ -234,8 +233,8 @@ static void usage() {
" put at most n milliseconds of data into each\n" " put at most n milliseconds of data into each\n"
" cluster.\n" " cluster.\n"
" --no-cues Do not write the cue data (the index).\n" " --no-cues Do not write the cue data (the index).\n"
" --no-meta-seek Do not write any meta seek information.\n" " --no-clusters-in-meta-seek\n"
" --meta-seek-size <d> Reserve d bytes for the meta seek entries.\n" " Do not write meta seek data for clusters.\n"
" --no-lacing Do not use lacing.\n" " --no-lacing Do not use lacing.\n"
"\n File splitting and linking (still global):\n" "\n File splitting and linking (still global):\n"
" --split <d[K,M,G]|HH:MM:SS|ns>\n" " --split <d[K,M,G]|HH:MM:SS|ns>\n"
@ -770,19 +769,12 @@ static void render_headers(mm_io_c *out, bool last_file, bool first_file) {
kax_segment->WriteHead(*out, 5); kax_segment->WriteHead(*out, 5);
// Reserve some space for the meta seek stuff. // Reserve some space for the meta seek stuff.
if (write_meta_seek) { kax_sh_main = new KaxSeekHead();
kax_seekhead = new KaxSeekHead(); kax_sh_void = new EbmlVoid();
kax_seekhead_void = new EbmlVoid(); kax_sh_void->SetSize(100);
if (meta_seek_size == 0) kax_sh_void->Render(*out);
if (video_track_present) if (write_meta_seek_for_clusters)
meta_seek_size = kax_sh_cues = new KaxSeekHead();
(int64_t)((float)file_sizes * 1.8 / 10240.0);
else
meta_seek_size =
(int64_t)((float)file_sizes * 5 / 4096.0);
kax_seekhead_void->SetSize(meta_seek_size);
kax_seekhead_void->Render(*out);
}
kax_infos->Render(*out); kax_infos->Render(*out);
@ -1153,20 +1145,11 @@ static void parse_args(int argc, char **argv) {
i++; i++;
} else if (!strcmp(argv[i], "--meta-seek-size")) {
if ((i + 1) >= argc)
mxerror("--meta-seek-size lacks the size argument.\n");
if (!parse_int(argv[i + 1], meta_seek_size) || (meta_seek_size < 1))
mxerror("Invalid size given for --meta-seek-size.\n");
i++;
} else if (!strcmp(argv[i], "--no-cues")) } else if (!strcmp(argv[i], "--no-cues"))
write_cues = false; write_cues = false;
else if (!strcmp(argv[i], "--no-meta-seek")) else if (!strcmp(argv[i], "--no-clusters-in-meta-seek"))
write_meta_seek = false; write_meta_seek_for_clusters = false;
else if (!strcmp(argv[i], "--no-lacing")) else if (!strcmp(argv[i], "--no-lacing"))
no_lacing = true; no_lacing = true;
@ -1243,6 +1226,12 @@ static void parse_args(int argc, char **argv) {
dump_packets = safestrdup(argv[i + 1]); dump_packets = safestrdup(argv[i + 1]);
i++; i++;
} else if (!strcmp(argv[i], "--meta-seek-size")) {
mxwarn("The option '--meta-seek-size' is no longer supported. Please "
"read mkvmerge's documentation, especially the section about "
"the MATROSKA FILE LAYOUT.");
i++;
} }
// Options that apply to the next input file only. // Options that apply to the next input file only.
@ -1526,8 +1515,9 @@ static void setup() {
static void init_globals() { static void init_globals() {
track_number = 1; track_number = 1;
cluster_helper = NULL; cluster_helper = NULL;
kax_seekhead = NULL; kax_sh_main = NULL;
kax_seekhead_void = NULL; kax_sh_cues = NULL;
kax_sh_void = NULL;
video_fps = -1.0; video_fps = -1.0;
default_tracks[0] = 0; default_tracks[0] = 0;
default_tracks[1] = 0; default_tracks[1] = 0;
@ -1578,7 +1568,7 @@ static void cleanup() {
// }}} // }}}
// {{{ output file creation and finishing // {{{ FUNCTIONs create_output_name()/file(), finish_file()
// Transform the output filename and insert the current file number. // Transform the output filename and insert the current file number.
// Rules and search order: // Rules and search order:
@ -1720,7 +1710,6 @@ void finish_file() {
int i; int i;
KaxChapters *chapters_here; KaxChapters *chapters_here;
int64_t start, end, offset; int64_t start, end, offset;
KaxSeekHead *emerg_seek_head = NULL;
// Render the cues. // Render the cues.
if (write_cues && cue_writing_requested) { if (write_cues && cue_writing_requested) {
@ -1756,6 +1745,13 @@ void finish_file() {
} else } else
chapters_here = NULL; chapters_here = NULL;
// Render the meta seek information with the cues
if (write_meta_seek_for_clusters && (kax_sh_cues->ListSize() > 0)) {
kax_sh_cues->UpdateSize();
kax_sh_cues->Render(*out);
kax_sh_main->IndexThis(*kax_sh_cues, *kax_segment);
}
// Render the tags if we have some. // Render the tags if we have some.
if (kax_tags != NULL) { if (kax_tags != NULL) {
kax_tags->UpdateSize(); kax_tags->UpdateSize();
@ -1763,53 +1759,31 @@ void finish_file() {
} }
// Write meta seek information if it is not disabled. // Write meta seek information if it is not disabled.
if (write_meta_seek) { if (cue_writing_requested)
emerg_seek_head = new KaxSeekHead(); kax_sh_main->IndexThis(*kax_cues, *kax_segment);
if (write_cues && cue_writing_requested) { if (kax_tags != NULL)
kax_seekhead->IndexThis(*kax_cues, *kax_segment); kax_sh_main->IndexThis(*kax_tags, *kax_segment);
emerg_seek_head->IndexThis(*kax_cues, *kax_segment);
}
if (kax_tags != NULL) {
kax_seekhead->IndexThis(*kax_tags, *kax_segment);
emerg_seek_head->IndexThis(*kax_tags, *kax_segment);
}
if (chapters_here != NULL) { if (chapters_here != NULL) {
kax_seekhead->IndexThis(*chapters_here, *kax_segment); kax_sh_main->IndexThis(*chapters_here, *kax_segment);
emerg_seek_head->IndexThis(*chapters_here, *kax_segment);
delete chapters_here; delete chapters_here;
} else if ((pass == 0) && (kax_chapters != NULL)) { } else if ((pass == 0) && (kax_chapters != NULL))
kax_seekhead->IndexThis(*kax_chapters, *kax_segment); kax_sh_main->IndexThis(*kax_chapters, *kax_segment);
emerg_seek_head->IndexThis(*kax_chapters, *kax_segment);
}
if (kax_as != NULL) { if (kax_as != NULL) {
kax_seekhead->IndexThis(*kax_as, *kax_segment); kax_sh_main->IndexThis(*kax_as, *kax_segment);
emerg_seek_head->IndexThis(*kax_as, *kax_segment);
delete kax_as; delete kax_as;
kax_as = NULL; kax_as = NULL;
} }
if (kax_seekhead->ListSize() > 0) if (kax_sh_main->ListSize() > 0) {
kax_seekhead->UpdateSize(); kax_sh_main->UpdateSize();
if (kax_seekhead_void->ReplaceWith(*kax_seekhead, *out, true) == 0) { if (kax_sh_void->ReplaceWith(*kax_sh_main, *out, true) == 0)
mxwarn("Could not update the meta seek information " mxwarn("This should REALLY not have happened. The space reserved for "
"with all cluster entries as the space reserved for them was " "the first meta seek element was too small. Size needed: %lld. "
"too small. This is NOT fatal! The resulting file will be " "Please contact Moritz Bunkus at moritz@bunkus.org.\n",
"fine. All important elements (attachments, chapters, cues, " kax_sh_main->ElementSize());
"tags) are still indexed in the meta seek. If you really want "
"to have all clusters indexed in the meta seek, then re-run "
"mkvmerge with the additional parameters '--meta-seek-size "
"%lld'.\n", kax_seekhead->ElementSize() + 100);
if (write_cues && cue_writing_requested)
if (emerg_seek_head->ListSize() > 0) {
emerg_seek_head->UpdateSize();
kax_seekhead_void->ReplaceWith(*emerg_seek_head, *out, true);
}
}
} }
// Set the correct size for the segment. // Set the correct size for the segment.
@ -1821,12 +1795,10 @@ void finish_file() {
delete out; delete out;
delete kax_segment; delete kax_segment;
delete kax_cues; delete kax_cues;
if (write_meta_seek) { delete kax_sh_void;
delete kax_seekhead_void; delete kax_sh_main;
delete kax_seekhead; if (kax_sh_cues != NULL)
} delete kax_sh_cues;
if (emerg_seek_head != NULL)
delete emerg_seek_head;
for (i = 0; i < packetizers.size(); i++) for (i = 0; i < packetizers.size(); i++)
packetizers[i]->packetizer->reset();; packetizers[i]->packetizer->reset();;

View File

@ -41,7 +41,7 @@ extern KaxSegment *kax_segment;
extern KaxTracks *kax_tracks; extern KaxTracks *kax_tracks;
extern KaxTrackEntry *kax_last_entry; extern KaxTrackEntry *kax_last_entry;
extern KaxCues *kax_cues; extern KaxCues *kax_cues;
extern KaxSeekHead *kax_seekhead; extern KaxSeekHead *kax_sh_main, *kax_sh_cues;
extern int track_number; extern int track_number;
extern int64_t tags_size; extern int64_t tags_size;