summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--audio/out/ao_alsa.c48
1 files changed, 23 insertions, 25 deletions
diff --git a/audio/out/ao_alsa.c b/audio/out/ao_alsa.c
index 97c8b5acfd..2ef35db6cf 100644
--- a/audio/out/ao_alsa.c
+++ b/audio/out/ao_alsa.c
@@ -52,12 +52,11 @@
struct priv {
snd_pcm_t *alsa;
snd_pcm_format_t alsa_fmt;
- size_t bytes_per_sample;
int can_pause;
snd_pcm_sframes_t prepause_frames;
float delay_before_pause;
- int buffersize;
- int outburst;
+ int buffersize; // in frames
+ int outburst; // in frames
int cfg_block;
char *cfg_device;
@@ -251,6 +250,7 @@ static const int mp_to_alsa_format[][2] = {
static int find_alsa_format(int af_format)
{
+ af_format = af_fmt_from_planar(af_format);
for (int n = 0; mp_to_alsa_format[n][0] != AF_FORMAT_UNKNOWN; n++) {
if (mp_to_alsa_format[n][0] == af_format)
return mp_to_alsa_format[n][1];
@@ -432,12 +432,6 @@ static int init(struct ao *ao)
err = snd_pcm_hw_params_any(p->alsa, alsa_hwparams);
CHECK_ALSA_ERROR("Unable to get initial parameters");
- err = snd_pcm_hw_params_set_access
- (p->alsa, alsa_hwparams, SND_PCM_ACCESS_RW_INTERLEAVED);
- CHECK_ALSA_ERROR("Unable to set access type");
-
- ao->format = af_fmt_from_planar(ao->format);
-
p->alsa_fmt = find_alsa_format(ao->format);
if (p->alsa_fmt == SND_PCM_FORMAT_UNKNOWN) {
p->alsa_fmt = SND_PCM_FORMAT_S16;
@@ -460,6 +454,12 @@ static int init(struct ao *ao)
err = snd_pcm_hw_params_set_format(p->alsa, alsa_hwparams, p->alsa_fmt);
CHECK_ALSA_ERROR("Unable to set format");
+ snd_pcm_access_t access = af_fmt_is_planar(ao->format)
+ ? SND_PCM_ACCESS_RW_NONINTERLEAVED
+ : SND_PCM_ACCESS_RW_INTERLEAVED;
+ err = snd_pcm_hw_params_set_access(p->alsa, alsa_hwparams, access);
+ CHECK_ALSA_ERROR("Unable to set access type");
+
int num_channels = ao->channels.num;
err = snd_pcm_hw_params_set_channels_near
(p->alsa, alsa_hwparams, &num_channels);
@@ -480,9 +480,6 @@ static int init(struct ao *ao)
(p->alsa, alsa_hwparams, &ao->samplerate, NULL);
CHECK_ALSA_ERROR("Unable to set samplerate-2");
- p->bytes_per_sample = af_fmt2bits(ao->format) / 8;
- p->bytes_per_sample *= ao->channels.num;
-
err = snd_pcm_hw_params_set_buffer_time_near
(p->alsa, alsa_hwparams, &(unsigned int){BUFFER_TIME}, NULL);
CHECK_ALSA_ERROR("Unable to set buffer time near");
@@ -501,14 +498,14 @@ static int init(struct ao *ao)
err = snd_pcm_hw_params_get_buffer_size(alsa_hwparams, &bufsize);
CHECK_ALSA_ERROR("Unable to get buffersize");
- p->buffersize = bufsize * p->bytes_per_sample;
- MP_VERBOSE(ao, "got buffersize=%i\n", p->buffersize);
+ p->buffersize = bufsize;
+ MP_VERBOSE(ao, "got buffersize=%i samples\n", p->buffersize);
err = snd_pcm_hw_params_get_period_size(alsa_hwparams, &chunk_size, NULL);
CHECK_ALSA_ERROR("Unable to get period size");
MP_VERBOSE(ao, "got period size %li\n", chunk_size);
- p->outburst = chunk_size * p->bytes_per_sample;
+ p->outburst = chunk_size;
/* setting software parameters */
err = snd_pcm_sw_params_current(p->alsa, alsa_swparams);
@@ -539,8 +536,8 @@ static int init(struct ao *ao)
p->can_pause = snd_pcm_hw_params_can_pause(alsa_hwparams);
- MP_VERBOSE(ao, "opened: %d Hz/%d channels/%d bpf/%d bytes buffer/%s\n",
- ao->samplerate, ao->channels.num, (int)p->bytes_per_sample,
+ MP_VERBOSE(ao, "opened: %d Hz/%d channels/%d bps/%d samples buffer/%s\n",
+ ao->samplerate, ao->channels.num, af_fmt2bits(ao->format),
p->buffersize, snd_pcm_format_description(p->alsa_fmt));
return 0;
@@ -639,23 +636,24 @@ alsa_error: ;
static int play(struct ao *ao, void **data, int samples, int flags)
{
struct priv *p = ao->priv;
- int num_frames;
snd_pcm_sframes_t res = 0;
- int len = samples * p->bytes_per_sample;
if (!(flags & AOPLAY_FINAL_CHUNK))
- len = len / p->outburst * p->outburst;
- num_frames = len / p->bytes_per_sample;
+ samples = samples / p->outburst * p->outburst;
if (!p->alsa) {
MP_ERR(ao, "Device configuration error.");
return -1;
}
- if (num_frames == 0)
+ if (samples == 0)
return 0;
do {
- res = snd_pcm_writei(p->alsa, data[0], num_frames);
+ if (af_fmt_is_planar(ao->format)) {
+ res = snd_pcm_writen(p->alsa, data, samples);
+ } else {
+ res = snd_pcm_writei(p->alsa, data[0], samples);
+ }
if (res == -EINTR) {
/* nothing to do */
@@ -692,10 +690,10 @@ static int get_space(struct ao *ao)
err = snd_pcm_status(p->alsa, status);
CHECK_ALSA_ERROR("cannot get pcm status");
- unsigned space = snd_pcm_status_get_avail(status) * p->bytes_per_sample;
+ unsigned space = snd_pcm_status_get_avail(status);
if (space > p->buffersize) // Buffer underrun?
space = p->buffersize;
- return space / p->bytes_per_sample;
+ return space;
alsa_error:
return 0;