Skip to content
Snippets Groups Projects
oss_audio.c 3.84 KiB
Newer Older
  • Learn to ignore specific revisions
  • Fabrice Bellard's avatar
    Fabrice Bellard committed
    /*
     * Linux audio play and grab interface
    
     * Copyright (c) 2000, 2001 Fabrice Bellard
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
     *
    
     * This file is part of FFmpeg.
     *
     * FFmpeg is free software; you can redistribute it and/or
    
     * modify it under the terms of the GNU Lesser General Public
     * License as published by the Free Software Foundation; either
    
     * version 2.1 of the License, or (at your option) any later version.
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
     *
    
     * FFmpeg is distributed in the hope that it will be useful,
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
     * but WITHOUT ANY WARRANTY; without even the implied warranty of
    
     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     * Lesser General Public License for more details.
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
     *
    
     * You should have received a copy of the GNU Lesser General Public
    
     * License along with FFmpeg; if not, write to the Free Software
    
     * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
     */
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    
    
    #include "config.h"
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    #include <string.h>
    
    #if HAVE_SOUNDCARD_H
    
    #include <sys/soundcard.h>
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    #include <unistd.h>
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    #include <fcntl.h>
    #include <sys/ioctl.h>
    
    
    #include "libavutil/log.h"
    
    #include "libavcodec/avcodec.h"
    
    #include "oss_audio.h"
    
    int ff_oss_audio_open(AVFormatContext *s1, int is_output,
                          const char *audio_device)
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    {
    
        OSSAudioData *s = s1->priv_data;
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
        int tmp, err;
    
        char *flip = getenv("AUDIO_FLIP_LEFT");
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    
    
            audio_fd = avpriv_open(audio_device, O_WRONLY);
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
        else
    
            audio_fd = avpriv_open(audio_device, O_RDONLY);
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
        if (audio_fd < 0) {
    
            av_log(s1, AV_LOG_ERROR, "%s: %s\n", audio_device, strerror(errno));
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
        }
    
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
        /* non blocking mode */
    
        if (!is_output) {
            if (fcntl(audio_fd, F_SETFL, O_NONBLOCK) < 0) {
                av_log(s1, AV_LOG_WARNING, "%s: Could not enable non block mode (%s)\n", audio_device, strerror(errno));
            }
        }
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    
    
        s->frame_size = OSS_AUDIO_BLOCK_SIZE;
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    
    
    #define CHECK_IOCTL_ERROR(event)                                              \
        if (err < 0) {                                                            \
            av_log(s1, AV_LOG_ERROR, #event ": %s\n", strerror(errno));         \
            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
         * fail anyway. `err =` kept to eliminate compiler warning. */
    
        err = ioctl(audio_fd, SNDCTL_DSP_GETFMTS, &tmp);
    
    #if HAVE_BIGENDIAN
    
        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:
    
            s->codec_id = AV_CODEC_ID_PCM_S16LE;
    
            s->codec_id = AV_CODEC_ID_PCM_S16BE;
    
            av_log(s1, AV_LOG_ERROR, "Soundcard does not support 16 bit sample format\n");
    
        }
        err=ioctl(audio_fd, SNDCTL_DSP_SETFMT, &tmp);
    
        CHECK_IOCTL_ERROR(SNDCTL_DSP_SETFMTS)
    
        tmp = (s->channels == 2);
        err = ioctl(audio_fd, SNDCTL_DSP_STEREO, &tmp);
    
        CHECK_IOCTL_ERROR(SNDCTL_DSP_STEREO)
    
        tmp = s->sample_rate;
        err = ioctl(audio_fd, SNDCTL_DSP_SPEED, &tmp);
    
        CHECK_IOCTL_ERROR(SNDCTL_DSP_SPEED)
    
        s->sample_rate = tmp; /* store real sample rate */
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
        s->fd = audio_fd;
    
        return 0;
     fail:
        close(audio_fd);
    
    #undef CHECK_IOCTL_ERROR
    
    int ff_oss_audio_close(OSSAudioData *s)
    
    Fabrice Bellard's avatar
    Fabrice Bellard committed
    {
        close(s->fd);