oss.c 3.88 KB
Newer Older
Fabrice Bellard's avatar
Fabrice Bellard committed
1 2
/*
 * Linux audio play and grab interface
3
 * Copyright (c) 2000, 2001 Fabrice Bellard
Fabrice Bellard's avatar
Fabrice Bellard committed
4
 *
5 6 7
 * This file is part of FFmpeg.
 *
 * FFmpeg is free software; you can redistribute it and/or
8 9
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
10
 * version 2.1 of the License, or (at your option) any later version.
Fabrice Bellard's avatar
Fabrice Bellard committed
11
 *
12
 * FFmpeg is distributed in the hope that it will be useful,
Fabrice Bellard's avatar
Fabrice Bellard committed
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
Fabrice Bellard's avatar
Fabrice Bellard committed
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
Fabrice Bellard's avatar
Fabrice Bellard committed
20
 */
Fabrice Bellard's avatar
Fabrice Bellard committed
21

22
#include "config.h"
23

Fabrice Bellard's avatar
Fabrice Bellard committed
24
#include <string.h>
25

26
#if HAVE_UNISTD_H
Fabrice Bellard's avatar
Fabrice Bellard committed
27
#include <unistd.h>
28
#endif
Fabrice Bellard's avatar
Fabrice Bellard committed
29 30
#include <fcntl.h>
#include <sys/ioctl.h>
31
#include <sys/soundcard.h>
Fabrice Bellard's avatar
Fabrice Bellard committed
32

33
#include "libavutil/log.h"
34

35
#include "libavcodec/avcodec.h"
36
#include "avdevice.h"
37

38
#include "oss.h"
39

40 41
int ff_oss_audio_open(AVFormatContext *s1, int is_output,
                      const char *audio_device)
Fabrice Bellard's avatar
Fabrice Bellard committed
42
{
43
    OSSAudioData *s = s1->priv_data;
44
    int audio_fd;
Fabrice Bellard's avatar
Fabrice Bellard committed
45
    int tmp, err;
46
    char *flip = getenv("AUDIO_FLIP_LEFT");
Fabrice Bellard's avatar
Fabrice Bellard committed
47

48
    if (is_output)
49
        audio_fd = avpriv_open(audio_device, O_WRONLY);
Fabrice Bellard's avatar
Fabrice Bellard committed
50
    else
51
        audio_fd = avpriv_open(audio_device, O_RDONLY);
Fabrice Bellard's avatar
Fabrice Bellard committed
52
    if (audio_fd < 0) {
53
        av_log(s1, AV_LOG_ERROR, "%s: %s\n", audio_device, av_err2str(AVERROR(errno)));
54
        return AVERROR(EIO);
Fabrice Bellard's avatar
Fabrice Bellard committed
55 56
    }

57 58 59 60
    if (flip && *flip == '1') {
        s->flip_left = 1;
    }

Fabrice Bellard's avatar
Fabrice Bellard committed
61
    /* non blocking mode */
62 63
    if (!is_output) {
        if (fcntl(audio_fd, F_SETFL, O_NONBLOCK) < 0) {
64
            av_log(s1, AV_LOG_WARNING, "%s: Could not enable non block mode (%s)\n", audio_device, av_err2str(AVERROR(errno)));
65 66
        }
    }
Fabrice Bellard's avatar
Fabrice Bellard committed
67

68
    s->frame_size = OSS_AUDIO_BLOCK_SIZE;
Fabrice Bellard's avatar
Fabrice Bellard committed
69

70 71
#define CHECK_IOCTL_ERROR(event)                                              \
    if (err < 0) {                                                            \
72
        av_log(s1, AV_LOG_ERROR, #event ": %s\n", av_err2str(AVERROR(errno)));\
73 74 75 76 77 78
        goto fail;                                                            \
    }

    /* select format : favour native format
     * We don't CHECK_IOCTL_ERROR here because even if failed OSS still may be
     * usable. If OSS is not usable the SNDCTL_DSP_SETFMTS later is going to
79
     * fail anyway. */
80
    err = ioctl(audio_fd, SNDCTL_DSP_GETFMTS, &tmp);
81
    if (err < 0) {
82
        av_log(s1, AV_LOG_WARNING, "SNDCTL_DSP_GETFMTS: %s\n", av_err2str(AVERROR(errno)));
83
    }
84

85
#if HAVE_BIGENDIAN
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
    if (tmp & AFMT_S16_BE) {
        tmp = AFMT_S16_BE;
    } else if (tmp & AFMT_S16_LE) {
        tmp = AFMT_S16_LE;
    } else {
        tmp = 0;
    }
#else
    if (tmp & AFMT_S16_LE) {
        tmp = AFMT_S16_LE;
    } else if (tmp & AFMT_S16_BE) {
        tmp = AFMT_S16_BE;
    } else {
        tmp = 0;
    }
#endif

    switch(tmp) {
    case AFMT_S16_LE:
105
        s->codec_id = AV_CODEC_ID_PCM_S16LE;
106 107
        break;
    case AFMT_S16_BE:
108
        s->codec_id = AV_CODEC_ID_PCM_S16BE;
109 110
        break;
    default:
111
        av_log(s1, AV_LOG_ERROR, "Soundcard does not support 16 bit sample format\n");
112
        close(audio_fd);
113
        return AVERROR(EIO);
114 115
    }
    err=ioctl(audio_fd, SNDCTL_DSP_SETFMT, &tmp);
116
    CHECK_IOCTL_ERROR(SNDCTL_DSP_SETFMTS)
117

118 119
    tmp = (s->channels == 2);
    err = ioctl(audio_fd, SNDCTL_DSP_STEREO, &tmp);
120
    CHECK_IOCTL_ERROR(SNDCTL_DSP_STEREO)
121

122 123
    tmp = s->sample_rate;
    err = ioctl(audio_fd, SNDCTL_DSP_SPEED, &tmp);
124
    CHECK_IOCTL_ERROR(SNDCTL_DSP_SPEED)
125
    s->sample_rate = tmp; /* store real sample rate */
Fabrice Bellard's avatar
Fabrice Bellard committed
126 127 128 129 130
    s->fd = audio_fd;

    return 0;
 fail:
    close(audio_fd);
131
    return AVERROR(EIO);
132
#undef CHECK_IOCTL_ERROR
Fabrice Bellard's avatar
Fabrice Bellard committed
133 134
}

135
int ff_oss_audio_close(OSSAudioData *s)
Fabrice Bellard's avatar
Fabrice Bellard committed
136 137
{
    close(s->fd);
138 139
    return 0;
}