31
31
#include <alsa/asoundlib.h>
32
32
#include "libavformat/avformat.h"
33
#include "libavutil/avassert.h"
34
#include "libavutil/audioconvert.h"
34
36
#include "alsa-audio.h"
36
38
static av_cold snd_pcm_format_t codec_id_to_pcm_format(int codec_id)
41
case CODEC_ID_PCM_F64LE: return SND_PCM_FORMAT_FLOAT64_LE;
42
case CODEC_ID_PCM_F64BE: return SND_PCM_FORMAT_FLOAT64_BE;
43
case CODEC_ID_PCM_F32LE: return SND_PCM_FORMAT_FLOAT_LE;
44
case CODEC_ID_PCM_F32BE: return SND_PCM_FORMAT_FLOAT_BE;
45
case CODEC_ID_PCM_S32LE: return SND_PCM_FORMAT_S32_LE;
46
case CODEC_ID_PCM_S32BE: return SND_PCM_FORMAT_S32_BE;
47
case CODEC_ID_PCM_U32LE: return SND_PCM_FORMAT_U32_LE;
48
case CODEC_ID_PCM_U32BE: return SND_PCM_FORMAT_U32_BE;
49
case CODEC_ID_PCM_S24LE: return SND_PCM_FORMAT_S24_3LE;
50
case CODEC_ID_PCM_S24BE: return SND_PCM_FORMAT_S24_3BE;
51
case CODEC_ID_PCM_U24LE: return SND_PCM_FORMAT_U24_3LE;
52
case CODEC_ID_PCM_U24BE: return SND_PCM_FORMAT_U24_3BE;
39
53
case CODEC_ID_PCM_S16LE: return SND_PCM_FORMAT_S16_LE;
40
54
case CODEC_ID_PCM_S16BE: return SND_PCM_FORMAT_S16_BE;
55
case CODEC_ID_PCM_U16LE: return SND_PCM_FORMAT_U16_LE;
56
case CODEC_ID_PCM_U16BE: return SND_PCM_FORMAT_U16_BE;
41
57
case CODEC_ID_PCM_S8: return SND_PCM_FORMAT_S8;
58
case CODEC_ID_PCM_U8: return SND_PCM_FORMAT_U8;
59
case CODEC_ID_PCM_MULAW: return SND_PCM_FORMAT_MU_LAW;
60
case CODEC_ID_PCM_ALAW: return SND_PCM_FORMAT_A_LAW;
42
61
default: return SND_PCM_FORMAT_UNKNOWN;
65
#define REORDER_OUT_50(NAME, TYPE) \
66
static void alsa_reorder_ ## NAME ## _out_50(const void *in_v, void *out_v, int n) \
68
const TYPE *in = in_v; \
82
#define REORDER_OUT_51(NAME, TYPE) \
83
static void alsa_reorder_ ## NAME ## _out_51(const void *in_v, void *out_v, int n) \
85
const TYPE *in = in_v; \
100
#define REORDER_OUT_71(NAME, TYPE) \
101
static void alsa_reorder_ ## NAME ## _out_71(const void *in_v, void *out_v, int n) \
103
const TYPE *in = in_v; \
120
REORDER_OUT_50(int8, int8_t)
121
REORDER_OUT_51(int8, int8_t)
122
REORDER_OUT_71(int8, int8_t)
123
REORDER_OUT_50(int16, int16_t)
124
REORDER_OUT_51(int16, int16_t)
125
REORDER_OUT_71(int16, int16_t)
126
REORDER_OUT_50(int32, int32_t)
127
REORDER_OUT_51(int32, int32_t)
128
REORDER_OUT_71(int32, int32_t)
129
REORDER_OUT_50(f32, float)
130
REORDER_OUT_51(f32, float)
131
REORDER_OUT_71(f32, float)
138
#define PICK_REORDER(layout)\
140
case FORMAT_I8: s->reorder_func = alsa_reorder_int8_out_ ##layout; break;\
141
case FORMAT_I16: s->reorder_func = alsa_reorder_int16_out_ ##layout; break;\
142
case FORMAT_I32: s->reorder_func = alsa_reorder_int32_out_ ##layout; break;\
143
case FORMAT_F32: s->reorder_func = alsa_reorder_f32_out_ ##layout; break;\
146
static av_cold int find_reorder_func(AlsaData *s, int codec_id, uint64_t layout, int out)
150
/* reordering input is not currently supported */
152
return AVERROR(ENOSYS);
154
/* reordering is not needed for QUAD or 2_2 layout */
155
if (layout == AV_CH_LAYOUT_QUAD || layout == AV_CH_LAYOUT_2_2)
159
case CODEC_ID_PCM_S8:
160
case CODEC_ID_PCM_U8:
161
case CODEC_ID_PCM_ALAW:
162
case CODEC_ID_PCM_MULAW: format = FORMAT_I8; break;
163
case CODEC_ID_PCM_S16LE:
164
case CODEC_ID_PCM_S16BE:
165
case CODEC_ID_PCM_U16LE:
166
case CODEC_ID_PCM_U16BE: format = FORMAT_I16; break;
167
case CODEC_ID_PCM_S32LE:
168
case CODEC_ID_PCM_S32BE:
169
case CODEC_ID_PCM_U32LE:
170
case CODEC_ID_PCM_U32BE: format = FORMAT_I32; break;
171
case CODEC_ID_PCM_F32LE:
172
case CODEC_ID_PCM_F32BE: format = FORMAT_F32; break;
173
default: return AVERROR(ENOSYS);
176
if (layout == AV_CH_LAYOUT_5POINT0_BACK || layout == AV_CH_LAYOUT_5POINT0)
178
else if (layout == AV_CH_LAYOUT_5POINT1_BACK || layout == AV_CH_LAYOUT_5POINT1)
180
else if (layout == AV_CH_LAYOUT_7POINT1)
183
return s->reorder_func ? 0 : AVERROR(ENOSYS);
46
186
av_cold int ff_alsa_open(AVFormatContext *ctx, snd_pcm_stream_t mode,
47
187
unsigned int *sample_rate,
48
188
int channels, enum CodecID *codec_id)
147
291
snd_pcm_hw_params_free(hw_params);
293
if (channels > 2 && layout) {
294
if (find_reorder_func(s, *codec_id, layout, mode == SND_PCM_STREAM_PLAYBACK) < 0) {
296
av_get_channel_layout_string(name, sizeof(name), channels, layout);
297
av_log(ctx, AV_LOG_WARNING, "ALSA channel layout unknown or unimplemented for %s %s.\n",
298
name, mode == SND_PCM_STREAM_PLAYBACK ? "playback" : "capture");
300
if (s->reorder_func) {
301
s->reorder_buf_size = buffer_size;
302
s->reorder_buf = av_malloc(s->reorder_buf_size * s->frame_size);