BTIC1H - cr88192/bgbtech_misc GitHub Wiki
General idea here is that encoder will work with blocks of 16 pixels at a time, likely using some internal variables and a state-machine to determine what to emit, as well as memory for up to N intermediate blocks (though, working a single block at a time would be possible, and a decoder should not need a multi-block memory for static images or I-frames).
Note that it should be possible to drive most of the block encoding choices with arithmetic-based heuristics.
For encoding or decoding video, it will be necessary to keep a block-buffer for the current and prior frames.
It is blocky VQ mapped to a bitstream, and encoding values as adaptive rice-coded deltas. A linear quantizer will be used.
Will reuse the same packaging from other BTIC variants (BTIC_CTLV):
- 0xE1, len:Word24, data:byte[len] (Image Data)
Similar goes for embedding in AVI.
Embedding in BTEMP will use 'VS1H'.
- Possibly allow AVI stream to have a series of 'VS1H' chunks, making it easier to direct-record from robot stream.
- Alternately, repack blocks from current MB2 buffer.
For the top-level structure, a TLV format will be used. This may be used for headers or extensions or other things.
Lengths are big-endian, and will include the length of the chunk header.
Tag Bytes:
- 0xE0: End-Of-Image Marker
- 0xE1: len=Word24, Image Data
- 0xE2: len=Byte, Image Data
- 0xE3: len=Word24, tag=TWOCC
- 0xE4: len=Word24, tag=FOURCC
- 0xE5: len=Byte, tag=TWOCC
- 0xE6: len=Word56, tag=FOURCC
- E1 and E2 will be encode an image in the current ImageMode.
- Image mode will default to 0, and may be specified for I-Frames.
- E3 and E5,'I#', where # is 0-9, gives an image as an image mode.
- Encoding an I-Frame in this mode will change the current mode.
- This is undefined for P-Frames.
- I0 is the default mode.
- I1 uses extended sub-headers and SMTF-only commands.
- Image mode 1 may be either a raw bitstream or a range-coded bitstream.
- Encoding an I-Frame in this mode will change the current mode.
This consists of a small 8-bit init header.
- X-NNN-TTTT
- X indicates if extended headers follow.
- NNN: Depends on TTTT (MBZ for Type=0)
- TTTT: Gives the type of bitstream.
- 0: Raw bitstream with SMTF-only commands.
- 1: Use a bitwise range coder.
- X-LLL-TTTT
- X=More tags follow.
- LLL=Length of header (1-7 bytes)
- TTTT=Header Tag (1-15)
If both an explicit length and tag are used, then the length will precede the tag.
The length encodes the full size of the header (includes tag byte, as well as the explicit tag and length fields, in addition to any payload data).
Ext Header 1:
- Sliced Image
- Contents are a VLI encoding the number of scanlines per slice.
- If zero or absent, slices are not used, and the whole image is a single bitstream.
- The value is stored divided by 4. As such, the value is required to be a multiple of 4.
- Colorspace
- Bits 0-2: Color Transform
- 0=Default/YCbCr
- 1=CheapYUV
- 2=GDbDr
- Bits 3-5: Bit depth
- 0=8-bit LDR
- 1=10-bit LDR
- 2=12-bit LDR
- 3=16-bit HDR
00-7F 00000000-0000007F 80-BF XX 00000080-00003FFF C0-DF XX(x2) 00004000-001FFFFF E0-EF XX(x3) 00200000-0FFFFFFF F0 XX(x4) 10000000-FFFFFFFF
Overlong encodings are allowed in most cases.
Bitstream will be encoded in MSB first order.
AdRice:
- Will have a unary prefix (Q) of zero or more 1 bits, terminated by a 0 bit.
- This will be followed by a k bit suffix (j).
- Value=(Q SHL k)|j;
- Q will adjust k:
- 0: if(k GT 0)k=k-1;
- 1: k is unchanged.
- 2+: k=k+log2(Q).
Signed Rice values (AdSRice) will have the sign folded into the LSB (0, -1, 1, -2, 2, ...).
Colorspaces:
- YCbCr, with sample-points ranging from 0 to 255.
- CheapYUV:
- Y=(2*G+B+R) SHR 2
- U=((B-Y) SHR 1)+128
- V=((R-Y) SHR 1)+128
- B'=Y+((U-128) SHL 1)
- R'=Y+((V-128) SHL 1)
- G'=(4*Y-B-R) SHR 1
- GDbDr:
- Y=G
- U=((B-G) SHR 1)+128
- V=((R-G) SHR 1)+128
- B'=Y+((U-128) SHL 1)
- G'=Y
- R'=Y+((V-128) SHL 1)
- Ya=Y-(D SHR 1), Yb=Yb+D
- ColorA=(Ya, U, V)
- ColorB=(Yb, U, V)
- Ya=Y-(Dy SHR 1), Yb=Yb+Dy
- Ua=U-(Du SHR 1), Ub=Ub+Du
- Va=V-(Dv SHR 1), Vb=Vb+Dv
- ColorA=(Ya, Ua, Va)
- ColorB=(Yb, Ub, Vb)
- YUVD:
- Y'=Y+(DeltaY*QfDeltaY)
- U'=U+(DeltaU*QfDeltaUV)
- V'=V+(DeltaV*QfDeltaUV)
- D'=D+(DeltaD*QfDeltaD)
- YUVDyuv:
- Y'=Y+(DeltaY*QfDeltaY)
- U'=U+(DeltaU*QfDeltaUV)
- V'=V+(DeltaV*QfDeltaUV)
- Dy'=Dy+(DeltaDy*QfDeltaDy)
- Du'=Du+(DeltaDu*QfDeltaDuv)
- Dv'=Dv+(DeltaDv*QfDeltaDuv)
Dyuv will have an allowed range of -256 .. 255, but with the requirement that the resultant YUV values (after calculating the color endpoints) are required to fall in the range of 0 to 255.
The results of going out of range are undefined.
- A decoder may, but is not required to, implement range clamping.
- An encoder may not assume the use of modular arithmetic here.
- Likewise, out of gamut colors are not allowed.
(Possible) Exception, HDR:
- HDR will use a 16-bit Half-Float space.
- Ranges in this case are 0 to 65535, and +/- 65536.
- Bias for absolute colors is 0x3800 (+0.5), rather than 128.
- Possible: HDR will map positive values as 0..32767
- Negative values will map to (-32768)..(-1)
- Will be essentially stored as one's complement.
- DeltaYUV: 3 AdSRice coded deltas (dY, dU, dV).
- DeltaYUVD: 4 AdSRice coded deltas (dY, dU, dV, dD).
- DeltaYUVDyuv: 6 AdSRice coded deltas (dY, dU, dV, dDy, dDu, dDv).
- Deltas will be sign-folded, so good old: 0, -1, 1, -2, 2, ... sequence.
- AbsYUV: AdSRice coded YUV
- AbsYUVD: AdSRice coded YUVD
- AbsYUVDyuv: AdSRice coded YUVDyuv
- Absolute colors YUV will be stored as a signed value relative to 128.
- Absolute D, and Dyuv values will be stored as a signed value relative to 0.
- QfDeltaYUVD: 3 AdRice quantization factors (QfDeltaY, QfDeltaUV, QfDeltaD)
- QfDeltaYUVDyuv: 4 AdRice quantization factors (QfDeltaY, QfDeltaUV, QfDeltaDy, QfDeltaDuv)
- QfAbsYUV*: Similar, but for the absolute quantization factors (QfAbs)
BTIC1H is essentially an advanced case of Color Cell Compression.
Pixel-blocks will be represented as XxY pixels, which would typically be 2 bits each, ex:
- 00=ColorA
- 01=2/3 ColorA + 1/3 ColorB
- 10=1/3 ColorA + 2/3 ColorB
- 11=ColorB
- PixelBlock2x2: grid of 2x2 pixels, 8 bits
- PixelBlock2x1: grid of 2x1 pixels (left, right), 4 bits
- PixelBlock1x2: grid of 1x2 pixels (up, down), 4 bits
- PixelBlock4x4: grid of 4x4 pixels, 32 bits
- PixelBlock4x2: grid of 4x2 pixels (reduced vertical), 16 bits
- PixelBlock2x4: grid of 2x4 pixels (reduced horizontal), 16 bits
- PixelBlock4x4_UV2x2: grid of 4x4 pixels + 2x 2x2, 48 bits
- PixelBlock4x4_UV2x4: grid of 4x4 pixels + 2x 2x4, 64 bits
- 0=ColorA
- 1=ColorB
- PixelBlock2x2x1: grid of 4 1bpp pixels, 4 bits
- PixelBlock4x4x1: grid of 16 1bpp pixels, 16 bits
- 0=ColorA
- 1=6/7 ColorA + 1/7 ColorB
- 2=5/7 ColorA + 2/7 ColorB
- 3=4/7 ColorA + 3/7 ColorB
- 4=3/7 ColorA + 4/7 ColorB
- 5=2/7 ColorA + 5/7 ColorB
- 6=1/7 ColorA + 6/7 ColorB
- 7=ColorB
- PixelBlock4x4x3: grid of 4x4x3 pixels, 48 bits
- PixelBlock4x4x3_UV2x2: grid of 4x4x3 pixels + 2x 2x2, 64 bits
- PixelBlock4x4x3_UV2x4: grid of 4x4x3 pixels + 2x 2x4, 80 bits
- PixelBlock4x4x3_UV4x4: grid of 4x4x3 pixels + 2x 4x4, 112 bits
4x4: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 Becomes: 0, 1, 5, 4, 8, 12, 13, 9, 10, 14, 15, 11, 7, 6, 2, 3
2x2: 0 1 2 3 Becomes: 0 2 3 1
Most Rice k factors will be per-variable (with initial values):
- AdRice,Rk(CmdRIdx)=2 (Command Indices)
- AdRice,Rk(CmdAbs)=4 (Absolute Commands)
- AdRice,Rk(CmdCnt)=2 (RunCount)
- AdRice,Rk(MaskIdx)=2 (Mask Index)
- AdSRice,Rk(ParmXY)=2 (X/Y Offset)
- AdSRice,Rk(ParmVar)=2 (Parameter Variable, Feature ID)
- AdSRice,Rk(ParmVal)=2 (Parameter Value)
- Ad*Rice,Rk(ParmIx)=2 (Parameter Value-Count, Index)
- AdSRice,Rk(DeltaY)=2 (Delta Y)
- AdSRice,Rk(DeltaUV)=2 (Delta U and V)
- AdSRice,Rk(DeltaDy)=2 (Delta D and Dy)
- AdSRice,Rk(DeltaDuv)=2 (Delta Du and Dv)
- AdSRice,Rk(AbsY)=5 (Absolute Y)
- AdSRice,Rk(AbsUV)=5 (Absolute U and V)
- AdSRice,Rk(AbsDy)=5 (Absolute D and Dy)
- AdSRice,Rk(AbsDuv)=5 (Absolute Du and Dv)
- AdSRice,Rk(QfY)=3 (Quantization Factor, Y)
- AdSRice,Rk(QfUV)=3 (Quantization Factor, UV)
- AdSRice,Rk(QfDy)=3 (Quantization Factor, Dy)
- AdSRice,Rk(QfDuv)=3 (Quantization Factor, Duv)
ParmIx: AdSRice for ParmIndex, AdRice for ParmCount.
The command table will start with its contents initially undefined.
C(XX), expresses a logical command number in Hex:
- CmdRIdx encoded as AdRice
- 0: Followed by CmdAbs, which encodes an absolute command number.
- 1..256: Repeat a prior command (encodes RIdx 0..255).
- RIdx=0: Use command at index 0, table is unchanged.
- (Drop) RIdx=1..255: Use command at entry RIdx, Swap entries RIdx and RIdx-1.
- (New) RIdx=1..31: Use command at entry RIdx, Swap entries RIdx and RIdx-1.
- (New) RIdx=32..255: Rotate back one place and swap new 0 and old RIdx.
- Table rotates back 1 place, command added to front of table.
- Initial contents of the table are undefined and may not be used.
- If the command exists at a prior location in the table, a hole is created.
- A value may fall off the end, but is swapped into the hole.
In ImageMode 1, A different command coding will be used (SMTF).
- 0..255 will give RIdx
- Only RIdx will be used (CmdAbs may not be encoded).
- C(00) DeltaYUV
- delta flat-color block.
- C(01) DeltaYUVD, Pixblock2x2
- Delta 2x2 block.
- C(02) DeltaYUVD, Pixblock2x1
- C(03) DeltaYUVD, Pixblock1x2
- 2x1 and 1x2 blocks.
- C(04) QfDeltaYUVD
- Update delta quantization factors.
- C(05) DeltaYUVD, Pixblock4x4
- C(06) DeltaYUVD, Pixblock4x2
- C(07) DeltaYUVD, Pixblock2x4
- color and pixel-blocks
- C(08) QfDeltaYUVDyuv
- Update delta quantization factors.
- C(09) DeltaYUVDyuv, Pixblock4x4
- C(0A) DeltaYUVDyuv, Pixblock4x2
- C(0B) DeltaYUVDyuv, Pixblock2x4
- Color and pixel-blocks (but with more endpoints)
- C(0C) AbsYUVD, Pixblock2x2
- C(0D) AbsYUVD, Pixblock4x4
- C(0E) AbsYUVDyuv, Pixblock2x2
- C(0F) AbsYUVDyuv, Pixblock4x4
- C(10) RunCount
- Run of blocks repeating a single color.
- C(11) RunCount, PixelBlock2x2*RunCount
- C(12) RunCount, PixelBlock2x1*RunCount
- C(13) RunCount, PixelBlock1x2*RunCount
- Run of blocks with reusing prior color.
- Note: YUVD or YUVDyuv depending on prior block.
- C(14) QfAbsYUVD
- Update absolute quantization factors.
- C(15) RunCount, PixelBlock4x4*RunCount
- C(16) RunCount, PixelBlock4x2*RunCount
- C(17) RunCount, PixelBlock2x4*RunCount
- Run of blocks with reusing prior color.
- Note: YUVD or YUVDyuv depending on prior block.
- C(18) QfAbsYUVDyuv
- Update absolute quantization factors.
- C(19) RunCount, PixelBlock2x2x1*RunCount
- C(1A) RunCount, PixelBlock4x4x1*RunCount
- Run of blocks with reusing prior color (1bpp).
- C(1B) RunCount, DeltaYUV*RunCount
- Run of flat-color blocks.
- C(1C) DeltaYUV*4
- Logical 4:2:0, 2x2 with 1 color per pixel
- Colors are encoded in Hilbert(2x2) order
- Deprecate?
- C(1D) DeltaYUVD*4, Pixblock4x4
- Logical 4:2:0, 4x4 consisting of 2x2 sub-blocks
- Colors are encoded in Hilbert(2x2) order
- Deprecate?
- C(1E) DeltaYUV*16
- Logical 4:4:4, 4x4 with 1 color per pixel
- Pixels are encoded in Hilbert(4x4) order
- Note: Non-Alpha Only
- Deprecate?
- C(1F) AbsYUV*16
- Logical 4:4:4, 4x4 with 1 color per pixel
- Pixels are encoded in Hilbert(4x4) order
- Note: Non-Alpha Only
- Deprecate?
- C(20) End Of Data
- Logical end of bitstream data. For multi-segment images, indicates the end of the current segment.
- Any subsequent data in the message lump is to be ignored.
- C(21) RunCount
- Skip, Blocks are copied from the prior frame
- C(22) RunCount, XOffset, YOffset
- Skip+Translate, Blocks are copied from the prior frame.
- Offsets indicate the source position in blocks relative to the current block.
- Referenced blocks may not fall outside the bounds of the current image frame.
- Blocks will be seen as they were in the previous frame.
- C(23), Var, Val
- Set Parameter (Signed Integer)
- C(24), Var, IxB, ParmCount, Val[ParmCount]
- Set Parameter (Signed Int Vector)
- C(25), Reserved
- C(26), FlagID
- Enable Feature Flag
- C(27), FlagID
- Disable Feature Flag
- C(28) RunCount, (DeltaYUVD, Pixblock2x2)*RunCount
- C(29) RunCount, (DeltaYUVDyuv, Pixblock2x2)*RunCount
- Delta 2x2 gradient blocks.
- Pixel blocks give values at the corners, with the intermediate pixels being interpolated.
- C(2A) DeltaYUVD, PixelBlock4x4x1
- C(2B) DeltaYUVD, PixelBlock2x2x1
- 2x2x1 and 4x4x1 blocks.
- C(2C) DeltaYUVD, Pixblock4x4x3
- Pixel Block 4x4x3
- C(2D) DeltaYUVDyuv, Pixblock4x4x3
- Pixel Block 4x4x3
- C(2E) DeltaY*16, DeltaUV*4
- Logical 4:2:0, Pixels are delta-coded, with Y and UV in Hilbert order.
- Note: Non-Alpha Only
- Deprecate?
- C(2F) AbsY*16, AbsUV*4
- Logical 4:2:0, Pixels are absolute, with Y and UV in Hilbert order.
- Note: Non-Alpha Only
- Deprecate?
- C(30) DeltaYUVDyuv, Pixblock4x4_UV2x2
- Logical 4:2:0, 4x4 Y block followed by 2x2 U and V sub-blocks
- Y, U, and V are interpolated separately.
- C(31) DeltaYUVDyuv, Pixblock4x4x3_UV4x4
- Logical 4:4:4, 4x4x3 Y block followed by 4x4x2 U and V sub-blocks
- Y, U, and V are interpolated separately.
- C(32) DeltaYUVDyuv, Pixblock4x4x3_UV2x2
- Logical 4:2:0, 4x4x3 Y block followed by 2x2 U and V sub-blocks
- Y, U, and V are interpolated separately.
- C(33) DeltaYUVDyuv, Pixblock2x2_UV2x2
- Logical 4:2:0, 2x2 Y block followed by 2x2 U and V sub-blocks
- Y, U, and V are interpolated separately.
- C(34) RunCount, PixelBlock4x4_UV2x2*RunCount
- Separately interpolated YUV.
- YUVDyuv only.
- C(35) RunCount, PixelBlock4x4x3_UV4x4*RunCount
- Separately interpolated YUV.
- YUVDyuv only.
- C(36) RunCount, PixelBlock4x4x3_UV2x2*RunCount
- Separately interpolated YUV.
- YUVDyuv only.
- C(37) RunCount, PixelBlock2x2_UV2x2*RunCount
- Separately interpolated YUV.
- YUVDyuv only.
- C(38) DeltaYUVDyuv, Pixblock4x4_UV2x4
- Logical 4:2:2, 4x4 Y block followed by 2x4 U and V sub-blocks
- C(39) DeltaYUVDyuv, Pixblock4x4x3_UV2x4
- Logical 4:2:2, 4x4x3 Y block followed by 2x4x2 U and V sub-blocks
- C(3A) DeltaYUVDyuv, Pixblock4x4x3_UV2x4x3
- Logical 4:2:2, 4x4x3 Y block followed by 2x4x3 U and V sub-blocks
- C(3C) RunCount, PixelBlock4x4_UV2x4*RunCount
- Separately interpolated YUV.
- YUVDyuv only.
- C(3D) RunCount, PixelBlock4x4x3_UV2x4*RunCount
- Separately interpolated YUV.
- YUVDyuv only.
- C(3E) RunCount, PixelBlock4x4x3_UV2x4x3*RunCount
- Separately interpolated YUV.
- YUVDyuv only.
ParmVar and FlagID:
- Values greater than 0 are optional / hints.
- An unknown value here is ignored.
- Values less than 0 indicate features which change the bitstream.
- An unrecognized value here will abort decoding.
- Stream Version (0)
- Indicates the major version of the bitstream.
- YUVD Color Delta Predictor
- 0: Default, Use last color.
- -1: Use half-linear prediction.
- P=(3A-B)>>1;
- -2: Use linear prediction.
- P=2A-B;
- If enabled, a mask update may precede color-point delta updates.
- Enabling the mask initially sets all components active.
- It is no-op if already enabled.
- This mask indicates which of the encoded components are encoded.
- If disabled, no mask update is encoded, and components are always encoded.
- Basically the same, but applies to Abs events.
- Will share the same mask table state as Delta events.
- However, it will have its own mask state.
- If disabled, no mask update is encoded, and components are always encoded.
DeltaYUV, DeltaYUVD, and DeltaYUVDyuv update masks.
- If enabled, may also apply to AbsYUV, AbsYUVD, and AbsYUVDyuv.
- Does not apply to DeltaY, DeltaUV, AbsY, or AbsUV.
A disabled component is treated as 0 for Delta, and thus remains unchanged when a color-point is updated. For an Abs event, the prior component value is unchanged.
The mask is encoded as an AdRice value:
- 0, Reuses the current mask value.
- 1..256: Pull a value from the mask table (Index of 0 to 255).
- If an index is greater than 1, it is swapped with the prior index.
- Initial table state is values counting down from 255 to 0.
- Unlike the command-table, there are no absolute masks or holes.
- s: Sticky
- 0=Mask only applies for this color-point.
- 1=Mask replaces the currently active mask value.
- YUV: Indicates whether each component is enabled.
- D: Applies to both the D and Dy components.
- uv: Applies to Du and Dv
- 0=Component is Disabled
- 1=Component is Enabled
- x: Reserved, currently must be 1.
Alpha(A) and Diff-Alpha(Da) are the main variables, and work similarly to Y and D.
They will be stored in a separate chunk:
- TWOCC('AX')
- Will follow immediately after the Image Data (0xE1) tag.
Commands:
- C(00) DeltaA
- Delta flat-alpha block.
- C(01) DeltaAD, Pixblock2x2
- Delta 2x2 block.
- C(02) DeltaAD, Pixblock4x4
- Pixel Block 4x4x2
- C(03) DeltaAD, Pixblock4x4x3
- Pixel Block 4x4x3
- C(04) QfDeltaAD
- Update delta quantization factors.
- C(05) DeltaYUVD, PixelBlock4x4x1
- 4x4x1 blocks.
- C(06) AbsAD, Pixblock2x2
- C(07) AbsAD, Pixblock4x4
- Absolute Pixel Block
- C(08) QfAbsAD
- Update absolute quantization factors.
- C(09) DeltaYUVD, PixelBlock2x2x1
- 2x2x1 blocks.
- C(0A)
- Non-Alpha Block
- A non-alpha block is for a block which does not have an alpha channel.
- If used with a block which may have an alpha channel, it is interpreted as an opaque block.
- C(0B) RunCount
- Run of Non-Alpha blocks.
- C(0C) RunCount
- Run of blocks repeating a single value.
- C(0D) RunCount, PixelBlock2x2*RunCount
- Run of blocks with reusing prior alpha.
- C(0E) RunCount, PixelBlock4x4*RunCount
- Run of blocks with reusing prior alpha.
- C(0F) RunCount, PixelBlock4x4x1*RunCount
- Run of blocks with reusing prior alpha.
- C(10) Reserved
- C(11)
- Transparent Block
- Block is fully transparent
- C(12) RunCount
- Run of transparent blocks.
- C(20) End Of Data
- Logical end of bitstream data. For multi-segment images, indicates the end of the current segment.
- Any subsequent data in the message lump is to be ignored.
- C(21) RunCount
- Skip, Blocks are copied from the prior frame
- C(22) RunCount, XOffset, YOffset
- Skip+Translate, Blocks are copied from the prior frame.
- Offsets indicate the source position in blocks relative to the current block.
Metablock is the block representation used internally by the codec. It represents an intermediate step between the internal bitstream Encode/Decode process, and the Input/Output framebuffer.
Addition of HDR Mode:
- Frames may only be HDR or LDR
- Different blocks will be used between them.
A: Y, U, V, D, Pa,Pb,Pc,Pd, x, x, x, x, x, x, x, x, y, y, y, y, y, y, y, y, a, a, a, a, a, a, a, a B: Y, U, V, 0, M,Dy,Pc,Pd, Du,Dv,Qe,Qf, Qa,Qb,Qc,Qd, y, y, y, y, y, y, y, y, a, a, a, a, a, a, a, a C: Y, U, V, 0, M, D,Pn, x, Y1,U1,V1,d1, Qa,Qb,Qc,Qd, Y2,U2,V2,D2, Y3,U3,V3,D3, a, a, a, a, a, a, a, a D: Y, U, V, 0, M, D,Pn, x, U0,U1,U2,U3, V0,V1,V2,V2, Y0,Y1,Y2,Y3, Y4,Y5,Y6,Y7, Y8,Y9,Ya,Yb, Yc,Yd,Ye,Yf E: Y, U, V, 0, M,Dy,Pc,Pd, Du,Dv,Qe,Qf, Qa,Qb,Qc,Qd, Sa,Sb,Sc,Sd, Ta,Tb,Tc,Td, a, a, a, a, a, a, a, a
Y,U,V,D: YUV and Diff (Primary Color, 0) Dy/D, Du, Dv: YUV differential values. Yn,Un,Vn,Dn: YUV and Diff (Secondary Color n) Pa,Pb,Pc,Pd: Pixel Data (Primary) Pc, Pd: Pixel Data (4x2, 2x4, 2x2, and 4x4x1 modes). Qe,Qf,Qa,Qb,Qc,Qd: Pixel Data (Secondary) Sa,Sb,Sc,Sd: Pixel Data (Alternate U) Ta,Tb,Tc,Td: Pixel Data (Alternate V) Pn: Partition Number x/y: reserved, MBZ a,a,a,a: alpha block
d!=0: 4x4x2bpp (A) d==0: Flat or Special M==0: Flat M==1: 2x2x2bpp (B) Pc=Pixel Bits M==2: 4x4x1bpp (B) Pc/Pd=Pixel Bits M==3: Skip (No Translate) M==4: Skip+Translate Pc=Y Offset Pd=X Offset
M==5: 2x2x1bpp (B) Pc=Pixel Bits M==6: 4x4x3bpp (YUVD, B) Qe/Qf/Qa/Qb/Qc/Qd=Pixel Bits M==7: YUV 4:2:0 (D) Y0..Y15 (16..31), U0..U3 (8..11), V0..V3 (12..15) M==8: 2x1x2bpp (B) M==9: 1x2x2bpp (B) Pc=Pixel Bits
M==10: 4x2x2bpp (B) M==11: 2x4x2bpp (B) Pc/Pd=Pixel Bits M==12: 4x2x2bpp (YUVDyuv, B) M==13: 2x4x2bpp Pc/Pd=Pixel Bits M==14: 4x4x2bpp (YUVDyuv, B) Qa/Qb/Qc/Qd=Pixel Bits M==15: 4x4x3bpp (YUVDyuv, B) Qa/Qb/Qc/Qd/Qe/Qf=Pixel Bits
M==16: 4x4x2bpp (YUVDx2, C) Pn=1(Horz), 2(Vert) Qa/Qb/Qc/Qd=Pixel Bits M==17: 4x4x2bpp (YUVDx4, C) Qa/Qb/Qc/Qd=Pixel Bits M==18: 2x2x2bpp (Gradient, B) M==19: 2x2x2bpp (YUVDyuv, B)
M==20: 4x4x2bpp 4:2:0 (YUVDyuv, B/E) Qa/Qb/Qc/Qd=Pixel Bits (Y, 4x4x2) Qe=Pixel Bits (U, 2x2x2) Qf=Pixel Bits (V, 2x2x2) M==21: 4x4x3bpp 4:4:4 (YUVDyuv, E) Qe/Qf/Qa/Qb/Qc/Qd=Pixel Bits (Y, 4x4x3) Sa/Sb/Sc/Sd=Pixel Bits (U, 4x4x2) Ta/Tb/Tc/Td=Pixel Bits (V, 4x4x2) M==22: 4x4x3bpp 4:2:0 (YUVDyuv, B/E) Qe/Qf/Qa/Qb/Qc/Qd=Pixel Bits (Y, 4x4x3) Pc=Pixel Bits (U, 2x2x2) Pd=Pixel Bits (V, 2x2x2) M==23: 2x2x2bpp 4:2:0 (YUVDyuv, B/E) Pc=Pixel Bits (Y, 2x2x2) Qe=Pixel Bits (U, 2x2x2) Qf=Pixel Bits (V, 2x2x2)
M==24: 4x4x2bpp 4:2:2 (YUVDyuv, E) Qa/Qb/Qc/Qd=Pixel Bits (Y, 4x4x2) Sa/Sb=Pixel Bits (U, 2x4x2) Ta/Tb=Pixel Bits (V, 2x4x2) M==25: 4x4x3bpp 4:2:2 (YUVDyuv, E) Qe/Qf/Qa/Qb/Qc/Qd=Pixel Bits (Y, 4x4x3) Sa/Sb=Pixel Bits (U, 2x4x2) Ta/Tb=Pixel Bits (V, 2x4x2) M==26: 4x4x3bpp 4:2:2 (YUVDyuv, E) Qe/Qf/Qa/Qb/Qc/Qd=Pixel Bits (Y, 4x4x3) Sa/Sb/Sc=Pixel Bits (U, 2x4x3) Ta/Tb/Tc=Pixel Bits (V, 2x4x3)
Alpha Block
A: A,D,Pe,Pf, Pa,Pb,Pc,Pd (A-E) B: A,0, D, M, Pa,Pb,Pc,Pd (A-E)
A=(A0+A1) SHR 1 D=A1-A0
Default mode encodes alpha at 3 bits/pixel. M==0: Non-Alpha M==1: 2x2x2bpp Pc=Pixel Bits M==2: 4x4x1bpp Pc/Pd=Pixel Bits M==3: Skip (No Translate) M==4: Skip+Translate Pc=Y Offset Pd=X Offset M==5: 2x2x1bpp Pb=Diff Pc=Pixel Bits M==6: 4x4x2bpp Pb=Diff Pc=Pixel Bits M==7: Flat
HDR Pixel Blocks
HA: CY-Cy,DY-Dy, CU-Cu,DU-Du, CV-Cv,DV-Dv, Sa,Sb,Sc,Ta, Tb,Tc,Qe,Qf, Qa,Qb,Qc,Qd, a, a, a, a, a, a, a, a HB: Z- M,CY-Cy, DY-Dy,CU,Cu, DU,Du,CV,Cv, DV,Dv,Sa,Sb, Ta,Tb,Qe,Qf, Qa,Qb,Qc,Qd, a, a, a, a, a, a, a, a HC: Z- M,CY-Cy, DY-Dy,CU-Cu, DU-Du,CV-Cv, DV-Dv,Pc,Pd, Qg,Qh,Qe,Qf, Qa,Qb,Qc,Qd, Sa,Sb,Sc,Sd, Ta,Tb,Tc,Td CY-Cy, ...: 16-bit Half-Float Component (HDR). Z-M: Z+Mode, High 8 bits encode 0x82 (-NaN, ~)
M==0: Flat (YUV, HB) M==1: 2x2x2bpp (YUVD, HB) M==2: 4x2x2bpp (YUVD, HB) M==3: 2x4x2bpp (YUVD, HB) M==4: 4x4x2bpp (YUVD, HB) Qa/Qb/Qc/Qd=Pixel Bits M==5: 4x4x2bpp (YUVDyuv, HB) Qa/Qb/Qc/Qd=Pixel Bits M==6: 4x4x3bpp (YUVD, HB) Qe/Qf/Qa/Qb/Qc/Qd=Pixel Bits M==7: 4x4x3bpp (YUVDyuv, HB) Qe/Qf/Qa/Qb/Qc/Qd=Pixel Bits
M==16: 4x4x2bpp 4:2:0 (YUVDyuv, HB) Qa/Qb/Qc/Qd=Pixel Bits (Y, 4x4x2) Sa=Pixel Bits (U, 2x2x2) Ta=Pixel Bits (V, 2x2x2) M==17: 4x4x2bpp 4:2:2 (YUVDyuv, HB) Qa/Qb/Qc/Qd=Pixel Bits (Y, 4x4x2) Sa/Sb=Pixel Bits (U, 2x4x2) Ta/Tb=Pixel Bits (V, 2x4x2) M==18: 4x4x3bpp 4:2:0 (YUVDyuv, HB) Qe/Qf/Qa/Qb/Qc/Qd=Pixel Bits (Y, 4x4x3) Sa=Pixel Bits (U, 2x2x2) Ta=Pixel Bits (V, 2x2x2) M==19: 4x4x3bpp 4:2:2 (YUVDyuv, HB) Qe/Qf/Qa/Qb/Qc/Qd=Pixel Bits (Y, 4x4x3) Sa/Sb=Pixel Bits (U, 2x4x2) Ta/Tb=Pixel Bits (V, 2x4x2) M==20: 4x4x3bpp 4:4:4 (YUVDyuv, HC) Qe/Qf/Qa/Qb/Qc/Qd=Pixel Bits (Y, 4x4x3) Sa/Sb/Sc/Sd=Pixel Bits (U, 4x4x2) Ta/Tb/Tc/Td=Pixel Bits (V, 4x4x2)
HDR Alpha Block
HA: A-a, D- d, Pa,Pb,Pc,Pd (F/G) HB: Z,M, A- a, D- d,Pc,Pd (F/G)
Mini-Mode will be a BTIC1H subset.
- Will use a 64-bit metablock, and only use block-types which can be encoded in 64 bits.
- Will only have block types: Flat, 2x2x2, 4x4x1, 4x4x2.
- Will only use DeltaYUV and DeltaYUVD.
- Does not support update masks.
- Command Index Table is limited to 16 entries.
In sliced images, the images will be divided up into slices each of a given number of scanlines (required to be a multiple of 4). Each slice is encoded with its own bitstream. The slices may be encoded or decoded independently and in any order.
The slices are packed end-to-end in the frame, each prefixed with a VLI giving its coded length in bytes.
While the slice only encodes blocks within a certain range, note that motion compensation may still refer to blocks outside of the range controlled by this slice. The contents of skip blocks will be seen as they were in the previous frame.
Will use a bitwise range coder. This will be considered a non-core feature, and future decodability of range-coded video is not assured.
Basically, it uses a bit-at-a-time encoder, with a variable context size. Rather than bit patterns written directly into a bitstream, they are fed into the range coder, which may in turn derive some additional compression over a raw bitstream.
The context consists of the last N preceding bits, which is used as an index into a probabilities table. After encoding each bit, the context is shifted left 1 bit and the encoded bit is added to the LSB.
This context is masked by the context-size, namely ((1 SHL n)-1), when accessing the model weights.
The RC data starts with a small header.
- X-NNN-TTTT
- X=Extended Headers Follow
- NNN: Size of Context (8..15 bits)
- TTTT: RC Mode
- 0: No RC used.
- 1: Basic bitwise Range Coder.
- 2-15 Reserved.
A main model will be used for uncategorized bits. This includes pixel data.
A secondary model will be used for Rice-code bits. This will be used for all bits within the Rice coded symbol. A symbol will be emitted as 2 bit sequences, one for the unary prefix, and another for the suffix.
Logically, there will be several values in use:
- min: Lower bound of the coder range (init=0x00000000)
- max: Upper bound of the coder range (init=0xFFFFFFFF)
- range=max-min: Difference between the lower and upper bounds
- val: Encoded value stream (decode)
A division bound will be calculated from the weight as:
- bound=(range SHR 8)*weight.
- Values above this point (rval GT dval) will correspond to a logical 1 bit
- min=bound+1;
- weight=weight-(w SHR 5);
- Values less than or equal to this value will be interpreted as 0
- max=bound;
- weight=weight+((256-w) SHR 5);
- Weights will be clamped to the range of 32..223
- This is to attempt to prevent premature range collapse.
For encoding:
- Write the high 8 bits to the output;
- WriteByte(min SHR 24);
- min=(min SHL 8); max=(max SHL 8)|255;
- Repeat again if high 8 bits of min and max are still equal.
- min=(min SHL 8); max=(max SHL 8)|255;
- val=(val SHL 8)|ReadByte();
- Repeat again if high 8 bits of min and max are still equal.
MipMaps currently may only be used with still images. Secondarily, MipMaps may (generally) only be used with images whose dimensions are powers of 2.
Mipmap images will have the main image followed by a series of recursively downsampled images.
The main Image (MipLevel 0) will be represented as normally, and may be followed by an 'AX' lump.
After the AX lump, there will be miplevel lumps. These will be represented using FOURCC "MIPx" where x='1'..'9' or 'a'..'f'.
Each miplevel will have its own Image Data and optional AX lump.
Each miplevel will have 1/2 the X and Y resolution as the one preceding it, and is required to be the same format (same colorspace, encoding, etc). Likewise, the presence or absence of 'AX' lumps is all or nothing.