Libav 0.7.1
|
00001 /* 00002 * sndio play and grab interface 00003 * Copyright (c) 2010 Jacob Meuser 00004 * 00005 * This file is part of Libav. 00006 * 00007 * Libav is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU Lesser General Public 00009 * License as published by the Free Software Foundation; either 00010 * version 2.1 of the License, or (at your option) any later version. 00011 * 00012 * Libav is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 * Lesser General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU Lesser General Public 00018 * License along with Libav; if not, write to the Free Software 00019 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00020 */ 00021 00022 #include <stdint.h> 00023 #include <sndio.h> 00024 00025 #include "libavformat/avformat.h" 00026 00027 #include "sndio_common.h" 00028 00029 static inline void movecb(void *addr, int delta) 00030 { 00031 SndioData *s = addr; 00032 00033 s->hwpos += delta * s->channels * s->bps; 00034 } 00035 00036 av_cold int ff_sndio_open(AVFormatContext *s1, int is_output, 00037 const char *audio_device) 00038 { 00039 SndioData *s = s1->priv_data; 00040 struct sio_hdl *hdl; 00041 struct sio_par par; 00042 00043 hdl = sio_open(audio_device, is_output ? SIO_PLAY : SIO_REC, 0); 00044 if (!hdl) { 00045 av_log(s1, AV_LOG_ERROR, "Could not open sndio device\n"); 00046 return AVERROR(EIO); 00047 } 00048 00049 sio_initpar(&par); 00050 00051 par.bits = 16; 00052 par.sig = 1; 00053 par.le = SIO_LE_NATIVE; 00054 00055 if (is_output) 00056 par.pchan = s->channels; 00057 else 00058 par.rchan = s->channels; 00059 par.rate = s->sample_rate; 00060 00061 if (!sio_setpar(hdl, &par) || !sio_getpar(hdl, &par)) { 00062 av_log(s1, AV_LOG_ERROR, "Impossible to set sndio parameters, " 00063 "channels: %d sample rate: %d\n", s->channels, s->sample_rate); 00064 goto fail; 00065 } 00066 00067 if (par.bits != 16 || par.sig != 1 || 00068 (is_output && (par.pchan != s->channels)) || 00069 (!is_output && (par.rchan != s->channels)) || 00070 (par.rate != s->sample_rate)) { 00071 av_log(s1, AV_LOG_ERROR, "Could not set appropriate sndio parameters, " 00072 "channels: %d sample rate: %d\n", s->channels, s->sample_rate); 00073 goto fail; 00074 } 00075 00076 s->buffer_size = par.round * par.bps * 00077 (is_output ? par.pchan : par.rchan); 00078 00079 if (is_output) { 00080 s->buffer = av_malloc(s->buffer_size); 00081 if (!s->buffer) { 00082 av_log(s1, AV_LOG_ERROR, "Could not allocate buffer\n"); 00083 goto fail; 00084 } 00085 } 00086 00087 s->codec_id = par.le ? CODEC_ID_PCM_S16LE : CODEC_ID_PCM_S16BE; 00088 s->channels = is_output ? par.pchan : par.rchan; 00089 s->sample_rate = par.rate; 00090 s->bps = par.bps; 00091 00092 sio_onmove(hdl, movecb, s); 00093 00094 if (!sio_start(hdl)) { 00095 av_log(s1, AV_LOG_ERROR, "Could not start sndio\n"); 00096 goto fail; 00097 } 00098 00099 s->hdl = hdl; 00100 00101 return 0; 00102 00103 fail: 00104 av_freep(&s->buffer); 00105 00106 if (hdl) 00107 sio_close(hdl); 00108 00109 return AVERROR(EIO); 00110 } 00111 00112 int ff_sndio_close(SndioData *s) 00113 { 00114 av_freep(&s->buffer); 00115 00116 if (s->hdl) 00117 sio_close(s->hdl); 00118 00119 return 0; 00120 }