Sunday, March 1, 2009

AVI File Format -Subtitle & Garbage

Subtitles in AVI files

This section explains how to store subtitles in AVI files, so that VSFilter can be used to load and select subtitles.

One subtitle stream is stored in one single chunk. That chunk contains header data, followed by an entire SRT or SSA file. If that file is using UTF-8 encoding, the BOM should be included as well. The header is defined as follows:

char[4]; // 'GAB2'
BYTE 0x00;
WORD 0x02; // unicode
DWORD dwSize_name; // length of stream name in bytes
char name[dwSize_name]; // zero-terminated subtitle stream name encoded in UTF-16
WORD 0x04;DWORD dwSize; // size of SRT/SSA text file
char data[dwSize]; // entire SRT/SSA file

Stream header chunk

typedef struct
{

FOURCC fccType; // "txts"
FOURCC fccHandler; // 00 00 00 00
DWORD dwFlags;
WORD wPriority;
WORD wLanguage;
DWORD dwInitialFrames;
DWORD dwScale;
DWORD dwRate; // dwRate / dwScale == duration in seconds
DWORD dwStart;
DWORD dwLength; // In units above..., should be 1
DWORD dwSuggestedBufferSize;
DWORD dwQuality;
DWORD dwSampleSize; // = 0 -> treated as VBR
RECT rcFrame; // 0, 0, 0, 0

} AVIStreamHeader;

Stream format chunk

This chunk has a size of 0.

Stream name chunk

The strn chunk is ignored by VSlter, so there is no need to read or write it.

Garbage in AVI files

One way to set a delay in AVI files is using the AVIStreamHeader::dwStart value. However, not every player reads this value, so that such files would not properly playon them. Some applications, like VirtualDub and derivates (NanDub, VirtualDubMod) add some data to the beginning of streams to be delayed.

Unfortunately, those applications don't care about the data format, but rather pad with zeros. Those zeros are refered to as 'garbage' in this section. The scope is to explain how to read such files, which requires that the duration of the garbage section be determined.It is of course required that the beginning of the valid data be found, for example in the caseof MP3, AC3 or DTS by looking for frame headers. Formats which don't use frame headers that can be detected easily, like AAC, will result in broken streams if zeros are added to the beginning.

Constant Bitrate

If the bitrate of a stream is constant, the duration of the garbage section is simply garbage_length * data_rate.

Variable Bitrate

In this case, the duration must be retrieved chunk-wise:

The duration of one chunk is roundup (size_of_chunk / strf::nBlockAlign) * duration_per_frame.

Consequently, if the beginning of the valid data is the m-th byte in chunk n, the duration of the garbage section is

sum[i=0..n-1](duration(chunk[i])) + roundup(m/nBlockAlign)

Overhead of AVI files

This section describes how to predict the overhead of an AVI file before muxing. Note: In the case of low overhead AVI files, the wording in this section is not applicable. Basicly, one video/audio frame causes about 8-9 bytes of overhead in low overhead AVI fies.

General

The overhead of AVI files depends on the number of CHUNKs in the file. Other structures has only very little influence on the total overhead. Each CHUNK causes the following amount of overhead:

• 8 Bytes chunk header (all avi types)

• 16 Bytes for entry in Legacy Index (AVI 1.0 and the RIFF-AVI-List of Hybride files)

• 8 Bytes for entry in Standard Index(Open-DML)

That means, each CHUNK causes an amount of overhead of 16, 24 or 32 bytes.

Getting number of CHUNKS

Video

The easier part is the video stream: Each video frame takes one CHUNK.

Audio

The number of chunks for an audio stream depends on its format and packing. For specific formats, where very special packing is required or considered normal, the overhead can be calculated easily from the settings. Otherwise, more precise information on the muxing settings is needed.

Examples

Video: 3 hours, 25 fps ( = 3,600,000 / 40ms = 90,000 frames per hour)

Audio: 2x MP3-VBR (with 1 frame per CHUNK and 24 ms per frame)

Audio: 2x AC3 (with 4 frames per CHUNK and 32ms per frame)

-> Video: 270,000 CHUNKs
-> Audio: 2*150,000 + 2*3*28,125 = 468,750 CHUNKs
-> Sum = 738,750 CHUNKs

No comments:

Post a Comment