Vividas VIV

From MultimediaWiki
Jump to navigation Jump to search

Overview

A Vividas file consists of one or more "tracks", each comprising one or more audio and/or video elementary streams.

Encryption

All data relating to a track is encoded using a 32-bit key given in obfuscated form in the file header.

Keys

The header contains, for each track, a 187-byte block, 32 bits of which form the key. The following C function will extract a key from such a block.

const unsigned short keybits[32] = {
     163,  416,  893,   82,  223,  572, 1137,  430,
     659, 1104,   13,  626,  695,  972, 1465,  686,
     843, 1216,  317, 1122, 1383,   92,  513, 1158,
    1243,   48,  573, 1306, 1495,  396, 1009,  350,
};

uint32_t decode_key(uint8_t *buf)
{
    uint32_t key = 0;
    int i;

    for (i = 0; i < 32; i++) {
        unsigned p = keybits[i];
        key |= !!(buf[p>>3] & (1<<(p&7))) << i;
    }

    return key;
}

Decoding

To decode a data block with a given key, this C function can be used:

void decode(uint32_t *d, unsigned size, uint32_t key)
{
    uint32_t k = key;

    size >>= 2;

    while (size--) {
        *d++ ^= k;
        k += key;
    }
}

File Format

Data Types

The following data types are used in the syntax description below.

u(n)
n-byte unsigned little endian integer.
v
Variable-length integer, the 7 low bits of each byte being data bits, and the MSB indicating whether more bytes follow.
a(n)
n-byte ASCII string.
z
NUL-terminated ASCII string.
d(n)
n bytes unspecified data.
'x'
Literal byte with hex value x.
"s"
Literal ASCII string.

Overall Structure

vividas_file() {
    signature                           a(7)
    version                             a(2)
    file_header()
    if (skin_size > 0) {
        skin()
    }
    for (i = 0; i < num_tracks; i++) {
        reset_key()
        track_header()
        track_index()
    }
    for (;;) {
        reset_key()
        sb_block()
    }
}
signature
The string vividas.
version
File version as two decimal digits. All known samples have the value 03.
file_header()
Sets skin_size and num_tracks.
reset_key()
The decoding key is reset to the value from the file_header.

File Header

file_header() {
    header_length                       v
    num_tracks                          u(1)
    for (i = 0; i < num_tracks; i++) {
        title_length                    u(1)
        track_title                     a(title_length)
        track_key                       d(187)
        track_header_length             d(4)
    }
    for (;;) {
        block_length                    v
        block_type                      u(1)
        if (block_type == 15) {
            key                         d(187)
            for (;;) {
                descriptor()
            }
        } else if (block_type == 22) {
            skin_key                    d(187)
            skin_size                   d(4)
        }
    }
}
header_length
Total length of the file_header element in bytes.
num_tracks
Number of tracks in the file.
title_length
Number of bytes in the immediately following title.
track_title
Title of track i.
track_key
Scrambled key for track i.
track_header_length
Total size in bytes of track_header and track_index for track i.
block_length
Size in bytes of the following block, including this field.

Skin

skin() {
    length                              v
    'd'                                 u(1)
    for (;;) {    
        size                            v
        tag                             u(1)
        data                            d(size)
    }             
}
length
Total size of skin data including length field.
size
Size of data chunk.
tag
Unique identifier for data chunk.
data
XML or JPEG data.

Track Header

track_header() {
    track_header_length                 v
    '1'                                 u(1)
    val_1                               u(1)
    for (i = 0; i < val_1; i++) {
        val_2                           u(1)
        for (j = 0; j < val_2; j++) {
            val_3                       u(1)
            val_4                       u(1)
        }
    }
    num_streams                         u(1)
    size_1                              v
    '2'                                 u(1)
    num_video                           u(1)
    def_video                           u(1)
    for (i = 0; i < num_video; i++) {
        length                          v
        '3'                             u(1)
        val_7                           u(1)
        frame_rate_den                  u(4)
        frame_rate_num                  u(4)
        num_frames                      u(4)
        width                           u(2)
        height                          u(2)
        val_8                           u(1)
        val_9                           u(4)
    }
    size_2                              v
    '4'                                 u(1)
    num_audio                           u(1)
    def_audio                           u(1)
    for (i = 0; i < num_audio; i++) {
        length                          v
        '5'                             u(1)
        codec_id                        u(1)
        codec_subid                     u(2)
        channels                        u(2)
        sample_rate                     u(4)
        data_1                          d(10)
        len_2                           u(1)
        data_2                          d(len_2)
        junk                            d(1)
        val_13                          v
        '19'                            u(1)
        len_3                           v
        num_data                        u(1)
        for (i = 0; i < num_data; i++) {
            data_len[i]                 v
        }
        for (i = 0; i < num_data; i++) {
            data[i]                     d(data_len[i])
        }
    }
}
track_header_length
Length in bytes of track header including this field. Matches element of same name in file_header.
num_streams
Number of elementary streams in track.
size_1
Number of bytes preceding video streams loop, including this field.
num_video
Number of video streams.
def_video_stream
Default video stream number.
size_2
Number of bytes preceding audio streams loop, including this field.
num_audio
Number of audio streams.
def_audio_stream
Default audio stream number.
data[i]
Vorbis (or speex?) header packets

Track Index

track_index() {
    length                              v
    'c'                                 u(1)
    num_sb_blocks                       v
    for (i = 0; i < count; i++) {
        size                            v
        num_chunks                      v
    }
}
length
Length in bytes of track index.
num_sb_blocks
Number of entries in following table.
size
Size of a block.
num_chunks
Number of chunks in block.

"SB" Block

sb_block() {
    "SB"                                a(2)
    size                                v
    junk                                d(1)
    start_chunk                         v
    do {
        chunk_size                      v
        flag                            u(1)
    } while (chunk_size != 0)
}
size
Total size of this block.

The chunks for which flag is 0 have the following structure:

chunk_1() {
    video_length                        v
    audio_length                        v
    video_data                          d(video_length)
    do {
        end_of_packet[i]                v
        unknown                         v
    } while(end_of_packet != 0)

    for(int i=0;i<n_packets;i++)
        audio_data[i]                   d(end_of_packet[i] - end_of_packet[i-1])

}
video_data
VP6-encoded video packet (always a keyframe?)
audio_data
multiple Vorbis(or speex?)-encoded audio packets

The chunks for which flag is 1 have the following structure:

chunk_1() {
    length                              v
    video_data                          d(length)
}
video_data
VP6-encoded video packet (always non-keyframe?)

Tools

A decrypter and parser is available from git://git.mansr.com/vividas (gitweb http://git.mansr.com/?p=vividas).

External Resources

Extended company and product description is available on Wikipedia.

"Vividas Licenses TrueMotion VP7 for Mass Distribution of High Quality Video" January 13th, 2005

Vividas - Open Source Acknowledgement