de6d9b64 |
/*
* Linux audio play and grab interface |
406792e7 |
* Copyright (c) 2000, 2001 Fabrice Bellard |
de6d9b64 |
* |
b78e7197 |
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or |
19720f15 |
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either |
b78e7197 |
* version 2.1 of the License, or (at your option) any later version. |
de6d9b64 |
* |
b78e7197 |
* FFmpeg is distributed in the hope that it will be useful, |
de6d9b64 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
19720f15 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details. |
de6d9b64 |
* |
19720f15 |
* You should have received a copy of the GNU Lesser General Public |
b78e7197 |
* License along with FFmpeg; if not, write to the Free Software |
5509bffa |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
de6d9b64 |
*/ |
8be1c656 |
|
4f786086 |
#include "config.h" |
d6e1d371 |
|
de6d9b64 |
#include <string.h> |
d6e1d371 |
|
0dbcecc8 |
#if HAVE_UNISTD_H |
de6d9b64 |
#include <unistd.h> |
0dbcecc8 |
#endif |
de6d9b64 |
#include <fcntl.h>
#include <sys/ioctl.h> |
b586903a |
#include <sys/soundcard.h> |
de6d9b64 |
|
245976da |
#include "libavutil/log.h" |
d6e1d371 |
|
245976da |
#include "libavcodec/avcodec.h" |
6b899e16 |
#include "avdevice.h" |
4f786086 |
|
8d26c193 |
#include "oss.h" |
4972b26f |
|
d6e1d371 |
int ff_oss_audio_open(AVFormatContext *s1, int is_output,
const char *audio_device) |
de6d9b64 |
{ |
d6e1d371 |
OSSAudioData *s = s1->priv_data; |
4972b26f |
int audio_fd; |
de6d9b64 |
int tmp, err; |
1de1cce2 |
char *flip = getenv("AUDIO_FLIP_LEFT"); |
de6d9b64 |
|
4972b26f |
if (is_output) |
71bf6b41 |
audio_fd = avpriv_open(audio_device, O_WRONLY); |
de6d9b64 |
else |
71bf6b41 |
audio_fd = avpriv_open(audio_device, O_RDONLY); |
de6d9b64 |
if (audio_fd < 0) { |
afbaa9a7 |
av_log(s1, AV_LOG_ERROR, "%s: %s\n", audio_device, av_err2str(AVERROR(errno))); |
6f3e0b21 |
return AVERROR(EIO); |
de6d9b64 |
}
|
1de1cce2 |
if (flip && *flip == '1') {
s->flip_left = 1;
}
|
de6d9b64 |
/* non blocking mode */ |
1ba0d9b5 |
if (!is_output) {
if (fcntl(audio_fd, F_SETFL, O_NONBLOCK) < 0) { |
afbaa9a7 |
av_log(s1, AV_LOG_WARNING, "%s: Could not enable non block mode (%s)\n", audio_device, av_err2str(AVERROR(errno))); |
1ba0d9b5 |
}
} |
de6d9b64 |
|
d6e1d371 |
s->frame_size = OSS_AUDIO_BLOCK_SIZE; |
de6d9b64 |
|
69c7aad4 |
#define CHECK_IOCTL_ERROR(event) \
if (err < 0) { \ |
afbaa9a7 |
av_log(s1, AV_LOG_ERROR, #event ": %s\n", av_err2str(AVERROR(errno)));\ |
69c7aad4 |
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 |
b7c77912 |
* fail anyway. */ |
4972b26f |
err = ioctl(audio_fd, SNDCTL_DSP_GETFMTS, &tmp); |
39133efc |
if (err < 0) { |
afbaa9a7 |
av_log(s1, AV_LOG_WARNING, "SNDCTL_DSP_GETFMTS: %s\n", av_err2str(AVERROR(errno))); |
39133efc |
} |
115329f1 |
|
63613fe6 |
#if HAVE_BIGENDIAN |
4972b26f |
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: |
36ef5369 |
s->codec_id = AV_CODEC_ID_PCM_S16LE; |
4972b26f |
break;
case AFMT_S16_BE: |
36ef5369 |
s->codec_id = AV_CODEC_ID_PCM_S16BE; |
4972b26f |
break;
default: |
0c26e964 |
av_log(s1, AV_LOG_ERROR, "Soundcard does not support 16 bit sample format\n"); |
4972b26f |
close(audio_fd); |
6f3e0b21 |
return AVERROR(EIO); |
4972b26f |
}
err=ioctl(audio_fd, SNDCTL_DSP_SETFMT, &tmp); |
69c7aad4 |
CHECK_IOCTL_ERROR(SNDCTL_DSP_SETFMTS) |
115329f1 |
|
4972b26f |
tmp = (s->channels == 2);
err = ioctl(audio_fd, SNDCTL_DSP_STEREO, &tmp); |
69c7aad4 |
CHECK_IOCTL_ERROR(SNDCTL_DSP_STEREO) |
115329f1 |
|
4972b26f |
tmp = s->sample_rate;
err = ioctl(audio_fd, SNDCTL_DSP_SPEED, &tmp); |
69c7aad4 |
CHECK_IOCTL_ERROR(SNDCTL_DSP_SPEED) |
4972b26f |
s->sample_rate = tmp; /* store real sample rate */ |
de6d9b64 |
s->fd = audio_fd;
return 0;
fail:
close(audio_fd); |
6f3e0b21 |
return AVERROR(EIO); |
69c7aad4 |
#undef CHECK_IOCTL_ERROR |
de6d9b64 |
}
|
d6e1d371 |
int ff_oss_audio_close(OSSAudioData *s) |
de6d9b64 |
{
close(s->fd); |
4972b26f |
return 0;
} |