1/* 2 * Linux audio play and grab interface 3 * Copyright (c) 2000, 2001 Fabrice Bellard 4 * 5 * This file is part of Libav. 6 * 7 * Libav is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * Libav is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with Libav; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20 */ 21 22#include "config.h" 23#include <stdlib.h> 24#include <stdio.h> 25#include <stdint.h> 26#include <string.h> 27#include <errno.h> 28#if HAVE_SOUNDCARD_H 29#include <soundcard.h> 30#else 31#include <sys/soundcard.h> 32#endif 33#include <unistd.h> 34#include <fcntl.h> 35#include <sys/ioctl.h> 36#include <sys/time.h> 37#include <sys/select.h> 38 39#include "libavutil/log.h" 40#include "libavutil/opt.h" 41#include "libavcodec/avcodec.h" 42#include "libavformat/avformat.h" 43#include "libavformat/internal.h" 44 45#define AUDIO_BLOCK_SIZE 4096 46 47typedef struct { 48 AVClass *class; 49 int fd; 50 int sample_rate; 51 int channels; 52 int frame_size; /* in bytes ! */ 53 enum CodecID codec_id; 54 unsigned int flip_left : 1; 55 uint8_t buffer[AUDIO_BLOCK_SIZE]; 56 int buffer_ptr; 57} AudioData; 58 59static int audio_open(AVFormatContext *s1, int is_output, const char *audio_device) 60{ 61 AudioData *s = s1->priv_data; 62 int audio_fd; 63 int tmp, err; 64 char *flip = getenv("AUDIO_FLIP_LEFT"); 65 66 if (is_output) 67 audio_fd = open(audio_device, O_WRONLY); 68 else 69 audio_fd = open(audio_device, O_RDONLY); 70 if (audio_fd < 0) { 71 av_log(s1, AV_LOG_ERROR, "%s: %s\n", audio_device, strerror(errno)); 72 return AVERROR(EIO); 73 } 74 75 if (flip && *flip == '1') { 76 s->flip_left = 1; 77 } 78 79 /* non blocking mode */ 80 if (!is_output) 81 fcntl(audio_fd, F_SETFL, O_NONBLOCK); 82 83 s->frame_size = AUDIO_BLOCK_SIZE; 84 85 /* select format : favour native format */ 86 err = ioctl(audio_fd, SNDCTL_DSP_GETFMTS, &tmp); 87 88#if HAVE_BIGENDIAN 89 if (tmp & AFMT_S16_BE) { 90 tmp = AFMT_S16_BE; 91 } else if (tmp & AFMT_S16_LE) { 92 tmp = AFMT_S16_LE; 93 } else { 94 tmp = 0; 95 } 96#else 97 if (tmp & AFMT_S16_LE) { 98 tmp = AFMT_S16_LE; 99 } else if (tmp & AFMT_S16_BE) { 100 tmp = AFMT_S16_BE; 101 } else { 102 tmp = 0; 103 } 104#endif 105 106 switch(tmp) { 107 case AFMT_S16_LE: 108 s->codec_id = CODEC_ID_PCM_S16LE; 109 break; 110 case AFMT_S16_BE: 111 s->codec_id = CODEC_ID_PCM_S16BE; 112 break; 113 default: 114 av_log(s1, AV_LOG_ERROR, "Soundcard does not support 16 bit sample format\n"); 115 close(audio_fd); 116 return AVERROR(EIO); 117 } 118 err=ioctl(audio_fd, SNDCTL_DSP_SETFMT, &tmp); 119 if (err < 0) { 120 av_log(s1, AV_LOG_ERROR, "SNDCTL_DSP_SETFMT: %s\n", strerror(errno)); 121 goto fail; 122 } 123 124 tmp = (s->channels == 2); 125 err = ioctl(audio_fd, SNDCTL_DSP_STEREO, &tmp); 126 if (err < 0) { 127 av_log(s1, AV_LOG_ERROR, "SNDCTL_DSP_STEREO: %s\n", strerror(errno)); 128 goto fail; 129 } 130 131 tmp = s->sample_rate; 132 err = ioctl(audio_fd, SNDCTL_DSP_SPEED, &tmp); 133 if (err < 0) { 134 av_log(s1, AV_LOG_ERROR, "SNDCTL_DSP_SPEED: %s\n", strerror(errno)); 135 goto fail; 136 } 137 s->sample_rate = tmp; /* store real sample rate */ 138 s->fd = audio_fd; 139 140 return 0; 141 fail: 142 close(audio_fd); 143 return AVERROR(EIO); 144} 145 146static int audio_close(AudioData *s) 147{ 148 close(s->fd); 149 return 0; 150} 151 152/* sound output support */ 153static int audio_write_header(AVFormatContext *s1) 154{ 155 AudioData *s = s1->priv_data; 156 AVStream *st; 157 int ret; 158 159 st = s1->streams[0]; 160 s->sample_rate = st->codec->sample_rate; 161 s->channels = st->codec->channels; 162 ret = audio_open(s1, 1, s1->filename); 163 if (ret < 0) { 164 return AVERROR(EIO); 165 } else { 166 return 0; 167 } 168} 169 170static int audio_write_packet(AVFormatContext *s1, AVPacket *pkt) 171{ 172 AudioData *s = s1->priv_data; 173 int len, ret; 174 int size= pkt->size; 175 uint8_t *buf= pkt->data; 176 177 while (size > 0) { 178 len = FFMIN(AUDIO_BLOCK_SIZE - s->buffer_ptr, size); 179 memcpy(s->buffer + s->buffer_ptr, buf, len); 180 s->buffer_ptr += len; 181 if (s->buffer_ptr >= AUDIO_BLOCK_SIZE) { 182 for(;;) { 183 ret = write(s->fd, s->buffer, AUDIO_BLOCK_SIZE); 184 if (ret > 0) 185 break; 186 if (ret < 0 && (errno != EAGAIN && errno != EINTR)) 187 return AVERROR(EIO); 188 } 189 s->buffer_ptr = 0; 190 } 191 buf += len; 192 size -= len; 193 } 194 return 0; 195} 196 197static int audio_write_trailer(AVFormatContext *s1) 198{ 199 AudioData *s = s1->priv_data; 200 201 audio_close(s); 202 return 0; 203} 204 205/* grab support */ 206 207static int audio_read_header(AVFormatContext *s1, AVFormatParameters *ap) 208{ 209 AudioData *s = s1->priv_data; 210 AVStream *st; 211 int ret; 212 213 st = avformat_new_stream(s1, NULL); 214 if (!st) { 215 return AVERROR(ENOMEM); 216 } 217 218 ret = audio_open(s1, 0, s1->filename); 219 if (ret < 0) { 220 return AVERROR(EIO); 221 } 222 223 /* take real parameters */ 224 st->codec->codec_type = AVMEDIA_TYPE_AUDIO; 225 st->codec->codec_id = s->codec_id; 226 st->codec->sample_rate = s->sample_rate; 227 st->codec->channels = s->channels; 228 229 avpriv_set_pts_info(st, 64, 1, 1000000); /* 64 bits pts in us */ 230 return 0; 231} 232 233static int audio_read_packet(AVFormatContext *s1, AVPacket *pkt) 234{ 235 AudioData *s = s1->priv_data; 236 int ret, bdelay; 237 int64_t cur_time; 238 struct audio_buf_info abufi; 239 240 if ((ret=av_new_packet(pkt, s->frame_size)) < 0) 241 return ret; 242 243 ret = read(s->fd, pkt->data, pkt->size); 244 if (ret <= 0){ 245 av_free_packet(pkt); 246 pkt->size = 0; 247 if (ret<0) return AVERROR(errno); 248 else return AVERROR_EOF; 249 } 250 pkt->size = ret; 251 252 /* compute pts of the start of the packet */ 253 cur_time = av_gettime(); 254 bdelay = ret; 255 if (ioctl(s->fd, SNDCTL_DSP_GETISPACE, &abufi) == 0) { 256 bdelay += abufi.bytes; 257 } 258 /* subtract time represented by the number of bytes in the audio fifo */ 259 cur_time -= (bdelay * 1000000LL) / (s->sample_rate * s->channels); 260 261 /* convert to wanted units */ 262 pkt->pts = cur_time; 263 264 if (s->flip_left && s->channels == 2) { 265 int i; 266 short *p = (short *) pkt->data; 267 268 for (i = 0; i < ret; i += 4) { 269 *p = ~*p; 270 p += 2; 271 } 272 } 273 return 0; 274} 275 276static int audio_read_close(AVFormatContext *s1) 277{ 278 AudioData *s = s1->priv_data; 279 280 audio_close(s); 281 return 0; 282} 283 284#if CONFIG_OSS_INDEV 285static const AVOption options[] = { 286 { "sample_rate", "", offsetof(AudioData, sample_rate), AV_OPT_TYPE_INT, {.dbl = 48000}, 1, INT_MAX, AV_OPT_FLAG_DECODING_PARAM }, 287 { "channels", "", offsetof(AudioData, channels), AV_OPT_TYPE_INT, {.dbl = 2}, 1, INT_MAX, AV_OPT_FLAG_DECODING_PARAM }, 288 { NULL }, 289}; 290 291static const AVClass oss_demuxer_class = { 292 .class_name = "OSS demuxer", 293 .item_name = av_default_item_name, 294 .option = options, 295 .version = LIBAVUTIL_VERSION_INT, 296}; 297 298AVInputFormat ff_oss_demuxer = { 299 .name = "oss", 300 .long_name = NULL_IF_CONFIG_SMALL("Open Sound System capture"), 301 .priv_data_size = sizeof(AudioData), 302 .read_header = audio_read_header, 303 .read_packet = audio_read_packet, 304 .read_close = audio_read_close, 305 .flags = AVFMT_NOFILE, 306 .priv_class = &oss_demuxer_class, 307}; 308#endif 309 310#if CONFIG_OSS_OUTDEV 311AVOutputFormat ff_oss_muxer = { 312 .name = "oss", 313 .long_name = NULL_IF_CONFIG_SMALL("Open Sound System playback"), 314 .priv_data_size = sizeof(AudioData), 315 /* XXX: we make the assumption that the soundcard accepts this format */ 316 /* XXX: find better solution with "preinit" method, needed also in 317 other formats */ 318 .audio_codec = AV_NE(CODEC_ID_PCM_S16BE, CODEC_ID_PCM_S16LE), 319 .video_codec = CODEC_ID_NONE, 320 .write_header = audio_write_header, 321 .write_packet = audio_write_packet, 322 .write_trailer = audio_write_trailer, 323 .flags = AVFMT_NOFILE, 324}; 325#endif 326