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
.