mirror of
https://github.com/curioustorvald/tsvm.git
synced 2026-06-12 23:54:04 +09:00
turns out extra sync packet at the end of video was a terrible idea
This commit is contained in:
@@ -562,13 +562,117 @@ let trueFrameCount = 0
|
|||||||
let stopPlay = false
|
let stopPlay = false
|
||||||
let akku = FRAME_TIME
|
let akku = FRAME_TIME
|
||||||
let akku2 = 0.0
|
let akku2 = 0.0
|
||||||
|
let currentFileIndex = 1 // Track which file we're playing in concatenated stream
|
||||||
|
|
||||||
let blockDataPtr = sys.malloc(2377744)
|
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 {
|
try {
|
||||||
let t1 = sys.nanoTime()
|
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
|
// Handle interactive controls
|
||||||
if (interactive) {
|
if (interactive) {
|
||||||
@@ -713,7 +817,11 @@ try {
|
|||||||
if (!hasSubtitles) {
|
if (!hasSubtitles) {
|
||||||
con.move(31, 1)
|
con.move(31, 1)
|
||||||
con.color_pair(253, 0)
|
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.move(32, 1)
|
||||||
con.color_pair(253, 0)
|
con.color_pair(253, 0)
|
||||||
print(`VRate: ${(getVideoRate() / 1024 * 8)|0} kbps `)
|
print(`VRate: ${(getVideoRate() / 1024 * 8)|0} kbps `)
|
||||||
@@ -738,7 +846,11 @@ finally {
|
|||||||
con.clear()
|
con.clear()
|
||||||
|
|
||||||
if (errorlevel === 0) {
|
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 {
|
} else {
|
||||||
console.log(`Playback failed with error ${errorlevel}`)
|
console.log(`Playback failed with error ${errorlevel}`)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 Magic[8]: "\x1F TSVM UCF"
|
||||||
uint8 Version: 1
|
uint8 Version: 1
|
||||||
uint16 Number of cue elements
|
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
|
## Cue Element
|
||||||
uint8 Addressing Mode
|
uint8 Addressing Mode (low nybble) and Role Flags (high nybble)
|
||||||
- 0x01: External
|
- 0x01: External
|
||||||
- 0x02: Internal
|
- 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
|
uint16 String Length for name
|
||||||
* Name of the element in UTF-8
|
* Name of the element in UTF-8
|
||||||
|
|
||||||
|
|||||||
@@ -2940,10 +2940,6 @@ int main(int argc, char *argv[]) {
|
|||||||
// Update actual frame count in encoder struct
|
// Update actual frame count in encoder struct
|
||||||
enc->total_frames = frame_count;
|
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)
|
// Update header with actual frame count (seek back to header position)
|
||||||
if (enc->output_fp != stdout) {
|
if (enc->output_fp != stdout) {
|
||||||
long current_pos = ftell(enc->output_fp);
|
long current_pos = ftell(enc->output_fp);
|
||||||
|
|||||||
@@ -2995,11 +2995,6 @@ int main(int argc, char *argv[]) {
|
|||||||
// Update actual frame count in encoder struct
|
// Update actual frame count in encoder struct
|
||||||
enc->total_frames = frame_count;
|
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)
|
// Update header with actual frame count (seek back to header position)
|
||||||
if (!enc->output_to_stdout) {
|
if (!enc->output_to_stdout) {
|
||||||
long current_pos = ftell(output);
|
long current_pos = ftell(output);
|
||||||
|
|||||||
Reference in New Issue
Block a user