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)
354 const char *
filter = stream_type == SND_PCM_STREAM_PLAYBACK ?
"Output" :
"Input";
356 if (snd_device_name_hint(-1,
"pcm", &hints) < 0)
360 name = snd_device_name_get_hint(*n,
"NAME");
361 descr = snd_device_name_get_hint(*n,
"DESC");
362 io = snd_device_name_get_hint(*n,
"IOID");
363 if (!io || !strcmp(io, filter)) {
370 if ((tmp = strrchr(descr,
'\n')) && tmp[1])
397 snd_device_name_free_hint(hints);
Structure describes basic parameters of the device.
#define AV_CH_LAYOUT_7POINT1
static av_cold int find_reorder_func(AlsaData *s, int codec_id, uint64_t layout, int out)
void ff_timefilter_destroy(TimeFilter *self)
Free all resources associated with the filter.
char * device_description
human friendly name
#define AV_LOG_WARNING
Something somehow does not look correct.
char * device_name
device name, format depends on device
#define AV_CH_LAYOUT_5POINT0
ALSA input and output: definitions and structures.
#define av_assert0(cond)
assert() equivalent, that is always enabled.
void(* reorder_func)(const void *, void *, int)
int av_dynarray_add_nofree(void *tab_ptr, int *nb_ptr, void *elem)
Add an element to a dynamic array.
AVStream ** streams
A list of all streams in the file.
int flags
Flags modifying the (de)muxer behaviour.
int ff_alsa_extend_reorder_buf(AlsaData *s, int min_size)
#define AV_CH_LAYOUT_5POINT1
Main libavdevice API header.
static av_cold snd_pcm_format_t codec_id_to_pcm_format(int codec_id)
AVCodecID
Identify the syntax and semantics of the bitstream.
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
int av_get_bits_per_sample(enum AVCodecID codec_id)
Return codec bits per sample.
simple assert() macros that are a bit more flexible than ISO C assert().
#define AV_CH_LAYOUT_QUAD
AVDeviceInfo ** devices
list of autodetected devices
#define MAKE_REORDER_FUNCS(CHANNELS, LAYOUT, MAP)
#define ALSA_BUFFER_SIZE_MAX
uint64_t channel_layout
Audio channel layout.
AVCodecContext * codec
Codec context associated with this stream.
audio channel layout utility functions
char filename[1024]
input or output filename
#define AV_CH_LAYOUT_5POINT1_BACK
void av_get_channel_layout_string(char *buf, int buf_size, int nb_channels, uint64_t channel_layout)
Return a description of a channel layout.
char * av_strdup(const char *s)
Duplicate the string s.
int ff_alsa_xrun_recover(AVFormatContext *s1, int err)
Try to recover from ALSA buffer underrun.
av_cold int ff_alsa_close(AVFormatContext *s1)
Close the ALSA PCM.
uint8_t pi<< 24) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_U8, uint8_t,(*(constuint8_t *) pi-0x80)*(1.0f/(1<< 7))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_U8, uint8_t,(*(constuint8_t *) pi-0x80)*(1.0/(1<< 7))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S16, int16_t,(*(constint16_t *) pi >>8)+0x80) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S16, int16_t,*(constint16_t *) pi *(1.0f/(1<< 15))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S16, int16_t,*(constint16_t *) pi *(1.0/(1<< 15))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S32, int32_t,(*(constint32_t *) pi >>24)+0x80) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S32, int32_t,*(constint32_t *) pi *(1.0f/(1U<< 31))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S32, int32_t,*(constint32_t *) pi *(1.0/(1U<< 31))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_FLT, float, av_clip_uint8(lrintf(*(constfloat *) pi *(1<< 7))+0x80)) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_FLT, float, av_clip_int16(lrintf(*(constfloat *) pi *(1<< 15)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_FLT, float, av_clipl_int32(llrintf(*(constfloat *) pi *(1U<< 31)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_DBL, double, av_clip_uint8(lrint(*(constdouble *) pi *(1<< 7))+0x80)) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_DBL, double, av_clip_int16(lrint(*(constdouble *) pi *(1<< 15)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_DBL, double, av_clipl_int32(llrint(*(constdouble *) pi *(1U<< 31))))#defineSET_CONV_FUNC_GROUP(ofmt, ifmt) staticvoidset_generic_function(AudioConvert *ac){}voidff_audio_convert_free(AudioConvert **ac){if(!*ac) return;ff_dither_free(&(*ac) ->dc);av_freep(ac);}AudioConvert *ff_audio_convert_alloc(AVAudioResampleContext *avr, enumAVSampleFormatout_fmt, enumAVSampleFormatin_fmt, intchannels, intsample_rate, intapply_map){AudioConvert *ac;intin_planar, out_planar;ac=av_mallocz(sizeof(*ac));if(!ac) returnNULL;ac->avr=avr;ac->out_fmt=out_fmt;ac->in_fmt=in_fmt;ac->channels=channels;ac->apply_map=apply_map;if(avr->dither_method!=AV_RESAMPLE_DITHER_NONE &&av_get_packed_sample_fmt(out_fmt)==AV_SAMPLE_FMT_S16 &&av_get_bytes_per_sample(in_fmt)>2){ac->dc=ff_dither_alloc(avr, out_fmt, in_fmt, channels, sample_rate, apply_map);if(!ac->dc){av_free(ac);returnNULL;}returnac;}in_planar=ff_sample_fmt_is_planar(in_fmt, channels);out_planar=ff_sample_fmt_is_planar(out_fmt, channels);if(in_planar==out_planar){ac->func_type=CONV_FUNC_TYPE_FLAT;ac->planes=in_planar?ac->channels:1;}elseif(in_planar) ac->func_type=CONV_FUNC_TYPE_INTERLEAVE;elseac->func_type=CONV_FUNC_TYPE_DEINTERLEAVE;set_generic_function(ac);if(ARCH_AARCH64) ff_audio_convert_init_aarch64(ac);if(ARCH_ARM) ff_audio_convert_init_arm(ac);if(ARCH_X86) ff_audio_convert_init_x86(ac);returnac;}intff_audio_convert(AudioConvert *ac, AudioData *out, AudioData *in){intuse_generic=1;intlen=in->nb_samples;intp;if(ac->dc){av_log(ac->avr, AV_LOG_TRACE,"%dsamples-audio_convert:%sto%s(dithered)\n", len, av_get_sample_fmt_name(ac->in_fmt), av_get_sample_fmt_name(ac->out_fmt));returnff_convert_dither(ac-> in
int ff_alsa_get_device_list(AVDeviceInfoList *device_list, snd_pcm_stream_t stream_type)
#define AV_CH_LAYOUT_5POINT0_BACK
int default_device
index of default device or -1 if no default
#define PICK_REORDER(layout)
int period_size
preferred size for reads and writes, in frames
static void filter(MpegAudioContext *s, int ch, const short *samples, int incr)
void * av_realloc_array(void *ptr, size_t nmemb, size_t size)
void * priv_data
Format private data.
uint8_t pi<< 24) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_U8, uint8_t,(*(constuint8_t *) pi-0x80)*(1.0f/(1<< 7))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_U8, uint8_t,(*(constuint8_t *) pi-0x80)*(1.0/(1<< 7))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S16, int16_t,(*(constint16_t *) pi >>8)+0x80) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S16, int16_t,*(constint16_t *) pi *(1.0f/(1<< 15))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S16, int16_t,*(constint16_t *) pi *(1.0/(1<< 15))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S32, int32_t,(*(constint32_t *) pi >>24)+0x80) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S32, int32_t,*(constint32_t *) pi *(1.0f/(1U<< 31))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S32, int32_t,*(constint32_t *) pi *(1.0/(1U<< 31))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_FLT, float, av_clip_uint8(lrintf(*(constfloat *) pi *(1<< 7))+0x80)) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_FLT, float, av_clip_int16(lrintf(*(constfloat *) pi *(1<< 15)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_FLT, float, av_clipl_int32(llrintf(*(constfloat *) pi *(1U<< 31)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_DBL, double, av_clip_uint8(lrint(*(constdouble *) pi *(1<< 7))+0x80)) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_DBL, double, av_clip_int16(lrint(*(constdouble *) pi *(1<< 15)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_DBL, double, av_clipl_int32(llrint(*(constdouble *) pi *(1U<< 31))))#defineSET_CONV_FUNC_GROUP(ofmt, ifmt) staticvoidset_generic_function(AudioConvert *ac){}voidff_audio_convert_free(AudioConvert **ac){if(!*ac) return;ff_dither_free(&(*ac) ->dc);av_freep(ac);}AudioConvert *ff_audio_convert_alloc(AVAudioResampleContext *avr, enumAVSampleFormatout_fmt, enumAVSampleFormatin_fmt, intchannels, intsample_rate, intapply_map){AudioConvert *ac;intin_planar, out_planar;ac=av_mallocz(sizeof(*ac));if(!ac) returnNULL;ac->avr=avr;ac->out_fmt=out_fmt;ac->in_fmt=in_fmt;ac->channels=channels;ac->apply_map=apply_map;if(avr->dither_method!=AV_RESAMPLE_DITHER_NONE &&av_get_packed_sample_fmt(out_fmt)==AV_SAMPLE_FMT_S16 &&av_get_bytes_per_sample(in_fmt)>2){ac->dc=ff_dither_alloc(avr, out_fmt, in_fmt, channels, sample_rate, apply_map);if(!ac->dc){av_free(ac);returnNULL;}returnac;}in_planar=ff_sample_fmt_is_planar(in_fmt, channels);out_planar=ff_sample_fmt_is_planar(out_fmt, channels);if(in_planar==out_planar){ac->func_type=CONV_FUNC_TYPE_FLAT;ac->planes=in_planar?ac->channels:1;}elseif(in_planar) ac->func_type=CONV_FUNC_TYPE_INTERLEAVE;elseac->func_type=CONV_FUNC_TYPE_DEINTERLEAVE;set_generic_function(ac);if(ARCH_AARCH64) ff_audio_convert_init_aarch64(ac);if(ARCH_ARM) ff_audio_convert_init_arm(ac);if(ARCH_X86) ff_audio_convert_init_x86(ac);returnac;}intff_audio_convert(AudioConvert *ac, AudioData *out, AudioData *in){intuse_generic=1;intlen=in->nb_samples;intp;if(ac->dc){av_log(ac->avr, AV_LOG_TRACE,"%dsamples-audio_convert:%sto%s(dithered)\n", len, av_get_sample_fmt_name(ac->in_fmt), av_get_sample_fmt_name(ac->out_fmt));returnff_convert_dither(ac-> out
int frame_size
bytes per sample * channels
#define av_malloc_array(a, b)
int nb_devices
number of autodetected devices
#define AVERROR_EXTERNAL
Generic error in an external library.
int reorder_buf_size
in frames
void * av_mallocz(size_t size)
Allocate a block of size bytes with alignment suitable for all memory accesses (including vectors if ...
av_cold int ff_alsa_open(AVFormatContext *ctx, snd_pcm_stream_t mode, unsigned int *sample_rate, int channels, enum AVCodecID *codec_id)
Open an ALSA PCM.