mirror of
https://github.com/curioustorvald/tsvm.git
synced 2026-06-09 22:54:03 +09:00
rate control not quite working but committing anyway due to format change
This commit is contained in:
@@ -201,8 +201,20 @@ try {
|
|||||||
sys.memcpy(CURRENT_RGB_ADDR, PREV_RGB_ADDR, FRAME_PIXELS * 3)
|
sys.memcpy(CURRENT_RGB_ADDR, PREV_RGB_ADDR, FRAME_PIXELS * 3)
|
||||||
|
|
||||||
} else if (packetType == TEV_PACKET_IFRAME || packetType == TEV_PACKET_PFRAME) {
|
} 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()
|
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)
|
let compressedPtr = seqread.readBytes(payloadLen)
|
||||||
updateDataRateBin(payloadLen)
|
updateDataRateBin(payloadLen)
|
||||||
|
|
||||||
@@ -232,9 +244,9 @@ try {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hardware-accelerated TEV YCoCg-R decoding to RGB buffers
|
// Hardware-accelerated TEV YCoCg-R decoding to RGB buffers (with rate control factor)
|
||||||
try {
|
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
|
// Upload RGB buffer to display framebuffer with dithering
|
||||||
graphics.uploadRGBToFramebuffer(CURRENT_RGB_ADDR, DISPLAY_RG_ADDR, DISPLAY_BA_ADDR,
|
graphics.uploadRGBToFramebuffer(CURRENT_RGB_ADDR, DISPLAY_RG_ADDR, DISPLAY_BA_ADDR,
|
||||||
|
|||||||
@@ -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
|
TEV is a modern video codec optimized for TSVM's 4096-color hardware, featuring
|
||||||
DCT-based compression, motion compensation, and efficient temporal coding.
|
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
|
# File Structure
|
||||||
\x1F T S V M T E V
|
\x1F T S V M T E V
|
||||||
[HEADER]
|
[HEADER]
|
||||||
@@ -694,7 +700,7 @@ DCT-based compression, motion compensation, and efficient temporal coding.
|
|||||||
uint16 Height: video height in pixels
|
uint16 Height: video height in pixels
|
||||||
uint16 FPS: frames per second
|
uint16 FPS: frames per second
|
||||||
uint32 Total Frames: number of video frames
|
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
|
byte[5] Reserved
|
||||||
|
|
||||||
## Packet Types
|
## Packet Types
|
||||||
@@ -705,7 +711,8 @@ DCT-based compression, motion compensation, and efficient temporal coding.
|
|||||||
|
|
||||||
## Video Packet Structure
|
## Video Packet Structure
|
||||||
uint8 Packet Type
|
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
|
* Gzip-compressed Block Data
|
||||||
|
|
||||||
## Block Data (per 16x16 block)
|
## 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)
|
int16[64] DCT Coefficients Cg (subsampled by two, aggressively quantised)
|
||||||
For SKIP and MOTION mode, DCT coefficients are filled with zero
|
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
|
TEV uses 8 quality levels (0=lowest, 7=highest) with progressive quantization
|
||||||
tables optimized for perceptual quality. DC coefficients use fixed quantizer
|
tables optimized for perceptual quality. DC coefficients use fixed quantizer
|
||||||
of 8, while AC coefficients are quantized according to quality tables.
|
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
|
## Motion Compensation
|
||||||
- Search range: ±8 pixels
|
- Search range: ±8 pixels
|
||||||
- Sub-pixel precision: 1/4 pixel (again, integer precision for now)
|
- Sub-pixel precision: 1/4 pixel (again, integer precision for now)
|
||||||
|
|||||||
@@ -1567,7 +1567,8 @@ class GraphicsJSR223Delegate(private val vm: VM) {
|
|||||||
* @param frameCounter Frame counter for temporal patterns
|
* @param frameCounter Frame counter for temporal patterns
|
||||||
*/
|
*/
|
||||||
fun tevDecode(blockDataPtr: Long, currentRGBAddr: Long, prevRGBAddr: Long,
|
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 blocksX = (width + 15) / 16 // 16x16 blocks now
|
||||||
val blocksY = (height + 15) / 16
|
val blocksY = (height + 15) / 16
|
||||||
@@ -1576,9 +1577,22 @@ class GraphicsJSR223Delegate(private val vm: VM) {
|
|||||||
val quantCOmult = QUANT_MULT_CO[quality]
|
val quantCOmult = QUANT_MULT_CO[quality]
|
||||||
val quantCGmult = QUANT_MULT_CG[quality]
|
val quantCGmult = QUANT_MULT_CG[quality]
|
||||||
|
|
||||||
val quantTableY = QUANT_TABLE_Y.map { it * quantYmult }.toIntArray()
|
// Apply rate control factor to quantization tables (if not ~1.0, skip optimization)
|
||||||
val quantTableCo = QUANT_TABLE_C.map { it * quantCOmult }.toIntArray()
|
val quantTableY = if (rateControlFactor in 0.999f..1.001f) {
|
||||||
val quantTableCg = QUANT_TABLE_C.map { it * quantCGmult }.toIntArray()
|
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
|
var readPtr = blockDataPtr
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user