[Matroska-devel] Clarification on CueRelativePosition

Moritz Bunkus moritz at bunkus.org
Fri Jul 19 09:01:27 CEST 2013


Hey,

On Fri, Jul 19, 2013 at 3:45 AM, Bernie Habermeier <bernt at wulfram.com> wrote:

> The relative position of the referenced block inside the cluster with 0
> being the first possible position for an element inside that cluster.

"block" references the Matroska element containing the actual
block/frame/field. This can be either a BlockGroup or a SimpleBlock
element (or some hypothetical other block structure we might invent in
the future).

Example (partial output of mkvinfo) for a file with a video track (track
number 1), an audio track (2, not shown here) and a subtitle track
(track 3):

|+ Cluster at 212216
| + Cluster timecode: 3.545s at 212148
| + SimpleBlock (key, track number 1, 1 frame(s), timecode 3.545s =
00:00:03.545) at 212152
|  + Frame with size 7315
...
|+ Cluster at 212216
| + Cluster timecode: 3.545s at 212223
...
| + Block group at 282677
|  + Block (track number 3, 1 frame(s), timecode 4.700s =
00:00:04.700) at 282679
...
| + Cue point at 3970367
|  + Cue time: 3.545s at 3970369
|  + Cue track positions at 3970373
|   + Cue track: 1 at 3970375
|   + Cue cluster position: 212164 at 3970378
|   + Cue relative position: 4 at 3970383
| + Cue point at 3970386
|  + Cue time: 4.700s at 3970388
|  + Cue track positions at 3970392
|   + Cue track: 3 at 3970394
|   + Cue cluster position: 212164 at 3970397
|   + Cue relative position: 70456 at 3970402
|   + Cue duration: 00:00:02.036000000 at 3970407

The first cue point references a SimpleBlock, the second one a
BlockGroup.

> But the Cluster contains a BlockGroup, which in turn contains a Block.  To
> really make use of a Block, you'd need the BlockGroup, given that the
> BlockGroup may contain information vital to the use of the Block itself,
> such as the BlockDuration.

That's exactly what CueRelativePosition points to.

Keep in mind how positions are calculated:

- CueRelativePosition is relative to the cluster's data start position
- CueClusterPosition in turn is relative to the segment's data start
  position

As you've copy & pasted...

> with 0 being the first possible position for an element inside that
> cluster

...the data start position 0 is the first possible position for any
Matroska child element inside its parent.

The segment data position is: segment EBML ID position + segment EBML ID
size + size of the "size" field, which might e.g. be

+ Segment, size 3971064 at 40
|+ Seek head at 52

40 + 4 (number of bytes in the segment EBML ID) + 8 (the "size" field of
a segment is often set to the maximum size possible which means 8 bytes;
mkvinfo does not explicitly state the length of the "size" field). So
the segment data start position is 52.

Similar for a cluster. From the example above:

|+ Cluster at 212216
...
|+ Cluster at 334657

Cluster data start position = cluster EBML ID position (212216) +
cluster EBML ID size (4) + size of the "size" field (which can be
calculated in my example above as the difference between the next
position, this position and the size of the EBML ID field: 334657 -
212216 - 4 = 122437; this value can be coded in 3 bytes, so that's the
size of the cluster's 'size' field.

(Note: the way I've calculated it is not 100% correct -- but for our
example the correct way would yield the same result, and you don't have
to calculate this yourself as you know the length of the 'size' field as
soon as you've read the element from the disk anyway.)

So we have our cluster data start position = 212216 + 4 + 3 =
212223. Let's compare this theoretical calculation with actual content,
namely the first child element output by mkvinfo for that cluster:

| + Cluster timecode: 3.545s at 212223

All is good.

Let's continue our calculation. We're looking at the first cue point
from the example above:

| + Cue point at 3970367
|  + Cue time: 3.545s at 3970369
|  + Cue track positions at 3970373
|   + Cue track: 1 at 3970375
|   + Cue cluster position: 212164 at 3970378
|   + Cue relative position: 4 at 3970383

CueRelativePosition = 4. Meaning 4 bytes into the cluster, and the
cluster is at 212164 inside the segment. This last part is important;
remember what I said above how those elements are calculated.

So what a player reading this cue point has to calculate is as follows:

absolute block start position = segment data start position + cue
cluster position + cluster ID size (4) + cluster "size" size + cue
relative position

Now in practical terms a player would do this:

- At the beginning: read the header data, read the cues table
- When a user wants to seek:
  * Look up corresponding cue point
  * Seek to absolute cluster position indicated by CueClusterPosition /
    segment data start position
  * Read cluster header
  * Read first child element (almost always the cluster timecode)
  * Calculate wanted absolute block position with the formula above,
    seek to it, read it, play

> It was my impression that the order of the child elements of a Cluster
> is not specific,

It is: http://www.matroska.org/technical/order/index.html Quoting the
section about the cluster timecode:

> As each Block+BlockGroup/SimpleBlock in a Cluster needs the Cluster
> timecode, the Cluster Timecode must be the first element in the
> Cluster.

> Also, the second half of the description is vague:

No, it is not.

> with 0 being the first possible position for an element inside that
> cluster

0 is the first possible position for any Matroska element inside that
cluster. Combine that with the order specs from above (cluster timecode
must be the first element inside a cluster) and you'll see that
CueRelativePosition can never be 0.

> 1) if 0 is the first possible position for the block in the cluster,

The spec say that 0 is the first possible position for an ELEMENT in the
cluster. The first technically possible position. That can be any
Matroska element. The specs pose the additional restriction that the
first element must be a timecode.

> an easier implementation would be to simply force the start of a new
> Cluster.

Of course you can force a new cluster before each and every key
frame. The drawback is higher overhead.

Kind regards,
mosu


More information about the Matroska-devel mailing list