-
Notifications
You must be signed in to change notification settings - Fork 2.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add ao_sndio as pull driver #8347
Conversation
This reverts commit 71d218e.
Changes from previous version: - Use a local buffer for write() calls that happen before start(), since sndio doesn't have an API for pause and can't take writes unless it's been started. Calling sio_start() will make it start playing as soon as the buffers are full, so the sio_write() loop in start() doesn't introduce any noticeable latency. - Allow libsndio to pick a buffer size by itself. - Allow core to emulate pause with reset().
audio/out/ao_sndio.c
Outdated
* using a multiple of block size */ | ||
to_write = ((ao->device_buffer - p->delay) / p->par.round) * p->par.round; | ||
/* time until buffer is heard is: (<current sample delay> + <new samples>) / <sample rate> */ | ||
n = ao_read_data(ao, data, to_write, mp_time_us() + ((p->delay + to_write) * 1000000LL) / p->par.rate); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it be okay to add a macro for 1000000LL
in osdeps/time.h
?
It works. But, if in #8314 I remove |
da69907
to
0903658
Compare
Yes, mpv feeds it silence. Currently, the jack backend does the same thing. I like the pull driver because it gives mpv the most information possible while at the same time simplifying pause. |
Via Current push sndio backend (#8314) has no |
Yes, but 4 parameters which aren't entirely necessary. The only information that mpv needs is latency, and if we can take care of the rest inside the driver, it's much simpler. And it's the "best quality" latency information that we can give, as well. @noiseless could you try this one out as well? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did some more testing and noticed an issue with parameter negotiation.
Also added a few style comments. Feel free to ignore the ones you disagree with.
audio/out/ao_sndio.c
Outdated
|
||
sio_initpar(&p->par); | ||
for (i = 0, ap = af_to_par;; i++, ap++) { | ||
if (i == sizeof(af_to_par) / sizeof(struct af_to_par)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You could use MP_ARRAY_SIZE(af_to_par)
here.
Or better yet, how about this instead:
sio_initpar(&p->par);
p->par.bits = 16;
p->par.sig = 1;
p->par.le = SIO_LE_NATIVE;
for (i = 0; i < MP_ARRAY_SIZE(af_to_par); i++) {
ap = &af_to_par[i];
if (ap->format == ao->format) {
p->par.bits = ap->bits;
p->par.sig = ap->sig;
if (ap->bits > 8)
p->par.le = SIO_LE_NATIVE;
if (ap->bits != SIO_BPS(ap->bits))
p->par.bps = ap->bits / 8;
break;
}
}
I don't think the message about format conversion is necessary.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a bit cleaner, but I think
if (ap->bits > 8)
p->par.le = SIO_LE_NATIVE;
is unnecessary? Since it's set to SIO_LE_NATIVE
by default.
The
if (ap->bits != SIO_BPS(ap->bits))
p->par.bps = ap->bits / 8;
is weird to me as well, since it's comparing a number of bytes with a number of bits.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That last block was in the original code as well, which is quite interesting.
I'm sorry I missed your message. I will try to test it tonight (MSK). |
Built mpv with your patch (0903658). I didn't notice any problems, everything works as expected. |
e9aa1a2
to
2b54c75
Compare
@noiseless thank you very much for testing :) I've updated the PR and it should now be more correct for channel mappings. |
I took a stab at making it use non-blocking I/O here: I think the only real advantage it has over your current version is that if our estimate of how much to write was wrong (sndio manual says "Note that sio_write() might block even if there is buffer space left"), it moves into a cancellable state rather than blocking in |
Removes some complexity, since the pull interface is much simpler. Also fix some weird parts in the previous backend. Allow libsndio greater control over most of the parameters. Thanks to @michaelforney and @rozhuk-im for suggestions and @noiseless for testing.
I don't think it would block for long; we are writing at most Being in a cancellable state more often could be useful if there are cases where |
Any update on this? There is no longer any sound support for OpenBSD with 0.33. |
ping. |
1 similar comment
ping. |
Any chance of seeing this commited? |
This is not the right way forward, because sndio's mixing depends on the amount of active sources. Pausing a video here will still make the daemon think the source is active, and therefore other sources will be a bit more muted. It's necessary to use |
I don't know for others but I think it would be better to have a "good enough" audio backend in mpv that could get heavily modified later than the current situation where it's either no audio at all or having to use compat-layers like alsa-sndio which probably are doomed to be worse than an okay driver (for example the lack of volume integration). |
If we are striving for the least amount of code to maintain, I believe a
pull
driver is the way. It requires launching a thread inside the backend, but nothing too complicated.This is an alternative for #8320 and #8314 . I'd be ok with closing #8320 in favor of this PR.
@rozhuk-im what do you think of this solution?