]> git.sesse.net Git - vlc/commitdiff
aout: separate time and play callbacks
authorRémi Denis-Courmont <remi@remlab.net>
Mon, 12 Nov 2012 21:01:24 +0000 (23:01 +0200)
committerRémi Denis-Courmont <remi@remlab.net>
Mon, 12 Nov 2012 21:01:24 +0000 (23:01 +0200)
18 files changed:
include/vlc_aout.h
modules/audio_output/adummy.c
modules/audio_output/alsa.c
modules/audio_output/amem.c
modules/audio_output/audioqueue.c
modules/audio_output/audiotrack.c
modules/audio_output/auhal.c
modules/audio_output/directx.c
modules/audio_output/file.c
modules/audio_output/jack.c
modules/audio_output/kai.c
modules/audio_output/oss.c
modules/audio_output/packet.c
modules/audio_output/pulse.c
modules/audio_output/sndio.c
modules/audio_output/wasapi.c
modules/audio_output/waveout.c
src/audio_output/output.c

index 0ecbc88b43c45e8f0f3374e501cfa968a83babf5..8aefd4df14266d6aab8a999ba98a3d0ab7d02574 100644 (file)
@@ -150,7 +150,14 @@ struct audio_output
     /**< Stops the existing stream (optional, may be NULL).
       * \note A stream must have been started when called.
       */
-    void (*play)(audio_output_t *, block_t *, mtime_t *);
+    int (*time_get)(audio_output_t *, mtime_t *write_pts);
+    /**< Estimates the date/time of the playback buffer write offset
+      * (optional, may be NULL). The read offset is not returned since it is
+      * always implicitly equal to the current time (mdate()).
+      * \param write_pts timestamp of the write offset [OUT]
+      * \note A stream must have been started when called.
+      */
+    void (*play)(audio_output_t *, block_t *);
     /**< Queues a block of samples for playback (mandatory, cannot be NULL).
       * \note A stream must have been started when called.
       */
@@ -311,7 +318,6 @@ typedef struct
     aout_fifo_t partial; /**< Audio blocks before packetization */
     aout_fifo_t fifo; /**< Packetized audio blocks */
     mtime_t pause_date; /**< Date when paused or VLC_TS_INVALID */
-    mtime_t time_report; /**< Desynchronization estimate or VLC_TS_INVALID */
     unsigned samples; /**< Samples per packet */
     bool starving; /**< Whether currently starving (to limit error messages) */
 } aout_packet_t;
@@ -319,7 +325,8 @@ typedef struct
 VLC_DEPRECATED void aout_PacketInit(audio_output_t *, aout_packet_t *, unsigned, const audio_sample_format_t *);
 VLC_DEPRECATED void aout_PacketDestroy(audio_output_t *);
 
-VLC_DEPRECATED void aout_PacketPlay(audio_output_t *, block_t *, mtime_t *);
+VLC_DEPRECATED int aout_PacketTimeGet(audio_output_t *, mtime_t *);
+VLC_DEPRECATED void aout_PacketPlay(audio_output_t *, block_t *);
 VLC_DEPRECATED void aout_PacketPause(audio_output_t *, bool, mtime_t);
 VLC_DEPRECATED void aout_PacketFlush(audio_output_t *, bool);
 
index 887947b93b5567393509cb3234e29e113fb1414d..0495536c587222493600449d166664c96ee03eb7 100644 (file)
@@ -42,11 +42,10 @@ vlc_module_end ()
 
 #define A52_FRAME_NB 1536
 
-static void Play( audio_output_t *aout, block_t *block, mtime_t *drift )
+static void Play(audio_output_t *aout, block_t *block)
 {
     block_Release( block );
     (void) aout;
-    (void) drift;
 }
 
 static int Start(audio_output_t *aout, audio_sample_format_t *restrict fmt)
@@ -68,6 +67,7 @@ static int Open(vlc_object_t *obj)
     audio_output_t *aout = (audio_output_t *)obj;
 
     aout->start = Start;
+    aout->time_get = NULL;
     aout->play = Play;
     aout->pause = NULL;
     aout->flush = NULL;
index af16da62e5c10f19db42c67aa6f1ef48456e04a5..7b0fa8fe6231acbb9a92feaef506aa6f9c6e1de8 100644 (file)
@@ -153,7 +153,8 @@ static int DeviceChanged (vlc_object_t *obj, const char *varname,
     return VLC_SUCCESS;
 }
 
-static void Play (audio_output_t *, block_t *, mtime_t *);
+static int TimeGet (audio_output_t *aout, mtime_t *);
+static void Play (audio_output_t *, block_t *);
 static void Pause (audio_output_t *, bool, mtime_t);
 static void PauseDummy (audio_output_t *, bool, mtime_t);
 static void Flush (audio_output_t *, bool);
@@ -508,6 +509,7 @@ static int Start (audio_output_t *aout, audio_sample_format_t *restrict fmt)
     }
     sys->format = *fmt;
 
+    aout->time_get = TimeGet;
     aout->play = Play;
     if (snd_pcm_hw_params_can_pause (hw))
         aout->pause = Pause;
@@ -540,11 +542,33 @@ error:
     return VLC_EGENERIC;
 }
 
+static int TimeGet (audio_output_t *aout, mtime_t *restrict pts)
+{
+    aout_sys_t *sys = aout->sys;
+    snd_pcm_t *pcm = sys->pcm;
+    snd_pcm_status_t *status;
+    int val;
+
+    snd_pcm_status_alloca (&status);
+    val = snd_pcm_status (pcm, status);
+    if (val < 0)
+    {
+        msg_Err (aout, "cannot get status: %s", snd_strerror (val));
+        return -1;
+    }
+
+    if (snd_pcm_status_get_state (status) != SND_PCM_STATE_RUNNING)
+        return -1;
+
+    snd_pcm_sframes_t frames = snd_pcm_status_get_delay (status);
+    *pts = mdate () + (frames * CLOCK_FREQ / sys->format.i_rate);
+    return 0;
+}
+
 /**
  * Queues one audio buffer to the hardware.
  */
-static void Play (audio_output_t *aout, block_t *block,
-                  mtime_t *restrict drift)
+static void Play (audio_output_t *aout, block_t *block)
 {
     aout_sys_t *sys = aout->sys;
 
@@ -561,40 +585,36 @@ static void Play (audio_output_t *aout, block_t *block,
     if (val < 0)
         msg_Err (aout, "cannot get status: %s", snd_strerror (val));
     else
+    if (snd_pcm_status_get_state (status) != SND_PCM_STATE_RUNNING)
     {
         snd_pcm_sframes_t frames = snd_pcm_status_get_delay (status);
         mtime_t delay = frames * CLOCK_FREQ / sys->format.i_rate;
-        delay += mdate () - block->i_pts;
 
-        if (snd_pcm_status_get_state (status) != SND_PCM_STATE_RUNNING)
+        delay += mdate () - block->i_pts;
+        if (delay < 0)
         {
-            if (delay < 0)
+            if (sys->format.i_format != VLC_CODEC_SPDIFL)
             {
-                if (sys->format.i_format != VLC_CODEC_SPDIFL)
-                {
-                    frames = (delay * sys->format.i_rate) / -CLOCK_FREQ;
-                    msg_Dbg (aout, "prepending %ld zeroes", frames);
-
-                    void *z = calloc (frames, sys->format.i_bytes_per_frame);
-                    if (likely(z != NULL))
-                    {
-                        snd_pcm_writei (pcm, z, frames);
-                        free (z);
-                        delay = 0;
-                    }
-                }
-                /* Lame fallback if zero padding does not work */
-                if (delay < 0)
+                frames = (delay * sys->format.i_rate) / -CLOCK_FREQ;
+                msg_Dbg (aout, "prepending %ld zeroes", frames);
+
+                void *z = calloc (frames, sys->format.i_bytes_per_frame);
+                if (likely(z != NULL))
                 {
-                    msg_Dbg (aout, "deferring start (%"PRId64" us)", -delay);
-                    msleep (-delay);
+                    snd_pcm_writei (pcm, z, frames);
+                    free (z);
+                    delay = 0;
                 }
             }
-            else
-                msg_Dbg (aout, "starting late (%"PRId64" us)", delay);
+            /* Lame fallback if zero padding does not work */
+            if (delay < 0)
+            {
+                msg_Dbg (aout, "deferring start (%"PRId64" us)", -delay);
+                msleep (-delay);
+            }
         }
         else
-            *drift = delay;
+            msg_Dbg (aout, "starting late (%"PRId64" us)", delay);
     }
 
     /* TODO: better overflow handling */
index 68ed27132d013b4a4be8bcf8a3a51f044c8dfab6..ebac668aaf97347e8190f072b1e55b15e2c60de5 100644 (file)
@@ -75,15 +75,13 @@ struct aout_sys_t
     bool mute;
 };
 
-static void Play (audio_output_t *aout, block_t *block,
-                  mtime_t *restrict drift)
+static void Play (audio_output_t *aout, block_t *block)
 {
     aout_sys_t *sys = aout->sys;
 
     sys->play (sys->opaque, block->p_buffer, block->i_nb_samples,
                block->i_pts);
     block_Release (block);
-    (void) drift;
 }
 
 static void Pause (audio_output_t *aout, bool paused, mtime_t date)
@@ -251,6 +249,7 @@ static int Open (vlc_object_t *obj)
 
     aout->start = Start;
     aout->stop = Stop;
+    aout->time_get = NULL;
     aout->play = Play;
     aout->pause = Pause;
     aout->flush = Flush;
index 802d839835996068f4a508f320ec85b2b68d9843..678ccfbf80de8aa7c3ac384355b6520853e30379 100644 (file)
@@ -123,6 +123,7 @@ static int Start( audio_output_t *aout, audio_sample_format_t *restrict fmt )
     fmt->i_physical_channels = AOUT_CHANS_STEREO;
     fmt->i_rate = 44100;
     aout_PacketInit(p_aout, &p_sys->packet, FRAME_SIZE, fmt);
+    p_aout->time_get = aout_PacketTimeGet;
     p_aout->play = aout_PacketPlay;
     p_aout->pause = aout_PacketPause;
     p_aout->flush = aout_PacketFlush;
index 127fc32b1b61812371543071f260ea9f9655cf4f..6046c1c48bad64c4ae884a4158ab1faf2194c583 100644 (file)
@@ -266,6 +266,7 @@ static int Start(audio_output_t *aout, audio_sample_format_t *restrict fmt)
     }
 
     aout->sys = p_sys;
+    aout->time_get = NULL;
     aout->play = Play;
     aout->pause = Pause;
 
@@ -287,9 +288,8 @@ static void Stop(audio_output_t* p_aout)
 }
 
 /* FIXME: lipsync */
-static void Play(audio_output_t* p_aout, block_t* p_buffer, mtime_t* restrict drift)
+static void Play(audio_output_t* p_aout, block_t* p_buffer)
 {
-    VLC_UNUSED(drift);
     aout_sys_t *p_sys = p_aout->sys;
 
     size_t length = 0;
index b0adc1e5b20b2cdabedc5c8d007ea6f596296579..f2f32d916f6d13bdce6cc7398c829f2a5ee4656a 100644 (file)
@@ -172,6 +172,7 @@ static int Start(audio_output_t *p_aout, audio_sample_format_t *restrict fmt)
     p_sys->b_changed_mixing = false;
     memset(p_sys->p_remainder_buffer, 0, sizeof(uint8_t) * BUFSIZE);
 
+    p_aout->time_get = aout_PacketTimeGet;
     p_aout->play = aout_PacketPlay;
     p_aout->pause = aout_PacketPause;
     p_aout->flush = aout_PacketFlush;
index 55c5a6c3b16a1a21639738d208e0f93eea44d8dc..ea2b99ca1edc9ecae0f8b82decc6082006c58f5d 100644 (file)
@@ -96,7 +96,7 @@ struct aout_sys_t
 static int  Open( vlc_object_t * );
 static void Close( vlc_object_t * );
 static void Stop( audio_output_t * );
-static void Play       ( audio_output_t *, block_t *, mtime_t * );
+static void Play       ( audio_output_t *, block_t * );
 static int  VolumeSet  ( audio_output_t *, float );
 static int  MuteSet    ( audio_output_t *, bool );
 
@@ -282,6 +282,7 @@ static int Start( audio_output_t *p_aout, audio_sample_format_t *restrict fmt )
         goto error;
     }
 
+    p_aout->time_get = aout_PacketTimeGet;
     p_aout->play = Play;
     p_aout->pause = aout_PacketPause;
     p_aout->flush = aout_PacketFlush;
@@ -509,8 +510,7 @@ static void Probe( audio_output_t * p_aout, const audio_sample_format_t *fmt )
  *       we know the first buffer has been put in the aout fifo and we also
  *       know its date.
  *****************************************************************************/
-static void Play( audio_output_t *p_aout, block_t *p_buffer,
-                  mtime_t *restrict drift )
+static void Play( audio_output_t *p_aout, block_t *p_buffer )
 {
     /* get the playing date of the first aout buffer */
     p_aout->sys->notif.start_date = p_buffer->i_pts;
@@ -521,7 +521,7 @@ static void Play( audio_output_t *p_aout, block_t *p_buffer,
     /* wake up the audio output thread */
     SetEvent( p_aout->sys->notif.event );
 
-    aout_PacketPlay( p_aout, p_buffer, drift );
+    aout_PacketPlay( p_aout, p_buffer );
     p_aout->play = aout_PacketPlay;
 }
 
index fcdbf791362975bc8612aa9a51d1e07eb06966b4..3a5a32f43952d03bf83e57208513f4849b48f22a 100644 (file)
@@ -71,7 +71,7 @@ static const int pi_channels_maps[CHANNELS_MAX+1] =
  * Local prototypes.
  *****************************************************************************/
 static int     Open        ( vlc_object_t * );
-static void    Play        ( audio_output_t *, block_t *, mtime_t * );
+static void    Play        ( audio_output_t *, block_t * );
 
 /*****************************************************************************
  * Module descriptor
@@ -154,6 +154,7 @@ static int Start( audio_output_t *p_aout, audio_sample_format_t *restrict fmt )
         return VLC_EGENERIC;
     }
 
+    p_aout->time_get = NULL;
     p_aout->play = Play;
     p_aout->pause = NULL;
     p_aout->flush = NULL;
@@ -296,8 +297,7 @@ static void Stop( audio_output_t *p_aout )
 /*****************************************************************************
  * Play: pretend to play a sound
  *****************************************************************************/
-static void Play( audio_output_t * p_aout, block_t *p_buffer,
-                  mtime_t *restrict drift )
+static void Play( audio_output_t * p_aout, block_t *p_buffer )
 {
     if( fwrite( p_buffer->p_buffer, p_buffer->i_buffer, 1,
                 p_aout->sys->p_file ) != 1 )
@@ -312,7 +312,6 @@ static void Play( audio_output_t * p_aout, block_t *p_buffer,
     }
 
     block_Release( p_buffer );
-    (void) drift;
 }
 
 static int Open(vlc_object_t *obj)
index b07536a8284fae8a6333713f551084c787f1a22c..0d12c01ebc3022ae1979aaf35a0b721a5bc45126 100644 (file)
@@ -132,6 +132,7 @@ static int Start( audio_output_t *p_aout, audio_sample_format_t *restrict fmt )
     // TODO add buffer size callback
     fmt->i_rate = jack_get_sample_rate( p_sys->p_jack_client );
 
+    p_aout->time_get = aout_PacketTimeGet;
     p_aout->play = aout_PacketPlay;
     p_aout->pause = aout_PacketPause;
     p_aout->flush = aout_PacketFlush;
index 9160affab7342a0403fdd5a20e308066ca9ce42e..8b2724ae5fdbdefdd38faac7c133043f1a08d9d9 100644 (file)
@@ -57,7 +57,7 @@ struct aout_sys_t
  *****************************************************************************/
 static int  Open  ( vlc_object_t * );
 static void Close ( vlc_object_t * );
-static void Play  ( audio_output_t *_p_aout, block_t *block, mtime_t * );
+static void Play  ( audio_output_t *_p_aout, block_t *block );
 
 static ULONG APIENTRY KaiCallback ( PVOID, PVOID, ULONG );
 
@@ -195,6 +195,7 @@ static int Start ( audio_output_t *p_aout, audio_sample_format_t *fmt )
 
     p_sys->format = *fmt = format;
 
+    p_aout->time_get = aout_PacketTimeGet;
     p_aout->play  = Play;
     p_aout->pause = aout_PacketPause;
     p_aout->flush = aout_PacketFlush;
@@ -244,14 +245,13 @@ exit_kai_done :
 /*****************************************************************************
  * Play: play a sound samples buffer
  *****************************************************************************/
-static void Play (audio_output_t *p_aout, block_t *block,
-                  mtime_t *restrict drift)
+static void Play (audio_output_t *p_aout, block_t *block)
 {
     aout_sys_t *p_sys = p_aout->sys;
 
     kaiPlay( p_sys->hkai );
 
-    aout_PacketPlay( p_aout, block, drift );
+    aout_PacketPlay( p_aout, block );
 }
 
 /*****************************************************************************
index 52faed1470fe29a57c4acdf152b446e12bb17a1c..24d7af9c2230578817b28278e616d0eab3500b92 100644 (file)
@@ -75,7 +75,8 @@ vlc_module_begin ()
     set_callbacks (Open, NULL)
 vlc_module_end ()
 
-static void Play (audio_output_t *, block_t *, mtime_t *);
+static int TimeGet (audio_output_t *, mtime_t *);
+static void Play (audio_output_t *, block_t *);
 static void Pause (audio_output_t *, bool, mtime_t);
 static void Flush (audio_output_t *, bool);
 static int VolumeSync (audio_output_t *);
@@ -219,6 +220,7 @@ static int Start (audio_output_t *aout, audio_sample_format_t *restrict fmt)
     }
 
     /* Setup audio_output_t */
+    aout->time_get = TimeGet;
     aout->play = Play;
     aout->pause = Pause;
     aout->flush = Flush;
@@ -311,38 +313,30 @@ static void Stop (audio_output_t *aout)
     free (sys);
 }
 
-/**
- * Queues one audio buffer to the hardware.
- */
-static void Play (audio_output_t *aout, block_t *block,
-                  mtime_t *restrict drift)
+static int TimeGet (audio_output_t *aout, mtime_t *restrict pts)
 {
     aout_sys_t *sys = aout->sys;
-    int fd = sys->fd;
-
     int delay;
-    if (ioctl (sys->fd, SNDCTL_DSP_GETODELAY, &delay) >= 0)
+
+    if (ioctl (sys->fd, SNDCTL_DSP_GETODELAY, &delay) < 0)
     {
-        mtime_t latency = (delay * CLOCK_FREQ * sys->format.i_frame_length)
-                      / (sys->format.i_rate * sys->format.i_bytes_per_frame);
-        *drift = mdate () + latency - block->i_pts;
-    }
-    else
         msg_Warn (aout, "cannot get delay: %m");
-
-    if (sys->starting)
-    {   /* Start on time */
-        /* TODO: resync on pause resumption and underflow recovery */
-        mtime_t delta = -*drift;
-        if (delta > 0) {
-            msg_Dbg(aout, "deferring start (%"PRId64" us)", delta);
-            msleep(delta);
-            *drift = 0;
-        } else
-            msg_Warn(aout, "starting late (%"PRId64" us)", delta);
-        sys->starting = false;
+        return -1;
     }
 
+    *pts = mdate () + ((delay * CLOCK_FREQ * sys->format.i_frame_length)
+                      / (sys->format.i_rate * sys->format.i_bytes_per_frame));
+    return 0;
+}
+
+/**
+ * Queues one audio buffer to the hardware.
+ */
+static void Play (audio_output_t *aout, block_t *block)
+{
+    aout_sys_t *sys = aout->sys;
+    int fd = sys->fd;
+
     while (block->i_buffer > 0)
     {
         ssize_t bytes = write (fd, block->p_buffer, block->i_buffer);
index 9bfa6fe147b4d79d7397a5560cacb09441715ca4..3562c0e36c5bdb6c6cab59597081e5dffcda4d9f 100644 (file)
@@ -144,7 +144,6 @@ void aout_PacketInit (audio_output_t *aout, aout_packet_t *p, unsigned samples,
     aout_FifoInit (&p->partial, p->format.i_rate);
     aout_FifoInit (&p->fifo, p->format.i_rate);
     p->pause_date = VLC_TS_INVALID;
-    p->time_report = INT64_MIN;
     p->samples = samples;
     p->starving = true;
 }
@@ -158,25 +157,32 @@ void aout_PacketDestroy (audio_output_t *aout)
     vlc_mutex_destroy (&p->lock);
 }
 
+int aout_PacketTimeGet (audio_output_t *aout,  mtime_t *restrict pts)
+{
+    aout_packet_t *p = aout_packet (aout);
+    mtime_t time_report;
+
+    vlc_mutex_lock (&p->lock);
+    time_report = date_Get (&p->fifo.end_date);
+    vlc_mutex_unlock (&p->lock);
+
+    if (time_report == VLC_TS_INVALID)
+        return -1;
+    *pts = time_report;
+    return 0;
+}
+
 static block_t *aout_OutputSlice (audio_output_t *);
 
-void aout_PacketPlay (audio_output_t *aout, block_t *block,
-                      mtime_t *restrict drift)
+void aout_PacketPlay (audio_output_t *aout, block_t *block)
 {
     aout_packet_t *p = aout_packet (aout);
-    mtime_t time_report;
 
     vlc_mutex_lock (&p->lock);
     aout_FifoPush (&p->partial, block);
     while ((block = aout_OutputSlice (aout)) != NULL)
         aout_FifoPush (&p->fifo, block);
-
-    time_report = p->time_report;
-    p->time_report = INT64_MIN;
     vlc_mutex_unlock (&p->lock);
-
-    if (time_report != INT64_MIN)
-        *drift = time_report;
 }
 
 void aout_PacketPause (audio_output_t *aout, bool pause, mtime_t date)
@@ -375,7 +381,6 @@ block_t *aout_PacketNext (audio_output_t *p_aout, mtime_t start_date)
                           "adjusting dates (%"PRId64" us)", delta);
         aout_FifoMoveDates (&p->partial, delta);
         aout_FifoMoveDates (p_fifo, delta);
-        p->time_report = delta;
     }
     vlc_mutex_unlock( &p->lock );
     return p_buffer;
index 1f9dff5a70775df282872885112816c1e6c64a3f..a32ac0b6fcc69b9e0d8b61ea067e37fbff2c619e 100644 (file)
@@ -539,7 +539,7 @@ static void *data_convert(block_t **pp)
 /**
  * Queue one audio frame to the playback stream
  */
-static void Play(audio_output_t *aout, block_t *block, mtime_t *restrict drift)
+static void Play(audio_output_t *aout, block_t *block)
 {
     aout_sys_t *sys = aout->sys;
     pa_stream *s = sys->stream;
@@ -581,7 +581,6 @@ static void Play(audio_output_t *aout, block_t *block, mtime_t *restrict drift)
     }
 
     pa_threaded_mainloop_unlock(sys->mainloop);
-    (void) drift;
 }
 
 /**
@@ -1030,6 +1029,7 @@ static int Open(vlc_object_t *obj)
     aout->sys = sys;
     aout->start = Start;
     aout->stop = Stop;
+    aout->time_get = NULL;
     aout->play = Play;
     aout->pause = Pause;
     aout->flush = Flush;
index 4ec390ec3860eb02d18b98f97324327f7d6a0a4f..efde5a6e54cdc98db350dd2a867ffff47ea12f8d 100644 (file)
@@ -43,7 +43,8 @@ vlc_module_begin ()
     set_callbacks (Open, Close)
 vlc_module_end ()
 
-static void Play (audio_output_t *, block_t *, mtime_t *);
+static int TimeGet (audio_output, mtime_t *);
+static void Play (audio_output_t *, block_t *);
 static void Pause (audio_output_t *, bool, mtime_t);
 static int VolumeSet (audio_output_t *, float);
 static int MuteSet (audio_output_t *, bool);
@@ -149,6 +150,7 @@ static int Start (audio_output_t *aout, audio_sample_format_t *restrict fmt)
     aout_FormatPrepare (fmt);
 
     aout->sys = sys;
+    aout->time_get = TimeGet;
     aout->play = Play;
     aout->pause = Pause;
     aout->flush  = NULL; /* sndio sucks! */
@@ -179,18 +181,21 @@ static void Close (vlc_object_t *obj)
     sio_close (sys->hdl);
 }
 
-static void Play (audio_output_t *aout, block_t *block,
-                  mtime_t *restrict drift)
+static int TimeGet (audio_output_t *aout, mtime_t *restrict pts)
 {
     aout_sys_t *sys = aout->sys;
     struct sio_par par;
 
-    if (sio_getpar (sys->hdl, &par) == 0)
-    {
-        mtime_t delay = par.bufsz * CLOCK_FREQ / aout->format.i_rate;
+    if (sio_getpar (sys->hdl, &par))
+        return -1;
 
-        *drift = mdate () + delay - block->i_pts;
-    }
+    *pts = mdate () + (par.bufsz * CLOCK_FREQ / aout->format.i_rate);
+    return 0;
+}
+
+static void Play (audio_output_t *aout, block_t *block)
+{
+    aout_sys_t *sys = aout->sys;
 
     while (block->i_buffer > 0 && !sio_eof (sys->hdl))
     {
index cb54d9e680f12f73381f6a3c09de31674d6e8e4d..c71958d090706bdcc485a95c7b770390429e31cb 100644 (file)
@@ -135,7 +135,34 @@ struct aout_sys_t
 
 
 /*** VLC audio output callbacks ***/
-static void Play(audio_output_t *aout, block_t *block, mtime_t *restrict drift)
+static int TimeGet(audio_output_t *aout, mtime_t *restrict pts)
+{
+    aout_sys_t *sys = aout->sys;
+    UINT64 pos, qpcpos;
+    HRESULT hr;
+
+    if (sys->clock == NULL)
+        return -1;
+
+    Enter();
+    hr = IAudioClock_GetPosition(sys->clock, &pos, &qpcpos);
+    Leave();
+    if (FAILED(hr))
+    {
+        msg_Err(aout, "cannot get position (error 0x%lx)", hr);
+        return -1;
+    }
+
+    mtime_t delay =  ((GetQPC() - qpcpos) / (10000000 / CLOCK_FREQ));
+    static_assert((10000000 % CLOCK_FREQ) == 0, "Frequency conversion broken");
+
+    if (delay < 1000) /* device is still buffering, time is screwed */
+        return -1;
+    *pts += mdate () + delay;
+    return 0;
+}
+
+static void Play(audio_output_t *aout, block_t *block)
 {
     aout_sys_t *sys = aout->sys;
     HRESULT hr = S_OK;
@@ -145,22 +172,6 @@ static void Play(audio_output_t *aout, block_t *block, mtime_t *restrict drift)
                           sys->chans_to_reorder, sys->chans_table, sys->bits);
 
     Enter();
-    if (likely(sys->clock != NULL))
-    {
-        UINT64 pos, qpcpos;
-
-        hr = IAudioClock_GetPosition(sys->clock, &pos, &qpcpos);
-        if (SUCCEEDED(hr))
-        {
-            qpcpos = GetQPC() - qpcpos;
-            static_assert((10000000 % CLOCK_FREQ) == 0,
-                          "Frequency conversion broken");
-            *drift = qpcpos / (10000000 / CLOCK_FREQ);
-        }
-        else
-            msg_Warn(aout, "cannot get position (error 0x%lx)", hr);
-    }
-
     for (;;)
     {
         UINT32 frames;
@@ -799,6 +810,7 @@ retry:
 
     sys->rate = fmt->i_rate;
     sys->bytes_per_frame = fmt->i_bytes_per_frame;
+    aout->time_get = TimeGet;
     aout->play = Play;
     aout->pause = Pause;
     aout->flush = Flush;
index 5c9cc780da7fb3cc5ea6426da4d9a534db144223..0ec14129fee4cae77b79354daaa90b92566ff2b5 100644 (file)
@@ -50,7 +50,7 @@
  *****************************************************************************/
 static int  Open         ( vlc_object_t * );
 static void Close        ( vlc_object_t * );
-static void Play         ( audio_output_t *, block_t *, mtime_t * );
+static void Play         ( audio_output_t *, block_t * );
 
 /*****************************************************************************
  * notification_thread_t: waveOut event thread
@@ -160,6 +160,7 @@ static int Start( audio_output_t *p_aout, audio_sample_format_t *restrict fmt )
 {
     vlc_value_t val;
 
+    p_aout->time_get = aout_PacketTimeGet;
     p_aout->play = Play;
     p_aout->pause = aout_PacketPause;
     p_aout->flush = aout_PacketFlush;
@@ -449,8 +450,7 @@ static void Probe( audio_output_t * p_aout, const audio_sample_format_t *fmt )
  * This doesn't actually play the buffer. This just stores the buffer so it
  * can be played by the callback thread.
  *****************************************************************************/
-static void Play( audio_output_t *_p_aout, block_t *block,
-                  mtime_t *restrict drift )
+static void Play( audio_output_t *_p_aout, block_t *block )
 {
     if( !_p_aout->sys->b_playing )
     {
@@ -467,7 +467,7 @@ static void Play( audio_output_t *_p_aout, block_t *block,
         SetEvent( _p_aout->sys->new_buffer_event );
     }
 
-    aout_PacketPlay( _p_aout, block, drift );
+    aout_PacketPlay( _p_aout, block );
 }
 
 /*****************************************************************************
index 098bc9fda6ed934fd425cf216ff03db79744cedc..102dbd4308eae73beb3f001634134ddb0a99425a 100644 (file)
@@ -440,7 +440,7 @@ void aout_OutputDelete (audio_output_t *aout)
 void aout_OutputPlay (audio_output_t *aout, block_t *block)
 {
     aout_owner_t *owner = aout_owner (aout);
-    mtime_t drift = 0;
+    mtime_t drift;
 
     aout_assert_locked (aout);
 
@@ -454,7 +454,12 @@ void aout_OutputPlay (audio_output_t *aout, block_t *block)
         return;
     }
 
-    aout->play (aout, block, &drift);
+    if (aout->time_get != NULL && aout->time_get (aout, &drift) == 0)
+        drift -= block->i_pts;
+    else
+        drift = 0;
+
+    aout->play (aout, block);
 /**
  * Notifies the audio input of the drift from the requested audio
  * playback timestamp (@ref block_t.i_pts) to the anticipated playback time
@@ -463,14 +468,9 @@ void aout_OutputPlay (audio_output_t *aout, block_t *block)
  * 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.
+ * The audio output plugin is responsible for estimating the time. Typically,
+ * the audio output can estimate the total buffer delay. Then:
+ *    pts = mdate() + delay
  */
     if (drift < -AOUT_MAX_PTS_ADVANCE || +AOUT_MAX_PTS_DELAY < drift)
     {