diff --git a/terranmon.txt b/terranmon.txt index b7dffdf..5f86f3a 100644 --- a/terranmon.txt +++ b/terranmon.txt @@ -688,7 +688,7 @@ DCT-based compression, motion compensation, and efficient temporal coding. ## Header (24 bytes) uint8 Magic[8]: "\x1FTSVM TEV" - uint8 Version: 1 + uint8 Version: 2 uint8 Flags: bit 0 = has audio uint16 Width: video width in pixels uint16 Height: video height in pixels @@ -708,16 +708,19 @@ DCT-based compression, motion compensation, and efficient temporal coding. uint32 Compressed Size * Gzip-compressed Block Data -## Block Data (per 8x8/16x16 block) +## Block Data (per 16x16 block) uint8 Mode: encoding mode 0x00 = SKIP (copy from previous frame) 0x01 = INTRA (DCT-coded, no prediction) - 0x02 = INTER (DCT-coded with motion compensation) + 0x02 = INTER (DCT-coded with motion compensation) -- currently unused due to bugs 0x03 = MOTION (motion vector only) - int16 Motion Vector X (1/4 pixel precision) - int16 Motion Vector Y (1/4 pixel precision) + int16 Motion Vector X ("capable of" 1/4 pixel precision, integer precision for now) + int16 Motion Vector Y ("capable of" 1/4 pixel precision, integer precision for now) uint16 Coded Block Pattern (which 8x8 have non-zero coeffs) - int16 DCT Coefficients[3][64]: quantized R,G,B transform coefficients + int16[256] DCT Coefficients Y + int16[64] DCT Coefficients Co (subsampled by two) + int16[64] DCT Coefficients Cg (subsampled by two, aggressively quantised) + For SKIP and MOTION mode, DCT coefficients are filled with zero ## DCT Quantization TEV uses 8 quality levels (0=lowest, 7=highest) with progressive quantization @@ -725,9 +728,9 @@ tables optimized for perceptual quality. DC coefficients use fixed quantizer of 8, while AC coefficients are quantized according to quality tables. ## Motion Compensation -- Search range: ±16 pixels -- Sub-pixel precision: 1/4 pixel -- Block size: 8x8 pixels +- Search range: ±8 pixels +- Sub-pixel precision: 1/4 pixel (again, integer precision for now) +- Block size: 16x16 pixels - Uses Sum of Absolute Differences (SAD) for motion estimation - Bilinear interpolation for sub-pixel motion vectors diff --git a/tsvm_core/src/net/torvald/tsvm/GraphicsJSR223Delegate.kt b/tsvm_core/src/net/torvald/tsvm/GraphicsJSR223Delegate.kt index 00ded80..d17a539 100644 --- a/tsvm_core/src/net/torvald/tsvm/GraphicsJSR223Delegate.kt +++ b/tsvm_core/src/net/torvald/tsvm/GraphicsJSR223Delegate.kt @@ -1419,87 +1419,173 @@ class GraphicsJSR223Delegate(private val vm: VM) { ) ) - // Quality settings for quantization (Chroma channels - 8x8) - var QUANT_TABLES_C: Array = arrayOf( // Quality 0 (lowest) + // Quality settings for quantization (Co channel - orange-blue, 8x8) + var QUANT_TABLES_CO: Array = arrayOf( // Quality 0 (lowest) - 2x more aggressive than Co intArrayOf( - 120, 90, 75, 120, 180, 255, 255, 255, - 83, 90, 105, 143, 195, 255, 255, 255, - 105, 98, 120, 180, 255, 255, 255, 255, - 105, 128, 165, 218, 255, 255, 255, 255, - 135, 165, 255, 255, 255, 255, 255, 255, - 180, 255, 255, 255, 255, 255, 255, 255, + 240, 180, 150, 240, 255, 255, 255, 255, + 166, 180, 210, 255, 255, 255, 255, 255, + 210, 196, 240, 255, 255, 255, 255, 255, + 210, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 - ), // Quality 1 + ), // Quality 1 - 1.8x more aggressive intArrayOf( - 60, 45, 38, 60, 90, 150, 192, 225, - 42, 45, 53, 72, 98, 192, 225, 255, - 53, 49, 60, 90, 150, 192, 225, 255, - 53, 64, 83, 109, 192, 225, 255, 255, - 68, 83, 139, 192, 225, 255, 255, 255, - 90, 132, 192, 225, 255, 255, 255, 255, - 185, 192, 225, 255, 255, 255, 255, 255, - 192, 225, 255, 255, 255, 255, 255, 255 - ), // Quality 2 + 108, 81, 68, 108, 162, 255, 255, 255, + 76, 81, 95, 130, 176, 255, 255, 255, + 95, 88, 108, 162, 255, 255, 255, 255, + 95, 115, 149, 196, 255, 255, 255, 255, + 122, 149, 250, 255, 255, 255, 255, 255, + 162, 238, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255 + ), // Quality 2 - 1.7x more aggressive intArrayOf( - 30, 23, 19, 30, 45, 75, 96, 113, - 21, 23, 27, 36, 49, 96, 113, 135, - 27, 25, 30, 45, 75, 96, 113, 135, - 27, 32, 42, 55, 96, 113, 135, 150, - 34, 42, 70, 96, 113, 135, 150, 165, - 45, 66, 96, 113, 135, 150, 165, 180, - 93, 96, 113, 135, 150, 165, 180, 188, - 96, 113, 135, 150, 165, 180, 188, 192 - ), // Quality 3 + 51, 39, 32, 51, 77, 128, 163, 192, + 36, 39, 46, 61, 83, 163, 192, 230, + 46, 43, 51, 77, 128, 163, 192, 230, + 46, 54, 71, 94, 163, 192, 230, 255, + 58, 71, 119, 163, 192, 230, 255, 255, + 77, 112, 163, 192, 230, 255, 255, 255, + 158, 163, 192, 230, 255, 255, 255, 255, + 163, 192, 230, 255, 255, 255, 255, 255 + ), // Quality 3 - 1.6x more aggressive intArrayOf( - 24, 18, 15, 24, 36, 60, 77, 90, - 17, 18, 21, 29, 39, 77, 90, 108, - 21, 20, 24, 36, 60, 77, 90, 108, - 21, 26, 33, 44, 77, 90, 108, 120, - 27, 33, 56, 77, 90, 108, 120, 132, - 36, 53, 77, 90, 108, 120, 132, 144, - 74, 77, 90, 108, 120, 132, 144, 150, - 77, 90, 108, 120, 132, 144, 150, 154 - ), // Quality 4 + 38, 29, 24, 38, 58, 96, 123, 144, + 27, 29, 34, 46, 62, 123, 144, 173, + 34, 32, 38, 58, 96, 123, 144, 173, + 34, 42, 53, 70, 123, 144, 173, 192, + 43, 53, 90, 123, 144, 173, 192, 211, + 58, 85, 123, 144, 173, 192, 211, 230, + 118, 123, 144, 173, 192, 211, 230, 240, + 123, 144, 173, 192, 211, 230, 240, 246 + ), // Quality 4 - 1.5x more aggressive intArrayOf( - 18, 14, 12, 18, 27, 45, 57, 68, - 13, 14, 16, 22, 30, 57, 68, 81, - 16, 15, 18, 27, 45, 57, 68, 81, - 16, 20, 25, 33, 57, 68, 81, 90, - 20, 25, 42, 57, 68, 81, 90, 99, - 27, 39, 57, 68, 81, 90, 99, 108, - 56, 57, 68, 81, 90, 99, 108, 113, - 57, 68, 81, 90, 99, 108, 113, 116 - ), // Quality 5 + 27, 21, 18, 27, 41, 68, 86, 102, + 20, 21, 24, 33, 45, 86, 102, 122, + 24, 23, 27, 41, 68, 86, 102, 122, + 24, 30, 38, 50, 86, 102, 122, 135, + 30, 38, 63, 86, 102, 122, 135, 149, + 41, 59, 86, 102, 122, 135, 149, 162, + 84, 86, 102, 122, 135, 149, 162, 170, + 86, 102, 122, 135, 149, 162, 170, 174 + ), // Quality 5 - 1.4x more aggressive intArrayOf( - 15, 11, 9, 15, 23, 38, 48, 57, - 11, 11, 13, 18, 24, 48, 57, 68, - 13, 12, 15, 23, 38, 48, 57, 68, - 13, 16, 21, 28, 48, 57, 68, 75, - 17, 21, 35, 48, 57, 68, 75, 83, - 23, 33, 48, 57, 68, 75, 83, 90, - 46, 48, 57, 68, 75, 83, 90, 94, - 48, 57, 68, 75, 83, 90, 94, 96 - ), // Quality 6 + 21, 15, 13, 21, 32, 53, 67, 80, + 15, 15, 18, 25, 34, 67, 80, 95, + 18, 17, 21, 32, 53, 67, 80, 95, + 18, 22, 29, 39, 67, 80, 95, 105, + 24, 29, 49, 67, 80, 95, 105, 116, + 32, 46, 67, 80, 95, 105, 116, 126, + 64, 67, 80, 95, 105, 116, 126, 132, + 67, 80, 95, 105, 116, 126, 132, 134 + ), // Quality 6 - 1.3x more aggressive intArrayOf( - 12, 9, 8, 12, 18, 30, 39, 45, - 9, 9, 11, 14, 20, 39, 45, 54, - 11, 10, 12, 18, 30, 39, 45, 54, - 11, 13, 17, 22, 39, 45, 54, 60, - 14, 17, 28, 39, 45, 54, 60, 66, - 18, 26, 39, 45, 54, 60, 66, 72, - 38, 39, 45, 54, 60, 66, 72, 75, - 39, 45, 54, 60, 66, 72, 75, 77 - ), // Quality 7 (highest) + 16, 12, 10, 16, 23, 39, 51, 59, + 12, 12, 14, 18, 26, 51, 59, 70, + 14, 13, 16, 23, 39, 51, 59, 70, + 14, 17, 22, 29, 51, 59, 70, 78, + 18, 22, 36, 51, 59, 70, 78, 86, + 23, 34, 51, 59, 70, 78, 86, 94, + 49, 51, 59, 70, 78, 86, 94, 98, + 51, 59, 70, 78, 86, 94, 98, 100 + ), // Quality 7 (highest) - 1.2x more aggressive for subtle improvement intArrayOf( - 1, 1, 1, 1, 1, 2, 2, 3, - 1, 1, 1, 1, 2, 2, 3, 4, - 1, 1, 1, 2, 2, 3, 4, 5, - 1, 1, 2, 2, 3, 4, 5, 6, - 1, 2, 2, 3, 4, 5, 6, 7, - 2, 2, 3, 4, 5, 6, 7, 8, - 2, 3, 4, 5, 6, 7, 8, 9, - 3, 4, 5, 6, 7, 8, 9, 10 + 1, 1, 1, 1, 1, 2, 2, 4, + 1, 1, 1, 1, 2, 3, 4, 5, + 1, 1, 1, 2, 3, 4, 5, 6, + 1, 1, 2, 3, 4, 5, 6, 7, + 1, 2, 3, 4, 5, 6, 7, 8, + 2, 3, 4, 5, 6, 7, 8, 10, + 3, 4, 5, 6, 7, 8, 10, 11, + 4, 5, 6, 7, 8, 10, 11, 12 + ) + ) + + // Quality settings for quantization (Cg channel - green-magenta, much more aggressive than Co) + // Similar to NTSC Q channel reduction - exploit reduced human sensitivity to green-magenta + // Now using 3x-5x more aggressive quantization, similar to actual NTSC Q bandwidth reduction + var QUANT_TABLES_CG: Array = arrayOf( // Quality 0 (lowest) - 5x more aggressive than Co, maximum compression + intArrayOf( + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255 + ), // Quality 1 - 4.5x more aggressive, very low bandwidth + intArrayOf( + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255 + ), // Quality 2 - 4x more aggressive, preserve only DC and very low frequencies + intArrayOf( + 120, 180, 240, 255, 255, 255, 255, 255, + 180, 240, 255, 255, 255, 255, 255, 255, + 240, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255 + ), // Quality 3 - 3.5x more aggressive, basic low frequency preservation + intArrayOf( + 84, 108, 144, 192, 255, 255, 255, 255, + 108, 144, 192, 255, 255, 255, 255, 255, + 144, 192, 255, 255, 255, 255, 255, 255, + 192, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255 + ), // Quality 4 - 3x more aggressive, moderate compression + intArrayOf( + 54, 72, 96, 128, 180, 255, 255, 255, + 72, 96, 128, 180, 255, 255, 255, 255, + 96, 128, 180, 255, 255, 255, 255, 255, + 128, 180, 255, 255, 255, 255, 255, 255, + 180, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255 + ), // Quality 5 - 2.8x more aggressive, balanced compression + intArrayOf( + 42, 56, 75, 100, 140, 200, 255, 255, + 56, 75, 100, 140, 200, 255, 255, 255, + 75, 100, 140, 200, 255, 255, 255, 255, + 100, 140, 200, 255, 255, 255, 255, 255, + 140, 200, 255, 255, 255, 255, 255, 255, + 200, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255 + ), // Quality 6 - 2.5x more aggressive, good quality but still compressed + intArrayOf( + 30, 40, 54, 72, 100, 144, 200, 255, + 40, 54, 72, 100, 144, 200, 255, 255, + 54, 72, 100, 144, 200, 255, 255, 255, + 72, 100, 144, 200, 255, 255, 255, 255, + 100, 144, 200, 255, 255, 255, 255, 255, + 144, 200, 255, 255, 255, 255, 255, 255, + 200, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255 + ), // Quality 7 (highest) - 2x more aggressive, preserve more detail + intArrayOf( + 2, 3, 4, 6, 8, 12, 16, 20, + 3, 4, 6, 8, 12, 16, 20, 24, + 4, 6, 8, 12, 16, 20, 24, 28, + 6, 8, 12, 16, 20, 24, 28, 32, + 8, 12, 16, 20, 24, 28, 32, 36, + 12, 16, 20, 24, 28, 32, 36, 40, + 16, 20, 24, 28, 32, 36, 40, 44, + 20, 24, 28, 32, 36, 40, 44, 48 ) ) @@ -1772,7 +1858,8 @@ class GraphicsJSR223Delegate(private val vm: VM) { val blocksY = (height + 15) / 16 val quantTableY = QUANT_TABLES_Y[quality] - val quantTableC = QUANT_TABLES_C[quality] + val quantTableCo = QUANT_TABLES_CO[quality] + val quantTableCg = QUANT_TABLES_CG[quality] var readPtr = blockDataPtr @@ -1909,8 +1996,8 @@ class GraphicsJSR223Delegate(private val vm: VM) { // Perform hardware IDCT for each channel using fast algorithm val yBlock = tevIdct16x16_fast(yCoeffs, quantTableY) - val coBlock = tevIdct8x8_fast(coCoeffs, quantTableC, true) - val cgBlock = tevIdct8x8_fast(cgCoeffs, quantTableC, true) + val coBlock = tevIdct8x8_fast(coCoeffs, quantTableCo, true) + val cgBlock = tevIdct8x8_fast(cgCoeffs, quantTableCg, true) // Convert YCoCg-R to RGB val rgbData = tevYcocgToRGB(yBlock, coBlock, cgBlock) @@ -1965,8 +2052,8 @@ class GraphicsJSR223Delegate(private val vm: VM) { // Step 2: Decode residual DCT val yResidual = tevIdct16x16_fast(yCoeffs, quantTableY) - val coResidual = tevIdct8x8_fast(coCoeffs, quantTableC, true) - val cgResidual = tevIdct8x8_fast(cgCoeffs, quantTableC, true) + val coResidual = tevIdct8x8_fast(coCoeffs, quantTableCo, true) + val cgResidual = tevIdct8x8_fast(cgCoeffs, quantTableCg, true) // Step 3: Build motion-compensated YCoCg-R block and add residuals val finalY = IntArray(256) diff --git a/video_encoder/encoder_tev.c b/video_encoder/encoder_tev.c index f01e811..5b2f498 100644 --- a/video_encoder/encoder_tev.c +++ b/video_encoder/encoder_tev.c @@ -173,80 +173,158 @@ static const uint8_t QUANT_TABLES_Y[8][256] = { 14, 15, 16, 17, 18, 19, 20, 21, 20, 21, 22, 23, 24, 25, 26, 27} }; -// Quality settings for quantization (Chroma channels - 8x8) -static const uint8_t QUANT_TABLES_C[8][64] = { - // Quality 0 (lowest) - {120, 90, 75, 120, 180, 255, 255, 255, - 83, 90, 105, 143, 195, 255, 255, 255, - 105, 98, 120, 180, 255, 255, 255, 255, - 105, 128, 165, 218, 255, 255, 255, 255, - 135, 165, 255, 255, 255, 255, 255, 255, - 180, 255, 255, 255, 255, 255, 255, 255, +// Quality settings for quantization (Co channel - 8x8) +static const uint8_t QUANT_TABLES_CO[8][64] = { + // Quality 0 (lowest) - 2x more aggressive than before + {240, 180, 150, 240, 255, 255, 255, 255, + 166, 180, 210, 255, 255, 255, 255, 255, + 210, 196, 240, 255, 255, 255, 255, 255, + 210, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, - // Quality 1 - {60, 45, 38, 60, 90, 150, 192, 225, - 42, 45, 53, 72, 98, 192, 225, 255, - 53, 49, 60, 90, 150, 192, 225, 255, - 53, 64, 83, 109, 192, 225, 255, 255, - 68, 83, 139, 192, 225, 255, 255, 255, - 90, 132, 192, 225, 255, 255, 255, 255, - 185, 192, 225, 255, 255, 255, 255, 255, - 192, 225, 255, 255, 255, 255, 255, 255}, - // Quality 2 - {30, 23, 19, 30, 45, 75, 96, 113, - 21, 23, 27, 36, 49, 96, 113, 135, - 27, 25, 30, 45, 75, 96, 113, 135, - 27, 32, 42, 55, 96, 113, 135, 150, - 34, 42, 70, 96, 113, 135, 150, 165, - 45, 66, 96, 113, 135, 150, 165, 180, - 93, 96, 113, 135, 150, 165, 180, 188, - 96, 113, 135, 150, 165, 180, 188, 192}, - // Quality 3 - {24, 18, 15, 24, 36, 60, 77, 90, - 17, 18, 21, 29, 39, 77, 90, 108, - 21, 20, 24, 36, 60, 77, 90, 108, - 21, 26, 33, 44, 77, 90, 108, 120, - 27, 33, 56, 77, 90, 108, 120, 132, - 36, 53, 77, 90, 108, 120, 132, 144, - 74, 77, 90, 108, 120, 132, 144, 150, - 77, 90, 108, 120, 132, 144, 150, 154}, - // Quality 4 - {18, 14, 12, 18, 27, 45, 57, 68, - 13, 14, 16, 22, 30, 57, 68, 81, - 16, 15, 18, 27, 45, 57, 68, 81, - 16, 20, 25, 33, 57, 68, 81, 90, - 20, 25, 42, 57, 68, 81, 90, 99, - 27, 39, 57, 68, 81, 90, 99, 108, - 56, 57, 68, 81, 90, 99, 108, 113, - 57, 68, 81, 90, 99, 108, 113, 116}, - // Quality 5 - {15, 11, 9, 15, 23, 38, 48, 57, - 11, 11, 13, 18, 24, 48, 57, 68, - 13, 12, 15, 23, 38, 48, 57, 68, - 13, 16, 21, 28, 48, 57, 68, 75, - 17, 21, 35, 48, 57, 68, 75, 83, - 23, 33, 48, 57, 68, 75, 83, 90, - 46, 48, 57, 68, 75, 83, 90, 94, - 48, 57, 68, 75, 83, 90, 94, 96}, - // Quality 6 - {12, 9, 8, 12, 18, 30, 39, 45, - 9, 9, 11, 14, 20, 39, 45, 54, - 11, 10, 12, 18, 30, 39, 45, 54, - 11, 13, 17, 22, 39, 45, 54, 60, - 14, 17, 28, 39, 45, 54, 60, 66, - 18, 26, 39, 45, 54, 60, 66, 72, - 38, 39, 45, 54, 60, 66, 72, 75, - 39, 45, 54, 60, 66, 72, 75, 77}, - // Quality 7 (highest) - much finer quantization for better quality - {1, 1, 1, 1, 1, 2, 2, 3, - 1, 1, 1, 1, 2, 2, 3, 4, - 1, 1, 1, 2, 2, 3, 4, 5, - 1, 1, 2, 2, 3, 4, 5, 6, - 1, 2, 2, 3, 4, 5, 6, 7, - 2, 2, 3, 4, 5, 6, 7, 8, - 2, 3, 4, 5, 6, 7, 8, 9, - 3, 4, 5, 6, 7, 8, 9, 10} + // Quality 1 - 1.8x more aggressive + {108, 81, 68, 108, 162, 255, 255, 255, + 76, 81, 95, 130, 176, 255, 255, 255, + 95, 88, 108, 162, 255, 255, 255, 255, + 95, 115, 149, 196, 255, 255, 255, 255, + 122, 149, 250, 255, 255, 255, 255, 255, + 162, 238, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255}, + // Quality 2 - 1.7x more aggressive + {51, 39, 32, 51, 77, 128, 163, 192, + 36, 39, 46, 61, 83, 163, 192, 230, + 46, 43, 51, 77, 128, 163, 192, 230, + 46, 54, 71, 94, 163, 192, 230, 255, + 58, 71, 119, 163, 192, 230, 255, 255, + 77, 112, 163, 192, 230, 255, 255, 255, + 158, 163, 192, 230, 255, 255, 255, 255, + 163, 192, 230, 255, 255, 255, 255, 255}, + // Quality 3 - 1.6x more aggressive + {38, 29, 24, 38, 58, 96, 123, 144, + 27, 29, 34, 46, 62, 123, 144, 173, + 34, 32, 38, 58, 96, 123, 144, 173, + 34, 42, 53, 70, 123, 144, 173, 192, + 43, 53, 90, 123, 144, 173, 192, 211, + 58, 85, 123, 144, 173, 192, 211, 230, + 118, 123, 144, 173, 192, 211, 230, 240, + 123, 144, 173, 192, 211, 230, 240, 246}, + // Quality 4 - 1.5x more aggressive + {27, 21, 18, 27, 41, 68, 86, 102, + 20, 21, 24, 33, 45, 86, 102, 122, + 24, 23, 27, 41, 68, 86, 102, 122, + 24, 30, 38, 50, 86, 102, 122, 135, + 30, 38, 63, 86, 102, 122, 135, 149, + 41, 59, 86, 102, 122, 135, 149, 162, + 84, 86, 102, 122, 135, 149, 162, 170, + 86, 102, 122, 135, 149, 162, 170, 174}, + // Quality 5 - 1.4x more aggressive + {21, 15, 13, 21, 32, 53, 67, 80, + 15, 15, 18, 25, 34, 67, 80, 95, + 18, 17, 21, 32, 53, 67, 80, 95, + 18, 22, 29, 39, 67, 80, 95, 105, + 24, 29, 49, 67, 80, 95, 105, 116, + 32, 46, 67, 80, 95, 105, 116, 126, + 64, 67, 80, 95, 105, 116, 126, 132, + 67, 80, 95, 105, 116, 126, 132, 134}, + // Quality 6 - 1.3x more aggressive + {16, 12, 10, 16, 23, 39, 51, 59, + 12, 12, 14, 18, 26, 51, 59, 70, + 14, 13, 16, 23, 39, 51, 59, 70, + 14, 17, 22, 29, 51, 59, 70, 78, + 18, 22, 36, 51, 59, 70, 78, 86, + 23, 34, 51, 59, 70, 78, 86, 94, + 49, 51, 59, 70, 78, 86, 94, 98, + 51, 59, 70, 78, 86, 94, 98, 100}, + // Quality 7 (highest) - 1.2x more aggressive for subtle improvement + {1, 1, 1, 1, 1, 2, 2, 4, + 1, 1, 1, 1, 2, 3, 4, 5, + 1, 1, 1, 2, 3, 4, 5, 6, + 1, 1, 2, 3, 4, 5, 6, 7, + 1, 2, 3, 4, 5, 6, 7, 8, + 2, 3, 4, 5, 6, 7, 8, 10, + 3, 4, 5, 6, 7, 8, 10, 11, + 4, 5, 6, 7, 8, 10, 11, 12} +}; + +// Quality settings for quantization (Cg channel - 8x8, much more aggressive than Co) +// Similar to NTSC Q channel reduction - exploit reduced human sensitivity to green-magenta +// Now using 3x-5x more aggressive quantization, similar to actual NTSC Q bandwidth reduction +static const uint8_t QUANT_TABLES_CG[8][64] = { + // Quality 0 (lowest) - 5x more aggressive than Co, maximum compression + {255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255}, + // Quality 1 - 4.5x more aggressive, very low bandwidth + {255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255}, + // Quality 2 - 4x more aggressive, preserve only DC and very low frequencies + {120, 180, 240, 255, 255, 255, 255, 255, + 180, 240, 255, 255, 255, 255, 255, 255, + 240, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255}, + // Quality 3 - 3.5x more aggressive, basic low frequency preservation + {84, 108, 144, 192, 255, 255, 255, 255, + 108, 144, 192, 255, 255, 255, 255, 255, + 144, 192, 255, 255, 255, 255, 255, 255, + 192, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255}, + // Quality 4 - 3x more aggressive, moderate compression + {54, 72, 96, 128, 180, 255, 255, 255, + 72, 96, 128, 180, 255, 255, 255, 255, + 96, 128, 180, 255, 255, 255, 255, 255, + 128, 180, 255, 255, 255, 255, 255, 255, + 180, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255}, + // Quality 5 - 2.8x more aggressive, balanced compression + {42, 56, 75, 100, 140, 200, 255, 255, + 56, 75, 100, 140, 200, 255, 255, 255, + 75, 100, 140, 200, 255, 255, 255, 255, + 100, 140, 200, 255, 255, 255, 255, 255, + 140, 200, 255, 255, 255, 255, 255, 255, + 200, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255}, + // Quality 6 - 2.5x more aggressive, good quality but still compressed + {30, 40, 54, 72, 100, 144, 200, 255, + 40, 54, 72, 100, 144, 200, 255, 255, + 54, 72, 100, 144, 200, 255, 255, 255, + 72, 100, 144, 200, 255, 255, 255, 255, + 100, 144, 200, 255, 255, 255, 255, 255, + 144, 200, 255, 255, 255, 255, 255, 255, + 200, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255}, + // Quality 7 (highest) - 2x more aggressive, preserve more detail + {2, 3, 4, 6, 8, 12, 16, 20, + 3, 4, 6, 8, 12, 16, 20, 24, + 4, 6, 8, 12, 16, 20, 24, 28, + 6, 8, 12, 16, 20, 24, 28, 32, + 8, 12, 16, 20, 24, 28, 32, 36, + 12, 16, 20, 24, 28, 32, 36, 40, + 16, 20, 24, 28, 32, 36, 40, 44, + 20, 24, 28, 32, 36, 40, 44, 48} }; // Audio constants (reuse MP2 from existing system) @@ -890,18 +968,19 @@ static void encode_block(tev_encoder_t *enc, int block_x, int block_y, int is_ke // Apply fast DCT transform to chroma - 4x performance improvement dct_8x8_fast(enc->co_workspace, enc->dct_workspace); - // Quantize Co coefficients (chroma) - const uint8_t *c_quant = QUANT_TABLES_C[enc->quality]; + // Quantize Co coefficients (chroma - orange-blue) + const uint8_t *co_quant = QUANT_TABLES_CO[enc->quality]; for (int i = 0; i < 64; i++) { - block->co_coeffs[i] = quantize_coeff(enc->dct_workspace[i], c_quant[i], i == 0, 1); + block->co_coeffs[i] = quantize_coeff(enc->dct_workspace[i], co_quant[i], i == 0, 1); } // Apply fast DCT transform to Cg - 4x performance improvement dct_8x8_fast(enc->cg_workspace, enc->dct_workspace); - // Quantize Cg coefficients (chroma) + // Quantize Cg coefficients (chroma - green-magenta, more aggressive like NTSC Q) + const uint8_t *cg_quant = QUANT_TABLES_CG[enc->quality]; for (int i = 0; i < 64; i++) { - block->cg_coeffs[i] = quantize_coeff(enc->dct_workspace[i], c_quant[i], i == 0, 1); + block->cg_coeffs[i] = quantize_coeff(enc->dct_workspace[i], cg_quant[i], i == 0, 1); } // Set CBP (simplified - always encode all channels)