[vlc-commits] [Git][videolan/vlc][master] 2 commits: coreaudio: don't send timing when not started

Jean-Baptiste Kempf (@jbk) gitlab at videolan.org
Thu May 16 05:58:48 UTC 2024



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


Commits:
79ecf3ba by Thomas Guillem at 2024-05-16T05:40:20+00:00
coreaudio: don't send timing when not started

A first timing was sent with ts = 0 (so pts = 1, fixed by the core) with
a valid system date. This could cause invalid start (video glitches if
master, audio glitch if slave).

- - - - -
b42481c7 by Thomas Guillem at 2024-05-16T05:40:20+00:00
aout: handle pts in TimingReport()

Timing reports are now based on the pts of the first block.

This will allow finer controls by modules in case of PTS discontinuity
(not yet handled).

- - - - -


11 changed files:

- include/vlc_aout.h
- modules/audio_output/adummy.c
- modules/audio_output/android/aaudio.c
- modules/audio_output/android/audiotrack.c
- modules/audio_output/apple/avsamplebuffer.m
- modules/audio_output/apple/coreaudio_common.c
- modules/audio_output/apple/coreaudio_common.h
- modules/audio_output/pulse.c
- modules/audio_output/wasapi.c
- src/audio_output/dec.c
- test/src/player/player.c


Changes:

=====================================
include/vlc_aout.h
=====================================
@@ -317,15 +317,13 @@ struct audio_output
  * \param aout the audio output instance
  * \param system_ts system timestamp when audio_ts is played, based on
  * vlc_tick_now(), can be now, in the past or in the future.
- * \param audio_ts audio timestamp played at system_ts, starts at 0 for the
- * first sample played (must not take block->i_pts, passed in play(), into
- * account).
- *
+ * \param audio_pts audio timestamp played at system_ts, starts at block->i_pts
+ * for the first sample played.
  */
 static inline void aout_TimingReport(audio_output_t *aout, vlc_tick_t system_ts,
-                                     vlc_tick_t audio_ts)
+                                     vlc_tick_t audio_pts)
 {
-    aout->events->timing_report(aout, system_ts, audio_ts);
+    aout->events->timing_report(aout, system_ts, audio_pts);
 }
 
 /**


=====================================
modules/audio_output/adummy.c
=====================================
@@ -42,6 +42,7 @@ vlc_module_end ()
 
 struct aout_sys
 {
+    vlc_tick_t first_pts;
     vlc_tick_t first_play_date;
     vlc_tick_t last_timing_date;
     vlc_tick_t paused_date;
@@ -52,7 +53,11 @@ static void Play(audio_output_t *aout, block_t *block, vlc_tick_t date)
     struct aout_sys *sys = aout->sys;
 
     if (unlikely(sys->first_play_date == VLC_TICK_INVALID))
+    {
+        assert(sys->first_pts == VLC_TICK_INVALID);
         sys->first_play_date = date;
+        sys->first_pts = block->i_pts;
+    }
 
     block_Release( block );
 
@@ -65,7 +70,8 @@ static void Play(audio_output_t *aout, block_t *block, vlc_tick_t date)
         now - sys->last_timing_date >= VLC_TICK_FROM_SEC(1))
     {
         sys->last_timing_date = now;
-        aout_TimingReport(aout, now, now - sys->first_play_date);
+        aout_TimingReport(aout, now,
+                          now - sys->first_play_date + sys->first_pts);
     }
 }
 
@@ -86,6 +92,7 @@ static void Flush(audio_output_t *aout)
     struct aout_sys *sys = aout->sys;
 
     sys->first_play_date = sys->last_timing_date = VLC_TICK_INVALID;
+    sys->first_pts = VLC_TICK_INVALID;
     sys->paused_date = VLC_TICK_INVALID;
 }
 
@@ -135,6 +142,7 @@ static int Open(vlc_object_t *obj)
     if (!sys)
         return VLC_ENOMEM;
     sys->first_play_date = sys->last_timing_date = VLC_TICK_INVALID;
+    sys->first_pts = VLC_TICK_INVALID;
     sys->paused_date = VLC_TICK_INVALID;
 
     aout->start = Start;


=====================================
modules/audio_output/android/aaudio.c
=====================================
@@ -80,6 +80,7 @@ struct sys
     size_t timing_report_last_written_bytes;
     /* Number of bytes to write before sending a timing report */
     size_t timing_report_delay_bytes;
+    vlc_tick_t first_pts;
 };
 
 /* dlopen/dlsym symbols */
@@ -454,7 +455,8 @@ DataCallback(AAudioStream *as, void *user, void *data_, int32_t num_frames)
             /* Add the start silence to the system time and don't subtract
              * it from pos_ticks to avoid (unlikely) negatives ts */
             system_ts += BytesToTicks(sys, sys->start_silence_bytes);
-            aout_stream_TimingReport(stream, system_ts, pos_ticks);
+            aout_stream_TimingReport(stream, system_ts,
+                                     pos_ticks + sys->first_pts);
         }
 
         memcpy(data, f->p_buffer, tocopy);
@@ -620,6 +622,8 @@ Play(aout_stream_t *stream, vlc_frame_t *frame, vlc_tick_t date)
     {
         vlc_tick_t now = vlc_tick_now();
         sys->first_play_date = date - BytesToTicks(sys, sys->frames_total_bytes);
+        if (sys->first_pts == VLC_TICK_INVALID)
+            sys->first_pts = frame->i_pts;
 
         if (sys->first_play_date > now)
             msg_Dbg(stream, "deferring start (%"PRId64" us)",
@@ -713,7 +717,7 @@ Flush(aout_stream_t *stream)
 
     sys->started = false;
     sys->draining = false;
-    sys->first_play_date = VLC_TICK_INVALID;
+    sys->first_pts = sys->first_play_date = VLC_TICK_INVALID;
     sys->start_silence_bytes = 0;
     sys->timing_report_last_written_bytes = 0;
     sys->timing_report_delay_bytes = 0;
@@ -836,7 +840,7 @@ Start(aout_stream_t *stream, audio_sample_format_t *fmt,
     sys->underrun_bytes = 0;
     sys->started = false;
     sys->draining = false;
-    sys->first_play_date = VLC_TICK_INVALID;
+    sys->first_pts = sys->first_play_date = VLC_TICK_INVALID;
     sys->timing_report_last_written_bytes = 0;
     sys->timing_report_delay_bytes = 0;
 


=====================================
modules/audio_output/android/audiotrack.c
=====================================
@@ -119,6 +119,7 @@ typedef struct
     size_t timing_report_last_written_bytes;
     /* Number of bytes to write before sending a timing report */
     size_t timing_report_delay_bytes;
+    vlc_tick_t first_pts;
 } aout_sys_t;
 
 
@@ -574,6 +575,7 @@ AudioTrack_Reset( JNIEnv *env, aout_stream_t *stream )
     p_sys->i_samples_written = 0;
     p_sys->timing_report_last_written_bytes = 0;
     p_sys->timing_report_delay_bytes = 0;
+    p_sys->first_pts = VLC_TICK_INVALID;
 }
 
 static vlc_tick_t
@@ -1216,7 +1218,8 @@ AudioTrack_ReportTiming( JNIEnv *env, aout_stream_t *stream )
                            + (p_sys->timestamp.i_frame_wrap_count << 32);
 
         aout_stream_TimingReport( stream, frame_date_us,
-                                  FRAMES_TO_US( frame_pos ) );
+                                  FRAMES_TO_US( frame_pos ) +
+                                  p_sys->first_pts );
         return VLC_SUCCESS;
     }
 
@@ -1412,6 +1415,9 @@ Play( aout_stream_t *stream, block_t *p_buffer, vlc_tick_t i_date )
                             p_sys->i_chans_to_reorder, p_sys->p_chan_table,
                             p_sys->fmt.i_format );
 
+    if( p_sys->first_pts == VLC_TICK_INVALID )
+        p_sys->first_pts = p_buffer->i_pts;
+
     vlc_frame_ChainLastAppend(&p_sys->frame_last, p_buffer);
     vlc_cond_signal(&p_sys->thread_cond);
 


=====================================
modules/audio_output/apple/avsamplebuffer.m
=====================================
@@ -62,6 +62,7 @@ API_AVAILABLE(macos(MIN_MACOS), ios(MIN_IOS), tvos(MIN_TVOS))
     block_t **_outChainLast;
 
     int64_t _ptsSamples;
+    vlc_tick_t _firstPts;
     unsigned _sampleRate;
     BOOL _stopped;
 }
@@ -204,6 +205,7 @@ customBlock_Free(void *refcon, void *doomedMemoryBlock, size_t sizeInBytes)
         [self stopSyncRenderer];
 
     _ptsSamples = -1;
+    _firstPts = VLC_TICK_INVALID;
 }
 
 - (void)pause:(BOOL)pause date:(vlc_tick_t)date
@@ -216,10 +218,12 @@ customBlock_Free(void *refcon, void *doomedMemoryBlock, size_t sizeInBytes)
 
 - (void)whenTimeObserved:(CMTime) time
 {
+    assert(_firstPts != VLC_TICK_INVALID);
+
     if (time.value == 0)
         return;
     vlc_tick_t system_now = vlc_tick_now();
-    vlc_tick_t pos_ticks = [VLCAVSample CMTimeTotick:time];
+    vlc_tick_t pos_ticks = [VLCAVSample CMTimeTotick:time] + _firstPts;
 
     aout_TimingReport(_aout, system_now, pos_ticks);
 }
@@ -266,6 +270,7 @@ customBlock_Free(void *refcon, void *doomedMemoryBlock, size_t sizeInBytes)
             [weakSelf whenDataReady];
         }];
 
+        _firstPts = block->i_pts;
         const CMTime interval = CMTimeMake(CLOCK_FREQ, CLOCK_FREQ);
         _observer = [_sync addPeriodicTimeObserverForInterval:interval
                                                         queue:_timeQueue
@@ -415,6 +420,7 @@ customBlock_Free(void *refcon, void *doomedMemoryBlock, size_t sizeInBytes)
     _stopped = NO;
 
     _ptsSamples = -1;
+    _firstPts = VLC_TICK_INVALID;
     _sampleRate = fmt->i_rate;
     _bytesPerFrame = desc.mBytesPerFrame;
 


=====================================
modules/audio_output/apple/coreaudio_common.c
=====================================
@@ -214,6 +214,12 @@ ca_Render(audio_output_t *p_aout, uint64_t host_time,
     }
 
     size_t bytes_copied = 0;
+
+    /* Store the previous started state, in order to skip the timing report
+     * from the first render call, in order to avoid small timing
+     * discontinuities when starting.  */
+    bool was_started = p_sys->started;
+
     while (bytes > 0)
     {
         vlc_frame_t *f = p_sys->p_out_chain;
@@ -252,7 +258,8 @@ ca_Render(audio_output_t *p_aout, uint64_t host_time,
 
     p_sys->timing_report_last_written_bytes += bytes_copied;
 
-    if (p_sys->timing_report_last_written_bytes >=
+    if (was_started &&
+        p_sys->timing_report_last_written_bytes >=
         p_sys->timing_report_delay_bytes)
     {
         p_sys->timing_report_last_written_bytes = 0;
@@ -261,7 +268,8 @@ ca_Render(audio_output_t *p_aout, uint64_t host_time,
         p_sys->timing_report_delay_bytes =
             TicksToBytes(p_sys, TIMING_REPORT_DELAY_TICKS);
 
-        vlc_tick_t pos_ticks = BytesToTicks(p_sys, p_sys->i_total_bytes);
+        vlc_tick_t pos_ticks = BytesToTicks(p_sys, p_sys->i_total_bytes)
+                             + p_sys->first_pts;
         aout_TimingReport(p_aout, end_ticks + GetLatency(p_aout), pos_ticks);
     }
 
@@ -280,6 +288,7 @@ ca_Flush(audio_output_t *p_aout)
     p_sys->i_out_size = 0;
     p_sys->i_total_bytes = 0;
     p_sys->first_play_date = VLC_TICK_INVALID;
+    p_sys->first_pts = VLC_TICK_INVALID;
     p_sys->timing_report_delay_bytes =
     p_sys->timing_report_last_written_bytes = 0;
 
@@ -327,6 +336,8 @@ ca_Play(audio_output_t * p_aout, block_t * p_block, vlc_tick_t date)
     if (!p_sys->started)
     {
         vlc_tick_t now = vlc_tick_now();
+        if (p_sys->first_pts == VLC_TICK_INVALID)
+            p_sys->first_pts = p_block->i_pts;
         p_sys->first_play_date = date - BytesToTicks(p_sys, p_sys->i_out_size);
 
         if (p_sys->first_play_date > now)
@@ -367,6 +378,7 @@ ca_Initialize(audio_output_t *p_aout, const audio_sample_format_t *fmt,
     p_sys->i_out_size = 0;
     p_sys->i_total_bytes = 0;
     p_sys->first_play_date = VLC_TICK_INVALID;
+    p_sys->first_pts = VLC_TICK_INVALID;
 
     p_sys->i_rate = fmt->i_rate;
     p_sys->i_bytes_per_frame = fmt->i_bytes_per_frame;


=====================================
modules/audio_output/apple/coreaudio_common.h
=====================================
@@ -65,6 +65,7 @@ struct aout_sys_common
     size_t              i_out_size;
     /* Size written via the render callback */
     uint64_t            i_total_bytes;
+    vlc_tick_t first_pts;
     /* Date when the data callback should start to process audio */
     vlc_tick_t first_play_date;
     /* Bytes written since the last timing report */


=====================================
modules/audio_output/pulse.c
=====================================
@@ -80,6 +80,7 @@ typedef struct
     } fifo;
 
     pa_usec_t flush_rt;
+    vlc_tick_t first_pts;
 
     pa_volume_t volume_force; /**< Forced volume (stream must be NULL) */
     pa_stream_flags_t flags_force; /**< Forced flags (stream must be NULL) */
@@ -286,7 +287,7 @@ static void stream_latency_cb(pa_stream *s, void *userdata)
     if (sys->start_date_reached
      && likely(rt >= sys->flush_rt + silence_us))
     {
-        vlc_tick_t audio_ts = VLC_TICK_0 +
+        vlc_tick_t audio_ts = sys->first_pts +
             VLC_TICK_FROM_US(rt - sys->flush_rt - silence_us);
 
         aout_TimingReport(aout, sys->timing_system_ts, audio_ts);
@@ -650,6 +651,9 @@ static void Play(audio_output_t *aout, block_t *block, vlc_tick_t date)
 
     if (!sys->start_date_reached)
     {
+        if (sys->first_pts == VLC_TICK_INVALID)
+            sys->first_pts = block->i_pts;
+
         vlc_tick_t now = vlc_tick_now();
         sys->start_date = date
                         - pa_bytes_to_usec(sys->fifo.size, ss);
@@ -737,6 +741,7 @@ static void Flush(audio_output_t *aout)
     const pa_timing_info *ti = pa_stream_get_timing_info(s);
     if (ti != NULL && !ti->read_index_corrupt)
         sys->flush_rt = pa_bytes_to_usec(ti->read_index, ss);
+    sys->first_pts = VLC_TICK_INVALID;
 
     pa_threaded_mainloop_unlock(sys->mainloop);
 }
@@ -981,6 +986,7 @@ static int Start(audio_output_t *aout, audio_sample_format_t *restrict fmt)
     sys->draining = false;
     pa_cvolume_init(&sys->cvolume);
     sys->flush_rt = 0;
+    sys->first_pts = VLC_TICK_INVALID;
 
     sys->start_date_reached = false;
     sys->start_date = VLC_TICK_INVALID;


=====================================
modules/audio_output/wasapi.c
=====================================
@@ -125,6 +125,7 @@ typedef struct aout_stream_sys
     UINT64 written; /**< Frames written to the buffer */
     UINT32 frames; /**< Total buffer size (frames) */
     bool s24s32; /**< Output configured as S24N, but input as S32N */
+    vlc_tick_t first_pts;
 } aout_stream_sys_t;
 
 /*** VLC audio output callbacks ***/
@@ -157,7 +158,8 @@ static void TimingReport(aout_stream_t *s)
     }
 
     aout_stream_TimingReport(s, VLC_TICK_FROM_MSFTIME(qpcpos),
-                             vlc_tick_from_frac(pos, clock_freq));
+                             vlc_tick_from_frac(pos, clock_freq) +
+                             sys->first_pts);
 
     aout_stream_TriggerTimer(s, TimingReport,
                              vlc_tick_now() + TIMING_REPORT_DELAY);
@@ -231,6 +233,9 @@ static HRESULT Play(aout_stream_t *s, block_t *block, vlc_tick_t date)
             goto out;
     }
 
+    if (sys->first_pts == VLC_TICK_INVALID)
+        sys->first_pts = block->i_pts;
+
     if (sys->chans_to_reorder)
         aout_ChannelReorder(block->p_buffer, block->i_buffer,
                           sys->chans_to_reorder, sys->chans_table, sys->format);
@@ -354,6 +359,7 @@ static HRESULT Flush(aout_stream_t *s)
     else
         hr = S_OK;
 
+    sys->first_pts = VLC_TICK_INVALID;
     if (SUCCEEDED(hr))
     {
         msg_Dbg(s, "reset");
@@ -926,6 +932,7 @@ static HRESULT Start(aout_stream_t *s, audio_sample_format_t *restrict pfmt,
     CoTaskMemFree(pwf_mix);
     *pfmt = fmt;
     sys->written = 0;
+    sys->first_pts = VLC_TICK_INVALID;
     s->sys = sys;
     s->play = Play;
     s->pause = Pause;


=====================================
src/audio_output/dec.c
=====================================
@@ -688,20 +688,9 @@ void vlc_aout_stream_NotifyTiming(vlc_aout_stream *stream, vlc_tick_t system_ts,
 {
     vlc_mutex_lock(&stream->timing.lock);
 
-    if (unlikely(stream->timing.first_pts == VLC_TICK_INVALID))
-    {
-        /* While closing the stream, it is possible (but unlikely) that the
-         * module updates a timing point just after the stream is reset, and
-         * just before the module is stopped. */
-        vlc_mutex_unlock(&stream->timing.lock);
-        return;
-    }
-
     vlc_tick_t rate_audio_ts = stream->timing.rate_audio_ts;
     vlc_tick_t rate_system_ts = stream->timing.rate_system_ts;
 
-    audio_ts += stream->timing.first_pts;
-
     if (rate_audio_ts != VLC_TICK_INVALID)
     {
         /* Drop timing updates that comes before the rate change */


=====================================
test/src/player/player.c
=====================================
@@ -3141,6 +3141,7 @@ const char vlc_module_name[] = MODULE_STRING;
 
 struct aout_sys
 {
+    vlc_tick_t first_pts;
     vlc_tick_t first_play_date;
     vlc_tick_t pos;
 };
@@ -3150,9 +3151,14 @@ static void aout_Play(audio_output_t *aout, block_t *block, vlc_tick_t date)
     struct aout_sys *sys = aout->sys;
 
     if (sys->first_play_date == VLC_TICK_INVALID)
+    {
+        assert(sys->first_pts == VLC_TICK_INVALID);
         sys->first_play_date = date;
+        sys->first_pts = block->i_pts;
+    }
 
-    aout_TimingReport(aout, sys->first_play_date + sys->pos - VLC_TICK_0, sys->pos);
+    aout_TimingReport(aout, sys->first_play_date + sys->pos - VLC_TICK_0,
+                      sys->first_pts + sys->pos);
     sys->pos += block->i_length;
     block_Release(block);
 }
@@ -3161,7 +3167,7 @@ static void aout_Flush(audio_output_t *aout)
 {
     struct aout_sys *sys = aout->sys;
     sys->pos = 0;
-    sys->first_play_date = VLC_TICK_INVALID;
+    sys->first_pts = sys->first_play_date = VLC_TICK_INVALID;
 }
 
 static int aout_Start(audio_output_t *aout, audio_sample_format_t *restrict fmt)



View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/7f73777104c30d43b9c48fd5932ac6e2a9c64a56...b42481c79ee78c668cafe2e6c8867a8caf47e2ae

-- 
This project does not include diff previews in email notifications.
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/7f73777104c30d43b9c48fd5932ac6e2a9c64a56...b42481c79ee78c668cafe2e6c8867a8caf47e2ae
You're receiving this email because of your account on code.videolan.org.


VideoLAN code repository instance


More information about the vlc-commits mailing list