diff --git a/assets/disk0/tvdos/bin/playtav.js b/assets/disk0/tvdos/bin/playtav.js index 92d6090..9e18219 100644 --- a/assets/disk0/tvdos/bin/playtav.js +++ b/assets/disk0/tvdos/bin/playtav.js @@ -644,11 +644,23 @@ try { notifHidden = true } - con.move(32, 1) + con.color_pair(253, 0) - print(`B=${(getVideoRate() / 1024 * 8)|0}k F=${frameCount}/${header.totalFrames} qY=${decoderDbgInfo.qY} f=${(frameCount / akku2).toFixed(2)}`) - con.color_pair(255, 255);print(" ") - con.move(1, 1) + let guiStatus = { + fps: header.fps, + videoRate: getVideoRate(), + frameCount: frameCount, + totalFrames: header.totalFrames, + qY: decoderDbgInfo.qY, + qCo: decoderDbgInfo.qCo, + qCg: decoderDbgInfo.qCg, + akku: akku2, + fileName: fullFilePathStr, + fileOrd: currentFileIndex, + currentStatus: 1 + } + gui.printBottomBar(guiStatus) + gui.printTopBar(guiStatus, 1) } t1 = t2 diff --git a/assets/disk0/tvdos/include/playgui.mjs b/assets/disk0/tvdos/include/playgui.mjs index ca027e7..ef26107 100644 --- a/assets/disk0/tvdos/include/playgui.mjs +++ b/assets/disk0/tvdos/include/playgui.mjs @@ -172,7 +172,121 @@ function displaySubtitle(text, position = 0) { con.color_pair(oldFgColour, oldBgColour) } +function emit(c) { + return "\x84"+c+"u" +} + +function formatTime(seconds) { + const hours = Math.floor(seconds / 3600) + const minutes = Math.floor((seconds % 3600) / 60) + const secs = Math.floor(seconds % 60) + + return [hours, minutes, secs] + .map(val => val.toString().padStart(2, '0')) + .join(':') +} + +function drawProgressBar(progress, width) { + // Clamp progress between 0 and 1 + progress = Math.max(0, Math.min(1, progress)); + + // Calculate position in "half-character" resolution + const position = progress * width * 2; + const charIndex = Math.floor(position / 2); + const isRightHalf = (position % 2) >= 1; + + let bar = ''; + + for (let i = 0; i < width; i++) { + if (i == charIndex) { + bar += isRightHalf ? '\xDE' : '\xDD'; + } else { + bar += '\xC4'; + } + } + + return bar; +} + +/* +status = { + videoRate: int, + frameCount: int, + totalFrames: int, + fps: int, + qY: int, + akku: float, + fileName: String, + fileOrd: int, + currentStatus: int (0: stop/init, 1: play, 2: pause) +} + +*/ +function printBottomBar(status) { + con.color_pair(253, 0) + con.move(32, 1) + + const fullTimeInSec = status.totalFrames / status.fps + const progress = status.frameCount / (status.totalFrames - 1) + const elapsed = progress * fullTimeInSec + const remaining = (1 - progress) * fullTimeInSec + + const BAR = '\xB3' + const statIcon = [emit(0xFE), emit(0x10), emit(0x13)] + let sLeft = `${emit(0x1E)}${status.fileOrd}${emit(0x1F)}${BAR}${statIcon[status.currentStatus]} ` + let sRate = `${BAR}${(''+((status.videoRate/128)|0)).padStart(6, ' ')}` + let timeElapsed = formatTime(elapsed) + let timeRemaining = formatTime(remaining) + let barWidth = 80 - (sLeft.length - 8 - ((status.currentStatus == 0) ? 1 : 0) + timeElapsed.length + timeRemaining.length + sRate.length) - 2 + let bar = drawProgressBar(progress, barWidth) + + let s = sLeft + timeElapsed + ' ' + bar + ' ' + timeRemaining + sRate + print(s);con.addch(0x4B) + + con.move(1, 1) +} + +function printTopBar(status, moreInfo) { + con.color_pair(253, 0) + con.move(1) + + const BAR = '\xB3' + + if (moreInfo) { + let filename = status.fileName.split("\\").pop() + + let sF = `F ${(''+status.frameCount).padStart((''+status.totalFrames).length, ' ')}/${status.totalFrames}` + let sQ = `Q${(''+status.qY).padStart(4,' ')},${(''+status.qCo).padStart(2,' ')},${(''+status.qCg).padStart(2,' ')}` + let sFPS = `${(status.frameCount / status.akku).toFixed(2)}f` + + let sLeft = sF + BAR + sQ + BAR + sFPS + BAR + let filenameSpace = 80 - sLeft.length + if (filename.length > filenameSpace) { + filename = filename.slice(0, filenameSpace - 1) + '~' + } + let remainingSpc = filenameSpace - status.fileName.length + let sRight = (remainingSpc > 0) ? ' '.repeat(filenameSpace - status.fileName.length + 3) : '' + + print(sLeft + filename + sRight) + } else { + let s = status.fileName + if (s.length > 80) { + s = s.slice(0, 79) + '~' + } + let spcs = 80 - s.length + let spcsLeft = (spcs / 2)|0 + let spcsRight = spcs - spcsLeft + print(' '.repeat(spcsLeft)) + print(s) + print(' '.repeat(spcsRight)) + } + + con.move(1, 1) +} + exports = { clearSubtitleArea, - displaySubtitle + displaySubtitle, + printTopBar, + printBottomBar } \ No newline at end of file diff --git a/tsvm_core/src/net/torvald/tsvm/GraphicsJSR223Delegate.kt b/tsvm_core/src/net/torvald/tsvm/GraphicsJSR223Delegate.kt index d197653..ed7c14f 100644 --- a/tsvm_core/src/net/torvald/tsvm/GraphicsJSR223Delegate.kt +++ b/tsvm_core/src/net/torvald/tsvm/GraphicsJSR223Delegate.kt @@ -4394,6 +4394,8 @@ class GraphicsJSR223Delegate(private val vm: VM) { val qCg = vm.peek(readPtr++).toUint().let { if (it == 0) qCgGlobal else TAV_QLUT[it - 1] } dbgOut["qY"] = qY + dbgOut["qCo"] = qCo + dbgOut["qCg"] = qCg // debug print: raw decompressed bytes /*print("TAV Decode raw bytes (Frame $frameCount, mode: ${arrayOf("SKIP", "INTRA", "DELTA")[mode]}): ") diff --git a/video_encoder/encoder_tav.c b/video_encoder/encoder_tav.c index e75aa91..01a34c9 100644 --- a/video_encoder/encoder_tav.c +++ b/video_encoder/encoder_tav.c @@ -2375,6 +2375,7 @@ static int start_audio_conversion(tav_encoder_t *enc) { } else { bitrate = enc->lossless ? 384 : MP2_RATE_TABLE[enc->quality_level]; } + printf(" Audio format: MP2 %dkbps (via libtwolame)\n", bitrate); snprintf(command, sizeof(command), "ffmpeg -v quiet -i \"%s\" -acodec libtwolame -psymodel 4 -b:a %dk -ar 32000 -ac 2 -y \"%s\" 2>/dev/null", enc->input_file, bitrate, TEMP_AUDIO_FILE); @@ -3366,15 +3367,12 @@ int main(int argc, char *argv[]) { enc->wavelet_filter == WAVELET_HAAR ? "Haar" : "unknown"); printf("Decomposition levels: %d\n", enc->decomp_levels); printf("Colour space: %s\n", enc->ictcp_mode ? "ICtCp" : "YCoCg-R"); - printf("Quantisation: %s\n", enc->perceptual_tuning ? "Perceptual (HVS-optimised)" : "Uniform (legacy)"); + printf("Quantisation: %s\n", enc->perceptual_tuning ? "Perceptual (HVS-optimised)" : "Uniform"); if (enc->ictcp_mode) { printf("Base quantiser: I=%d, Ct=%d, Cp=%d\n", QLUT[enc->quantiser_y], QLUT[enc->quantiser_co], QLUT[enc->quantiser_cg]); } else { printf("Base quantiser: Y=%d, Co=%d, Cg=%d\n", QLUT[enc->quantiser_y], QLUT[enc->quantiser_co], QLUT[enc->quantiser_cg]); } - if (enc->perceptual_tuning) { - printf("Perceptual tuning enabled\n"); - } // Open output file if (strcmp(enc->output_file, "-") == 0) {