Below is an update of mplayer sndio backend:
  - use sndiod volume knob if available, rather than
    chaining two soft volume knobs (consumes less CPU)
  - stop audio during pause, consumes less CPU
  - remove unnecessary checks
  - honour AOPLAY_FINAL_CHUNK flag, fixes playback of
    very short files

comments? ok?

-- Alexandre

Index: Makefile
===================================================================
RCS file: /cvs/ports/x11/mplayer/Makefile,v
retrieving revision 1.197
diff -u -p -r1.197 Makefile
--- Makefile    30 Dec 2011 17:40:40 -0000      1.197
+++ Makefile    24 Jan 2012 22:21:08 -0000
@@ -13,7 +13,7 @@ SUBST_VARS +=                 PREFIX CONFDIR
 # Distfiles must be hand-rolled, see README
 N =                    mplayer
 DISTNAME =             mplayer-${V}
-REVISION =             11
+REVISION =             12
 
 CATEGORIES =           x11 multimedia
 
Index: files/ao_sndio.c
===================================================================
RCS file: /cvs/ports/x11/mplayer/files/ao_sndio.c,v
retrieving revision 1.6
diff -u -p -r1.6 ao_sndio.c
--- files/ao_sndio.c    8 Nov 2010 21:25:44 -0000       1.6
+++ files/ao_sndio.c    24 Jan 2012 22:21:08 -0000
@@ -40,7 +40,7 @@ LIBAO_EXTERN(sndio)
 
 static struct sio_hdl *hdl = NULL;
 static struct sio_par par;
-static long long realpos = 0, playpos = 0;
+static int delay, vol, havevol;
 #define SILENCE_NMAX 0x1000
 static char silence[SILENCE_NMAX];
 
@@ -49,7 +49,21 @@ static char silence[SILENCE_NMAX];
  */
 static int control(int cmd, void *arg)
 {
-       return CONTROL_FALSE;
+       ao_control_vol_t *ctl = arg;
+
+       if (!havevol)
+               return CONTROL_FALSE;
+       switch (cmd) {
+       case AOCONTROL_GET_VOLUME:
+               ctl->left = ctl->right = vol * 100 / SIO_MAXVOL;
+               break;
+       case AOCONTROL_SET_VOLUME:
+               sio_setvol(hdl, ctl->left * SIO_MAXVOL / 100);
+               break;
+       default:
+               return CONTROL_UNKNOWN;
+       }
+       return CONTROL_OK;
 }
 
 /*
@@ -57,7 +71,15 @@ static int control(int cmd, void *arg)
  */
 static void movecb(void *addr, int delta)
 {
-       realpos += delta * (int)(par.bps * par.pchan);
+       delay -= delta * (int)(par.bps * par.pchan);
+}
+
+/*
+ * call-back invoked to notify about volume changes
+ */
+static void volcb(void *addr, unsigned newvol)
+{
+       vol = newvol;
 }
 
 /*
@@ -74,7 +96,6 @@ static int init(int rate, int channels, 
                mp_msg(MSGT_AO, MSGL_ERR, "ao2: can't open sndio\n");
                return 0;
        }
-
        sio_initpar(&par);
        switch (format) {
        case AF_FORMAT_U8:
@@ -194,24 +215,22 @@ static int init(int rate, int channels, 
        }
 
        bpf = par.bps * par.pchan;
-       ao_data.samplerate = par.rate;
        ao_data.channels = par.pchan;
        ao_data.format = ac3 ? AF_FORMAT_AC3_NE : format;
        ao_data.bps = bpf * par.rate;
        ao_data.buffersize = par.appbufsz * bpf;
        ao_data.outburst = par.round * bpf;
+       /* avoid resampling for close rates */
+       if ((par.rate >= rate * 0.97) && (par.rate <= rate * 1.03))
+               ao_data.samplerate = rate;
+       else
+               ao_data.samplerate = par.rate;
+       havevol = sio_onvol(hdl, volcb, NULL);
        sio_onmove(hdl, movecb, NULL);
-       realpos = playpos = 0;
+       delay = 0;
        if (!sio_start(hdl)) {
                mp_msg(MSGT_AO, MSGL_ERR, "ao2: init: couldn't start\n");
        }
-
-       /* avoid resampling for close rates */
-       if ((ao_data.samplerate >= rate * 0.97) &&
-           (ao_data.samplerate <= rate * 1.03)) {
-               ao_data.samplerate = rate;
-       }
-
        if (ao_data.samplerate != rate) {
                /* apparently mplayer rounds a little when resampling.
                 * anyway, it doesn't write quite a full buffer on the first
@@ -220,8 +239,8 @@ static int init(int rate, int channels, 
                 * enough for everything I have come across.
                 */
                sio_write(hdl, silence, 8 * bpf);
+               delay += 8 * bpf;
        }
-
        return 1;
 }
 
@@ -237,11 +256,12 @@ static void uninit(int immed)
 /*
  * stop playing and empty buffers (for seeking/pause)
  */
-static void reset(void) {
+static void reset(void)
+{
        if (!sio_stop(hdl)) {
                mp_msg(MSGT_AO, MSGL_ERR, "ao2: reset: couldn't stop\n");
        }
-       realpos = playpos = 0;
+       delay = 0;
        if (!sio_start(hdl)) {
                mp_msg(MSGT_AO, MSGL_ERR, "ao2: reset: couldn't start\n");
        }
@@ -253,19 +273,17 @@ static void reset(void) {
 static int get_space(void)
 {
        struct pollfd pfd;
-       int bufused, space, revents, n;
+       int bufused, revents, n;
 
        /*
         * call poll() and sio_revents(), so the
-        * playpos and realpos counters are updated
+        * delay counter is updated
         */
        n = sio_pollfd(hdl, &pfd, POLLOUT);
        while (poll(&pfd, n, 0) < 0 && errno == EINTR)
                ; /* nothing */
        revents = sio_revents(hdl, &pfd);
-       bufused = (realpos < 0) ? playpos : playpos - realpos;
-       space = par.bufsz * par.pchan * par.bps - bufused;
-       return space;
+       return par.bufsz * par.pchan * par.bps - delay;
 }
 
 /*
@@ -276,7 +294,9 @@ static int play(void *data, int len, int
        int n;
 
        n = sio_write(hdl, data, len);
-       playpos += n;
+       delay += n;
+       if (flags & AOPLAY_FINAL_CHUNK)
+               reset();
        return n;
 }
 
@@ -285,9 +305,7 @@ static int play(void *data, int len, int
  */
 static float get_delay(void)
 {
-       int bufused;
-       bufused = (realpos < 0) ? playpos : playpos - realpos;
-       return (float)bufused / (par.bps * par.pchan * par.rate);
+       return (float)delay / (par.bps * par.pchan * par.rate);
 }
 
 /*
@@ -295,7 +313,7 @@ static float get_delay(void)
  */
 static void audio_pause(void)
 {
-       /* libsndio stops automatically if no data is available */
+       reset();
 }
 
 /*
@@ -305,13 +323,13 @@ static void audio_resume(void)
 {
        int n, count, todo;
 
-       todo = par.appbufsz * par.pchan * par.bps;
-
        /*
-        * libsndio starts automatically if enough data is available;
-        * however we want to start with buffers full, because video
-        * would accelerate during buffers are filled
+        * we want to start with buffers full, because mplayer uses
+        * get_space() pointer as clock, which would cause video to
+        * accelerate during buffers are filled. Remove this when not
+        * necessary anymore.
         */
+       todo = par.bufsz * par.pchan * par.bps;
        while (todo > 0) {
                count = todo;
                if (count > SILENCE_NMAX)
@@ -320,6 +338,6 @@ static void audio_resume(void)
                if (n == 0)
                        break;
                todo -= n;
-               realpos -= n;
+               delay += n;
        }
 }

Reply via email to