From d0d881c73514846990b1e86fe89c878f2cd09b17 Mon Sep 17 00:00:00 2001 From: ZGaetano Date: Tue, 2 Jun 2026 22:01:51 +0000 Subject: [PATCH] Revert "fix(audio): per-port A/V start barrier so video+audio FIFOs begin at the same instant (fixes fixed A/V offset)" This reverts commit bebfe7a43d2bb03b3fea6904a71366d711714f5a. --- services/capture/deltacast-bridge/main.c | 67 +----------------------- 1 file changed, 2 insertions(+), 65 deletions(-) diff --git a/services/capture/deltacast-bridge/main.c b/services/capture/deltacast-bridge/main.c index 59c1d3f..977a0ee 100644 --- a/services/capture/deltacast-bridge/main.c +++ b/services/capture/deltacast-bridge/main.c @@ -50,19 +50,6 @@ static void on_signal(int s) { (void)s; atomic_store(&g_stop, 1); } * rather than stopping the port, so the thread survives ffmpeg restarts. */ static atomic_int g_port_stop[MAX_PORTS]; -/* ── Per-port A/V start barrier ────────────────────────────────────────── - * Video and audio are two independent FIFOs that ffmpeg opens at slightly - * different times (input 0 video, then input 1 audio). Whichever thread's - * reader connects first would otherwise start pumping data immediately, - * giving its stream a head start → a fixed A/V offset that never recovers - * (raw streams carry no timestamps, so ffmpeg PTS-zeroes whatever each stream - * delivers first). To start both streams from the SAME instant, each thread - * publishes "my FIFO reader is connected" and then BOTH spin until the other - * side is also connected before writing their first real sample/frame. - * Reset to 0 each time a fresh pair of readers connects. */ -static atomic_int g_video_ready[MAX_PORTS]; -static atomic_int g_audio_ready[MAX_PORTS]; - /* ── Stream type by port index (non-contiguous SDK enum) ────────────── */ static ULONG rx_streamtype(unsigned port) { switch (port) { @@ -265,28 +252,6 @@ static void *audio_thread(void *arg) { #endif fcntl(fd, F_SETPIPE_SZ, 1024 * 1024); - /* A/V start barrier: announce ready, then wait (up to ~5s) for the - * video reader so both streams begin at the same instant. While - * waiting we drain+discard hardware audio slots so the board audio - * queue doesn't overflow and the first sample we write lines up with - * the first video frame. */ - atomic_store(&g_audio_ready[ps->port], 1); - { - int waited = 0; - while (!atomic_load(&g_video_ready[ps->port]) - && !atomic_load(&g_stop) && !atomic_load(&g_port_stop[ps->port]) - && waited < 5000) { - if (have_vhd_audio) { - HANDLE ds = NULL; - if (VHD_LockSlotHandle(stream, &ds) == VHDERR_NOERROR) - VHD_UnlockSlotHandle(ds); /* discard pre-roll audio */ - } - struct timespec t = {0, 1000000L}; nanosleep(&t, NULL); waited++; - } - fprintf(stderr, "[audio:%u] A/V barrier released (video_ready=%d)\n", - ps->port, atomic_load(&g_video_ready[ps->port])); - } - /* Reset wall-clock baseline after potentially blocking on open(). * Only used for the SILENCE fallback path (no hardware audio). */ struct timespec next; @@ -378,8 +343,6 @@ static void *audio_thread(void *arg) { } close(fd); - /* Reader gone — clear ready so the next session re-syncs at the barrier. */ - atomic_store(&g_audio_ready[ps->port], 0); } if (stream) { @@ -420,26 +383,6 @@ static void *video_thread(void *arg) { } } - /* A/V start barrier: announce ready, then wait (up to ~5s) for the - * audio reader so both streams begin at the same instant. While - * waiting we drain+discard incoming video slots so the board queue - * doesn't overflow and so the FIRST frame we actually write is the one - * captured at the moment audio also starts. */ - atomic_store(&g_video_ready[ps->port], 1); - { - int waited = 0; - while (!atomic_load(&g_audio_ready[ps->port]) - && !atomic_load(&g_stop) && !atomic_load(&g_port_stop[ps->port]) - && waited < 5000) { - HANDLE ds = NULL; - if (VHD_LockSlotHandle(ps->video_stream, &ds) == VHDERR_NOERROR) - VHD_UnlockSlotHandle(ds); /* discard pre-roll frame */ - struct timespec t = {0, 1000000L}; nanosleep(&t, NULL); waited++; - } - fprintf(stderr, "[video:%u] A/V barrier released (audio_ready=%d)\n", - ps->port, atomic_load(&g_audio_ready[ps->port])); - } - HANDLE slot = NULL; int fatal = 0; while (!atomic_load(&g_stop) && !atomic_load(&g_port_stop[ps->port])) { @@ -481,8 +424,6 @@ static void *video_thread(void *arg) { } close(fd); - /* Reader gone — clear ready so the next session re-syncs at the barrier. */ - atomic_store(&g_video_ready[ps->port], 0); if (fatal) break; } @@ -669,12 +610,8 @@ int main(int argc, char *argv[]) { memset(ps, 0, sizeof(ps)); int active_count = 0; - /* Initialise per-port stop + A/V barrier flags. */ - for (int pi = 0; pi < MAX_PORTS; pi++) { - atomic_store(&g_port_stop[pi], 0); - atomic_store(&g_video_ready[pi], 0); - atomic_store(&g_audio_ready[pi], 0); - } + /* Initialise per-port stop flags. */ + for (int pi = 0; pi < MAX_PORTS; pi++) atomic_store(&g_port_stop[pi], 0); for (int pi = 0; pi < port_count; pi++) { if (!locked[pi]) continue;