[vlc-commits] [Git][videolan/vlc][master] 9 commits: aout: remove old documentation
Rémi Denis-Courmont (@Courmisch)
gitlab at videolan.org
Tue Jan 18 13:26:23 UTC 2022
Rémi Denis-Courmont pushed to branch master at VideoLAN / VLC
Commits:
bb9f8f60 by Thomas Guillem at 2022-01-18T13:12:26+00:00
aout: remove old documentation
- - - - -
0dd8096f by Thomas Guillem at 2022-01-18T13:12:26+00:00
aout: make drain asynchronous
aout_DecDrain() is now asynchronous, except for modules still implementing
aout->drain (only during the transition).
Add aout->drain_async(). Aout modules should implement drain_async
instead of drain, and call aout_DrainedReport() to report that the
stream is drained.
Aout modules not implementing any drain functions will still rely on
aout_TimeGet() to detect the end of the stream.
- - - - -
680d334b by Thomas Guillem at 2022-01-18T13:12:26+00:00
pulse: implement drain_async
- - - - -
a8480f07 by Thomas Guillem at 2022-01-18T13:12:26+00:00
amem: implement asynchronous drain
"amem-drain" is still synchronous, the drained state is reported after
the call to this blocking callback.
- - - - -
fb08f5ee by Thomas Guillem at 2022-01-18T13:12:26+00:00
waveout: implement asynchronous drain
- - - - -
fbf9c0d3 by Thomas Guillem at 2022-01-18T13:12:26+00:00
declink: implement asynchronous drain
- - - - -
4a953e23 by Thomas Guillem at 2022-01-18T13:12:26+00:00
alsa: implement asynchronous drain
Lousy implementation since snd_pcm doesn't provide non blocking drain
API.
- - - - -
193ab0d0 by Thomas Guillem at 2022-01-18T13:12:26+00:00
aout: remove legacy drain
- - - - -
6c93cb0f by Thomas Guillem at 2022-01-18T13:12:26+00:00
aout: rename back drain_async to drain
Now that the legacy implementation is gone.
- - - - -
10 changed files:
- include/vlc_aout.h
- modules/audio_output/alsa.c
- modules/audio_output/amem.c
- modules/audio_output/pulse.c
- modules/audio_output/waveout.c
- modules/video_output/decklink.cpp
- src/audio_output/aout_internal.h
- src/audio_output/dec.c
- src/audio_output/output.c
- src/input/decoder.c
Changes:
=====================================
include/vlc_aout.h
=====================================
@@ -126,6 +126,7 @@
struct vlc_audio_output_events {
void (*timing_report)(audio_output_t *, vlc_tick_t system_now, vlc_tick_t pts);
+ void (*drained_report)(audio_output_t *);
void (*volume_report)(audio_output_t *, float);
void (*mute_report)(audio_output_t *, bool);
void (*policy_report)(audio_output_t *, bool);
@@ -240,14 +241,19 @@ struct audio_output
void (*flush)( audio_output_t *);
/**< Flushes the playback buffers (mandatory, cannot be NULL).
- *
- * \param wait true to wait for playback of pending buffers (drain),
- * false to discard pending buffers (flush)
*
* \note This callback cannot be called in stopped state.
*/
+
void (*drain)(audio_output_t *);
- /**< Drain the playback buffers (can be NULL).
+ /**< Drain the playback buffers asynchronously (can be NULL).
+ *
+ * A drain operation can be cancelled by aout->flush() or aout->stop().
+ *
+ * It is legal to continue playback after a drain_async, if flush() is
+ * called before the next play().
+ *
+ * Call aout_DrainedReport() to notify that the stream is drained.
*
* If NULL, the caller will wait for the delay returned by time_get before
* calling stop().
@@ -297,6 +303,14 @@ static inline int aout_TimeGet(audio_output_t *aout, vlc_tick_t *delay)
return aout->time_get(aout, delay);
}
+/**
+ * Report than the stream is drained (after a call to aout->drain_async)
+ */
+static inline void aout_DrainedReport(audio_output_t *aout)
+{
+ aout->events->drained_report(aout);
+}
+
/**
* Report change of configured audio volume to the core and UI.
*/
=====================================
modules/audio_output/alsa.c
=====================================
@@ -730,8 +730,12 @@ static void Drain (audio_output_t *aout)
{
aout_sys_t *p_sys = aout->sys;
snd_pcm_t *pcm = p_sys->pcm;
+
+ /* XXX: Synchronous drain, not interruptible. */
snd_pcm_drain (pcm);
snd_pcm_prepare (pcm);
+
+ aout_DrainedReport(aout);
}
/**
=====================================
modules/audio_output/amem.c
=====================================
@@ -142,6 +142,8 @@ static void Drain (audio_output_t *aout)
vlc_mutex_lock(&sys->lock);
sys->drain (sys->opaque);
vlc_mutex_unlock(&sys->lock);
+
+ aout_DrainedReport (aout);
}
static int VolumeSet (audio_output_t *aout, float vol)
=====================================
modules/audio_output/pulse.c
=====================================
@@ -66,6 +66,7 @@ typedef struct
pa_context *context; /**< PulseAudio connection context */
pa_threaded_mainloop *mainloop; /**< PulseAudio thread */
pa_time_event *trigger; /**< Deferred stream trigger */
+ pa_time_event *drain_trigger; /**< Drain stream trigger */
pa_cvolume cvolume; /**< actual sink input volume */
vlc_tick_t last_date; /**< Play system timestamp of last buffer */
@@ -556,6 +557,12 @@ static void Flush(audio_output_t *aout)
pa_threaded_mainloop_lock(sys->mainloop);
+ if (sys->drain_trigger != NULL)
+ {
+ vlc_pa_rttime_free(sys->mainloop, sys->drain_trigger);
+ sys->drain_trigger = NULL;
+ }
+
pa_operation *op = pa_stream_flush(s, NULL, NULL);
if (op != NULL)
pa_operation_unref(op);
@@ -565,6 +572,21 @@ static void Flush(audio_output_t *aout)
pa_threaded_mainloop_unlock(sys->mainloop);
}
+static void drain_trigger_cb(pa_mainloop_api *api, pa_time_event *e,
+ const struct timeval *tv, void *userdata)
+{
+ audio_output_t *aout = userdata;
+ aout_sys_t *sys = aout->sys;
+
+ assert(sys->drain_trigger == e);
+
+ vlc_pa_rttime_free(sys->mainloop, sys->drain_trigger);
+ sys->drain_trigger = NULL;
+
+ aout_DrainedReport(aout);
+ (void) api; (void) e; (void) tv;
+}
+
static void Drain(audio_output_t *aout)
{
aout_sys_t *sys = aout->sys;
@@ -593,15 +615,18 @@ static void Drain(audio_output_t *aout)
/* XXX: Loosy drain emulation.
* See #18141: drain callback is never received */
+ assert(sys->drain_trigger == NULL);
vlc_tick_t delay;
- if (TimeGet(aout, &delay) == 0 && delay <= VLC_TICK_FROM_SEC(5))
+ if (TimeGet(aout, &delay) == 0)
{
- pa_threaded_mainloop_unlock(sys->mainloop);
- vlc_tick_sleep(delay);
- pa_threaded_mainloop_lock(sys->mainloop);
+ delay += pa_rtclock_now();
+ sys->drain_trigger = pa_context_rttime_new(sys->context, delay,
+ drain_trigger_cb, aout);
}
- stream_stop(s, aout);
+ if (sys->drain_trigger == NULL)
+ aout_DrainedReport(aout);
+
pa_threaded_mainloop_unlock(sys->mainloop);
}
@@ -828,7 +853,7 @@ static int Start(audio_output_t *aout, audio_sample_format_t *restrict fmt)
pa_cvolume_set(cvolume, ss.channels, sys->volume_force);
}
- sys->trigger = NULL;
+ sys->trigger = sys->drain_trigger = NULL;
pa_cvolume_init(&sys->cvolume);
sys->last_date = VLC_TICK_INVALID;
@@ -1001,6 +1026,8 @@ static void Stop(audio_output_t *aout)
pa_threaded_mainloop_lock(sys->mainloop);
if (unlikely(sys->trigger != NULL))
vlc_pa_rttime_free(sys->mainloop, sys->trigger);
+ if (sys->drain_trigger != NULL)
+ vlc_pa_rttime_free(sys->mainloop, sys->drain_trigger);
pa_stream_disconnect(s);
/* Clear all callbacks */
=====================================
modules/audio_output/waveout.c
=====================================
@@ -80,6 +80,7 @@ static uint32_t findDeviceID(char *);
static int WaveOutTimeGet(audio_output_t * , vlc_tick_t *);
static void WaveOutFlush( audio_output_t *);
static void WaveOutDrain( audio_output_t *);
+static void WaveOutDrainAsync( audio_output_t *);
static void WaveOutPause( audio_output_t *, bool, vlc_tick_t);
static int WaveoutVolumeSet(audio_output_t * p_aout, float volume);
static int WaveoutMuteSet(audio_output_t * p_aout, bool mute);
@@ -128,6 +129,8 @@ struct aout_sys_t
vlc_mutex_t lock;
vlc_cond_t cond;
vlc_timer_t volume_poll_timer;
+
+ bool draining;
};
/*****************************************************************************
@@ -175,10 +178,12 @@ static int Start( audio_output_t *p_aout, audio_sample_format_t *restrict fmt )
p_aout->play = Play;
p_aout->pause = WaveOutPause;
p_aout->flush = WaveOutFlush;
- p_aout->drain = WaveOutDrain;
+ p_aout->drain = WaveOutDrainAsync;
aout_sys_t *sys = p_aout->sys;
+ sys->draining = false;
+
/* Default behaviour is to use software gain */
sys->b_soft = true;
@@ -647,6 +652,13 @@ static void CALLBACK WaveOutCallback( HWAVEOUT h_waveout, UINT uMsg,
p_waveheader->p_next = sys->p_free_list;
sys->p_free_list = p_waveheader;
sys->i_frames--;
+
+ if( sys->i_frames == 0 && sys->draining )
+ {
+ aout_DrainedReport( _p_aout );
+ sys->draining = false;
+ }
+
vlc_cond_broadcast( &sys->cond );
vlc_mutex_unlock( &sys->lock );
}
@@ -851,6 +863,10 @@ static void WaveOutFlush( audio_output_t *p_aout)
MMRESULT res;
aout_sys_t *sys = p_aout->sys;
+ vlc_mutex_lock( &sys->lock );
+ sys->draining = false;
+ vlc_mutex_unlock( &sys->lock );
+
res = waveOutReset( sys->h_waveout );
sys->i_played_length = 0;
if( res != MMSYSERR_NOERROR )
@@ -869,6 +885,18 @@ static void WaveOutDrain( audio_output_t *p_aout)
vlc_mutex_unlock( &sys->lock );
}
+static void WaveOutDrainAsync( audio_output_t *p_aout)
+{
+ aout_sys_t *sys = p_aout->sys;
+
+ vlc_mutex_lock( &sys->lock );
+ if( sys->i_frames == 0 )
+ aout_DrainedReport( p_aout );
+ else
+ sys->draining = true;
+ vlc_mutex_unlock( &sys->lock );
+}
+
static void WaveOutPause( audio_output_t * p_aout, bool pause, vlc_tick_t date)
{
MMRESULT res;
=====================================
modules/video_output/decklink.cpp
=====================================
@@ -215,6 +215,8 @@ struct decklink_sys_t
/* !With LOCK */
+ vlc_timer_t drain_timer;
+
/* single video module exclusive */
struct
{
@@ -833,6 +835,17 @@ static void CloseVideo(vout_display_t *vd)
* Audio
*****************************************************************************/
+static void DrainReset(audio_output_t *aout)
+{
+ decklink_sys_t *sys = (decklink_sys_t *) aout->sys;
+
+ if (sys->drain_timer != NULL)
+ {
+ vlc_timer_destroy(sys->drain_timer);
+ sys->drain_timer = NULL;
+ }
+}
+
static void Flush(audio_output_t *aout)
{
decklink_sys_t *sys = (decklink_sys_t *) aout->sys;
@@ -842,10 +855,19 @@ static void Flush(audio_output_t *aout)
if (!p_output)
return;
+ DrainReset(aout);
+
if (sys->p_output->FlushBufferedAudioSamples() == E_FAIL)
msg_Err(aout, "Flush failed");
}
+static void DrainTimerCb(void *data)
+{
+ audio_output_t *aout = (audio_output_t *) data;
+
+ aout_DrainedReport(aout);
+}
+
static void Drain(audio_output_t *aout)
{
decklink_sys_t *sys = (decklink_sys_t *) aout->sys;
@@ -855,9 +877,28 @@ static void Drain(audio_output_t *aout)
if (!p_output)
return;
+ assert(sys->drain_timer == NULL);
+
uint32_t samples;
sys->p_output->GetBufferedAudioSampleFrameCount(&samples);
- vlc_tick_sleep(vlc_tick_from_samples(samples, sys->i_rate));
+
+ if (samples == 0)
+ {
+ aout_DrainedReport(aout);
+ return;
+ }
+
+ /* Create and arm a timer to notify when drained */
+ int ret = vlc_timer_create(&sys->drain_timer, DrainTimerCb, aout);
+ if (ret != 0)
+ {
+ aout_DrainedReport(aout);
+ return;
+ }
+
+ vlc_timer_schedule(sys->drain_timer, false,
+ vlc_tick_from_samples(samples, sys->i_rate),
+ VLC_TIMER_FIRE_ONCE);
}
@@ -925,6 +966,7 @@ static int OpenAudio(vlc_object_t *p_this)
sys->i_rate = var_InheritInteger(aout, AUDIO_CFG_PREFIX "audio-rate");
vlc_cond_signal(&sys->cond);
vlc_mutex_unlock(&sys->lock);
+ sys->drain_timer = NULL;
aout->play = PlayAudio;
aout->start = Start;
@@ -933,7 +975,7 @@ static int OpenAudio(vlc_object_t *p_this)
aout->time_get = TimeGet;
aout->pause = aout_PauseDefault;
- aout->stop = NULL;
+ aout->stop = DrainReset;
aout->mute_set = NULL;
aout->volume_set= NULL;
=====================================
src/audio_output/aout_internal.h
=====================================
@@ -50,6 +50,9 @@ typedef struct
aout_volume_t *volume;
bool bitexact;
+ atomic_bool drained;
+ _Atomic vlc_tick_t drain_deadline;
+
struct
{
vlc_mutex_t lock;
@@ -166,6 +169,10 @@ void aout_DecChangeRate(audio_output_t *aout, float rate);
void aout_DecChangeDelay(audio_output_t *aout, vlc_tick_t delay);
void aout_DecFlush(audio_output_t *);
void aout_DecDrain(audio_output_t *);
+/* Contrary to other aout_Dec*() functions, this function can be called from
+ * any threads */
+bool aout_DecIsDrained(audio_output_t *);
+
void aout_RequestRestart (audio_output_t *, unsigned);
void aout_RequestRetiming(audio_output_t *aout, vlc_tick_t system_ts,
vlc_tick_t audio_ts);
=====================================
src/audio_output/dec.c
=====================================
@@ -38,18 +38,6 @@
#include "clock/clock.h"
#include "libvlc.h"
-static void aout_Drain(audio_output_t *aout)
-{
- if (aout->drain)
- aout->drain(aout);
- else
- {
- vlc_tick_t delay;
- if (aout_TimeGet(aout, &delay) == 0)
- vlc_tick_sleep(delay);
- }
-}
-
/**
* Creates an audio output
*/
@@ -586,10 +574,30 @@ void aout_DecFlush(audio_output_t *aout)
owner->sync.delay = 0;
}
}
+
+ atomic_store_explicit(&owner->drained, false, memory_order_relaxed);
+ atomic_store_explicit(&owner->drain_deadline, VLC_TICK_INVALID,
+ memory_order_relaxed);
+
owner->sync.discontinuity = true;
owner->original_pts = VLC_TICK_INVALID;
}
+bool aout_DecIsDrained(audio_output_t *aout)
+{
+ aout_owner_t *owner = aout_owner (aout);
+
+ if (aout->drain == NULL)
+ {
+ vlc_tick_t drain_deadline =
+ atomic_load_explicit(&owner->drain_deadline, memory_order_relaxed);
+ return drain_deadline != VLC_TICK_INVALID
+ && vlc_tick_now() >= drain_deadline;
+ }
+ else
+ return atomic_load_explicit(&owner->drained, memory_order_relaxed);
+}
+
void aout_DecDrain(audio_output_t *aout)
{
aout_owner_t *owner = aout_owner (aout);
@@ -604,7 +612,28 @@ void aout_DecDrain(audio_output_t *aout)
aout->play(aout, block, vlc_tick_now());
}
- aout_Drain(aout);
+ if (aout->drain)
+ {
+ assert(!atomic_load_explicit(&owner->drained, memory_order_relaxed));
+
+ aout->drain(aout);
+ }
+ else
+ {
+ assert(atomic_load_explicit(&owner->drain_deadline,
+ memory_order_relaxed) == VLC_TICK_INVALID);
+
+ vlc_tick_t drain_deadline = vlc_tick_now();
+
+ vlc_tick_t delay;
+ if (aout_TimeGet(aout, &delay) == 0)
+ drain_deadline += delay;
+ /* else the deadline is now, and aout_DecIsDrained() will return true
+ * on the first call. */
+
+ atomic_store_explicit(&owner->drain_deadline, drain_deadline,
+ memory_order_relaxed);
+ }
vlc_clock_Reset(owner->sync.clock);
if (owner->filters)
=====================================
src/audio_output/output.c
=====================================
@@ -69,6 +69,12 @@ static void aout_TimingNotify(audio_output_t *aout, vlc_tick_t system_ts,
aout_RequestRetiming(aout, system_ts, audio_ts);
}
+static void aout_DrainedNotify(audio_output_t *aout)
+{
+ aout_owner_t *owner = aout_owner (aout);
+ atomic_store_explicit(&owner->drained, true, memory_order_relaxed);
+}
+
/**
* Supply or update the current custom ("hardware") volume.
* @param volume current custom volume
@@ -160,6 +166,7 @@ static int aout_GainNotify (audio_output_t *aout, float gain)
static const struct vlc_audio_output_events aout_events = {
aout_TimingNotify,
+ aout_DrainedNotify,
aout_VolumeNotify,
aout_MuteNotify,
aout_PolicyNotify,
@@ -243,6 +250,9 @@ audio_output_t *aout_New (vlc_object_t *parent)
vlc_atomic_rc_init(&owner->rc);
vlc_audio_meter_Init(&owner->meter, aout);
+ atomic_init(&owner->drained, false);
+ atomic_init(&owner->drain_deadline, VLC_TICK_INVALID);
+
/* Audio output module callbacks */
var_Create (aout, "volume", VLC_VAR_FLOAT);
var_AddCallback (aout, "volume", var_Copy, parent);
=====================================
src/input/decoder.c
=====================================
@@ -158,7 +158,6 @@ struct vlc_input_decoder_t
/* Flushing */
bool flushing;
bool b_draining;
- atomic_bool drained;
bool b_idle;
bool aborting;
@@ -1748,10 +1747,7 @@ static void *DecoderThread( void *p_data )
vlc_mutex_lock( &p_owner->lock );
vlc_fifo_Lock( p_owner->p_fifo );
if( p_owner->b_draining && (frame == NULL) )
- {
p_owner->b_draining = false;
- p_owner->drained = true;
- }
vlc_cond_signal( &p_owner->wait_acknowledge );
vlc_mutex_unlock( &p_owner->lock );
}
@@ -1857,7 +1853,6 @@ CreateDecoder( vlc_object_t *p_parent, const es_format_t *fmt,
p_owner->flushing = false;
p_owner->b_draining = false;
- p_owner->drained = false;
atomic_init( &p_owner->reload, RELOAD_NO_REQUEST );
p_owner->b_idle = false;
@@ -2289,8 +2284,8 @@ bool vlc_input_decoder_IsEmpty( vlc_input_decoder_t * p_owner )
#endif
if( p_owner->fmt.i_cat == VIDEO_ES && p_owner->p_vout != NULL )
b_empty = vout_IsEmpty( p_owner->p_vout );
- else if( p_owner->fmt.i_cat == AUDIO_ES )
- b_empty = !p_owner->b_draining || p_owner->drained;
+ else if( p_owner->fmt.i_cat == AUDIO_ES && p_owner->p_aout != NULL )
+ b_empty = aout_DecIsDrained( p_owner->p_aout );
else
b_empty = true; /* TODO subtitles support */
vlc_mutex_unlock( &p_owner->lock );
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/1cf1991b648df877d7138ef79a3381026be2dd80...6c93cb0f0484b71048bfaf94d17e6962cfca42fd
--
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/1cf1991b648df877d7138ef79a3381026be2dd80...6c93cb0f0484b71048bfaf94d17e6962cfca42fd
You're receiving this email because of your account on code.videolan.org.
More information about the vlc-commits
mailing list