~ubuntu-branches/debian/experimental/libav/experimental

« back to all changes in this revision

Viewing changes to libavdevice/oss_audio.c

  • Committer: Package Import Robot
  • Author(s): Reinhard Tartler
  • Date: 2014-08-10 09:45:02 UTC
  • mfrom: (1.3.14)
  • mto: (1.3.16)
  • mto: This revision was merged to the branch mainline in revision 41.
  • Revision ID: package-import@ubuntu.com-20140810094502-mmdupdml8tixclg2
Tags: upstream-11~alpha1
ImportĀ upstreamĀ versionĀ 11~alpha1

Show diffs side-by-side

added added

removed removed

Lines of Context:
20
20
 */
21
21
 
22
22
#include "config.h"
23
 
#include <stdlib.h>
24
 
#include <stdio.h>
25
 
#include <stdint.h>
 
23
 
26
24
#include <string.h>
27
 
#include <errno.h>
 
25
 
28
26
#if HAVE_SOUNDCARD_H
29
27
#include <soundcard.h>
30
28
#else
31
29
#include <sys/soundcard.h>
32
30
#endif
 
31
 
33
32
#include <unistd.h>
34
33
#include <fcntl.h>
35
34
#include <sys/ioctl.h>
36
35
 
37
 
#include "libavutil/internal.h"
38
36
#include "libavutil/log.h"
39
 
#include "libavutil/opt.h"
40
 
#include "libavutil/time.h"
 
37
 
41
38
#include "libavcodec/avcodec.h"
 
39
 
42
40
#include "libavformat/avformat.h"
43
 
#include "libavformat/internal.h"
44
 
 
45
 
#define AUDIO_BLOCK_SIZE 4096
46
 
 
47
 
typedef struct {
48
 
    AVClass *class;
49
 
    int fd;
50
 
    int sample_rate;
51
 
    int channels;
52
 
    int frame_size; /* in bytes ! */
53
 
    enum AVCodecID codec_id;
54
 
    unsigned int flip_left : 1;
55
 
    uint8_t buffer[AUDIO_BLOCK_SIZE];
56
 
    int buffer_ptr;
57
 
} AudioData;
58
 
 
59
 
static int audio_open(AVFormatContext *s1, int is_output, const char *audio_device)
 
41
 
 
42
#include "oss_audio.h"
 
43
 
 
44
int ff_oss_audio_open(AVFormatContext *s1, int is_output,
 
45
                      const char *audio_device)
60
46
{
61
 
    AudioData *s = s1->priv_data;
 
47
    OSSAudioData *s = s1->priv_data;
62
48
    int audio_fd;
63
49
    int tmp, err;
64
50
    char *flip = getenv("AUDIO_FLIP_LEFT");
80
66
    if (!is_output)
81
67
        fcntl(audio_fd, F_SETFL, O_NONBLOCK);
82
68
 
83
 
    s->frame_size = AUDIO_BLOCK_SIZE;
 
69
    s->frame_size = OSS_AUDIO_BLOCK_SIZE;
84
70
 
85
71
    /* select format : favour native format */
86
72
    err = ioctl(audio_fd, SNDCTL_DSP_GETFMTS, &tmp);
143
129
    return AVERROR(EIO);
144
130
}
145
131
 
146
 
static int audio_close(AudioData *s)
 
132
int ff_oss_audio_close(OSSAudioData *s)
147
133
{
148
134
    close(s->fd);
149
135
    return 0;
150
136
}
151
 
 
152
 
/* sound output support */
153
 
static 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
 
 
170
 
static 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
 
 
197
 
static 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
 
 
207
 
static int audio_read_header(AVFormatContext *s1)
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
 
 
233
 
static 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
 
 
276
 
static 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
285
 
static const AVOption options[] = {
286
 
    { "sample_rate", "", offsetof(AudioData, sample_rate), AV_OPT_TYPE_INT, {.i64 = 48000}, 1, INT_MAX, AV_OPT_FLAG_DECODING_PARAM },
287
 
    { "channels",    "", offsetof(AudioData, channels),    AV_OPT_TYPE_INT, {.i64 = 2},     1, INT_MAX, AV_OPT_FLAG_DECODING_PARAM },
288
 
    { NULL },
289
 
};
290
 
 
291
 
static 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
 
 
298
 
AVInputFormat ff_oss_demuxer = {
299
 
    .name           = "oss",
300
 
    .long_name      = NULL_IF_CONFIG_SMALL("OSS (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
311
 
AVOutputFormat ff_oss_muxer = {
312
 
    .name           = "oss",
313
 
    .long_name      = NULL_IF_CONFIG_SMALL("OSS (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(AV_CODEC_ID_PCM_S16BE, AV_CODEC_ID_PCM_S16LE),
319
 
    .video_codec    = AV_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