From 7f951366da6581ff8c70062fb08ebf2c17f27199 Mon Sep 17 00:00:00 2001 From: minjaesong Date: Sat, 6 Dec 2025 23:49:16 +0900 Subject: [PATCH] tavlib: quant fix 2 --- assets/disk0/tvdos/bin/playtav.js | 7 +++ .../torvald/tsvm/GraphicsJSR223Delegate.kt | 53 +++++++++++-------- video_encoder/lib/libtavenc/tav_encoder_lib.c | 12 +---- 3 files changed, 39 insertions(+), 33 deletions(-) diff --git a/assets/disk0/tvdos/bin/playtav.js b/assets/disk0/tvdos/bin/playtav.js index 328afa4..6e076f5 100644 --- a/assets/disk0/tvdos/bin/playtav.js +++ b/assets/disk0/tvdos/bin/playtav.js @@ -1336,6 +1336,7 @@ try { graphics.tavDecodeGopToVideoBufferAsync( compressedPtr, compressedSize, gopSize, header.width, decodeHeight, // Use decodeHeight for interlaced field support + baseVersion >= 5, header.qualityLevel, QLUT[header.qualityY], QLUT[header.qualityCo], QLUT[header.qualityCg], header.channelLayout, @@ -1411,6 +1412,7 @@ try { graphics.tavDecodeGopToVideoBufferAsync( compressedPtr, compressedSize, gopSize, header.width, decodeHeight, // Use decodeHeight for interlaced field support + baseVersion >= 5, header.qualityLevel, QLUT[header.qualityY], QLUT[header.qualityCo], QLUT[header.qualityCg], header.channelLayout, @@ -1455,6 +1457,7 @@ try { graphics.tavDecodeGopToVideoBufferAsync( compressedPtr, compressedSize, gopSize, header.width, decodeHeight, // Use decodeHeight for interlaced field support + baseVersion >= 5, header.qualityLevel, QLUT[header.qualityY], QLUT[header.qualityCo], QLUT[header.qualityCg], header.channelLayout, @@ -1824,6 +1827,7 @@ try { graphics.tavDecodeGopToVideoBufferAsync( readyGopData.compressedPtr, readyGopData.compressedSize, readyGopData.gopSize, header.width, decodeHeight, // Use decodeHeight for interlaced field support + baseVersion >= 5, header.qualityLevel, QLUT[header.qualityY], QLUT[header.qualityCo], QLUT[header.qualityCg], header.channelLayout, @@ -2017,6 +2021,7 @@ try { graphics.tavDecodeGopToVideoBufferAsync( decodingGopData.compressedPtr, decodingGopData.compressedSize, decodingGopData.gopSize, header.width, header.height, + baseVersion >= 5, header.qualityLevel, QLUT[header.qualityY], QLUT[header.qualityCo], QLUT[header.qualityCg], header.channelLayout, @@ -2059,6 +2064,7 @@ try { graphics.tavDecodeGopToVideoBufferAsync( readyGopData.compressedPtr, readyGopData.compressedSize, readyGopData.gopSize, header.width, decodeHeight, // Use decodeHeight for interlaced field support + baseVersion >= 5, header.qualityLevel, QLUT[header.qualityY], QLUT[header.qualityCo], QLUT[header.qualityCg], header.channelLayout, @@ -2138,6 +2144,7 @@ try { graphics.tavDecodeGopToVideoBufferAsync( overflow.compressedPtr, overflow.compressedSize, overflow.gopSize, header.width, decodeHeight, // Use decodeHeight for interlaced field support + baseVersion >= 5, header.qualityLevel, QLUT[header.qualityY], QLUT[header.qualityCo], QLUT[header.qualityCg], header.channelLayout, diff --git a/tsvm_core/src/net/torvald/tsvm/GraphicsJSR223Delegate.kt b/tsvm_core/src/net/torvald/tsvm/GraphicsJSR223Delegate.kt index f95c473..2e5e9ad 100644 --- a/tsvm_core/src/net/torvald/tsvm/GraphicsJSR223Delegate.kt +++ b/tsvm_core/src/net/torvald/tsvm/GraphicsJSR223Delegate.kt @@ -6483,6 +6483,7 @@ class GraphicsJSR223Delegate(private val vm: VM) { gopSize: Int, width: Int, height: Int, + isPerceptual: Boolean, qIndex: Int, qYGlobal: Int, qCoGlobal: Int, @@ -6577,28 +6578,33 @@ class GraphicsJSR223Delegate(private val vm: VM) { val baseQCo = kotlin.math.round(qCoGlobal * temporalScale).coerceIn(1.0f, 4096.0f) val baseQCg = kotlin.math.round(qCgGlobal * temporalScale).coerceIn(1.0f, 4096.0f) - - dequantiseDWTSubbandsPerceptual( - qIndex, qYGlobal, - quantizedCoeffs[t][0], gopY[t], - subbands, baseQY, false, spatialLevels, - isEZBCMode - ) - - - dequantiseDWTSubbandsPerceptual( - qIndex, qYGlobal, - quantizedCoeffs[t][1], gopCo[t], - subbands, baseQCo, true, spatialLevels, - isEZBCMode - ) - - dequantiseDWTSubbandsPerceptual( - qIndex, qYGlobal, - quantizedCoeffs[t][2], gopCg[t], - subbands, baseQCg, true, spatialLevels, - isEZBCMode - ) + if (isPerceptual) { + dequantiseDWTSubbandsPerceptual( + qIndex, qYGlobal, + quantizedCoeffs[t][0], gopY[t], + subbands, baseQY, false, spatialLevels, + isEZBCMode + ) + dequantiseDWTSubbandsPerceptual( + qIndex, qYGlobal, + quantizedCoeffs[t][1], gopCo[t], + subbands, baseQCo, true, spatialLevels, + isEZBCMode + ) + dequantiseDWTSubbandsPerceptual( + qIndex, qYGlobal, + quantizedCoeffs[t][2], gopCg[t], + subbands, baseQCg, true, spatialLevels, + isEZBCMode + ) + } + else { + for (i in 0 until width * height) { + gopY[t][i] = quantizedCoeffs[t][0][i] * baseQY + gopCo[t][i] = quantizedCoeffs[t][1][i] * baseQCo + gopCg[t][i] = quantizedCoeffs[t][2][i] * baseQCg + } + } } @@ -6841,6 +6847,7 @@ class GraphicsJSR223Delegate(private val vm: VM) { gopSize: Int, width: Int, height: Int, + isPerceptual: Boolean, qIndex: Int, qYGlobal: Int, qCoGlobal: Int, @@ -6867,7 +6874,7 @@ class GraphicsJSR223Delegate(private val vm: VM) { try { val result = tavDecodeGopToVideoBuffer( compressedDataPtr, compressedSize, gopSize, - width, height, + width, height, isPerceptual, qIndex, qYGlobal, qCoGlobal, qCgGlobal, channelLayout, spatialFilter, spatialLevels, temporalLevels, entropyCoder, bufferOffset, temporalMotionCoder, encoderPreset diff --git a/video_encoder/lib/libtavenc/tav_encoder_lib.c b/video_encoder/lib/libtavenc/tav_encoder_lib.c index 62af123..3acfeed 100644 --- a/video_encoder/lib/libtavenc/tav_encoder_lib.c +++ b/video_encoder/lib/libtavenc/tav_encoder_lib.c @@ -1464,15 +1464,9 @@ static int encode_gop_unified(tav_encoder_context_t *ctx, gop_slot_t *slot) { int base_quantiser_co = QLUT[ctx->quantiser_co]; int base_quantiser_cg = QLUT[ctx->quantiser_cg]; - // CRITICAL: Force perceptual quantization for GOPs to match old encoder behavior - // The old encoder's quantise_dwt_coefficients_perceptual_per_coeff() does NOT check - // perceptual_tuning flag - it always applies perceptual weights for GOP encoding. - // The --no-perceptual-tuning flag only affects I-frame encoding in the old encoder. - int saved_perceptual = ctx->compat_enc->perceptual_tuning; - ctx->compat_enc->perceptual_tuning = 1; // Force perceptual for GOP encoding - + // Use perceptual or uniform quantization based on user setting if (ctx->verbose) { - fprintf(stderr, "[DEBUG] GOP quantization: decomp_levels=%d, base_q_y=%d, perceptual=%d (forced on for GOP), preset=0x%02x\n", + fprintf(stderr, "[DEBUG] GOP quantization: decomp_levels=%d, base_q_y=%d, perceptual=%d, preset=0x%02x\n", ctx->compat_enc->decomp_levels, base_quantiser_y, ctx->compat_enc->perceptual_tuning, ctx->compat_enc->encoder_preset); } @@ -1483,8 +1477,6 @@ static int encode_gop_unified(tav_encoder_context_t *ctx, gop_slot_t *slot) { tav_quantise_3d_dwt(ctx->compat_enc, work_cg, quant_cg, num_frames, num_pixels, base_quantiser_cg, 1); - ctx->compat_enc->perceptual_tuning = saved_perceptual; // Restore for I-frames - // Step 4: Unified GOP preprocessing (EZBC only) size_t preprocess_capacity = num_pixels * num_frames * 3 * sizeof(int16_t) + 65536; uint8_t *preprocess_buffer = tav_malloc(preprocess_capacity);