fix(deltacast-bridge): flush queued audio backlog to live edge on reader attach
The ~2.5s of leading silence at record start was the VHD audio slot QUEUE: while the recorder is idle (no FIFO reader), the bridge blocks on open(O_WRONLY) but the board keeps buffering audio slots. When the record ffmpeg attaches, the bridge streamed that stale backlog first — heard as leading silence and pushing audio out of alignment with the live video. On each reader attach, drain slots that lock FAST (already-queued backlog) and stop at the first lock that takes ~a frame period (= waiting on a live slot), so the reader is handed the live edge, A/V aligned.
This commit is contained in:
parent
b1a2249f36
commit
e9e883d06e
1 changed files with 36 additions and 0 deletions
|
|
@ -276,6 +276,42 @@ static void *audio_thread(void *arg) {
|
|||
}
|
||||
fcntl(fd, F_SETPIPE_SZ, 1024 * 1024);
|
||||
|
||||
/* ── Flush the VHD audio slot backlog to the LIVE edge ──────────────
|
||||
* While no reader is attached (recorder idle/standby), the open() above
|
||||
* blocks but the VHD audio stream keeps running, so its internal slot
|
||||
* queue fills with buffered audio. Without flushing, the first thing a
|
||||
* newly-attached reader (the record ffmpeg) receives is that backlog —
|
||||
* several seconds of stale/sync-warmup audio that plays as leading
|
||||
* silence and pushes the audio stream out of alignment with the live
|
||||
* video. Drain all immediately-available slots (non-blocking via the
|
||||
* SDK timeout) so we hand the reader the LIVE edge, frame-aligned with
|
||||
* the video that fc_pipe is delivering right now. */
|
||||
if (have_vhd_audio) {
|
||||
/* Drain the QUEUED backlog only: keep discarding slots while each
|
||||
* lock returns FAST (the board hands back already-buffered slots in
|
||||
* well under a frame period). The first lock that takes ~a full frame
|
||||
* period means the queue is empty and we're now waiting on a LIVE
|
||||
* slot — at that point we've reached the live edge, so stop WITHOUT
|
||||
* consuming it (the inner loop will pick it up and write it). */
|
||||
const long fast_ns = frame_ns / 2; /* "immediate" threshold */
|
||||
int flushed = 0;
|
||||
for (;;) {
|
||||
struct timespec a, b;
|
||||
clock_gettime(CLOCK_MONOTONIC, &a);
|
||||
HANDLE fslot = NULL;
|
||||
ULONG fr = VHD_LockSlotHandle(stream, &fslot);
|
||||
clock_gettime(CLOCK_MONOTONIC, &b);
|
||||
if (fr != VHDERR_NOERROR) break; /* TIMEOUT/error => drained */
|
||||
long lock_ns = (b.tv_sec - a.tv_sec) * 1000000000L + (b.tv_nsec - a.tv_nsec);
|
||||
VHD_UnlockSlotHandle(fslot);
|
||||
if (lock_ns >= fast_ns) break; /* waited for a live slot => stop */
|
||||
if (++flushed > 8192) break; /* hard safety cap */
|
||||
}
|
||||
if (flushed > 0)
|
||||
fprintf(stderr, "[audio:%u] flushed %d stale slots on reader attach\n",
|
||||
ps->port, flushed);
|
||||
}
|
||||
|
||||
/* Reset wall-clock baseline after potentially blocking on open().
|
||||
* Only used for the SILENCE fallback path (no hardware audio). */
|
||||
struct timespec next;
|
||||
|
|
|
|||
Loading…
Reference in a new issue