xref: /third_party/ffmpeg/libavdevice/oss.c (revision cabdff1a)
1cabdff1aSopenharmony_ci/*
2cabdff1aSopenharmony_ci * Linux audio play and grab interface
3cabdff1aSopenharmony_ci * Copyright (c) 2000, 2001 Fabrice Bellard
4cabdff1aSopenharmony_ci *
5cabdff1aSopenharmony_ci * This file is part of FFmpeg.
6cabdff1aSopenharmony_ci *
7cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or
8cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public
9cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either
10cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version.
11cabdff1aSopenharmony_ci *
12cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful,
13cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of
14cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15cabdff1aSopenharmony_ci * Lesser General Public License for more details.
16cabdff1aSopenharmony_ci *
17cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public
18cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software
19cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20cabdff1aSopenharmony_ci */
21cabdff1aSopenharmony_ci
22cabdff1aSopenharmony_ci#include "config.h"
23cabdff1aSopenharmony_ci
24cabdff1aSopenharmony_ci#include <string.h>
25cabdff1aSopenharmony_ci
26cabdff1aSopenharmony_ci#if HAVE_UNISTD_H
27cabdff1aSopenharmony_ci#include <unistd.h>
28cabdff1aSopenharmony_ci#endif
29cabdff1aSopenharmony_ci#include <fcntl.h>
30cabdff1aSopenharmony_ci#include <sys/ioctl.h>
31cabdff1aSopenharmony_ci#include <sys/soundcard.h>
32cabdff1aSopenharmony_ci
33cabdff1aSopenharmony_ci#include "libavutil/log.h"
34cabdff1aSopenharmony_ci
35cabdff1aSopenharmony_ci#include "avdevice.h"
36cabdff1aSopenharmony_ci
37cabdff1aSopenharmony_ci#include "oss.h"
38cabdff1aSopenharmony_ci
39cabdff1aSopenharmony_ciint ff_oss_audio_open(AVFormatContext *s1, int is_output,
40cabdff1aSopenharmony_ci                      const char *audio_device)
41cabdff1aSopenharmony_ci{
42cabdff1aSopenharmony_ci    OSSAudioData *s = s1->priv_data;
43cabdff1aSopenharmony_ci    int audio_fd;
44cabdff1aSopenharmony_ci    int tmp, err;
45cabdff1aSopenharmony_ci    char *flip = getenv("AUDIO_FLIP_LEFT");
46cabdff1aSopenharmony_ci
47cabdff1aSopenharmony_ci    if (is_output)
48cabdff1aSopenharmony_ci        audio_fd = avpriv_open(audio_device, O_WRONLY);
49cabdff1aSopenharmony_ci    else
50cabdff1aSopenharmony_ci        audio_fd = avpriv_open(audio_device, O_RDONLY);
51cabdff1aSopenharmony_ci    if (audio_fd < 0) {
52cabdff1aSopenharmony_ci        av_log(s1, AV_LOG_ERROR, "%s: %s\n", audio_device, av_err2str(AVERROR(errno)));
53cabdff1aSopenharmony_ci        return AVERROR(EIO);
54cabdff1aSopenharmony_ci    }
55cabdff1aSopenharmony_ci
56cabdff1aSopenharmony_ci    if (flip && *flip == '1') {
57cabdff1aSopenharmony_ci        s->flip_left = 1;
58cabdff1aSopenharmony_ci    }
59cabdff1aSopenharmony_ci
60cabdff1aSopenharmony_ci    /* non blocking mode */
61cabdff1aSopenharmony_ci    if (!is_output) {
62cabdff1aSopenharmony_ci        if (fcntl(audio_fd, F_SETFL, O_NONBLOCK) < 0) {
63cabdff1aSopenharmony_ci            av_log(s1, AV_LOG_WARNING, "%s: Could not enable non block mode (%s)\n", audio_device, av_err2str(AVERROR(errno)));
64cabdff1aSopenharmony_ci        }
65cabdff1aSopenharmony_ci    }
66cabdff1aSopenharmony_ci
67cabdff1aSopenharmony_ci    s->frame_size = OSS_AUDIO_BLOCK_SIZE;
68cabdff1aSopenharmony_ci
69cabdff1aSopenharmony_ci#define CHECK_IOCTL_ERROR(event)                                              \
70cabdff1aSopenharmony_ci    if (err < 0) {                                                            \
71cabdff1aSopenharmony_ci        av_log(s1, AV_LOG_ERROR, #event ": %s\n", av_err2str(AVERROR(errno)));\
72cabdff1aSopenharmony_ci        goto fail;                                                            \
73cabdff1aSopenharmony_ci    }
74cabdff1aSopenharmony_ci
75cabdff1aSopenharmony_ci    /* select format : favour native format
76cabdff1aSopenharmony_ci     * We don't CHECK_IOCTL_ERROR here because even if failed OSS still may be
77cabdff1aSopenharmony_ci     * usable. If OSS is not usable the SNDCTL_DSP_SETFMTS later is going to
78cabdff1aSopenharmony_ci     * fail anyway. */
79cabdff1aSopenharmony_ci    err = ioctl(audio_fd, SNDCTL_DSP_GETFMTS, &tmp);
80cabdff1aSopenharmony_ci    if (err < 0) {
81cabdff1aSopenharmony_ci        av_log(s1, AV_LOG_WARNING, "SNDCTL_DSP_GETFMTS: %s\n", av_err2str(AVERROR(errno)));
82cabdff1aSopenharmony_ci    }
83cabdff1aSopenharmony_ci
84cabdff1aSopenharmony_ci#if HAVE_BIGENDIAN
85cabdff1aSopenharmony_ci    if (tmp & AFMT_S16_BE) {
86cabdff1aSopenharmony_ci        tmp = AFMT_S16_BE;
87cabdff1aSopenharmony_ci    } else if (tmp & AFMT_S16_LE) {
88cabdff1aSopenharmony_ci        tmp = AFMT_S16_LE;
89cabdff1aSopenharmony_ci    } else {
90cabdff1aSopenharmony_ci        tmp = 0;
91cabdff1aSopenharmony_ci    }
92cabdff1aSopenharmony_ci#else
93cabdff1aSopenharmony_ci    if (tmp & AFMT_S16_LE) {
94cabdff1aSopenharmony_ci        tmp = AFMT_S16_LE;
95cabdff1aSopenharmony_ci    } else if (tmp & AFMT_S16_BE) {
96cabdff1aSopenharmony_ci        tmp = AFMT_S16_BE;
97cabdff1aSopenharmony_ci    } else {
98cabdff1aSopenharmony_ci        tmp = 0;
99cabdff1aSopenharmony_ci    }
100cabdff1aSopenharmony_ci#endif
101cabdff1aSopenharmony_ci
102cabdff1aSopenharmony_ci    switch(tmp) {
103cabdff1aSopenharmony_ci    case AFMT_S16_LE:
104cabdff1aSopenharmony_ci        s->codec_id = AV_CODEC_ID_PCM_S16LE;
105cabdff1aSopenharmony_ci        s->sample_size = 2;
106cabdff1aSopenharmony_ci        break;
107cabdff1aSopenharmony_ci    case AFMT_S16_BE:
108cabdff1aSopenharmony_ci        s->codec_id = AV_CODEC_ID_PCM_S16BE;
109cabdff1aSopenharmony_ci        s->sample_size = 2;
110cabdff1aSopenharmony_ci        break;
111cabdff1aSopenharmony_ci    default:
112cabdff1aSopenharmony_ci        av_log(s1, AV_LOG_ERROR, "Soundcard does not support 16 bit sample format\n");
113cabdff1aSopenharmony_ci        close(audio_fd);
114cabdff1aSopenharmony_ci        return AVERROR(EIO);
115cabdff1aSopenharmony_ci    }
116cabdff1aSopenharmony_ci    err=ioctl(audio_fd, SNDCTL_DSP_SETFMT, &tmp);
117cabdff1aSopenharmony_ci    CHECK_IOCTL_ERROR(SNDCTL_DSP_SETFMT)
118cabdff1aSopenharmony_ci
119cabdff1aSopenharmony_ci    tmp = (s->channels == 2);
120cabdff1aSopenharmony_ci    err = ioctl(audio_fd, SNDCTL_DSP_STEREO, &tmp);
121cabdff1aSopenharmony_ci    CHECK_IOCTL_ERROR(SNDCTL_DSP_STEREO)
122cabdff1aSopenharmony_ci
123cabdff1aSopenharmony_ci    tmp = s->sample_rate;
124cabdff1aSopenharmony_ci    err = ioctl(audio_fd, SNDCTL_DSP_SPEED, &tmp);
125cabdff1aSopenharmony_ci    CHECK_IOCTL_ERROR(SNDCTL_DSP_SPEED)
126cabdff1aSopenharmony_ci    s->sample_rate = tmp; /* store real sample rate */
127cabdff1aSopenharmony_ci    s->fd = audio_fd;
128cabdff1aSopenharmony_ci
129cabdff1aSopenharmony_ci    return 0;
130cabdff1aSopenharmony_ci fail:
131cabdff1aSopenharmony_ci    close(audio_fd);
132cabdff1aSopenharmony_ci    return AVERROR(EIO);
133cabdff1aSopenharmony_ci#undef CHECK_IOCTL_ERROR
134cabdff1aSopenharmony_ci}
135cabdff1aSopenharmony_ci
136cabdff1aSopenharmony_ciint ff_oss_audio_close(OSSAudioData *s)
137cabdff1aSopenharmony_ci{
138cabdff1aSopenharmony_ci    close(s->fd);
139cabdff1aSopenharmony_ci    return 0;
140cabdff1aSopenharmony_ci}
141