fix(growing): drop FIFO FD-priming deadlock — ffmpeg-first ordering feeds raw2bmx frames
Root cause of frozen 22KB growing MXF: the parent held a stray read-write priming writer (FD 7) on the video FIFO while raw2bmx opened it, so raw2bmx read a malformed/empty stream start and exited after the header (Duration:0). Proven live on zampp3: removing the FD-7/8 priming + fd-watch loop and simply starting ffmpeg before raw2bmx lets the blocking FIFO opens pair up naturally (ffmpeg sole writer). True-1080p59.94 AVC-Intra 100 then grows monotonically on disk and a mid-write snapshot decodes to its last frame (481 frames @ 8s).
This commit is contained in:
parent
bf486b93dd
commit
967547ae97
1 changed files with 6 additions and 30 deletions
|
|
@ -937,50 +937,26 @@ const bmx = [
|
|||
// overwrites them in-place. It is killed by the cleanup trap on exit.
|
||||
const script = `
|
||||
set -u
|
||||
# Save the ORIGINAL stdin (the fc_pipe video stream Node pipes in) to FD 9
|
||||
# BEFORE any FIFO priming touches fd 0. ffmpeg later reads from FD 9 explicitly,
|
||||
# guaranteeing it is the sole reader of the raw video — running ffmpeg as a
|
||||
# backgrounded subshell that merely inherited fd 0 starved it of bytes when the
|
||||
# input was a pipe (the "No filtered frames / empty output" growing failure).
|
||||
exec 9<&0
|
||||
VF=$(mktemp -u /tmp/grow_v.XXXXXX); AF=$(mktemp -u /tmp/grow_a.XXXXXX)
|
||||
OUT=${sh(outPath)}
|
||||
mkfifo "$VF" "$AF"
|
||||
PATCHPID=
|
||||
cleanup() { rm -f "$VF" "$AF"; [ -n "$PATCHPID" ] && kill "$PATCHPID" 2>/dev/null; }
|
||||
trap cleanup EXIT
|
||||
# Prime both FIFOs read-write (non-blocking) to break the open-order deadlock.
|
||||
exec 7<>"$VF" 8<>"$AF"
|
||||
# raw2bmx: close priming FDs (no stray writer) + read stdin from /dev/null before
|
||||
# exec so it sees real EOF and never competes for the video pipe.
|
||||
( exec 7>&- 8>&- 9>&- 0</dev/null; exec ${bmxLine} >/tmp/raw2bmx.log 2>&1 ) &
|
||||
BMXPID=$!
|
||||
# ffmpeg reads the raw video from FD 9 (the saved original stdin). pipe:0 in its
|
||||
# arg list maps to fd 0, so we point fd 0 at FD 9 for the child.
|
||||
( exec 7>&- 8>&- 0<&9 9<&-; exec ${ffLine} ) &
|
||||
cleanup() { rm -f "$VF" "$AF"; }
|
||||
trap cleanup EXIT
|
||||
( exec 0<&9 9<&-; exec ${ffLine} ) &
|
||||
FFPID=$!
|
||||
# Parent no longer needs the saved stdin — drop it so ffmpeg is the sole reader.
|
||||
exec 9<&-
|
||||
# Forward a clean stop to ffmpeg; raw2bmx then gets EOF and finalizes the footer.
|
||||
exec ${bmxLine} >/tmp/raw2bmx.log 2>&1 &
|
||||
BMXPID=$!
|
||||
stop() { kill -INT "$FFPID" 2>/dev/null; }
|
||||
trap stop INT TERM
|
||||
# Drop the parent priming FDs once raw2bmx has opened BOTH FIFOs, so ffmpeg is
|
||||
# the sole writer (its EOF reaches raw2bmx). If raw2bmx dies early, bail.
|
||||
for i in $(seq 1 200); do
|
||||
kill -0 "$BMXPID" 2>/dev/null || break
|
||||
n=$(ls -l /proc/$BMXPID/fd 2>/dev/null | grep -c -- "$VF\\|$AF")
|
||||
[ "\${n:-0}" -ge 2 ] && break
|
||||
sleep 0.1
|
||||
done
|
||||
exec 7>&- 8>&-
|
||||
PATCHPID=
|
||||
# Wait for ffmpeg (source end), then for raw2bmx to finalize the footer.
|
||||
wait "$FFPID"; FFRC=$?
|
||||
wait "$BMXPID"; BMXRC=$?
|
||||
echo "[grow] ffmpeg rc=$FFRC raw2bmx rc=$BMXRC out=$OUT" >&2
|
||||
exit "$BMXRC"
|
||||
`;
|
||||
return ['-c', script];
|
||||
return ['-c', script];
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Reference in a new issue