MCF logo

MCF specification, technical part/track-types

This is subpage of MCF-specification.

Progress: 93%

Short list

Track-types
IDNameDescription
0x00ControlControl-codes for menus and other stuff
0x01VideoRectangle-shaped non-transparent pictures aka video
0x02AudioAnything you can hear
0x03AVAudio and video in same track, used by DV
0x04Multi-track audioMore than one audio-track in one stream
0x10TitlesOverlay-pictures, displayed over video
0x11SubtitlesText-subtitles. One track contains one language and only one track can be active (player-side configuration)
0xFFCustomFor really custom extensions, try to avoid using this

Most offsets are relative to the start of the Track Entry.

Track-type 0x00: Control

Work in progress.

Used for DVD-like menusystems, switching tracks automatically, etc.. This can be abused, so there should be an option in all players for disabling control-codes. Your UI must be more or less multitasking - control-track might get stuck in an infinite loop, but this must not affect player's user-interface. Content in MCF-files should never steal focus from other parts of the UI, or other applications, either. Menues can be used with three buttons - up, down and enter. Addiotionally we support left/right, or alternatively some kind of pointing-device (mouse).

Oh, if you feel that you can't support menues in your player, feel free to drop the feature - no support is better than half support. Other controls of TOP-atom shouldn't be too difficult to implement.

Menu can display two alpha-equiped PNGs simultaneusly, blended with each other and then blended with other tracks (usually video, sometimes subtitles). The blending order depends on the order of Track Entries - Tracks with smaller Track Numbers are bottom.

Unlike elsewhere, here we have hierarchical structure. This allows interleaving PNG-images with commands, looping structures, etc. It also wastes some space, but because control-blocks are rare, this is acceptable. Developers familiar with QuickTime will feel like home when working with these :) ..

Structure of an atom
OffsetPlayerDescription
0x00mustSize of data in this atom (uint32)
0x04mustCommand (4 octets)
0x08-mustData

Control-block may contain one or more TOP-atoms. Keep reading more atoms you reach the size of the block. If a command is unknown, the atom should be skipped (and if there is no else-command right after the failing atom, a warning passed to the user). Currently we don't have any commands reserved for user-extensions - and we probably won't ever have.

When there are atoms inside an atom, keep reading those sub-atoms until you reach the size of data in current atom.

Atoms which are too big the fit in the space reserved for them should result to giving an error and aborting. 0-sized atoms are OK - they just don't contain any data.

Command instructs the parser of what data the atom contains - it can be pure data for the command, or a set of atoms, or both.

Commands for TOP-atom
CommandNameData contents
"Jump"Seek to timecodeTimecode (uint32)
"IfEd"If editionEdition number (uint8)
TOP-atom(s)
"ChEd"Change editionEdition number (uint8)
"Enab"Enable trackTrack number (uint8)
Sub-track (0 = all) (uint8)
"Disa"Disable trackTrack number (uint8)
Sub-track (0 = all) (uint8)
"Quit"Quit playingShould stop the movie; player may or may not terminate itself
"Menu"Define a menuMENU-atom(s)
"AltO"Alternative optionTOP-atom(s)
"Link"Use another TOP-atomPosition (relative to start of this block) of the TOP-atom to use (uint32)

If edition: only executes its TOP-atom(s) if the edition given as parameter is selected. Used for jumping, so that edits can be non-linear in the original material.

Alternative option: if command supplied for previous atom wasn't supported, execute this one instead. Currently the only sensible use for this is after a TOP-atom using Menu-command - to define a jump to start of the actual movie, skipping menu-graphics.

If you switch tracks, disable the old track first and then enable the new one. Sub-tracks are only used for audio-tracks containing multiple languages, but this might change in future. For tracks without sub-tracks, set it to 0.

It is recommended to do all Jumping at silent fade-downs (when the screen is black and there is no audio), so that the pause caused by seeking isn't too noticeable. Good players should be able to cache, so that there is no pause, but you can't rely on that.

Link-command can be used for moving back from deeper menu-levels.

Commands for MENU-atom
CommandNameData contents
"Stop"Pause-
"Loop"LoopTime (duration), in milliseconds (uint8)
"Pict"Display pictureSize (including titles-header) (uint32)
Flags (bits 7-5 defined below, 4-0 from titles-header)
Size of titles-header (consult titles-track specs for correct value) (uint16)
Block of type 0x10 (titles)
"Tout"TimeoutTimeout, in milliseconds (uint32)
TOP-atom(s) (what to do when timeout occurs)
"Area"Define entry of menuAREA-atom(s)

Pause-command pauses playback (a still-screen menu). Loop is alternative - it continues playback normally, but loops back to the block right after this control-block, when the time passes. Blocks with timecode exactly at the end of a loop won't be played. Blocks with the same timecode as this block-entry, but AFTER this block, will get played in a loop. If neither of those commands (pause or loop) is defined, playback continues normally to the end of movie or some other event. If user hasn't touched any controls for timeout milliseconds, the menu is disabled and player seeks to the position defined. Defining both pause and loop is illegal and should lead to a warning and discarding this control-block.

AREA-atom defines a single menu-entry (area it uses on screen, mouseover-pics, what to do when it gets selected, ..).

Commands for AREA-atom
CommandNameData contents
"Shap"Define areaSHAPE-atom(s)
"Left"-Number of the AREA to left from this one (uint8)
"Hili"HilightHILI-atom(s)
"Acti"Action on selectTOP-atom(s)

Areas are given sequential numbers, starting from 1, in defining-order. Each control-block has distinct numbering. Left-command is used for defining where to jump when left cursor-key is pressed while hilight is on this area.

Shapes are defined to allow making selections with mouse or other pointing-devices. Shapes aren't drawn on screen.

Commands for SHAPE-atom
CommandNameData contents
"Rect"RectangularX1, Y1, X2, Y2 (uint16, uint16, uint16, uint16)
"Poly"PolygonX1, Y1; X2, Y2; .. (number of points determined by the size of atom) (uint16, uint16)
"Circ"CircleX and Y of center (uint16, uint16)
Radius (uint16)

Coordinates are "percentages" of canvas height and width - 0 = left/top, 0xFFFF = right/bottom. Radius is percentage of canvas diameter (0xFFFF = sqrt(width^2 + height^2)).

Hilight activates when mouse is over the area defined by SHAPE-atoms, or when cursor-keys are used to select the item.

Commands for HILI-atom
CommandNameData contents
"Pict"Display pictureSize (including titles-header) (uint32)
Size of titles-header (consult titles-track specs for correct value) (uint16)
Flags (bits 7-3 defined below, 4-0 from titles-header)
Block of type 0x10 (titles)
"Soun"Play a soundNot implemented yet
"Link"Use media from another HILIPosition of the HILI-atom to use, relative to start of this control-block (uint32)

When hilight is moved out, the picture used for hilighting must be cleared (but menu-picture, if any, should stay).

Flags in Block Header
BitPlayerDescription
7mustTop - for HILI-atom's Pict-command (not meaningful for MENU-atom's Pict-command)
6-5-Reserved, set to 0
4-0-From titles-track

If top-flag is enabled, the image is painted on top of the menu-image (if any). Otherwise it goes under the menu-image.

There is a HTML-diagram (a draft) of a menusystem: complex menu

Work in progress: this is likely to change!

Track-type 0x01: Video

Track-type specific setting in Track Entry @0x180
OffsetPlayerDescription
0x180-
Flags
BitPlayerDescription
7mustInterlaced (fields are stored separately, but in same stream)
6mustStereo-3D (if you don't know what it is, you don't have it)
5-4mustIf stereo: 00=unknown/other (reserved), 01=right eye, 10=left eye, 11=both
2-0-Reserved
0x181-Reserved (set to 0x00)
0x182mustX-dimension (uint16) If unknown, should be set to 0
0x184mustY-dimension (uint16) If unknown, should be set to 0
0x186must Aspect-ratio, X:1000 (uint16) =width of the video-window if the height is 1000 units. Examples:
  • 4:3 = 1.333:1 -> 1333
  • 16:9 = 1.778:1 -> 1778
  • 2.35:1 = 2.350:1 -> 2350
This can range from 1 (0.001:1) to 65535 (65.535:1) .. This should be enough for everybody. 0 is not allowed.
0x188mustFourCC (for compatibility, check AVI-specs for more info, 0x00000000 if not available)
0x18Cfeat.Colorspace (4 octets, same as in AVI)
0x190feat.GUID subtype, used by M$ DirectShow codecs (16 octets, fill with 0x00 if not available)
0x1A0mustGamma value (uint8)
0x1A1--Reserved (fill with 0x00)

Dimensions (0x182-0x186) (most people call it resolution) are not always present: there can vector/wave formats, where compression doesn't work in per-pixel basis, so the actual decompression resolution must be negotiated with the codec. For interlaced video: field, not full frame, dimensions are used.

Constant framerate value should only be used for converting MCF to AVI or other non-variable framerate format. The format it is stored here might change (if you want it to change, please let me know). One converting to AVI should check that CFR-flag is set and that the "nanoseconds per frame"-value is valid. Anyway, when writing MCF, please include this field with any CBR-material. Dropped frames are allowed and converter should use timecodes to find out when one occurs.

Gamma-field contains the actual gamma-value multiplied by 100; 100 means 1.00 gamma, 45 means 0.45 gamma. Video encoded on PC usually has a gamma of 0.45 (CRT-monitors usually have a gamma of 2.2). Note: 0.45*2.2=1. Gamma correction is done seperately for each channel of R/G/B. The formula is: output = input^(file_gamma * display_gamma). Display-gamma is player-side option. On PC you should default to 2.2, but let user configure it. If file_gamma * display_gamma is very close to 1.0, you can optimize by not doing gamma-correction. More info about gamma here: http://libpng.org/pub/png/spec/PNG-GammaAppendix.html

We don't have color-correction yet - if you think that it should already be defined (it should be fast enough to calculate for each pixel!), drop an e-mail with your suggestions. Optional way would be letting hardware (display-card) do the correction.

For interlaced video: If bit 6 in FLAGS of a Block Header is set, the block contains EVEN scanlines (odd scanlines otherwise).

Track-type 0x02: Audio

Some formats (Vorbis, for example) can contain up to 256 channels in one stream. One audio-track of MCF contains one stream, but may contain many languages, each with many channels (2 for stereo, ..). We require that each language has same number of channels and same properties (samplerate, bitdepth, ..) for each channel.

Track-type specific setting in Track Entry @0x180
OffsetPlayerDescription
0x180mustSamplerate, in mHz (uint32, 0=unknown/variable)
0x184mustBitdepth (uint8) (not required for all audio-formats)
0x185-
Flags
BitPlayerDescription
7feat.Digital (S/PDIF) (Dolby Digital, DTS or something similar)
6feat.Secondary track (this track should be mixed with the selected primary audio)
5-0-Reserved (set to 0)
0x186mustNumber of subtracks (languages) in this track (uint8)
0x187mustNumber of PCM audio channels per subtrack (uint8)
0x188mustAVI-compatibility: wFormatTag (from waveformatex) (0x0000 if not available) (uint16)
0x190mustChannel positioning (uint32)
0x190--Reserved (fill with 0x00)

Set the number of PCM-channels to 0, if not applicable. Number of subtracks cannot be 0. If you only have one, set it to 1. If you are uncertain about something, ask it on the MCF-Devel mailing-list (at SourceForge).

If secondary track flag is set, selecting this track shouldn't deselect any primary-track, but mix sounds of those together.

Each language must be described in Codec Header, in a chunk called SubTrack Entry. The actual Codec Header, if any, comes right after these subTrack Entries.

SubTrack Entry (80 octets)
OffsetPlayerDescription
0x00mustName (language) of the subtrack (64 octets)
0x40infoISRC-code (http://www.riaa.org/Audio-Standards-3.cfm) (fill with 0x00 if not available) (12 octets ASCII)
0x4C--Reserved (fill with 0x00)

The normal situation is that you have one subtrack, with two channels.

Track-type 0x03: AV

I need help with this one. Any volunteers? It should be able to contain DV and other formats, which might or might not contain headers in the stream. As stated before, this track contains audio and video compressed together (ie. we can't just demux it nicely).

Track-type 0x10: Titles

Overlay-pictures (PNG) over video. Pictures can have alpha-channel. Try NOT to use this for subtitles.

I am not going to allow any other formats than PNG for this because it is the best alternative for titles and good enough even for photos and it is free. After all, it is much easier to only support one format. Later, when there is another good format (free, lossy, with alpha-support) around, we'll support it too.

Set 0x010 in Track Entry (compression format) to "PNG". Players must ignore titles-tracks with any other values in that field.

Track-type specific settings in Track Entry @0x180
OffsetPlayerDescription
0x180mustSize of titles-header (set to 16) (uint16)
0x182mustCanvas X-size (uint16)
0x184mustCanvas Y-size (uint16)
0x186-
Flags
BitPlayerDescription
7feat.Subtitles: this Titles track is actually used for subtitles
6-0-Reserved (set to 0)
0x187--Reserved (fill with 0x00)

Canvas size only applies when there is no video enabled - if there is video, the canvas will be automatically set to match video. Size is given in pixels, but players and users can override this; only proportions (aspect-ratio) survive. One example of this would be user switching to full-screen: if canvas X-size was 200 and Y-size 100, there will be black bars over and under the canvas (unless she has a monitor with 2:1 aspect-ratio), but it is still sized to full-screen. If no size is defined here (which is the normal case), and there is no video, players should default to 1.778:1 canvas of any size (player-developers do the decision).

Titles Header
OffsetPlayerDescription
0x00mustX1, Y1 (uint16, uint16)
0x04mustX2, Y2 (uint16, uint16)
0x08mustFade-in time in milliseconds (uint16)
0x0AmustFade-out time in milliseconds (uint16)
0x0CmustFlags

The actual image (with PNG-headers) is at size_of_titles-header (ie. right after titles-header).

Fade-in and fade-out adjust transparency linearly from full to none and vice-versa. Set to 0, if not used. Duration is determined by gap-start value at the end of Block. If the Block doesn't start a gap, infinite duration is assumed and fade-out cannot be used.

Coordinates are percentage (per-uint16-age, actually) of canvas - 0=left/top, 0xFFFF=right/bottom. Canvas is normally same size as the video (not same size as the player window).

Flags in Titles Header
BitPlayerDescription
4-3-Reserved, set to 0
2feat.Try to avoid scaling
1feat.Nearest neighbor scaling, instead of highest possible quality (bicubic)
0feat.Free positioning - instead of obeying X1 and Y1, player can freely position this image

Nearest neighbor flag should only be used for images which look better that way, not for reducing CPU-load (which should be in player-side configuration instead, if applicable on the target-platform).

If you have a nice, absolutely sharp, image, which you want to display without scaling, enable "no scaling"-flag, but remember that the size of the image (compared to canvas) might vary. When the flag is enabled, player must calculate requested size (x2-x1, and convert it to number of pixels). n = (req_size + image_width/2)/image_width; n is integer and result of that calculation is always rounded down. Now, if n is 0, scale the image normally to exactly fit requested size. In other case (n >= 1), scale the image by n (each pixel gets duplicated to n2 pixels). NOTE: we only use X-size for computing n; we assume that Y-size is to be scaled with the same factor.

Logo in normal position, in canvas - and in free position, right outside the canvasWhen doing free positioning, player should try to position over some empty space around the canvas and, if that is not possible, obey X1 and Y1. Preferrably players should, when deciding where exactly to put that image, try to get it as close to the coordinates as possible. In the sample-image we have "MCF"-logo in the normal position (on the canvas) and in free position, right outside the canvas. Notice that outside the canvas it is still horizontally aligned to where it would normally be. If it was in the lower part of the canvas instead, free positioning should move it to the black bar below the canvas.

Notes on using this for subtitles: Subtitles for average movie take around 1.4 Mo per language, when done with PNGs (3 colors: transparent, black and white). Same subtitles, when done correctly, in text-form, only take around 80 Ko per language. Also, when using images for subtitles, font, colors, etc. can't be changed by user. It is also worth noting that text-subtitles are much higher quality (anti-aliased scalable vector-fonts (true-type) versus bitmaps). So, don't use graphics for subtitles, okay?

If you still are going to use graphics, make sure you set Subtitles flag, so that players know to treat it as subtitles.

Track-type 0x11: Subtitles

Set 0x010 in Track Entry (compression format) to "INTERNAL". We might also support some kind of compression for this, in which case 0x010 reflects the compression used.

Track-type specific settings in Track Entry @0x180
OffsetPlayerDescription
0x180-
Flags
BitPlayerDescription
7feat.Has "l" instead of "I" or vice-versa, or other similar "looks like"-errors => player should use proper font (so that those errors are not visible)
6-Control-codes disabled (reserved for the future) (set to 0)
5-0-Reserved (set to 0)
0x181mustCharacter-set (currently 0=UTF8) (uint8)
0x182mustSize of the subtitle-header, to allow extensions in future (currently 4) (uint16)
0x184feat.Color #1 (default) (RGB/8-8-8)
0x187feat.Color #2 (RGB/8-8-8)
0x18Afeat.Color #3 (RGB/8-8-8)
0x18Dfeat.Color #4 (RGB/8-8-8)
0x190--Reserved (fill with 0x00)

If a color is set to 0x000000, player default should be used instead. Don't define colors here unless you really want to override users'/players' settings. Note: players should allow overriding colors defined here.

Following is what each subtitle-block contains:

Subtitle Header
OffsetPlayerDescription
0x00mustFlags (1 octet)

Right after the header comes the actual subtitle.

Subtitles stay on screen until the next subtitle comes or file ends, unless a gap is defined (Block Header).

Subtitle should be top-aligned to the bottom of video, if possible (ie. watching wide-screen video on non-ws-monitor). If that is not possible, it should be bottom-aligned to bottom of video, unless bit 6 is enabled, in which case it should be top-aligned to top. User-configuration should be allowed to override this, of course.

Flags in Subtitle Header
BitPlayerDescription
7feat.Black non-transparent background
6feat.Top-align: important stuff in the lower part of video
5feat.Hearing-impaired only (don't display this subtitle for normally hearing people)
4-0-Reserved, set to 0

Normal word-wrapping is performed (except if the subtitle-track is preformatted). Only use non-transparent background when you need to (when there is something bright, which makes reading the subtitle difficult).

NOTE: if subtitle is not positioned on the canvas (ie. it is positioned in the black space below the canvas), top-align-flag can be disregarded.

Effects such as letter-borders and shadows are player-side stuff.

In the subtitle we have control-codes, which start with 0x00 (uint8). UTF8 doesn't use zeroes anywhere: all zeroes are our codes, not UTF8. After the zero there is another uint8, which is the actual command.

Control Codes
CodePreferred colorDescription
0x00-Longer command
0x01#DDDDDDSwitch back to default color
0x02#AAAAFFSwitch to 2nd color
0x03#AAFFAASwitch to 3rd color
0x04#FFAAAASwitch to 4th color
0x05-Enable bold text (usually subtitles are already bold, but this makes it very bold)
0x06-Enable underline
0x07-Enable italics
0x08-Disable underline/bold/italics (reset back to normal text, but doesn't reset color)
0x0A-Force linefeed here

Longer code is two zeroes followed by the number of octets (size) used by parameters, and then one octet for the code + size octets of something.

Long Control Codes
Full CodeDescription
0x00 0x00 0x01 0x4B uint8:time-Karaoke timing.

Players must be able to skip all unknown codes quietly. Example: "Normal subtitle", 0x00, 0x00, 0x07, 0x01, "Example", "Normal subtitle continues". There 0x01 is the action, 0x07 the size of parameters for that action and "Example" (7 octets) the parameter.

If player finds unknown codes, those must be ignored silently. All attributes (colors, bold, etc) reset to defaults on every subtitle.

Only use linefeeds when needed (ie. you want a new line at precise position, not when you want to cut a long line). Automatical word-wrapping will do better job. Don't ever use single attribute for all text of all subtitles.. In example, if you happen to like red color, just configure your player to use red for color 1, instead of using color 4 in your subtitles. If you think that others will also like red with the movie you are encoding, define color #1 in Track Entry to the shade of red you prefer.

Misuse of attributes leads to users disabling attributes in their players (like many have disabled JavaScript in their browsers).

Karaoke

All karaoke timing is based on the total display time of the subtitle. Time (uint8) is a percentage: 255 denotes total display time (100%), 0 denotes no time (0%). The karaoke code affects all the text in front of it.

In the following example, I use syntax [K:time], for human-readability.

[K:15%]This part is read fast[K:35%], and this part is read slowly.[K:85%]

The first code has no charactes in front of it, so it only causes a pause of 15%. All text remains white (default color) during that time. The next code says 35%, which applies to the text in front of it ("This part is read fast"). So, during the time from 15% to 35%, player gradually paints the text red (color #4). When 35% of total time has passed, the first half of it is painted red, and the other half still is white. The last code says 85%. When 85% of time has passed, all text should be red. That leaves a 15% pause until total display time is reached, and the subtitle is removed.

If a player doesn't support karaoke, it will just skip these codes, just like it skips other unknown codes, and the text will stay white for the whole displaying time.

White and red are preferred player-side defaults; different colors can be defined in Track Entry.

Track-type 0xFF: Custom

This is the "clean" way to add something that doesn't exist in current specs into MCF. Hopefully no-one will ever use this, but "just in case". If a custom track is not recognized by the software reading it, it will be skipped (well, the player should still inform user about it).

This track-type has special uses for some of those fixed Track Entry fields:

Special uses for normal Track Entry fields (when track-type=0xFF)
OffsetPlayerDescription
0x010must16 bytes to identify your track. "3DSMAX anim" would be one option. Anyway, select anything you think no-one else will use. There are no standards about these, but 16 bytes should be enough for everybody, right?
0x030infoHuman-readable description of what the track does (64 octets)
0x070infoURL for plugin needed for this track or some info about it (64 octets)
0x0B0infoAnother URL, if available (64 octets)

Because this is really special track, there are no restrictions or standards in usage of that track-type-specific area (which starts at 0x180 in Track Entry). Blocks can naturally contain any data too.

Anyway, try to avoid this at all cost. Instead, contact MCF developers; so that we can add the feature (if it really is usable for someone else too). Even if it isn't usable for others, but you are going to distribute software that uses this track type for something, please let us know about it!