libavdevice/oss.c
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;
 }