31 #include <alsa/asoundlib.h>
61 default:
return SND_PCM_FORMAT_UNKNOWN;
65 #define MAKE_REORDER_FUNC(NAME, TYPE, CHANNELS, LAYOUT, MAP) \
66 static void alsa_reorder_ ## NAME ## _ ## LAYOUT(const void *in_v, \
70 const TYPE *in = in_v; \
80 #define MAKE_REORDER_FUNCS(CHANNELS, LAYOUT, MAP) \
81 MAKE_REORDER_FUNC(int8, int8_t, CHANNELS, LAYOUT, MAP) \
82 MAKE_REORDER_FUNC(int16, int16_t, CHANNELS, LAYOUT, MAP) \
83 MAKE_REORDER_FUNC(int32, int32_t, CHANNELS, LAYOUT, MAP) \
84 MAKE_REORDER_FUNC(f32, float, CHANNELS, LAYOUT, MAP)
119 #define PICK_REORDER(layout)\
121 case FORMAT_I8: s->reorder_func = alsa_reorder_int8_out_ ##layout; break;\
122 case FORMAT_I16: s->reorder_func = alsa_reorder_int16_out_ ##layout; break;\
123 case FORMAT_I32: s->reorder_func = alsa_reorder_int32_out_ ##layout; break;\
124 case FORMAT_F32: s->reorder_func = alsa_reorder_f32_out_ ##layout; break;\
154 default:
return AVERROR(ENOSYS);
172 const char *audio_device;
174 snd_pcm_format_t format;
176 snd_pcm_hw_params_t *hw_params;
177 snd_pcm_uframes_t buffer_size, period_size;
180 if (ctx->
filename[0] == 0) audio_device =
"default";
186 if (format == SND_PCM_FORMAT_UNKNOWN) {
193 flags = SND_PCM_NONBLOCK;
195 res = snd_pcm_open(&h, audio_device, mode, flags);
198 audio_device, snd_strerror(res));
202 res = snd_pcm_hw_params_malloc(&hw_params);
209 res = snd_pcm_hw_params_any(h, hw_params);
216 res = snd_pcm_hw_params_set_access(h, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED);
223 res = snd_pcm_hw_params_set_format(h, hw_params, format);
226 *codec_id, format, snd_strerror(res));
230 res = snd_pcm_hw_params_set_rate_near(h, hw_params, sample_rate, 0);
237 res = snd_pcm_hw_params_set_channels(h, hw_params, channels);
240 channels, snd_strerror(res));
244 snd_pcm_hw_params_get_buffer_size_max(hw_params, &buffer_size);
247 res = snd_pcm_hw_params_set_buffer_size_near(h, hw_params, &buffer_size);
254 snd_pcm_hw_params_get_period_size_min(hw_params, &period_size,
NULL);
256 period_size = buffer_size / 4;
257 res = snd_pcm_hw_params_set_period_size_near(h, hw_params, &period_size,
NULL);
265 res = snd_pcm_hw_params(h, hw_params);
272 snd_pcm_hw_params_free(hw_params);
274 if (channels > 2 && layout) {
275 if (
find_reorder_func(s, *codec_id, layout, mode == SND_PCM_STREAM_PLAYBACK) < 0) {
279 name, mode == SND_PCM_STREAM_PLAYBACK ?
"playback" :
"capture");
293 snd_pcm_hw_params_free(hw_params);
304 if (CONFIG_ALSA_INDEV)
313 snd_pcm_t *handle = s->
h;
317 err = snd_pcm_prepare(handle);
319 av_log(s1,
AV_LOG_ERROR,
"cannot recover from underrun (snd_pcm_prepare failed: %s)\n", snd_strerror(err));
323 }
else if (err == -ESTRPIPE) {
337 while (size < min_size)