2 * Copyright (c) 2011 Jonathan Baldwin
4 * This file is part of FFmpeg.
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
11 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
12 * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
13 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
14 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
15 * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16 * PERFORMANCE OF THIS SOFTWARE.
21 * OpenAL 1.1 capture device for libavdevice
27 #include "libavutil/opt.h"
28 #include "libavutil/time.h"
29 #include "libavformat/internal.h"
34 /** OpenAL capture device context. **/
36 /** The number of channels in the captured audio. **/
38 /** The sample rate (in Hz) of the captured audio. **/
40 /** The sample size (in bits) of the captured audio. **/
42 /** The OpenAL sample format of the captured audio. **/
43 ALCenum sample_format
;
44 /** The number of bytes between two consecutive samples of the same channel/component. **/
46 /** If true, print a list of capture devices on this system and exit. **/
52 enum AVCodecID codec_id
;
56 #define LOWEST_AL_FORMAT FFMIN(FFMIN(AL_FORMAT_MONO8,AL_FORMAT_MONO16),FFMIN(AL_FORMAT_STEREO8,AL_FORMAT_STEREO16))
59 * Get information about an AL_FORMAT value.
60 * @param al_fmt the AL_FORMAT value to find information about.
61 * @return A pointer to a structure containing information about the AL_FORMAT value.
63 static inline al_format_info
* get_al_format_info(ALCenum al_fmt
)
65 static al_format_info info_table
[] = {
66 [AL_FORMAT_MONO8
-LOWEST_AL_FORMAT
] = {AL_FORMAT_MONO8
, AV_CODEC_ID_PCM_U8
, 1},
67 [AL_FORMAT_MONO16
-LOWEST_AL_FORMAT
] = {AL_FORMAT_MONO16
, AV_NE (AV_CODEC_ID_PCM_S16BE
, AV_CODEC_ID_PCM_S16LE
), 1},
68 [AL_FORMAT_STEREO8
-LOWEST_AL_FORMAT
] = {AL_FORMAT_STEREO8
, AV_CODEC_ID_PCM_U8
, 2},
69 [AL_FORMAT_STEREO16
-LOWEST_AL_FORMAT
] = {AL_FORMAT_STEREO16
, AV_NE (AV_CODEC_ID_PCM_S16BE
, AV_CODEC_ID_PCM_S16LE
), 2},
72 return &info_table
[al_fmt
-LOWEST_AL_FORMAT
];
76 * Get the OpenAL error code, translated into an av/errno error code.
77 * @param device The ALC device to check for errors.
78 * @param error_msg_ret A pointer to a char* in which to return the error message, or NULL if desired.
79 * @return The error code, or 0 if there is no error.
81 static inline int al_get_error(ALCdevice
*device
, const char** error_msg_ret
)
83 ALCenum error
= alcGetError(device
);
85 *error_msg_ret
= (const char*) alcGetString(device
, error
);
89 case ALC_INVALID_DEVICE
:
90 return AVERROR(ENODEV
);
92 case ALC_INVALID_CONTEXT
:
93 case ALC_INVALID_ENUM
:
94 case ALC_INVALID_VALUE
:
95 return AVERROR(EINVAL
);
97 case ALC_OUT_OF_MEMORY
:
98 return AVERROR(ENOMEM
);
106 * Print out a list of OpenAL capture devices on this system.
108 static inline void print_al_capture_devices(void *log_ctx
)
112 if (!(devices
= alcGetString(NULL
, ALC_CAPTURE_DEVICE_SPECIFIER
)))
115 av_log(log_ctx
, AV_LOG_INFO
, "List of OpenAL capture devices on this system:\n");
117 for (; *devices
!= '\0'; devices
+= strlen(devices
) + 1)
118 av_log(log_ctx
, AV_LOG_INFO
, " %s\n", devices
);
121 static int read_header(AVFormatContext
*ctx
)
123 al_data
*ad
= ctx
->priv_data
;
124 static const ALCenum sample_formats
[2][2] = {
125 { AL_FORMAT_MONO8
, AL_FORMAT_STEREO8
},
126 { AL_FORMAT_MONO16
, AL_FORMAT_STEREO16
}
129 const char *error_msg
;
131 AVCodecContext
*codec
= NULL
;
133 if (ad
->list_devices
) {
134 print_al_capture_devices(ctx
);
138 ad
->sample_format
= sample_formats
[ad
->sample_size
/8-1][ad
->channels
-1];
140 /* Open device for capture */
142 alcCaptureOpenDevice(ctx
->filename
[0] ? ctx
->filename
: NULL
,
145 ad
->sample_rate
); /* Maximum 1 second of sample data to be read at once */
147 if (error
= al_get_error(ad
->device
, &error_msg
)) goto fail
;
150 if (!(st
= avformat_new_stream(ctx
, NULL
))) {
151 error
= AVERROR(ENOMEM
);
155 /* We work in microseconds */
156 avpriv_set_pts_info(st
, 64, 1, 1000000);
158 /* Set codec parameters */
160 codec
->codec_type
= AVMEDIA_TYPE_AUDIO
;
161 codec
->sample_rate
= ad
->sample_rate
;
162 codec
->channels
= get_al_format_info(ad
->sample_format
)->channels
;
163 codec
->codec_id
= get_al_format_info(ad
->sample_format
)->codec_id
;
165 /* This is needed to read the audio data */
166 ad
->sample_step
= (av_get_bits_per_sample(get_al_format_info(ad
->sample_format
)->codec_id
) *
167 get_al_format_info(ad
->sample_format
)->channels
) / 8;
169 /* Finally, start the capture process */
170 alcCaptureStart(ad
->device
);
177 alcCaptureCloseDevice(ad
->device
);
179 av_log(ctx
, AV_LOG_ERROR
, "Cannot open device: %s\n", error_msg
);
183 static int read_packet(AVFormatContext
* ctx
, AVPacket
*pkt
)
185 al_data
*ad
= ctx
->priv_data
;
187 const char *error_msg
;
190 /* Get number of samples available */
191 alcGetIntegerv(ad
->device
, ALC_CAPTURE_SAMPLES
, (ALCsizei
) sizeof(ALCint
), &nb_samples
);
192 if (error
= al_get_error(ad
->device
, &error_msg
)) goto fail
;
194 /* Create a packet of appropriate size */
195 av_new_packet(pkt
, nb_samples
*ad
->sample_step
);
196 pkt
->pts
= av_gettime();
198 /* Fill the packet with the available samples */
199 alcCaptureSamples(ad
->device
, pkt
->data
, nb_samples
);
200 if (error
= al_get_error(ad
->device
, &error_msg
)) goto fail
;
206 av_destruct_packet(pkt
);
208 av_log(ctx
, AV_LOG_ERROR
, "Error: %s\n", error_msg
);
212 static int read_close(AVFormatContext
* ctx
)
214 al_data
*ad
= ctx
->priv_data
;
217 alcCaptureStop(ad
->device
);
218 alcCaptureCloseDevice(ad
->device
);
223 #define OFFSET(x) offsetof(al_data, x)
225 static const AVOption options
[] = {
226 {"channels", "set number of channels", OFFSET(channels
), AV_OPT_TYPE_INT
, {.i64
=2}, 1, 2, AV_OPT_FLAG_DECODING_PARAM
},
227 {"sample_rate", "set sample rate", OFFSET(sample_rate
), AV_OPT_TYPE_INT
, {.i64
=44100}, 1, 192000, AV_OPT_FLAG_DECODING_PARAM
},
228 {"sample_size", "set sample size", OFFSET(sample_size
), AV_OPT_TYPE_INT
, {.i64
=16}, 8, 16, AV_OPT_FLAG_DECODING_PARAM
},
229 {"list_devices", "list available devices", OFFSET(list_devices
), AV_OPT_TYPE_INT
, {.i64
=0}, 0, 1, AV_OPT_FLAG_DECODING_PARAM
, "list_devices" },
230 {"true", "", 0, AV_OPT_TYPE_CONST
, {.i64
=1}, 0, 0, AV_OPT_FLAG_DECODING_PARAM
, "list_devices" },
231 {"false", "", 0, AV_OPT_TYPE_CONST
, {.i64
=0}, 0, 0, AV_OPT_FLAG_DECODING_PARAM
, "list_devices" },
235 static const AVClass
class = {
236 .class_name
= "openal",
237 .item_name
= av_default_item_name
,
239 .version
= LIBAVUTIL_VERSION_INT
,
240 .category
= AV_CLASS_CATEGORY_DEVICE_AUDIO_INPUT
,
243 AVInputFormat ff_openal_demuxer
= {
245 .long_name
= NULL_IF_CONFIG_SMALL("OpenAL audio capture device"),
246 .priv_data_size
= sizeof(al_data
),
248 .read_header
= read_header
,
249 .read_packet
= read_packet
,
250 .read_close
= read_close
,
251 .flags
= AVFMT_NOFILE
,