rate control not quite working but committing anyway due to format change

This commit is contained in:
minjaesong
2025-08-24 13:35:08 +09:00
parent b1857e355a
commit cb07ab1f3b
4 changed files with 409 additions and 219 deletions

View File

@@ -201,8 +201,20 @@ try {
sys.memcpy(CURRENT_RGB_ADDR, PREV_RGB_ADDR, FRAME_PIXELS * 3)
} else if (packetType == TEV_PACKET_IFRAME || packetType == TEV_PACKET_PFRAME) {
// Video frame packet
// Video frame packet (always includes rate control factor)
let payloadLen = seqread.readInt()
// Always read rate control factor (4 bytes, little-endian float)
let rateFactorBytes = seqread.readBytes(4)
let view = new DataView(new ArrayBuffer(4))
for (let i = 0; i < 4; i++) {
view.setUint8(i, sys.peek(rateFactorBytes + i))
}
let rateControlFactor = view.getFloat32(0, true) // true = little-endian
//serial.println(`rateControlFactor = ${rateControlFactor}`)
sys.free(rateFactorBytes)
payloadLen -= 4 // Subtract rate factor size from payload
let compressedPtr = seqread.readBytes(payloadLen)
updateDataRateBin(payloadLen)
@@ -232,9 +244,9 @@ try {
continue
}
// Hardware-accelerated TEV YCoCg-R decoding to RGB buffers
// Hardware-accelerated TEV YCoCg-R decoding to RGB buffers (with rate control factor)
try {
graphics.tevDecode(blockDataPtr, CURRENT_RGB_ADDR, PREV_RGB_ADDR, width, height, quality, debugMotionVectors)
graphics.tevDecode(blockDataPtr, CURRENT_RGB_ADDR, PREV_RGB_ADDR, width, height, quality, debugMotionVectors, rateControlFactor)
// Upload RGB buffer to display framebuffer with dithering
graphics.uploadRGBToFramebuffer(CURRENT_RGB_ADDR, DISPLAY_RG_ADDR, DISPLAY_BA_ADDR,

View File

@@ -678,6 +678,12 @@ Created by Claude on 2025-08-17
TEV is a modern video codec optimized for TSVM's 4096-color hardware, featuring
DCT-based compression, motion compensation, and efficient temporal coding.
## Version History
- Version 2.0: YCoCg-R 4:2:0 with 16x16/8x8 DCT blocks
- Version 2.1: Added Rate Control Factor to all video packets (breaking change)
* Enables bitrate-constrained encoding alongside quality modes
* All video frames now include 4-byte rate control factor after payload size
# File Structure
\x1F T S V M T E V
[HEADER]
@@ -694,7 +700,7 @@ DCT-based compression, motion compensation, and efficient temporal coding.
uint16 Height: video height in pixels
uint16 FPS: frames per second
uint32 Total Frames: number of video frames
uint8 Quality: quantization quality (0-7, higher = better)
uint8 Quality: quantization quality (0-4, higher = better)
byte[5] Reserved
## Packet Types
@@ -705,7 +711,8 @@ DCT-based compression, motion compensation, and efficient temporal coding.
## Video Packet Structure
uint8 Packet Type
uint32 Compressed Size
uint32 Compressed Size (includes rate control factor size)
float Rate Control Factor (4 bytes, little-endian)
* Gzip-compressed Block Data
## Block Data (per 16x16 block)
@@ -722,11 +729,19 @@ DCT-based compression, motion compensation, and efficient temporal coding.
int16[64] DCT Coefficients Cg (subsampled by two, aggressively quantised)
For SKIP and MOTION mode, DCT coefficients are filled with zero
## DCT Quantization
## DCT Quantization and Rate Control
TEV uses 8 quality levels (0=lowest, 7=highest) with progressive quantization
tables optimized for perceptual quality. DC coefficients use fixed quantizer
of 8, while AC coefficients are quantized according to quality tables.
### Rate Control Factor
Each video frame includes a Rate Control Factor that modifies quantization:
- Quality mode: Factor = 1.0 (fixed quantization based on quality level)
- Bitrate mode: Factor varies per frame based on content complexity and target bitrate
- Encoder: quantized_coeff = dct_coeff / (base_quant * rate_factor)
- Decoder: dequantized_coeff = quantized_coeff * (base_quant / rate_factor)
- Optimization: When factor ≈ 1.0 (0.999-1.001), decoder uses original tables
## Motion Compensation
- Search range: ±8 pixels
- Sub-pixel precision: 1/4 pixel (again, integer precision for now)

View File

@@ -1567,7 +1567,8 @@ class GraphicsJSR223Delegate(private val vm: VM) {
* @param frameCounter Frame counter for temporal patterns
*/
fun tevDecode(blockDataPtr: Long, currentRGBAddr: Long, prevRGBAddr: Long,
width: Int, height: Int, quality: Int, debugMotionVectors: Boolean = false) {
width: Int, height: Int, quality: Int, debugMotionVectors: Boolean = false,
rateControlFactor: Float = 1.0f) {
val blocksX = (width + 15) / 16 // 16x16 blocks now
val blocksY = (height + 15) / 16
@@ -1576,9 +1577,22 @@ class GraphicsJSR223Delegate(private val vm: VM) {
val quantCOmult = QUANT_MULT_CO[quality]
val quantCGmult = QUANT_MULT_CG[quality]
val quantTableY = QUANT_TABLE_Y.map { it * quantYmult }.toIntArray()
val quantTableCo = QUANT_TABLE_C.map { it * quantCOmult }.toIntArray()
val quantTableCg = QUANT_TABLE_C.map { it * quantCGmult }.toIntArray()
// Apply rate control factor to quantization tables (if not ~1.0, skip optimization)
val quantTableY = if (rateControlFactor in 0.999f..1.001f) {
QUANT_TABLE_Y.map { it * quantYmult }.toIntArray()
} else {
QUANT_TABLE_Y.map { (it * quantYmult * rateControlFactor).toInt() }.toIntArray()
}
val quantTableCo = if (rateControlFactor in 0.999f..1.001f) {
QUANT_TABLE_C.map { it * quantCOmult }.toIntArray()
} else {
QUANT_TABLE_C.map { (it * quantCOmult * rateControlFactor).toInt() }.toIntArray()
}
val quantTableCg = if (rateControlFactor in 0.999f..1.001f) {
QUANT_TABLE_C.map { it * quantCGmult }.toIntArray()
} else {
QUANT_TABLE_C.map { (it * quantCGmult * rateControlFactor).toInt() }.toIntArray()
}
var readPtr = blockDataPtr

File diff suppressed because it is too large Load Diff