[vlc-commits] [Git][videolan/vlc][master] 3 commits: aout: account for drained filter samples

Jean-Baptiste Kempf (@jbk) gitlab at videolan.org
Sun Oct 11 17:39:13 UTC 2026



Jean-Baptiste Kempf pushed to branch master at VideoLAN / VLC


Commits:
8b56c478 by Thomas Guillem at 2026-10-11T19:22:43+02:00
aout: account for drained filter samples

Also take into account drained samples from stream_GetDelay().

- - - - -
486fbfbe by Thomas Guillem at 2026-10-11T19:22:43+02:00
aout: fix the stream delay at rate != 1

At rate != 1, stream_GetDelay() mixed output samples, counted after the
rate filter, with stream-time timestamps: at a constant rate, the delay
was off by (1/rate - 1) times the output submitted since the last
flush.

Outputs without a drain callback (wasapi, coreaudio, avsamplebuffer,
AudioTrack) wait for this delay at EOF: with adummy, playing 4 s of
audio took 16.0 s at x0.5 and 1.6 s at x2, cutting the end (8.1 s and
2.2 s now). With --clock-master=monotonic, the audio inserted silence
every 100 ms at x2.5 and flushed its buffers every 5 s at x0.5.

- - - - -
38022073 by Thomas Guillem at 2026-10-11T19:22:43+02:00
test: player: check that EOF waits for the audio at rate != 1

Without the stream delay fix, EOF stopped the test output at least
180 ms before its last sample at x2, and up to 95 ms before at x4.

- - - - -


4 changed files:

- src/audio_output/dec.c
- test/src/player/common.h
- test/src/player/eof.c
- test/src/player/modules.c


Changes:

=====================================
src/audio_output/dec.c
=====================================
@@ -150,8 +150,7 @@ static int stream_GetDelay(vlc_aout_stream *stream, vlc_tick_t *delay)
      * coefficient is 1.0 (audio at the same speed than the monotonic
      * clock) since the calculation is done on a very small interval
      * (generally less than 2 seconds). */
-    vlc_tick_t play_date = (last_pts - audio_ts) / (double) stream->sync.rate
-                         + system_ts;
+    vlc_tick_t play_date = last_pts - audio_ts + system_ts;
     *delay = play_date - system_now;
     return 0;
 }
@@ -773,6 +772,10 @@ void vlc_aout_stream_NotifyTiming(vlc_aout_stream *stream, vlc_tick_t system_ts,
     vlc_tick_t rate_audio_ts = stream->timing.rate_audio_ts;
     vlc_tick_t rate_system_ts = stream->timing.rate_system_ts;
 
+    /* audio_ts is the output position: at rate != 1, it advances with the
+     * output samples, like played_samples, not with the stream timestamps
+     * of the clock. */
+    vlc_tick_t clock_audio_ts = audio_ts;
     if (rate_audio_ts != VLC_TICK_INVALID)
     {
         /* Drop timing updates that comes before the rate change */
@@ -783,8 +786,8 @@ void vlc_aout_stream_NotifyTiming(vlc_aout_stream *stream, vlc_tick_t system_ts,
         }
 
         /* Fix the audio timestamp with the rate */
-        audio_ts = rate_audio_ts + (system_ts - rate_system_ts)
-                   * stream->timing.rate;
+        clock_audio_ts = rate_audio_ts + (system_ts - rate_system_ts)
+                         * stream->timing.rate;
     }
 
     stream->timing.system_ts = system_ts;
@@ -792,7 +795,7 @@ void vlc_aout_stream_NotifyTiming(vlc_aout_stream *stream, vlc_tick_t system_ts,
     vlc_clock_Lock(stream->sync.clock);
     stream->timing.last_drift =
         vlc_clock_Update(stream->sync.clock, system_ts,
-                         audio_ts, stream->timing.rate);
+                         clock_audio_ts, stream->timing.rate);
     vlc_clock_Unlock(stream->sync.clock);
     vlc_mutex_unlock(&stream->timing.lock);
 }
@@ -1049,6 +1052,7 @@ void vlc_aout_stream_Drain(vlc_aout_stream *stream)
         if (block)
         {
             assert (block->i_pts != VLC_TICK_INVALID);
+            stream->timing.played_samples += block->i_nb_samples;
             aout->play(aout, block, vlc_tick_now());
         }
     }


=====================================
test/src/player/common.h
=====================================
@@ -146,8 +146,15 @@ struct report_aout_first_pts
     vlc_tick_t first_pts;
 };
 
+struct report_aout_stop
+{
+    vlc_tick_t date;
+    vlc_tick_t end_date;
+};
+
 #define REPORT_LIST \
     X(vlc_tick_t, on_aout_first_pts) \
+    X(struct report_aout_stop, on_aout_stop) \
 
 #define X(type, name) typedef struct VLC_VECTOR(type) vec_##name;
 PLAYER_REPORT_LIST


=====================================
test/src/player/eof.c
=====================================
@@ -62,6 +62,32 @@ test_repeat(struct ctx *ctx)
     test_end(ctx);
 }
 
+static void
+test_audio_end(struct ctx *ctx, float rate)
+{
+    test_log("audio_end: rate %f\n", rate);
+
+    vlc_player_t *player = ctx->player;
+
+    struct media_params params = DEFAULT_MEDIA_PARAMS(VLC_TICK_FROM_SEC(1));
+    params.track_count[VIDEO_ES] = 0;
+    params.track_count[SPU_ES] = 0;
+    player_set_next_mock_media(ctx, "media1", &params);
+    player_set_rate(ctx, rate);
+    player_start(ctx);
+
+    wait_state(ctx, VLC_PLAYER_STATE_STOPPED);
+
+    /* The test aout has no drain callback: EOF waits for the play date of its
+     * last sample, computed by the core from two clock reads. */
+    vec_on_aout_stop *vec = &ctx->report.on_aout_stop;
+    assert(vec->size > 0);
+    struct report_aout_stop report = VEC_LAST(vec);
+    assert(report.date >= report.end_date - VLC_TICK_FROM_MS(10));
+
+    test_end(ctx);
+}
+
 int
 main(void)
 {
@@ -69,6 +95,8 @@ main(void)
     ctx_init(&ctx, 0);
     test_play_pause(&ctx);
     test_repeat(&ctx);
+    test_audio_end(&ctx, 2.f);
+    test_audio_end(&ctx, 4.f);
     ctx_destroy(&ctx);
     return 0;
 }


=====================================
test/src/player/modules.c
=====================================
@@ -51,6 +51,27 @@ static void aout_Flush(audio_output_t *aout)
     sys->first_pts = sys->first_play_date = VLC_TICK_INVALID;
 }
 
+static void aout_Stop(audio_output_t *aout)
+{
+    struct aout_sys *sys = aout->sys;
+
+    if (sys->first_play_date != VLC_TICK_INVALID)
+    {
+        /* Same dates as the timing reports from Play() */
+        struct report_aout_stop report = {
+            .date = vlc_tick_now(),
+            .end_date = sys->first_play_date + sys->pos - VLC_TICK_0,
+        };
+
+        struct ctx *ctx = sys->ctx;
+        vlc_player_Lock(ctx->player);
+        VEC_PUSH(on_aout_stop, report);
+        vlc_player_Unlock(ctx->player);
+    }
+
+    aout_Flush(aout);
+}
+
 static void aout_Pause(audio_output_t *aout, bool pause, vlc_tick_t date)
 {
     (void) date;
@@ -84,7 +105,7 @@ static int aout_Open(vlc_object_t *obj)
     aout->play = aout_Play;
     aout->pause = aout_Pause;
     aout->flush = aout_Flush;
-    aout->stop = aout_Flush;
+    aout->stop = aout_Stop;
     aout->volume_set = NULL;
     aout->mute_set = NULL;
 



View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/a40028950c3a7d017049d961345414925af00908...38022073f64ca9321766117d7a402e1e3f5ed8fa

-- 
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/a40028950c3a7d017049d961345414925af00908...38022073f64ca9321766117d7a402e1e3f5ed8fa
You're receiving this email because of your account on code.videolan.org. Manage all notifications: https://code.videolan.org/-/profile/notifications | Help: https://code.videolan.org/help




More information about the vlc-commits mailing list