00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00024 #include <AL/al.h>
00025 #include <AL/alc.h>
00026
00027 #include "libavutil/opt.h"
00028 #include "libavformat/internal.h"
00029 #include "avdevice.h"
00030
00031 typedef struct {
00032 AVClass *class;
00034 ALCdevice *device;
00036 int channels;
00038 int sample_rate;
00040 int sample_size;
00042 ALCenum sample_format;
00044 ALCint sample_step;
00046 int list_devices;
00047 } al_data;
00048
00049 typedef struct {
00050 ALCenum al_fmt;
00051 enum CodecID codec_id;
00052 int channels;
00053 } al_format_info;
00054
00055 #define LOWEST_AL_FORMAT FFMIN(FFMIN(AL_FORMAT_MONO8,AL_FORMAT_MONO16),FFMIN(AL_FORMAT_STEREO8,AL_FORMAT_STEREO16))
00056
00062 static inline al_format_info* get_al_format_info(ALCenum al_fmt)
00063 {
00064 static al_format_info info_table[] = {
00065 [AL_FORMAT_MONO8-LOWEST_AL_FORMAT] = {AL_FORMAT_MONO8, CODEC_ID_PCM_U8, 1},
00066 [AL_FORMAT_MONO16-LOWEST_AL_FORMAT] = {AL_FORMAT_MONO16, AV_NE (CODEC_ID_PCM_S16BE, CODEC_ID_PCM_S16LE), 1},
00067 [AL_FORMAT_STEREO8-LOWEST_AL_FORMAT] = {AL_FORMAT_STEREO8, CODEC_ID_PCM_U8, 2},
00068 [AL_FORMAT_STEREO16-LOWEST_AL_FORMAT] = {AL_FORMAT_STEREO16, AV_NE (CODEC_ID_PCM_S16BE, CODEC_ID_PCM_S16LE), 2},
00069 };
00070
00071 return &info_table[al_fmt-LOWEST_AL_FORMAT];
00072 }
00073
00080 static inline int al_get_error(ALCdevice *device, const char** error_msg_ret)
00081 {
00082 ALCenum error = alcGetError(device);
00083 if (error_msg_ret)
00084 *error_msg_ret = (const char*) alcGetString(device, error);
00085 switch (error) {
00086 case ALC_NO_ERROR:
00087 return 0;
00088 case ALC_INVALID_DEVICE:
00089 return AVERROR(ENODEV);
00090 break;
00091 case ALC_INVALID_CONTEXT:
00092 case ALC_INVALID_ENUM:
00093 case ALC_INVALID_VALUE:
00094 return AVERROR(EINVAL);
00095 break;
00096 case ALC_OUT_OF_MEMORY:
00097 return AVERROR(ENOMEM);
00098 break;
00099 default:
00100 return AVERROR(EIO);
00101 }
00102 }
00103
00107 static inline void print_al_capture_devices(void *log_ctx)
00108 {
00109 const char *devices;
00110
00111 if (!(devices = alcGetString(NULL, ALC_CAPTURE_DEVICE_SPECIFIER)))
00112 return;
00113
00114 av_log(log_ctx, AV_LOG_INFO, "List of OpenAL capture devices on this system:\n");
00115
00116 for (; *devices != '\0'; devices += strlen(devices) + 1)
00117 av_log(log_ctx, AV_LOG_INFO, " %s\n", devices);
00118 }
00119
00120 static int read_header(AVFormatContext *ctx, AVFormatParameters *ap)
00121 {
00122 al_data *ad = ctx->priv_data;
00123 static const ALCenum sample_formats[2][2] = {
00124 { AL_FORMAT_MONO8, AL_FORMAT_STEREO8 },
00125 { AL_FORMAT_MONO16, AL_FORMAT_STEREO16 }
00126 };
00127 int error = 0;
00128 const char *error_msg;
00129 AVStream *st = NULL;
00130 AVCodecContext *codec = NULL;
00131
00132 if (ad->list_devices) {
00133 print_al_capture_devices(ctx);
00134 return AVERROR_EXIT;
00135 }
00136
00137 ad->sample_format = sample_formats[ad->sample_size/8-1][ad->channels-1];
00138
00139
00140 ad->device =
00141 alcCaptureOpenDevice(ctx->filename[0] ? ctx->filename : NULL,
00142 ad->sample_rate,
00143 ad->sample_format,
00144 ad->sample_rate);
00145
00146 if (error = al_get_error(ad->device, &error_msg)) goto fail;
00147
00148
00149 if (!(st = avformat_new_stream(ctx, NULL))) {
00150 error = AVERROR(ENOMEM);
00151 goto fail;
00152 }
00153
00154
00155 avpriv_set_pts_info(st, 64, 1, 1000000);
00156
00157
00158 codec = st->codec;
00159 codec->codec_type = AVMEDIA_TYPE_AUDIO;
00160 codec->sample_rate = ad->sample_rate;
00161 codec->channels = get_al_format_info(ad->sample_format)->channels;
00162 codec->codec_id = get_al_format_info(ad->sample_format)->codec_id;
00163
00164
00165 ad->sample_step = (av_get_bits_per_sample(get_al_format_info(ad->sample_format)->codec_id) *
00166 get_al_format_info(ad->sample_format)->channels) / 8;
00167
00168
00169 alcCaptureStart(ad->device);
00170
00171 return 0;
00172
00173 fail:
00174
00175 if (ad->device)
00176 alcCaptureCloseDevice(ad->device);
00177 if (error_msg)
00178 av_log(ctx, AV_LOG_ERROR, "Cannot open device: %s\n", error_msg);
00179 return error;
00180 }
00181
00182 static int read_packet(AVFormatContext* ctx, AVPacket *pkt)
00183 {
00184 al_data *ad = ctx->priv_data;
00185 int error=0;
00186 const char *error_msg;
00187 ALCint nb_samples;
00188
00189
00190 alcGetIntegerv(ad->device, ALC_CAPTURE_SAMPLES, (ALCsizei) sizeof(ALCint), &nb_samples);
00191 if (error = al_get_error(ad->device, &error_msg)) goto fail;
00192
00193
00194 av_new_packet(pkt, nb_samples*ad->sample_step);
00195 pkt->pts = av_gettime();
00196
00197
00198 alcCaptureSamples(ad->device, pkt->data, nb_samples);
00199 if (error = al_get_error(ad->device, &error_msg)) goto fail;
00200
00201 return pkt->size;
00202 fail:
00203
00204 if (pkt->data)
00205 av_destruct_packet(pkt);
00206 if (error_msg)
00207 av_log(ctx, AV_LOG_ERROR, "Error: %s\n", error_msg);
00208 return error;
00209 }
00210
00211 static int read_close(AVFormatContext* ctx)
00212 {
00213 al_data *ad = ctx->priv_data;
00214
00215 if (ad->device) {
00216 alcCaptureStop(ad->device);
00217 alcCaptureCloseDevice(ad->device);
00218 }
00219 return 0;
00220 }
00221
00222 #define OFFSET(x) offsetof(al_data, x)
00223
00224 static const AVOption options[] = {
00225 {"channels", "set number of channels", OFFSET(channels), AV_OPT_TYPE_INT, {.dbl=2}, 1, 2, AV_OPT_FLAG_DECODING_PARAM },
00226 {"sample_rate", "set sample rate", OFFSET(sample_rate), AV_OPT_TYPE_INT, {.dbl=44100}, 1, 192000, AV_OPT_FLAG_DECODING_PARAM },
00227 {"sample_size", "set sample size", OFFSET(sample_size), AV_OPT_TYPE_INT, {.dbl=16}, 8, 16, AV_OPT_FLAG_DECODING_PARAM },
00228 {"list_devices", "list available devices", OFFSET(list_devices), AV_OPT_TYPE_INT, {.dbl=0}, 0, 1, AV_OPT_FLAG_DECODING_PARAM, "list_devices" },
00229 {"true", "", 0, AV_OPT_TYPE_CONST, {.dbl=1}, 0, 0, AV_OPT_FLAG_DECODING_PARAM, "list_devices" },
00230 {"false", "", 0, AV_OPT_TYPE_CONST, {.dbl=0}, 0, 0, AV_OPT_FLAG_DECODING_PARAM, "list_devices" },
00231 {NULL},
00232 };
00233
00234 static const AVClass class = {
00235 .class_name = "openal",
00236 .item_name = av_default_item_name,
00237 .option = options,
00238 .version = LIBAVUTIL_VERSION_INT
00239 };
00240
00241 AVInputFormat ff_openal_demuxer = {
00242 .name = "openal",
00243 .long_name = NULL_IF_CONFIG_SMALL("OpenAL audio capture device"),
00244 .priv_data_size = sizeof(al_data),
00245 .read_probe = NULL,
00246 .read_header = read_header,
00247 .read_packet = read_packet,
00248 .read_close = read_close,
00249 .flags = AVFMT_NOFILE,
00250 .priv_class = &class
00251 };