DPEG
- Company: Escal Software GmbH
- Extension: .dpg
This is a rather simple video format with tile-based frames that employs motion compensation.
Container format
The file starts with 256-byte header followed by frames starting with 32-bit little-endian frame size and one byte flags (both being zero means end of stream) plus some information at the end. If container has audio then 16-bit audio size and payload follow, otherwise all of the payload is video frame data.
Known header fields:
+00 - some string +28 - another string +50 - always seven? +5A - width +5C - height +6A - some audio-related value +6C - sampling rate +6E - audio channels +70 - some start value +74 - some end value +8C - offset to the information at the end
Frame flags:
1 - probably audio data presence flag 2 - intra frame (768-byte VGA palette precedes the data) 4 - intra frame is scaled 2x horizontally (i.e. every pixel is repeated twice; should be used together with intra flag) 8 - inter frame
Video coding is described below, audio coding is IMA ADPCM.
Video format
Frames are split into 8x8 tiles decoded in scanning order. Full intra frame is merely a raw frame, scaled intra frame (flags 6 or 7) have each pixel in them repeated twice, inter frame may code tiles in different ways.
Inter coding:
for each 8x8 tile {
op = *src++;
if (op & 0xC0) != 0xC0 {
offset = (int16_t)((op * 256 + *src++) << 2) >> 2;
}
switch (op >> 6) {
case 0:
copy tile contents from the previous frame with given offset
break;
case 1:
run = *src++;
for (y = 0; y < 8; y++) {
for (x = 0; x < 8; x++) {
if (run == 0) {
frame[pos + x + y * width] = *src++;
run = *src++;
} else {
frame[pos + x + y * width] = prev_frame[pos + x + y * width + offset];
run--;
}
}
}
break;
case 2:
run = *src++;
raw = 0;
for (y = 0; y < 8; y++) {
for (x = 0; x < 8; x++) {
if (raw) {
if (!run) {
frame[pos + x + y * width] = prev_frame[pos + x + y * width + offset];
run = *src++;
raw = 0;
} else {
frame[pos + x + y * width] = *src++;
run--;
}
} else {
if (!run) {
run = *src++;
frame[pos + x + y * width] = *src++;
raw = 1;
} else {
frame[pos + x + y * width] = prev_frame[pos + x + y * width + offset];
run--;
}
}
}
}
break;
case 3:
switch (op & 0x3F) {
case 0x3F:
read raw 8x8 tile
break;
case 0x0F:
read raw 4x4 tile and scale it twice
break;
case 0x03:
read raw 4x4 tile and scale it four times
break;
case 0x01:
offset = (int16_t)((src[0] * 256 + src[1]) << 2) >> 2;
delta = (int16_t)(src[2] * 256 + src[3]);
src += 4;
for (y = 0; y < 8; y++)
for (x = 0; x < 8; x++)
frame[x + y * width] = clip8(prev_frame[x + y * width + offset] + delta);
case 0x00:
real fill value for the tile
break;
default:
do nothing
}
}
}
Audio coding
Audio is coded as IMA ADPCM in the following format:
16-bit LE - number of samples coded (including the one used for prediction) 8-bit - predictor value 8-bit - initial step
Compressed data is coded in nibbles, low nibble first. Initial predictor value is derived as (src[2] - 0x80) * 256.