[Matroska-devel] SimpleBlock payload header size: 4 or 6 bytes?

Moritz Bunkus moritz at bunkus.org
Mon Dec 30 20:20:04 CET 2013


Hey,

*sigh* Sent too early.

On Mon, Dec 30, 2013 at 7:56 PM, Daniel Neugebauer
<mailinglists at energiequant.de> wrote:

> The specification says: (see
> http://www.matroska.org/technical/specs/index.html#simpleblock_structure )
>
> "Size = 1 + (1-8) + 4 + (4 + (4)) octets. So from 6 to 21 octets."

The first 1 is the SimpleBlock's EBML ID.

1-8 is the total size of the SimpleBlock element; encoded as a
variable-length unsigned integer.

The 4 is not quite correct, they can be a lot more:
- 1-8 bytes for the track number. Most files use track numbers
starting at 1 and will only ever need 1 byte here, therefore the 1 is
mostly correct.
- 2 bytes timecode relative to the cluster timecode (signed 16bit
integer, always two bytes)
- 1 byte flags

The bytes in the parenthesis only apply if lacing is used.

> It's obvious that bytes 0..3 are mandatory, but what about 4..5?

My guess is that you're forgetting the EBML ID and element length.

> I discovered that because FFMPEG appears to expect a 4 byte header,

Yes, without the EBML ID and element length. The 1-8, as explained
above, is a variablen-length encoded unsigned integer which can be
anywhere between those values. So you need at LEAST six bytes for the
whole SimpleBlock element including its header (EBML ID and element
length).

You seem to think that the 6 bytes size refers to the content within
the SimpleBlock element (starting behind its element length), but
that's not the case.

> Who misread the specification, is it me or FFMPEG?

My guess would be: you. Otherwise FFMPEG would choke on each and every
file that mkvmerge produces (because they all use SimpleBlock
structures), but FFMPEG doesn't.

> unsigned long long len = timedPacket->dataLength + 4;

This is already wrong as track numbers aren't fixed-length integers of
1 byte but possibly more. Yes, for most files this will work, but as
soon as you have anything more than 128 tracks (or want to use track
numbers >= 128) you're screwed. Better get it right the first time
around ;)

>     out[0] = 0b10000000 | (trackNumber & 0b01111111); // track number
> encoded like EBML data size, thus prefixed MSB 1 for 7-bit values

Ah, you're aware of this. Anyway, it'll put a severe limitation into
your library that will be hard to track down for users of your
library.

> out[3] = 0b10000001; // keyframe, not invisible, no lacing, discardable
> //out[4] = 0x00; // no frames in lace
> //out[5] = 0b1000000; // lace size (EBML-encoded 0 because we use none)

If you don't signal lacing then you definitely need to write out
neither the number of frames in the lace nor the lace size.

Kind regards,
mosu


More information about the Matroska-devel mailing list