1/*
2 * Linux audio play and grab interface
3 * Copyright (c) 2000, 2001 Fabrice Bellard
4 *
5 * This file is part of FFmpeg.
6 *
7 * FFmpeg 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 * FFmpeg 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 FFmpeg; 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 "libavcodec/avcodec.h"
41#include "libavformat/avformat.h"
42
43#define AUDIO_BLOCK_SIZE 4096
44
45typedef struct {
46    int fd;
47    int sample_rate;
48    int channels;
49    int frame_size; /* in bytes ! */
50    enum CodecID codec_id;
51    unsigned int flip_left : 1;
52    uint8_t buffer[AUDIO_BLOCK_SIZE];
53    int buffer_ptr;
54} AudioData;
55
56static int audio_open(AVFormatContext *s1, int is_output, const char *audio_device)
57{
58    AudioData *s = s1->priv_data;
59    int audio_fd;
60    int tmp, err;
61    char *flip = getenv("AUDIO_FLIP_LEFT");
62
63    if (is_output)
64        audio_fd = open(audio_device, O_WRONLY);
65    else
66        audio_fd = open(audio_device, O_RDONLY);
67    if (audio_fd < 0) {
68        av_log(s1, AV_LOG_ERROR, "%s: %s\n", audio_device, strerror(errno));
69        return AVERROR(EIO);
70    }
71
72    if (flip && *flip == '1') {
73        s->flip_left = 1;
74    }
75
76    /* non blocking mode */
77    if (!is_output)
78        fcntl(audio_fd, F_SETFL, O_NONBLOCK);
79
80    s->frame_size = AUDIO_BLOCK_SIZE;
81#if 0
82    tmp = (NB_FRAGMENTS << 16) | FRAGMENT_BITS;
83    err = ioctl(audio_fd, SNDCTL_DSP_SETFRAGMENT, &tmp);
84    if (err < 0) {
85        perror("SNDCTL_DSP_SETFRAGMENT");
86    }
87#endif
88
89    /* select format : favour native format */
90    err = ioctl(audio_fd, SNDCTL_DSP_GETFMTS, &tmp);
91
92#if HAVE_BIGENDIAN
93    if (tmp & AFMT_S16_BE) {
94        tmp = AFMT_S16_BE;
95    } else if (tmp & AFMT_S16_LE) {
96        tmp = AFMT_S16_LE;
97    } else {
98        tmp = 0;
99    }
100#else
101    if (tmp & AFMT_S16_LE) {
102        tmp = AFMT_S16_LE;
103    } else if (tmp & AFMT_S16_BE) {
104        tmp = AFMT_S16_BE;
105    } else {
106        tmp = 0;
107    }
108#endif
109
110    switch(tmp) {
111    case AFMT_S16_LE:
112        s->codec_id = CODEC_ID_PCM_S16LE;
113        break;
114    case AFMT_S16_BE:
115        s->codec_id = CODEC_ID_PCM_S16BE;
116        break;
117    default:
118        av_log(s1, AV_LOG_ERROR, "Soundcard does not support 16 bit sample format\n");
119        close(audio_fd);
120        return AVERROR(EIO);
121    }
122    err=ioctl(audio_fd, SNDCTL_DSP_SETFMT, &tmp);
123    if (err < 0) {
124        av_log(s1, AV_LOG_ERROR, "SNDCTL_DSP_SETFMT: %s\n", strerror(errno));
125        goto fail;
126    }
127
128    tmp = (s->channels == 2);
129    err = ioctl(audio_fd, SNDCTL_DSP_STEREO, &tmp);
130    if (err < 0) {
131        av_log(s1, AV_LOG_ERROR, "SNDCTL_DSP_STEREO: %s\n", strerror(errno));
132        goto fail;
133    }
134
135    tmp = s->sample_rate;
136    err = ioctl(audio_fd, SNDCTL_DSP_SPEED, &tmp);
137    if (err < 0) {
138        av_log(s1, AV_LOG_ERROR, "SNDCTL_DSP_SPEED: %s\n", strerror(errno));
139        goto fail;
140    }
141    s->sample_rate = tmp; /* store real sample rate */
142    s->fd = audio_fd;
143
144    return 0;
145 fail:
146    close(audio_fd);
147    return AVERROR(EIO);
148}
149
150static int audio_close(AudioData *s)
151{
152    close(s->fd);
153    return 0;
154}
155
156/* sound output support */
157static int audio_write_header(AVFormatContext *s1)
158{
159    AudioData *s = s1->priv_data;
160    AVStream *st;
161    int ret;
162
163    st = s1->streams[0];
164    s->sample_rate = st->codec->sample_rate;
165    s->channels = st->codec->channels;
166    ret = audio_open(s1, 1, s1->filename);
167    if (ret < 0) {
168        return AVERROR(EIO);
169    } else {
170        return 0;
171    }
172}
173
174static int audio_write_packet(AVFormatContext *s1, AVPacket *pkt)
175{
176    AudioData *s = s1->priv_data;
177    int len, ret;
178    int size= pkt->size;
179    uint8_t *buf= pkt->data;
180
181    while (size > 0) {
182        len = AUDIO_BLOCK_SIZE - s->buffer_ptr;
183        if (len > size)
184            len = size;
185        memcpy(s->buffer + s->buffer_ptr, buf, len);
186        s->buffer_ptr += len;
187        if (s->buffer_ptr >= AUDIO_BLOCK_SIZE) {
188            for(;;) {
189                ret = write(s->fd, s->buffer, AUDIO_BLOCK_SIZE);
190                if (ret > 0)
191                    break;
192                if (ret < 0 && (errno != EAGAIN && errno != EINTR))
193                    return AVERROR(EIO);
194            }
195            s->buffer_ptr = 0;
196        }
197        buf += len;
198        size -= len;
199    }
200    return 0;
201}
202
203static int audio_write_trailer(AVFormatContext *s1)
204{
205    AudioData *s = s1->priv_data;
206
207    audio_close(s);
208    return 0;
209}
210
211/* grab support */
212
213static int audio_read_header(AVFormatContext *s1, AVFormatParameters *ap)
214{
215    AudioData *s = s1->priv_data;
216    AVStream *st;
217    int ret;
218
219    if (ap->sample_rate <= 0 || ap->channels <= 0)
220        return -1;
221
222    st = av_new_stream(s1, 0);
223    if (!st) {
224        return AVERROR(ENOMEM);
225    }
226    s->sample_rate = ap->sample_rate;
227    s->channels = ap->channels;
228
229    ret = audio_open(s1, 0, s1->filename);
230    if (ret < 0) {
231        return AVERROR(EIO);
232    }
233
234    /* take real parameters */
235    st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
236    st->codec->codec_id = s->codec_id;
237    st->codec->sample_rate = s->sample_rate;
238    st->codec->channels = s->channels;
239
240    av_set_pts_info(st, 64, 1, 1000000);  /* 64 bits pts in us */
241    return 0;
242}
243
244static int audio_read_packet(AVFormatContext *s1, AVPacket *pkt)
245{
246    AudioData *s = s1->priv_data;
247    int ret, bdelay;
248    int64_t cur_time;
249    struct audio_buf_info abufi;
250
251    if ((ret=av_new_packet(pkt, s->frame_size)) < 0)
252        return ret;
253
254    ret = read(s->fd, pkt->data, pkt->size);
255    if (ret <= 0){
256        av_free_packet(pkt);
257        pkt->size = 0;
258        if (ret<0)  return AVERROR(errno);
259        else        return AVERROR_EOF;
260    }
261    pkt->size = ret;
262
263    /* compute pts of the start of the packet */
264    cur_time = av_gettime();
265    bdelay = ret;
266    if (ioctl(s->fd, SNDCTL_DSP_GETISPACE, &abufi) == 0) {
267        bdelay += abufi.bytes;
268    }
269    /* subtract time represented by the number of bytes in the audio fifo */
270    cur_time -= (bdelay * 1000000LL) / (s->sample_rate * s->channels);
271
272    /* convert to wanted units */
273    pkt->pts = cur_time;
274
275    if (s->flip_left && s->channels == 2) {
276        int i;
277        short *p = (short *) pkt->data;
278
279        for (i = 0; i < ret; i += 4) {
280            *p = ~*p;
281            p += 2;
282        }
283    }
284    return 0;
285}
286
287static int audio_read_close(AVFormatContext *s1)
288{
289    AudioData *s = s1->priv_data;
290
291    audio_close(s);
292    return 0;
293}
294
295#if CONFIG_OSS_INDEV
296AVInputFormat oss_demuxer = {
297    "oss",
298    NULL_IF_CONFIG_SMALL("Open Sound System capture"),
299    sizeof(AudioData),
300    NULL,
301    audio_read_header,
302    audio_read_packet,
303    audio_read_close,
304    .flags = AVFMT_NOFILE,
305};
306#endif
307
308#if CONFIG_OSS_OUTDEV
309AVOutputFormat oss_muxer = {
310    "oss",
311    NULL_IF_CONFIG_SMALL("Open Sound System playback"),
312    "",
313    "",
314    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#if HAVE_BIGENDIAN
319    CODEC_ID_PCM_S16BE,
320#else
321    CODEC_ID_PCM_S16LE,
322#endif
323    CODEC_ID_NONE,
324    audio_write_header,
325    audio_write_packet,
326    audio_write_trailer,
327    .flags = AVFMT_NOFILE,
328};
329#endif
330