00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <stdint.h>
00023 #include <sndio.h>
00024
00025 #include "avdevice.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 }