[MPlayer-dev-eng] [PATCH] Add audio support for sndio API.
Alexandre Ratchov
alex at caoua.org
Mon Dec 9 08:02:42 CET 2013
On Fri, Dec 06, 2013 at 09:10:32PM +0100, Reimar Döffinger wrote:
> > +static int get_space(void)
> > +{
> > + int bufused, revents, n;
> > +
> > + /*
> > + * call poll() and sio_revents(), so the
> > + * delay counter is updated
> > + */
> > + n = sio_pollfd(hdl, pfds, POLLOUT);
> > + while (poll(pfds, n, 0) < 0 && errno == EINTR)
> > + ; /* nothing */
> > + revents = sio_revents(hdl, pfds);
> > + return par.bufsz * par.pchan * par.bps - delay;
>
> That has a bit of a smell of black magic.
> I guess there is no easier/more obvious way?
> Also, how do the callbacks work, would it be safer to
> mark delay "volatile"? Or does sndio make sure everything
> is done correctly?
the call-back is simply invoked by sio_revents(), so neither
locking nor volatile qualifier are necessary.
> > + int n;
> > +
> > + n = sio_write(hdl, data, len);
>
> Are you sure sndio will support if if you e,g.
> write 1 byte but the sample format is 6 channel U32
> or anything strange like that?
yes, any value of 'len' will work.
> And also without performance issues?
Sure, calling sio_write() for every byte will consume a lot of CPU,
but I guess play is called for larger chunks isn't it?
> I think most aos round to a good block size.
>
Are you suggesting to return 0 if (len < blocksize). This would
imply that play() is allowed to consime less data than the 'len'
argument, would this be ok ?
> > + delay += n;
> > + if (flags & AOPLAY_FINAL_CHUNK)
> > + reset();
>
> You definitely shouldn't do that! You explicitly throw away all
> the last data, possibly multiple seconds of audio! (Well,
> with the buffer size you have probably 0.5s max, but that is bad
> enough).
reset doesn't discard samples. Once samples are submitted with
sio_write() they cannot be discarted. Here, reset() just tells the
device to drain and stop. Instead of continuing to play silence.
> Also, in the uninit function you do not use the "immediate" argument,
> that can't be right.
> Depending on its value you should either let the ao finish playing the
> audio or stop directly.
yeah, but there's no way to discard samples, still we're talking
about around 250ms of audio.
> > +static float get_delay(void)
> > +{
> > + return (float)delay / (par.bps * par.pchan * par.rate);
>
> Implementations where get_delay and get_space do things significantly
> differently are usually broken.
> If get_space needs to do all those special things to get correct values,
> get_delay should do that as well or you will get bad A-V sync.
We did it this way because poll() is expencive, and at the time
this code was written get_delay() was called very often.
> > +/*
> > + * stop playing, keep buffers (for pause)
> > + */
> > +static void audio_pause(void)
> > +{
> > + reset();
>
> I don't think those generic comments have much of a value in
> general, but you should at least adjust them when the code does
> the exact opposite of what the comment says!
right :), this is probably what the function is supposed to do
> Also reading the documentation I don't think it is correct.
> On pause you should only do stop, the resume should only happen
> once there is data again, otherwise sndio might misunderstand this
> as a buffer underrun case.
reset() won't resume playback immediately. It puts the device in a
waiting state, where playback is triggered as soon there's enough
data buffered using sio_write(). So as long as play() is not called
the device wont restart.
> > +/*
> > + * resume playing, after audio_pause()
> > + */
> > +static void audio_resume(void)
> > +{
> > + int n, count, todo;
> > +
> > + /*
> > + * we want to start with buffers full, because mplayer uses
> > + * get_space() pointer as clock, which would cause video to
> > + * accelerate while buffers are filled.
> > + */
> > + todo = par.bufsz * par.pchan * par.bps;
> > + while (todo > 0) {
> > + count = todo;
> > + if (count > SILENCE_NMAX)
> > + count = SILENCE_NMAX;
> > + n = sio_write(hdl, silence, count);
> > + if (n == 0)
> > + break;
> > + todo -= n;
> > + delay += n;
> > + }
>
> We have mp_ao_resume_refill, why not use that?
I wasn't aware of this function, i'll try it and submit a new diff
with above suggestions.
thanks for the review.
-- Alexandre
More information about the MPlayer-dev-eng
mailing list