turns out extra sync packet at the end of video was a terrible idea

This commit is contained in:
minjaesong
2025-09-22 22:38:32 +09:00
parent e001445095
commit 05101ecd08
4 changed files with 123 additions and 15 deletions

View File

@@ -562,13 +562,117 @@ let trueFrameCount = 0
let stopPlay = false
let akku = FRAME_TIME
let akku2 = 0.0
let currentFileIndex = 1 // Track which file we're playing in concatenated stream
let blockDataPtr = sys.malloc(2377744)
// Playback loop - properly adapted from TEV
// Function to try reading next TAV file header at current position
function tryReadNextTAVHeader() {
// Save current position
let currentPos = seqread.getReadCount()
// Try to read magic number
let newMagic = new Array(8)
try {
for (let i = 0; i < 8; i++) {
newMagic[i] = seqread.readOneByte()
}
// compensating the old encoder emitting extra sync packets
while (newMagic[0] == 255) {
newMagic.shift(); newMagic[7] = seqread.readOneByte()
}
// Check if it matches TAV magic
let isValidTAV = true
for (let i = 0; i < 8; i++) {
if (newMagic[i] !== TAV_MAGIC[i]) {
isValidTAV = false
serial.printerr("Header mismatch: got "+newMagic.join())
break
}
}
if (isValidTAV) {
// Read the rest of the header
let newHeader = {
magic: newMagic,
version: seqread.readOneByte(),
width: seqread.readShort(),
height: seqread.readShort(),
fps: seqread.readOneByte(),
totalFrames: seqread.readInt(),
waveletFilter: seqread.readOneByte(),
decompLevels: seqread.readOneByte(),
qualityY: seqread.readOneByte(),
qualityCo: seqread.readOneByte(),
qualityCg: seqread.readOneByte(),
extraFlags: seqread.readOneByte(),
videoFlags: seqread.readOneByte(),
reserved: new Array(7)
}
// Skip reserved bytes
for (let i = 0; i < 7; i++) {
seqread.readOneByte()
}
return newHeader
}
} catch (e) {
serial.printerr(e)
// EOF or read error - restore position and return null
// Note: seqread doesn't have seek, so we can't restore position
// This is okay since we're at EOF anyway
}
return null
}
// Playback loop - properly adapted from TEV with multi-file support
try {
let t1 = sys.nanoTime()
while (!stopPlay && seqread.getReadCount() < FILE_LENGTH && (header.totalFrames == 0 || header.totalFrames > 0 && frameCount < header.totalFrames)) {
let totalFilesProcessed = 0
while (!stopPlay && seqread.getReadCount() < FILE_LENGTH) {
// Check if we've finished the current file
if (header.totalFrames > 0 && frameCount >= header.totalFrames) {
console.log(`Completed file ${currentFileIndex}: ${frameCount} frames`)
// Try to read next TAV file header
let nextHeader = tryReadNextTAVHeader()
if (nextHeader) {
// Found another TAV file - update header and reset counters
header = nextHeader
frameCount = 0
currentFileIndex++
totalFilesProcessed++
console.log(`\nStarting file ${currentFileIndex}:`)
console.log(`Resolution: ${header.width}x${header.height}`)
console.log(`FPS: ${header.fps}`)
console.log(`Total frames: ${header.totalFrames}`)
console.log(`Wavelet filter: ${header.waveletFilter === WAVELET_5_3_REVERSIBLE ? "5/3 reversible" : "9/7 irreversible"}`)
console.log(`Quality: Y=${header.qualityY}, Co=${header.qualityCo}, Cg=${header.qualityCg}`)
// Reset motion vectors for new file
for (let i = 0; i < numTiles; i++) {
motionVectors[i] = { mvX: 0, mvY: 0, rcf: 1.0 }
}
// Continue with new file
continue
} else {
// No more TAV files found
console.log(`\nNo more TAV files found. Total files processed: ${currentFileIndex}`)
break
}
}
// Original playback loop condition (but without totalFrames check since we handle it above)
if (seqread.getReadCount() >= FILE_LENGTH) {
break
}
// Handle interactive controls
if (interactive) {
@@ -713,7 +817,11 @@ try {
if (!hasSubtitles) {
con.move(31, 1)
con.color_pair(253, 0)
print(`Frame: ${frameCount}/${header.totalFrames} (${((frameCount / akku2 * 100)|0) / 100}f) `)
if (currentFileIndex > 1) {
print(`File ${currentFileIndex}: ${frameCount}/${header.totalFrames} (${((frameCount / akku2 * 100)|0) / 100}f) `)
} else {
print(`Frame: ${frameCount}/${header.totalFrames} (${((frameCount / akku2 * 100)|0) / 100}f) `)
}
con.move(32, 1)
con.color_pair(253, 0)
print(`VRate: ${(getVideoRate() / 1024 * 8)|0} kbps `)
@@ -738,7 +846,11 @@ finally {
con.clear()
if (errorlevel === 0) {
console.log(`Playback completed: ${frameCount} frames`)
if (currentFileIndex > 1) {
console.log(`Playback completed: ${currentFileIndex} files processed`)
} else {
console.log(`Playback completed: ${frameCount} frames`)
}
} else {
console.log(`Playback failed with error ${errorlevel}`)
}

View File

@@ -971,12 +971,17 @@ A universal, simle cue designed to work as both playlist to cue up external file
uint8 Magic[8]: "\x1F TSVM UCF"
uint8 Version: 1
uint16 Number of cue elements
unit8 Reserved[5]
uint32 (Optional) Size of the cue file, useful for allocating fixed length for future expansion; 0 when not used
unit8 Reserved
## Cue Element
uint8 Addressing Mode
uint8 Addressing Mode (low nybble) and Role Flags (high nybble)
- 0x01: External
- 0x02: Internal
- 0x10: Intended for machine interaction (GOP indices, frame indices, etc.)
- 0x20: Intended for human interaction (playlist, chapter markers, etc.)
- 0x30: Intended for both machine and human interaction
Role flags must be unset to assign no roles
uint16 String Length for name
* Name of the element in UTF-8

View File

@@ -2940,10 +2940,6 @@ int main(int argc, char *argv[]) {
// Update actual frame count in encoder struct
enc->total_frames = frame_count;
// Write final sync packet
uint8_t sync_packet = TAV_PACKET_SYNC;
fwrite(&sync_packet, 1, 1, enc->output_fp);
// Update header with actual frame count (seek back to header position)
if (enc->output_fp != stdout) {
long current_pos = ftell(enc->output_fp);

View File

@@ -2994,11 +2994,6 @@ int main(int argc, char *argv[]) {
// Update actual frame count in encoder struct
enc->total_frames = frame_count;
// Write final sync packet
uint8_t sync_packet = TEV_PACKET_SYNC;
fwrite(&sync_packet, 1, 1, output);
sync_packet_count++;
// Update header with actual frame count (seek back to header position)
if (!enc->output_to_stdout) {