Commit 32aa1b26 authored by Rémi Denis-Courmont's avatar Rémi Denis-Courmont

aout: report drift via parameter rather than callback

The time report callback could only be called from pf_play() so this is
cleaner and less prone to coding mistake.

Also pass the relative drift instead of the absolute play time stamp.
The drift is less subject to scheduling noise, i.e. drift evolves much
slower than current time advances.
parent 25f0a8f9
...@@ -143,7 +143,8 @@ struct audio_output ...@@ -143,7 +143,8 @@ struct audio_output
only when succesfully probed and not afterward) */ only when succesfully probed and not afterward) */
struct aout_sys_t *sys; /**< Output plugin private data */ struct aout_sys_t *sys; /**< Output plugin private data */
void (*pf_play)(audio_output_t *, block_t *); /**< Audio buffer callback */ void (*pf_play)(audio_output_t *, block_t *, mtime_t *); /**< Play callback
- queue a block for playback */
void (* pf_pause)( audio_output_t *, bool, mtime_t ); /**< Pause/resume void (* pf_pause)( audio_output_t *, bool, mtime_t ); /**< Pause/resume
callback (optional, may be NULL) */ callback (optional, may be NULL) */
void (* pf_flush)( audio_output_t *, bool ); /**< Flush/drain callback void (* pf_flush)( audio_output_t *, bool ); /**< Flush/drain callback
...@@ -152,7 +153,6 @@ struct audio_output ...@@ -152,7 +153,6 @@ struct audio_output
int (*mute_set)(audio_output_t *, bool); /**< Mute setter (or NULL) */ int (*mute_set)(audio_output_t *, bool); /**< Mute setter (or NULL) */
struct { struct {
void (*time_report)(audio_output_t *, mtime_t);
void (*volume_report)(audio_output_t *, float); void (*volume_report)(audio_output_t *, float);
void (*mute_report)(audio_output_t *, bool); void (*mute_report)(audio_output_t *, bool);
int (*gain_request)(audio_output_t *, float); int (*gain_request)(audio_output_t *, float);
...@@ -223,11 +223,6 @@ VLC_API void aout_FormatPrint(vlc_object_t *, const char *, ...@@ -223,11 +223,6 @@ VLC_API void aout_FormatPrint(vlc_object_t *, const char *,
#define aout_FormatPrint(o, t, f) aout_FormatPrint(VLC_OBJECT(o), t, f) #define aout_FormatPrint(o, t, f) aout_FormatPrint(VLC_OBJECT(o), t, f)
VLC_API const char * aout_FormatPrintChannels( const audio_sample_format_t * ) VLC_USED; VLC_API const char * aout_FormatPrintChannels( const audio_sample_format_t * ) VLC_USED;
static inline void aout_TimeReport(audio_output_t *aout, mtime_t date)
{
aout->event.time_report(aout, date);
}
static inline void aout_VolumeReport(audio_output_t *aout, float volume) static inline void aout_VolumeReport(audio_output_t *aout, float volume)
{ {
aout->event.volume_report(aout, volume); aout->event.volume_report(aout, volume);
...@@ -271,7 +266,7 @@ typedef struct ...@@ -271,7 +266,7 @@ typedef struct
VLC_DEPRECATED void aout_PacketInit(audio_output_t *, aout_packet_t *, unsigned); VLC_DEPRECATED void aout_PacketInit(audio_output_t *, aout_packet_t *, unsigned);
VLC_DEPRECATED void aout_PacketDestroy(audio_output_t *); VLC_DEPRECATED void aout_PacketDestroy(audio_output_t *);
VLC_DEPRECATED void aout_PacketPlay(audio_output_t *, block_t *); VLC_DEPRECATED void aout_PacketPlay(audio_output_t *, block_t *, mtime_t *);
VLC_DEPRECATED void aout_PacketPause(audio_output_t *, bool, mtime_t); VLC_DEPRECATED void aout_PacketPause(audio_output_t *, bool, mtime_t);
VLC_DEPRECATED void aout_PacketFlush(audio_output_t *, bool); VLC_DEPRECATED void aout_PacketFlush(audio_output_t *, bool);
......
...@@ -49,7 +49,7 @@ vlc_module_end () ...@@ -49,7 +49,7 @@ vlc_module_end ()
/***************************************************************************** /*****************************************************************************
* Local prototypes. * Local prototypes.
*****************************************************************************/ *****************************************************************************/
static void Play( audio_output_t *, block_t * ); static void Play( audio_output_t *, block_t *, mtime_t * );
/***************************************************************************** /*****************************************************************************
* OpenAudio: open a dummy audio device * OpenAudio: open a dummy audio device
...@@ -80,8 +80,9 @@ static int Open( vlc_object_t * p_this ) ...@@ -80,8 +80,9 @@ static int Open( vlc_object_t * p_this )
/***************************************************************************** /*****************************************************************************
* Play: pretend to play a sound * Play: pretend to play a sound
*****************************************************************************/ *****************************************************************************/
static void Play( audio_output_t *aout, block_t *block ) static void Play( audio_output_t *aout, block_t *block, mtime_t *drift )
{ {
block_Release( block ); block_Release( block );
(void) aout; (void) aout;
(void) drift;
} }
...@@ -160,7 +160,7 @@ static int DeviceChanged (vlc_object_t *obj, const char *varname, ...@@ -160,7 +160,7 @@ static int DeviceChanged (vlc_object_t *obj, const char *varname,
return VLC_SUCCESS; return VLC_SUCCESS;
} }
static void Play (audio_output_t *, block_t *); static void Play (audio_output_t *, block_t *, mtime_t *);
static void Pause (audio_output_t *, bool, mtime_t); static void Pause (audio_output_t *, bool, mtime_t);
static void PauseDummy (audio_output_t *, bool, mtime_t); static void PauseDummy (audio_output_t *, bool, mtime_t);
static void Flush (audio_output_t *, bool); static void Flush (audio_output_t *, bool);
...@@ -564,7 +564,8 @@ error: ...@@ -564,7 +564,8 @@ error:
/** /**
* Queues one audio buffer to the hardware. * Queues one audio buffer to the hardware.
*/ */
static void Play (audio_output_t *aout, block_t *block) static void Play (audio_output_t *aout, block_t *block,
mtime_t *restrict drift)
{ {
aout_sys_t *sys = aout->sys; aout_sys_t *sys = aout->sys;
...@@ -579,15 +580,15 @@ static void Play (audio_output_t *aout, block_t *block) ...@@ -579,15 +580,15 @@ static void Play (audio_output_t *aout, block_t *block)
if (snd_pcm_delay (pcm, &frames) == 0) if (snd_pcm_delay (pcm, &frames) == 0)
{ {
mtime_t delay = frames * CLOCK_FREQ / aout->format.i_rate; mtime_t delay = frames * CLOCK_FREQ / aout->format.i_rate;
delay += mdate () - block->i_pts;
if (state != SND_PCM_STATE_RUNNING) if (state != SND_PCM_STATE_RUNNING)
{ {
delay = block->i_pts - (mdate () + delay); if (delay < 0)
if (delay > 0)
{ {
if (aout->format.i_format != VLC_CODEC_SPDIFL) if (aout->format.i_format != VLC_CODEC_SPDIFL)
{ {
frames = (delay * aout->format.i_rate) / CLOCK_FREQ; frames = (delay * aout->format.i_rate) / -CLOCK_FREQ;
msg_Dbg (aout, "prepending %ld zeroes", frames); msg_Dbg (aout, "prepending %ld zeroes", frames);
void *z = calloc (frames, aout->format.i_bytes_per_frame); void *z = calloc (frames, aout->format.i_bytes_per_frame);
...@@ -599,17 +600,17 @@ static void Play (audio_output_t *aout, block_t *block) ...@@ -599,17 +600,17 @@ static void Play (audio_output_t *aout, block_t *block)
} }
} }
/* Lame fallback if zero padding does not work */ /* Lame fallback if zero padding does not work */
if (delay > 0) if (delay < 0)
{ {
msg_Dbg (aout, "deferring start (%"PRId64" us)", delay); msg_Dbg (aout, "deferring start (%"PRId64" us)", -delay);
msleep (delay); msleep (-delay);
} }
} }
else else
msg_Dbg (aout, "starting late (%"PRId64" us)", delay); msg_Dbg (aout, "starting late (%"PRId64" us)", delay);
} }
else else
aout_TimeReport (aout, block->i_pts - delay); *drift = delay;
} }
/* TODO: better overflow handling */ /* TODO: better overflow handling */
......
...@@ -66,13 +66,15 @@ struct aout_sys_t ...@@ -66,13 +66,15 @@ struct aout_sys_t
bool mute; bool mute;
}; };
static void Play (audio_output_t *aout, block_t *block) static void Play (audio_output_t *aout, block_t *block,
mtime_t *restrict drift)
{ {
aout_sys_t *sys = aout->sys; aout_sys_t *sys = aout->sys;
sys->play (sys->opaque, block->p_buffer, block->i_nb_samples, sys->play (sys->opaque, block->p_buffer, block->i_nb_samples,
block->i_pts); block->i_pts);
block_Release (block); block_Release (block);
(void) drift;
} }
static void Pause (audio_output_t *aout, bool paused, mtime_t date) static void Pause (audio_output_t *aout, bool paused, mtime_t date)
......
...@@ -57,7 +57,7 @@ struct aout_sys_t ...@@ -57,7 +57,7 @@ struct aout_sys_t
*****************************************************************************/ *****************************************************************************/
static int Open ( vlc_object_t * ); static int Open ( vlc_object_t * );
static void Close ( vlc_object_t * ); static void Close ( vlc_object_t * );
static void Play ( audio_output_t *, block_t * ); static void Play ( audio_output_t *, block_t *, mtime_t * );
static void AudioQueueCallback (void *, AudioQueueRef, AudioQueueBufferRef); static void AudioQueueCallback (void *, AudioQueueRef, AudioQueueBufferRef);
#include "volume.h" #include "volume.h"
......
...@@ -100,7 +100,7 @@ struct aout_sys_t ...@@ -100,7 +100,7 @@ struct aout_sys_t
*****************************************************************************/ *****************************************************************************/
static int OpenAudio ( vlc_object_t * ); static int OpenAudio ( vlc_object_t * );
static void CloseAudio ( vlc_object_t * ); static void CloseAudio ( vlc_object_t * );
static void Play ( audio_output_t *, block_t * ); static void Play ( audio_output_t *, block_t *, mtime_t * );
static int VolumeSet ( audio_output_t *, float ); static int VolumeSet ( audio_output_t *, float );
static int MuteSet ( audio_output_t *, bool ); static int MuteSet ( audio_output_t *, bool );
...@@ -576,7 +576,8 @@ static void Probe( audio_output_t * p_aout ) ...@@ -576,7 +576,8 @@ static void Probe( audio_output_t * p_aout )
* we know the first buffer has been put in the aout fifo and we also * we know the first buffer has been put in the aout fifo and we also
* know its date. * know its date.
*****************************************************************************/ *****************************************************************************/
static void Play( audio_output_t *p_aout, block_t *p_buffer ) static void Play( audio_output_t *p_aout, block_t *p_buffer,
mtime_t *restrict drift )
{ {
/* get the playing date of the first aout buffer */ /* get the playing date of the first aout buffer */
p_aout->sys->notif.start_date = p_buffer->i_pts; p_aout->sys->notif.start_date = p_buffer->i_pts;
...@@ -587,7 +588,7 @@ static void Play( audio_output_t *p_aout, block_t *p_buffer ) ...@@ -587,7 +588,7 @@ static void Play( audio_output_t *p_aout, block_t *p_buffer )
/* wake up the audio output thread */ /* wake up the audio output thread */
SetEvent( p_aout->sys->notif.event ); SetEvent( p_aout->sys->notif.event );
aout_PacketPlay( p_aout, p_buffer ); aout_PacketPlay( p_aout, p_buffer, drift );
p_aout->pf_play = aout_PacketPlay; p_aout->pf_play = aout_PacketPlay;
} }
......
...@@ -72,7 +72,7 @@ static const int pi_channels_maps[CHANNELS_MAX+1] = ...@@ -72,7 +72,7 @@ static const int pi_channels_maps[CHANNELS_MAX+1] =
*****************************************************************************/ *****************************************************************************/
static int Open ( vlc_object_t * ); static int Open ( vlc_object_t * );
static void Close ( vlc_object_t * ); static void Close ( vlc_object_t * );
static void Play ( audio_output_t *, block_t * ); static void Play ( audio_output_t *, block_t *, mtime_t * );
/***************************************************************************** /*****************************************************************************
* Module descriptor * Module descriptor
...@@ -308,7 +308,8 @@ static void Close( vlc_object_t * p_this ) ...@@ -308,7 +308,8 @@ static void Close( vlc_object_t * p_this )
/***************************************************************************** /*****************************************************************************
* Play: pretend to play a sound * Play: pretend to play a sound
*****************************************************************************/ *****************************************************************************/
static void Play( audio_output_t * p_aout, block_t *p_buffer ) static void Play( audio_output_t * p_aout, block_t *p_buffer,
mtime_t *restrict drift )
{ {
if( fwrite( p_buffer->p_buffer, p_buffer->i_buffer, 1, if( fwrite( p_buffer->p_buffer, p_buffer->i_buffer, 1,
p_aout->sys->p_file ) != 1 ) p_aout->sys->p_file ) != 1 )
...@@ -323,4 +324,5 @@ static void Play( audio_output_t * p_aout, block_t *p_buffer ) ...@@ -323,4 +324,5 @@ static void Play( audio_output_t * p_aout, block_t *p_buffer )
} }
block_Release( p_buffer ); block_Release( p_buffer );
(void) drift;
} }
...@@ -56,7 +56,7 @@ struct aout_sys_t ...@@ -56,7 +56,7 @@ struct aout_sys_t
*****************************************************************************/ *****************************************************************************/
static int Open ( vlc_object_t * ); static int Open ( vlc_object_t * );
static void Close ( vlc_object_t * ); static void Close ( vlc_object_t * );
static void Play ( audio_output_t *_p_aout, block_t *block ); static void Play ( audio_output_t *_p_aout, block_t *block, mtime_t * );
static ULONG APIENTRY KaiCallback ( PVOID, PVOID, ULONG ); static ULONG APIENTRY KaiCallback ( PVOID, PVOID, ULONG );
...@@ -255,13 +255,14 @@ exit_free_sys : ...@@ -255,13 +255,14 @@ exit_free_sys :
/***************************************************************************** /*****************************************************************************
* Play: play a sound samples buffer * Play: play a sound samples buffer
*****************************************************************************/ *****************************************************************************/
static void Play (audio_output_t *p_aout, block_t *block) static void Play (audio_output_t *p_aout, block_t *block,
mtime_t *restrict drift)
{ {
aout_sys_t *p_sys = p_aout->sys; aout_sys_t *p_sys = p_aout->sys;
kaiPlay( p_sys->hkai ); kaiPlay( p_sys->hkai );
aout_PacketPlay( p_aout, block ); aout_PacketPlay( p_aout, block, drift );
} }
/***************************************************************************** /*****************************************************************************
......
...@@ -141,7 +141,8 @@ static void Pause(audio_output_t *p_aout, bool pause, mtime_t date) ...@@ -141,7 +141,8 @@ static void Pause(audio_output_t *p_aout, bool pause, mtime_t date)
/***************************************************************************** /*****************************************************************************
* Play: play a sound * Play: play a sound
*****************************************************************************/ *****************************************************************************/
static void Play( audio_output_t *p_aout, block_t *p_buffer ) static void Play( audio_output_t *p_aout, block_t *p_buffer,
mtime_t *restrict drift )
{ {
aout_sys_t *p_sys = p_aout->sys; aout_sys_t *p_sys = p_aout->sys;
int tries = 5; int tries = 5;
...@@ -170,9 +171,8 @@ static void Play( audio_output_t *p_aout, block_t *p_buffer ) ...@@ -170,9 +171,8 @@ static void Play( audio_output_t *p_aout, block_t *p_buffer )
block_ChainLastAppend( &p_sys->pp_last, p_buffer ); block_ChainLastAppend( &p_sys->pp_last, p_buffer );
vlc_mutex_unlock( &p_sys->lock ); vlc_mutex_unlock( &p_sys->lock );
if (delay && st.count) { if (delay && st.count)
aout_TimeReport(p_aout, p_buffer->i_pts - delay); *drift = mdate() + delay - p_buffer->i_pts;
}
for (;;) for (;;)
{ {
......
...@@ -74,7 +74,7 @@ vlc_module_begin () ...@@ -74,7 +74,7 @@ vlc_module_begin ()
set_callbacks( Open, Close ) set_callbacks( Open, Close )
vlc_module_end () vlc_module_end ()
static void Play (audio_output_t *, block_t *); static void Play (audio_output_t *, block_t *, mtime_t *);
static void Pause (audio_output_t *, bool, mtime_t); static void Pause (audio_output_t *, bool, mtime_t);
static void Flush (audio_output_t *, bool); static void Flush (audio_output_t *, bool);
static int VolumeSync (audio_output_t *); static int VolumeSync (audio_output_t *);
...@@ -318,7 +318,8 @@ static void Close (vlc_object_t *obj) ...@@ -318,7 +318,8 @@ static void Close (vlc_object_t *obj)
/** /**
* Queues one audio buffer to the hardware. * Queues one audio buffer to the hardware.
*/ */
static void Play (audio_output_t *aout, block_t *block) static void Play (audio_output_t *aout, block_t *block,
mtime_t *restrict drift)
{ {
aout_sys_t *sys = aout->sys; aout_sys_t *sys = aout->sys;
int fd = sys->fd; int fd = sys->fd;
...@@ -329,7 +330,7 @@ static void Play (audio_output_t *aout, block_t *block) ...@@ -329,7 +330,7 @@ static void Play (audio_output_t *aout, block_t *block)
mtime_t latency = (delay * CLOCK_FREQ * aout->format.i_frame_length) mtime_t latency = (delay * CLOCK_FREQ * aout->format.i_frame_length)
/ (aout->format.i_rate * aout->format.i_bytes_per_frame); / (aout->format.i_rate * aout->format.i_bytes_per_frame);
/* TODO: insert zeroes when starting playback */ /* TODO: insert zeroes when starting playback */
aout_TimeReport (aout, block->i_pts - latency); *drift = mdate () + latency - block->i_pts;
} }
else else
msg_Warn (aout, "cannot get delay: %m"); msg_Warn (aout, "cannot get delay: %m");
......
...@@ -158,7 +158,8 @@ void aout_PacketDestroy (audio_output_t *aout) ...@@ -158,7 +158,8 @@ void aout_PacketDestroy (audio_output_t *aout)
static block_t *aout_OutputSlice (audio_output_t *); static block_t *aout_OutputSlice (audio_output_t *);
void aout_PacketPlay (audio_output_t *aout, block_t *block) void aout_PacketPlay (audio_output_t *aout, block_t *block,
mtime_t *restrict drift)
{ {
aout_packet_t *p = aout_packet (aout); aout_packet_t *p = aout_packet (aout);
mtime_t time_report; mtime_t time_report;
...@@ -173,7 +174,7 @@ void aout_PacketPlay (audio_output_t *aout, block_t *block) ...@@ -173,7 +174,7 @@ void aout_PacketPlay (audio_output_t *aout, block_t *block)
vlc_mutex_unlock (&p->lock); vlc_mutex_unlock (&p->lock);
if (time_report != INT64_MIN) if (time_report != INT64_MIN)
aout_TimeReport (aout, mdate () - time_report); *drift = time_report;
} }
void aout_PacketPause (audio_output_t *aout, bool pause, mtime_t date) void aout_PacketPause (audio_output_t *aout, bool pause, mtime_t date)
......
...@@ -515,7 +515,7 @@ static void *data_convert(block_t **pp) ...@@ -515,7 +515,7 @@ static void *data_convert(block_t **pp)
/** /**
* Queue one audio frame to the playabck stream * Queue one audio frame to the playabck stream
*/ */
static void Play(audio_output_t *aout, block_t *block) static void Play(audio_output_t *aout, block_t *block, mtime_t *restrict drift)
{ {
aout_sys_t *sys = aout->sys; aout_sys_t *sys = aout->sys;
pa_stream *s = sys->stream; pa_stream *s = sys->stream;
...@@ -554,6 +554,7 @@ static void Play(audio_output_t *aout, block_t *block) ...@@ -554,6 +554,7 @@ static void Play(audio_output_t *aout, block_t *block)
} }
pa_threaded_mainloop_unlock(sys->mainloop); pa_threaded_mainloop_unlock(sys->mainloop);
(void) drift;
} }
/** /**
......
...@@ -43,7 +43,7 @@ vlc_module_begin () ...@@ -43,7 +43,7 @@ vlc_module_begin ()
set_callbacks (Open, Close ) set_callbacks (Open, Close )
vlc_module_end () vlc_module_end ()
static void Play (audio_output_t *, block_t *); static void Play (audio_output_t *, block_t *, mtime_t *);
static void Pause (audio_output_t *, bool, mtime_t); static void Pause (audio_output_t *, bool, mtime_t);
static int VolumeSet (audio_output_t *, float); static int VolumeSet (audio_output_t *, float);
static int MuteSet (audio_output_t *, bool); static int MuteSet (audio_output_t *, bool);
...@@ -183,7 +183,8 @@ static void Close (vlc_object_t *obj) ...@@ -183,7 +183,8 @@ static void Close (vlc_object_t *obj)
free (sys); free (sys);
} }
static void Play (audio_output_t *aout, block_t *block) static void Play (audio_output_t *aout, block_t *block,
mtime_t *restrict drift)
{ {
aout_sys_t *sys = aout->sys; aout_sys_t *sys = aout->sys;
struct sio_par par; struct sio_par par;
...@@ -192,8 +193,7 @@ static void Play (audio_output_t *aout, block_t *block) ...@@ -192,8 +193,7 @@ static void Play (audio_output_t *aout, block_t *block)
{ {
mtime_t delay = par.bufsz * CLOCK_FREQ / aout->format.i_rate; mtime_t delay = par.bufsz * CLOCK_FREQ / aout->format.i_rate;
delay = block->i_pts - (mdate () - delay); *drift = mdate () + delay - block->i_pts;
aout_TimeReport (aout, block->i_pts - delay);
} }
while (block->i_buffer > 0 && !sio_eof (sys->hdl)) while (block->i_buffer > 0 && !sio_eof (sys->hdl))
......
...@@ -81,7 +81,7 @@ struct aout_sys_t ...@@ -81,7 +81,7 @@ struct aout_sys_t
HANDLE done; /**< Semaphore to MTA thread */ HANDLE done; /**< Semaphore to MTA thread */
}; };
static void Play(audio_output_t *aout, block_t *block) static void Play(audio_output_t *aout, block_t *block, mtime_t *restrict drift)
{ {
aout_sys_t *sys = aout->sys; aout_sys_t *sys = aout->sys;
HRESULT hr; HRESULT hr;
...@@ -94,7 +94,7 @@ static void Play(audio_output_t *aout, block_t *block) ...@@ -94,7 +94,7 @@ static void Play(audio_output_t *aout, block_t *block)
IAudioClock_GetPosition(sys->clock, &pos, &qpcpos); IAudioClock_GetPosition(sys->clock, &pos, &qpcpos);
qpcpos = (qpcpos + 5) / 10; /* 100ns -> 1µs */ qpcpos = (qpcpos + 5) / 10; /* 100ns -> 1µs */
/* NOTE: this assumes mdate() uses QPC() (which it currently does). */ /* NOTE: this assumes mdate() uses QPC() (which it currently does). */
aout_TimeReport(aout, qpcpos); *drift = mdate() - qpcpos;
} }
for (;;) for (;;)
......
...@@ -51,7 +51,7 @@ ...@@ -51,7 +51,7 @@
*****************************************************************************/ *****************************************************************************/
static int Open ( vlc_object_t * ); static int Open ( vlc_object_t * );
static void Close ( vlc_object_t * ); static void Close ( vlc_object_t * );
static void Play ( audio_output_t *, block_t * ); static void Play ( audio_output_t *, block_t *, mtime_t * );
/***************************************************************************** /*****************************************************************************
* notification_thread_t: waveOut event thread * notification_thread_t: waveOut event thread
...@@ -491,7 +491,8 @@ static void Probe( audio_output_t * p_aout ) ...@@ -491,7 +491,8 @@ static void Probe( audio_output_t * p_aout )
* This doesn't actually play the buffer. This just stores the buffer so it * This doesn't actually play the buffer. This just stores the buffer so it
* can be played by the callback thread. * can be played by the callback thread.
*****************************************************************************/ *****************************************************************************/
static void Play( audio_output_t *_p_aout, block_t *block ) static void Play( audio_output_t *_p_aout, block_t *block,
mtime_t *restrict drift )
{ {
if( !_p_aout->sys->b_playing ) if( !_p_aout->sys->b_playing )
{ {
...@@ -508,7 +509,7 @@ static void Play( audio_output_t *_p_aout, block_t *block ) ...@@ -508,7 +509,7 @@ static void Play( audio_output_t *_p_aout, block_t *block )
SetEvent( _p_aout->sys->new_buffer_event ); SetEvent( _p_aout->sys->new_buffer_event );
} }
aout_PacketPlay( _p_aout, block ); aout_PacketPlay( _p_aout, block, drift );
} }
/***************************************************************************** /*****************************************************************************
......
...@@ -73,7 +73,6 @@ audio_output_t *aout_New( vlc_object_t * p_parent ) ...@@ -73,7 +73,6 @@ audio_output_t *aout_New( vlc_object_t * p_parent )
owner->module = NULL; owner->module = NULL;
owner->input = NULL; owner->input = NULL;
aout->pf_play = aout_DecDeleteBuffer;
aout->volume_set = NULL; aout->volume_set = NULL;
aout->mute_set = NULL; aout->mute_set = NULL;
vlc_object_set_destructor (aout, aout_Destructor); vlc_object_set_destructor (aout, aout_Destructor);
......
...@@ -36,49 +36,6 @@ ...@@ -36,49 +36,6 @@
#include "libvlc.h" #include "libvlc.h"
#include "aout_internal.h" #include "aout_internal.h"
/**
* Notifies the audio input of the drift from the requested audio
* playback timestamp (@ref block_t.i_pts) to the anticipated playback time
* as reported by the audio output hardware.
* Depending on the drift amplitude, the input core may ignore the drift
* trigger upsampling or downsampling, or even discard samples.
* Future VLC versions may instead adjust the input decoding speed.
*
* The audio output plugin is responsible for estimating the ideal current
* playback time defined as follows:
* ideal time = buffer timestamp - (output latency + pending buffer duration)
*
* Practically, this is the PTS (block_t.i_pts) of the current buffer minus
* the latency reported by the output programming interface.
* Computing the estimated drift directly would probably be more intuitive.
* However the use of an absolute time value does not introduce extra
* measurement errors due to the CPU scheduling jitter and clock resolution.
* Furthermore, the ideal while it is an abstract value, is easy for most
* audio output plugins to compute.
* The following definition is equivalent but depends on the clock time:
* ideal time = real time + drift
* @note If aout_LatencyReport() is never called, the core will assume that
* there is no drift.
*
* @param ideal estimated ideal time as defined above.
*/
static void aout_OutputTimeReport (audio_output_t *aout, mtime_t ideal)
{
mtime_t delta = mdate() - ideal /* = -drift */;
aout_assert_locked (aout);
if (delta < -AOUT_MAX_PTS_ADVANCE || +AOUT_MAX_PTS_DELAY < delta)
{
aout_owner_t *owner = aout_owner (aout);
msg_Warn (aout, "not synchronized (%"PRId64" us), resampling",
delta);
if (date_Get (&owner->sync.date) != VLC_TS_INVALID)
date_Move (&owner->sync.date, delta);
}
}
/** /**
* Supply or update the current custom ("hardware") volume. * Supply or update the current custom ("hardware") volume.
* @note This only makes sense after calling aout_VolumeHardInit(). * @note This only makes sense after calling aout_VolumeHardInit().
...@@ -123,7 +80,6 @@ int aout_OutputNew( audio_output_t *p_aout, ...@@ -123,7 +80,6 @@ int aout_OutputNew( audio_output_t *p_aout,
p_aout->format = *p_format; p_aout->format = *p_format;
aout_FormatPrepare( &p_aout->format ); aout_FormatPrepare( &p_aout->format );
p_aout->event.time_report = aout_OutputTimeReport;
p_aout->event.volume_report = aout_OutputVolumeReport; p_aout->event.volume_report = aout_OutputVolumeReport;
p_aout->event.mute_report = aout_OutputMuteReport; p_aout->event.mute_report = aout_OutputMuteReport;
p_aout->event.gain_request = aout_OutputGainRequest; p_aout->event.gain_request = aout_OutputGainRequest;
...@@ -275,10 +231,6 @@ void aout_OutputDelete (audio_output_t *aout) ...@@ -275,10 +231,6 @@ void aout_OutputDelete (audio_output_t *aout)
return; return;
module_unneed (aout, owner->module); module_unneed (aout, owner->module);
/* Clear callbacks */
aout->pf_play = aout_DecDeleteBuffer; /* gruik */
aout->pf_pause = NULL;
aout->pf_flush = NULL;
aout->volume_set = NULL; aout->volume_set = NULL;
aout->mute_set = NULL; aout->mute_set = NULL;
owner->module = NULL; owner->module = NULL;
...@@ -291,6 +243,7 @@ void aout_OutputDelete (audio_output_t *aout) ...@@ -291,6 +243,7 @@ void aout_OutputDelete (audio_output_t *aout)
void aout_OutputPlay (audio_output_t *aout, block_t *block) void aout_OutputPlay (audio_output_t *aout, block_t *block)
{ {
aout_owner_t *owner = aout_owner (aout); aout_owner_t *owner = aout_owner (aout);
mtime_t drift = 0;
aout_assert_locked (aout); aout_assert_locked (aout);
...@@ -303,7 +256,34 @@ void aout_OutputPlay (audio_output_t *aout, block_t *block) ...@@ -303,7 +256,34 @@ void aout_OutputPlay (audio_output_t *aout, block_t *block)
return; return;
} }
aout->pf_play (aout, block); if (likely(owner->module != NULL))
aout->pf_play (aout, block, &drift);
else
block_Release (block);
/**
* Notifies the audio input of the drift from the requested audio
* playback timestamp (@ref block_t.i_pts) to the anticipated playback time
* as reported by the audio output hardware.
* Depending on the drift amplitude, the input core may ignore the drift
* trigger upsampling or downsampling, or even discard samples.
* Future VLC versions may instead adjust the input decoding speed.
*
* The audio output plugin is responsible for estimating the drift. A negative
* value means playback is ahead of the intended time and a positive value
* means playback is late from the intended time. In most cases, the audio
* output can estimate the delay until playback of the next sample to be
* queued. Then, before the block is queued:
* drift = mdate() + delay - block->i_pts
* where mdate() + delay is the estimated time when the sample will be rendered
* and block->i_pts is the intended time.
*/
if (drift < -AOUT_MAX_PTS_ADVANCE || +AOUT_MAX_PTS_DELAY < drift)
{
msg_Warn (aout, "not synchronized (%"PRId64" us), resampling",
drift);
if (date_Get (&owner->sync.date) != VLC_TS_INVALID)
date_Move (&owner->sync.date, drift);
}
} }
/** /**
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment