[Matroska-devel] Tagging MKV files
moritz at bunkus.org
Thu Aug 16 09:46:18 CEST 2012
On Wed, Aug 15, 2012 at 11:27 PM, Dan Hinsley <danhi at cox.net> wrote:
> So, I’m working on a library to allow tagging of MKV files and I
> have a question. What I’d like to do is write all the tags at the
> end of the file, so that I don’t have to rewrite the entire file.
> But it looks like I have to update the SeekPosition to point to the
> new location of the tags.
That is correct.
> The problem is that this will increase the number of bytes to
> specify the offset, and since there doesn’t appear to be any padding
> in this section (I’m using the cover_art.mkv test file), that
> prevents me from just updating this.
This is also correct.
> And even if I rewrite the entire file, calculating the offsets is
> tough because the offset is going to depend on the size of the
> SeekPosition lengths, which depends on the offset. Am I missing
> something obvious here?
There are three things that help us in such cases:
1. File layout is flexible. You can put tags in front of the clusters,
at the very end etc. This applies to MetaSeek elements as
well. Most parsers will parse elements linearly from the start up
to the first cluster. Therefore if there's a MetaSeek element
located before the first cluster then a parser should be able to
find all level 1 elements.
2. MetaSeek elements can index other MetaSeek elements -- just be
careful not to build loops. Most parsers protect themselves from
such loops, but you never know ;)
3. You can reserve space with EbmlVoid elements. This are simple
placeholders that are skipped completely by parsers. EbmlVoid
elements are used by mkvmerge in order to reserve some space after
certain important elements like track headers -- in case you want
to modify the track headers later on without having to remux the
whole file. EbmlVoid elements can also be used to overwrite
existing elements completely.
For example. Let's assume you have a file that doesn't contain ANY
tags but a MetaSeek entry at the start of the file which indexes four
level 1 elements (segment info, track headers, chapters and
cues). There's no space left after that first MetaSeek (let's call
this one "MS front") element.
In such cases you could:
1. Create a new EbmlVoid element at the end of the file for storing a
new MetaSeek element (called "MS back") there later. Reserve enough
space in this EbmlVoid element so that it can include all four
entries from "MS front" along with a fifth one for the tags we're
about to write in a moment.
2. Write the tags at the very end of the file.
3. Overwrite the EbmlVoid element from 1. with the new "MS back"
including the pointers to the five level 1 elements discussed in 1.
4. Overwrite the old MetaSeek entry ("MS front") with a much smaller
MetaSeek entry (let's call that one "MS front (new)") that only
references "MS back" (down from 4 to 1 indexed elements means it
will definitely fit into the space occupied by the former "MS
5. Overwrite the space freed up by shrinking "MS front" into "MS front
(new)" with a small EbmlVoid element.
MKVToolNix contains (pretty complex) code that uses all of these
techniques so that functions like mmg's header editor and the whole of
mkvpropedit do not have to re-write the whole file.
It's rather well documented (for my code at least). The entry point
into this class (from the application's view) is the
Yes, it is highly complicated. I know.
> Also (not that it matters for me at the moment) how are the Seek
> UID’s determined?
There are no elements called SeekUID (UID = unique ID), only SeekID. A
SeekID contains the ID of the level 1 element this MetaSeek entry
refers to, e.g. 0x1549A966 for the segment info element.
> Also, is there a forum anywhere for developers working to
> create/play/modify MKV files?
This mailing list is mostly it.
More information about the Matroska-devel