Statistics
| Branch: | Revision:

ffmpeg / libavdevice / audio.c @ 647148c6

History | View | Annotate | Download (8.4 KB)

1 de6d9b64 Fabrice Bellard
/*
2
 * Linux audio play and grab interface
3 19720f15 Fabrice Bellard
 * Copyright (c) 2000, 2001 Fabrice Bellard.
4 de6d9b64 Fabrice Bellard
 *
5 b78e7197 Diego Biurrun
 * This file is part of FFmpeg.
6
 *
7
 * FFmpeg is free software; you can redistribute it and/or
8 19720f15 Fabrice Bellard
 * modify it under the terms of the GNU Lesser General Public
9
 * License as published by the Free Software Foundation; either
10 b78e7197 Diego Biurrun
 * version 2.1 of the License, or (at your option) any later version.
11 de6d9b64 Fabrice Bellard
 *
12 b78e7197 Diego Biurrun
 * FFmpeg is distributed in the hope that it will be useful,
13 de6d9b64 Fabrice Bellard
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 19720f15 Fabrice Bellard
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
 * Lesser General Public License for more details.
16 de6d9b64 Fabrice Bellard
 *
17 19720f15 Fabrice Bellard
 * You should have received a copy of the GNU Lesser General Public
18 b78e7197 Diego Biurrun
 * License along with FFmpeg; if not, write to the Free Software
19 5509bffa Diego Biurrun
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 de6d9b64 Fabrice Bellard
 */
21 8be1c656 Fabrice Bellard
22 4f786086 Diego Biurrun
#include "config.h"
23 de6d9b64 Fabrice Bellard
#include <stdlib.h>
24
#include <stdio.h>
25 4f786086 Diego Biurrun
#include <stdint.h>
26 de6d9b64 Fabrice Bellard
#include <string.h>
27 4f786086 Diego Biurrun
#include <errno.h>
28 74476a3a Måns Rullgård
#ifdef HAVE_SOUNDCARD_H
29 8c802695 Jacob Meuser
#include <soundcard.h>
30
#else
31 b13788c5 Fabrice Bellard
#include <sys/soundcard.h>
32 8c802695 Jacob Meuser
#endif
33 de6d9b64 Fabrice Bellard
#include <unistd.h>
34
#include <fcntl.h>
35
#include <sys/ioctl.h>
36
#include <sys/time.h>
37
38 245976da Diego Biurrun
#include "libavutil/log.h"
39
#include "libavcodec/avcodec.h"
40
#include "libavformat/avformat.h"
41 4f786086 Diego Biurrun
42 4972b26f Fabrice Bellard
#define AUDIO_BLOCK_SIZE 4096
43
44 de6d9b64 Fabrice Bellard
typedef struct {
45
    int fd;
46 4972b26f Fabrice Bellard
    int sample_rate;
47 de6d9b64 Fabrice Bellard
    int channels;
48 4972b26f Fabrice Bellard
    int frame_size; /* in bytes ! */
49
    int codec_id;
50 72e043dd Erik Hovland
    unsigned int flip_left : 1;
51 0c1a9eda Zdenek Kabelac
    uint8_t buffer[AUDIO_BLOCK_SIZE];
52 4972b26f Fabrice Bellard
    int buffer_ptr;
53 de6d9b64 Fabrice Bellard
} AudioData;
54
55 7f172339 Fabrice Bellard
static int audio_open(AudioData *s, int is_output, const char *audio_device)
56 de6d9b64 Fabrice Bellard
{
57 4972b26f Fabrice Bellard
    int audio_fd;
58 de6d9b64 Fabrice Bellard
    int tmp, err;
59 1de1cce2 Philip Gladstone
    char *flip = getenv("AUDIO_FLIP_LEFT");
60 de6d9b64 Fabrice Bellard
61 4972b26f Fabrice Bellard
    if (is_output)
62
        audio_fd = open(audio_device, O_WRONLY);
63 de6d9b64 Fabrice Bellard
    else
64 4972b26f Fabrice Bellard
        audio_fd = open(audio_device, O_RDONLY);
65 de6d9b64 Fabrice Bellard
    if (audio_fd < 0) {
66 9f74582c Luca Abeni
        av_log(NULL, AV_LOG_ERROR, "%s: %s\n", audio_device, strerror(errno));
67 6f3e0b21 Panagiotis Issaris
        return AVERROR(EIO);
68 de6d9b64 Fabrice Bellard
    }
69
70 1de1cce2 Philip Gladstone
    if (flip && *flip == '1') {
71
        s->flip_left = 1;
72
    }
73
74 de6d9b64 Fabrice Bellard
    /* non blocking mode */
75 4364a3e0 Fabrice Bellard
    if (!is_output)
76
        fcntl(audio_fd, F_SETFL, O_NONBLOCK);
77 de6d9b64 Fabrice Bellard
78 4972b26f Fabrice Bellard
    s->frame_size = AUDIO_BLOCK_SIZE;
79 de6d9b64 Fabrice Bellard
#if 0
80 4972b26f Fabrice Bellard
    tmp = (NB_FRAGMENTS << 16) | FRAGMENT_BITS;
81
    err = ioctl(audio_fd, SNDCTL_DSP_SETFRAGMENT, &tmp);
82 de6d9b64 Fabrice Bellard
    if (err < 0) {
83
        perror("SNDCTL_DSP_SETFRAGMENT");
84
    }
85
#endif
86
87 4972b26f Fabrice Bellard
    /* select format : favour native format */
88
    err = ioctl(audio_fd, SNDCTL_DSP_GETFMTS, &tmp);
89 115329f1 Diego Biurrun
90 4972b26f Fabrice Bellard
#ifdef WORDS_BIGENDIAN
91
    if (tmp & AFMT_S16_BE) {
92
        tmp = AFMT_S16_BE;
93
    } else if (tmp & AFMT_S16_LE) {
94
        tmp = AFMT_S16_LE;
95
    } else {
96
        tmp = 0;
97
    }
98
#else
99
    if (tmp & AFMT_S16_LE) {
100
        tmp = AFMT_S16_LE;
101
    } else if (tmp & AFMT_S16_BE) {
102
        tmp = AFMT_S16_BE;
103
    } else {
104
        tmp = 0;
105
    }
106
#endif
107
108
    switch(tmp) {
109
    case AFMT_S16_LE:
110
        s->codec_id = CODEC_ID_PCM_S16LE;
111
        break;
112
    case AFMT_S16_BE:
113
        s->codec_id = CODEC_ID_PCM_S16BE;
114
        break;
115
    default:
116 bc874dae Michel Bardiaux
        av_log(NULL, AV_LOG_ERROR, "Soundcard does not support 16 bit sample format\n");
117 4972b26f Fabrice Bellard
        close(audio_fd);
118 6f3e0b21 Panagiotis Issaris
        return AVERROR(EIO);
119 4972b26f Fabrice Bellard
    }
120
    err=ioctl(audio_fd, SNDCTL_DSP_SETFMT, &tmp);
121 de6d9b64 Fabrice Bellard
    if (err < 0) {
122 9f74582c Luca Abeni
        av_log(NULL, AV_LOG_ERROR, "SNDCTL_DSP_SETFMT: %s\n", strerror(errno));
123 de6d9b64 Fabrice Bellard
        goto fail;
124
    }
125 115329f1 Diego Biurrun
126 4972b26f Fabrice Bellard
    tmp = (s->channels == 2);
127
    err = ioctl(audio_fd, SNDCTL_DSP_STEREO, &tmp);
128 de6d9b64 Fabrice Bellard
    if (err < 0) {
129 9f74582c Luca Abeni
        av_log(NULL, AV_LOG_ERROR, "SNDCTL_DSP_STEREO: %s\n", strerror(errno));
130 de6d9b64 Fabrice Bellard
        goto fail;
131
    }
132 115329f1 Diego Biurrun
133 4972b26f Fabrice Bellard
    tmp = s->sample_rate;
134
    err = ioctl(audio_fd, SNDCTL_DSP_SPEED, &tmp);
135 de6d9b64 Fabrice Bellard
    if (err < 0) {
136 9f74582c Luca Abeni
        av_log(NULL, AV_LOG_ERROR, "SNDCTL_DSP_SPEED: %s\n", strerror(errno));
137 de6d9b64 Fabrice Bellard
        goto fail;
138
    }
139 4972b26f Fabrice Bellard
    s->sample_rate = tmp; /* store real sample rate */
140 de6d9b64 Fabrice Bellard
    s->fd = audio_fd;
141
142
    return 0;
143
 fail:
144
    close(audio_fd);
145 6f3e0b21 Panagiotis Issaris
    return AVERROR(EIO);
146 de6d9b64 Fabrice Bellard
}
147
148 4972b26f Fabrice Bellard
static int audio_close(AudioData *s)
149 de6d9b64 Fabrice Bellard
{
150
    close(s->fd);
151 4972b26f Fabrice Bellard
    return 0;
152
}
153
154
/* sound output support */
155
static int audio_write_header(AVFormatContext *s1)
156
{
157 c9a65ca8 Fabrice Bellard
    AudioData *s = s1->priv_data;
158 4972b26f Fabrice Bellard
    AVStream *st;
159
    int ret;
160
161
    st = s1->streams[0];
162 01f4895c Michael Niedermayer
    s->sample_rate = st->codec->sample_rate;
163
    s->channels = st->codec->channels;
164 7bb7ad0e Baptiste Coudurier
    ret = audio_open(s, 1, s1->filename);
165 4972b26f Fabrice Bellard
    if (ret < 0) {
166 6f3e0b21 Panagiotis Issaris
        return AVERROR(EIO);
167 4972b26f Fabrice Bellard
    } else {
168
        return 0;
169
    }
170
}
171
172 e928649b Michael Niedermayer
static int audio_write_packet(AVFormatContext *s1, AVPacket *pkt)
173 4972b26f Fabrice Bellard
{
174
    AudioData *s = s1->priv_data;
175
    int len, ret;
176 e928649b Michael Niedermayer
    int size= pkt->size;
177
    uint8_t *buf= pkt->data;
178 4972b26f Fabrice Bellard
179
    while (size > 0) {
180
        len = AUDIO_BLOCK_SIZE - s->buffer_ptr;
181
        if (len > size)
182
            len = size;
183
        memcpy(s->buffer + s->buffer_ptr, buf, len);
184
        s->buffer_ptr += len;
185
        if (s->buffer_ptr >= AUDIO_BLOCK_SIZE) {
186
            for(;;) {
187
                ret = write(s->fd, s->buffer, AUDIO_BLOCK_SIZE);
188 4364a3e0 Fabrice Bellard
                if (ret > 0)
189 4972b26f Fabrice Bellard
                    break;
190
                if (ret < 0 && (errno != EAGAIN && errno != EINTR))
191 6f3e0b21 Panagiotis Issaris
                    return AVERROR(EIO);
192 4972b26f Fabrice Bellard
            }
193
            s->buffer_ptr = 0;
194
        }
195
        buf += len;
196
        size -= len;
197
    }
198
    return 0;
199
}
200
201
static int audio_write_trailer(AVFormatContext *s1)
202
{
203
    AudioData *s = s1->priv_data;
204
205
    audio_close(s);
206 de6d9b64 Fabrice Bellard
    return 0;
207
}
208
209 4972b26f Fabrice Bellard
/* grab support */
210
211
static int audio_read_header(AVFormatContext *s1, AVFormatParameters *ap)
212
{
213 c9a65ca8 Fabrice Bellard
    AudioData *s = s1->priv_data;
214 4972b26f Fabrice Bellard
    AVStream *st;
215
    int ret;
216
217 c04c3282 Michael Niedermayer
    if (ap->sample_rate <= 0 || ap->channels <= 0)
218 4972b26f Fabrice Bellard
        return -1;
219
220 c9a65ca8 Fabrice Bellard
    st = av_new_stream(s1, 0);
221 4972b26f Fabrice Bellard
    if (!st) {
222 8fa36ae0 François Revol
        return AVERROR(ENOMEM);
223 4972b26f Fabrice Bellard
    }
224
    s->sample_rate = ap->sample_rate;
225
    s->channels = ap->channels;
226
227 cc58300e Ramiro Polla
    ret = audio_open(s, 0, s1->filename);
228 4972b26f Fabrice Bellard
    if (ret < 0) {
229 1ea4f593 Fabrice Bellard
        av_free(st);
230 6f3e0b21 Panagiotis Issaris
        return AVERROR(EIO);
231 4972b26f Fabrice Bellard
    }
232 45dd5c69 Fabrice Bellard
233
    /* take real parameters */
234 01f4895c Michael Niedermayer
    st->codec->codec_type = CODEC_TYPE_AUDIO;
235
    st->codec->codec_id = s->codec_id;
236
    st->codec->sample_rate = s->sample_rate;
237
    st->codec->channels = s->channels;
238 45dd5c69 Fabrice Bellard
239 0a7b514f Luca Abeni
    av_set_pts_info(st, 64, 1, 1000000);  /* 64 bits pts in us */
240 45dd5c69 Fabrice Bellard
    return 0;
241 4972b26f Fabrice Bellard
}
242
243
static int audio_read_packet(AVFormatContext *s1, AVPacket *pkt)
244
{
245
    AudioData *s = s1->priv_data;
246 45dd5c69 Fabrice Bellard
    int ret, bdelay;
247
    int64_t cur_time;
248
    struct audio_buf_info abufi;
249 115329f1 Diego Biurrun
250 4972b26f Fabrice Bellard
    if (av_new_packet(pkt, s->frame_size) < 0)
251 6f3e0b21 Panagiotis Issaris
        return AVERROR(EIO);
252 4972b26f Fabrice Bellard
    for(;;) {
253 79134973 Philip Gladstone
        struct timeval tv;
254
        fd_set fds;
255
256
        tv.tv_sec = 0;
257
        tv.tv_usec = 30 * 1000; /* 30 msecs -- a bit shorter than 1 frame at 30fps */
258
259
        FD_ZERO(&fds);
260
        FD_SET(s->fd, &fds);
261
262
        /* This will block until data is available or we get a timeout */
263
        (void) select(s->fd + 1, &fds, 0, 0, &tv);
264
265 4972b26f Fabrice Bellard
        ret = read(s->fd, pkt->data, pkt->size);
266
        if (ret > 0)
267
            break;
268 4606ac8d Zdenek Kabelac
        if (ret == -1 && (errno == EAGAIN || errno == EINTR)) {
269
            av_free_packet(pkt);
270
            pkt->size = 0;
271 0a7b514f Luca Abeni
            pkt->pts = av_gettime();
272 4606ac8d Zdenek Kabelac
            return 0;
273
        }
274 4972b26f Fabrice Bellard
        if (!(ret == 0 || (ret == -1 && (errno == EAGAIN || errno == EINTR)))) {
275
            av_free_packet(pkt);
276 6f3e0b21 Panagiotis Issaris
            return AVERROR(EIO);
277 4972b26f Fabrice Bellard
        }
278
    }
279
    pkt->size = ret;
280 45dd5c69 Fabrice Bellard
281
    /* compute pts of the start of the packet */
282
    cur_time = av_gettime();
283
    bdelay = ret;
284
    if (ioctl(s->fd, SNDCTL_DSP_GETISPACE, &abufi) == 0) {
285
        bdelay += abufi.bytes;
286
    }
287 52b541ad Vitor Sessak
    /* subtract time represented by the number of bytes in the audio fifo */
288 45dd5c69 Fabrice Bellard
    cur_time -= (bdelay * 1000000LL) / (s->sample_rate * s->channels);
289
290
    /* convert to wanted units */
291 0a7b514f Luca Abeni
    pkt->pts = cur_time;
292 45dd5c69 Fabrice Bellard
293 1de1cce2 Philip Gladstone
    if (s->flip_left && s->channels == 2) {
294
        int i;
295
        short *p = (short *) pkt->data;
296
297
        for (i = 0; i < ret; i += 4) {
298
            *p = ~*p;
299
            p += 2;
300
        }
301
    }
302 4972b26f Fabrice Bellard
    return 0;
303
}
304
305
static int audio_read_close(AVFormatContext *s1)
306
{
307
    AudioData *s = s1->priv_data;
308
309
    audio_close(s);
310
    return 0;
311
}
312
313 50383e88 Ramiro Polla
#ifdef CONFIG_OSS_DEMUXER
314
AVInputFormat oss_demuxer = {
315 1156c6b0 Ramiro Polla
    "oss",
316 c57c4897 Benoit Fouet
    NULL_IF_CONFIG_SMALL("Open Sound System capture"),
317 c9a65ca8 Fabrice Bellard
    sizeof(AudioData),
318
    NULL,
319
    audio_read_header,
320
    audio_read_packet,
321
    audio_read_close,
322 bb76a117 Måns Rullgård
    .flags = AVFMT_NOFILE,
323 c9a65ca8 Fabrice Bellard
};
324 ff70e601 Måns Rullgård
#endif
325 c9a65ca8 Fabrice Bellard
326 50383e88 Ramiro Polla
#ifdef CONFIG_OSS_MUXER
327
AVOutputFormat oss_muxer = {
328 1156c6b0 Ramiro Polla
    "oss",
329 c57c4897 Benoit Fouet
    NULL_IF_CONFIG_SMALL("Open Sound System playback"),
330 4972b26f Fabrice Bellard
    "",
331
    "",
332 c9a65ca8 Fabrice Bellard
    sizeof(AudioData),
333 4972b26f Fabrice Bellard
    /* XXX: we make the assumption that the soundcard accepts this format */
334
    /* XXX: find better solution with "preinit" method, needed also in
335
       other formats */
336
#ifdef WORDS_BIGENDIAN
337
    CODEC_ID_PCM_S16BE,
338
#else
339
    CODEC_ID_PCM_S16LE,
340
#endif
341
    CODEC_ID_NONE,
342
    audio_write_header,
343
    audio_write_packet,
344
    audio_write_trailer,
345 bb76a117 Måns Rullgård
    .flags = AVFMT_NOFILE,
346 de6d9b64 Fabrice Bellard
};
347 ff70e601 Måns Rullgård
#endif