OggText
This page describes a generic media mapping (i.e. rules for multiplexing) of "text codecs" into Ogg.
Text codecs are sequences of text chunks that have a timing relationship to an audio or video stream.
Prominent examples of such text codecs are:
- CC: closed captions (for the deaf)
- SUB: subtitles
- TAD: textual audio descriptions (for the blind)
- KTV: karaoke
- TIK: ticker text
- AR: active regions
- NB: metadata & semantic annotations
- TRX: transcripts / scripts
- LRC: lyrics
There are a multitude of existing open formats for specifying some of these - in particular for specifying closed captions and subtitles. They come in different complexities - some being simply a time stamp and a text, others providing for extensive styling, graphics, and motion of the text blocks over time.
No matter what the differences - when multiplexing such codecs into Ogg, they all have to solve the same problems. This is why this page describes generically how to multiplex text codecs into Ogg.
Codecs with existing mappings are:
- CMML
- Kate
Bitstream Format
Ogg codecs consist of a sequence of header packets and data packets.
Header packets contain information necessary to identify and set up the codec. Data packets contain the actual codec data, in this case the time-aligned text.
When these packets are multiplexed into Ogg, they are mapped to Ogg pages. For text codecs, there is a sequence of header pages, a sequence of data pages, and an EOS page, which finishes the stream. The pages have to be ordered non-decreasing with time. No data can come after the EOS page.
Header pages
Header packets are a sequence of:
- one ident header, which identifies the codec
- one (optional) vorbis-comment header
- one or more secondary header packets that are codec specific
Any text codec has to map its header information into these header packets.
Header packets must appear in order and all header packets must appear before any data packet. Each header packet is encapsulated in one Ogg page.
The format of the ident header
0 1 2 3 | 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1| Byte +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | packtype | Identifier char[3]: 'txt' | 0-3 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Identifier char[4]: codec identifier | 4-7 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Version major | Version minor | 8-11 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Each text codec page starts with a one byte type, just like this ident header. Similar to Kate, a type with the MSB set (eg, between 0x80 and 0xff) indicates a header packet, while a type with the MSB cleared (eg, between 0x00 and 0x7f) indicates a data packet. We use the packtype field in order to distinguish between the different header and data packet types.
The following packtypes are distinguished:
- headers:
- 0x80 ID header (BOS page)
- 0x81 vorbis-comment header (optional)
- 0x82-0xff secondary header pages of the codec in an order defined by the codec (optional)
- data:
- 0x00 text data (including optional motions and overrides)
- 0x01 keepalive
- 0x7f end page (EOS page)
As per the Ogg specification, granule positions of pages must be non decreasing within the stream. Header pages have granule position 0.
In all header pages, the packtype is followed by the text codec magic from byte offset 1 to byte offset 3 ("txt"). The succeeding four bytes are to be used by the text codec to identify itself.
For example, when CMML moves to using this generic text codec mapping approach rather than its own, the first eight bytes of the ident header will identify the track as a CMML codec track through a signature string of "\200txtCMML".
Or as another example take a signature string of "\200txtsrt\0" which will identify srt being mapped.
Version major & minor are fields that are used by the text codec to define the version of its mapping.
The format of the Skeleton Fisbone
Text codecs are required to be used in conjunction with Ogg Skeleton.
The following fields are defined in the Fisbone header for a text codec:
- granulerate numerator & denominator
- granuleshift
- number of header pages/packets
- Content-Type message header field, e.g. text/x-cmml, text/x-srt according to rfc2045
- if no charset parameter is given, it defaults to UTF-8
- directionality of this text is implicitly given by the charset
- Content-Language, e.g. en-AU, de-DE according to rfc4646 and http://www.iana.org/assignments/language-tags
- Text-Type, e.g. CC, SUB, etc (see abbreviations as defined above)
The default granule rate for text codecs is: 1/1000.
The granule position format
Text codecs are discontinuous codecs. The data packets are placed into the Ogg stream at the time where the data starts. Their duration is given inside the data packet. Thus, when seeking to a specific time offset in a Ogg file that has a text codec, it can be quite difficult to determine what text data should still be on screen.
The solution is to seek forward to the next text codec page, which then has information on the first text codec page that is still active. Then you can seek back to this page and seek forward to the previous page to gather all the pages that are still active.
For this, the granulepos is being segmented into two parts, where one part signifies the insertion time of the current page, and the other part contains the granulepos of the first page with text codec data that is still active.
+-----------------+-----------------+ | granulepos prev | current time | +-----------------+-----------------+
The size of this segmentation is stored in the 1 Byte integer granuleshift number of the Skeleton Fisbone. It describes how many of the lower bits to use for the partitioning. The upper bits then still signify a time-continuous granule position for a directly decodable and presentable data granule. The lower bits allow for specification of the granule position of a previous still active text codec page.
The default granule shift used for text codecs is 32, which halfs the granule position to allow for the backwards pointer.
Data pages
Data packets are generally the text data that is encapsulated into Ogg at a specific time.
For text codecs, each data packet is mapped onto a single Ogg data page with all its content. This is possible because generally text codec packets are rather small. The insertion time is encoded in the granule_pos of the Ogg page.
EOS page
The EOS page ends a text codec stream. It is an empty packet because all the information of the codec is encapsulated in the earlier data pages.