[FFmpeg-devel] [PATCH] Add support for sndio to libavdevice
Stefano Sabatini
stefano.sabatini-lala
Tue Aug 10 22:21:47 CEST 2010
On date Sunday 2010-08-08 15:12:31 -0400, Brad encoded:
[...]
> Index: libavdevice/sndio-common.c
> ===================================================================
> --- libavdevice/sndio-common.c (revision 0)
> +++ libavdevice/sndio-common.c (revision 0)
> @@ -0,0 +1,112 @@
> +/*
> + * sndio play and grab interface
> + * Copyright (c) 2010 Jacob Meuser
> + *
> + * 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.
> + *
> + * FFmpeg is distributed in the hope that it will be useful,
> + * 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.
> + *
> + * 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
> + */
> +
> +#include <sndio.h>
> +#include "libavformat/avformat.h"
> +
> +#include "sndio-common.h"
> +
> +static void movecb(void *addr, int delta)
> +{
> + AudioData *s = addr;
> +
> + s->hwpos += delta * s->channels * s->bps;
> +}
> +
> +av_cold int ff_sndio_open(AVFormatContext *s1, int is_output,
> + const char *audio_device)
> +{
> + AudioData *s = s1->priv_data;
> + struct sio_hdl *hdl = NULL;
> + struct sio_par par;
> +
> + hdl = sio_open(audio_device, is_output ? SIO_PLAY : SIO_REC, 0);
> + if (!hdl) {
> + av_log(s1, AV_LOG_ERROR, "could not open sndio device\n");
> + return AVERROR(EIO);
> + }
> +
> + sio_initpar(&par);
> +
> + par.bits = 16;
> + par.sig = 1;
> + par.le = SIO_LE_NATIVE;
> +
> + if (is_output)
> + par.pchan = s->channels;
> + else
> + par.rchan = s->channels;
par.pchan = is_output ? ...
-3 lines
> + par.rate = s->sample_rate;
> +
> + if (!sio_setpar(hdl, &par) || !sio_getpar(hdl, &par)) {
> + av_log(s1, AV_LOG_ERROR, "impossible to set sndio parameters\n");
Capitalize the first character here and below, possibly more
consistent with the other FFmpeg log messages.
> + goto fail;
> + }
> +
> + if (par.bits != 16 || par.sig != 1 || par.le != SIO_LE_NATIVE ||
> + (is_output && (par.pchan != s->channels)) ||
> + (!is_output && (par.rchan != s->channels)) ||
> + (par.rate != s->sample_rate)) {
> + av_log(s1, AV_LOG_ERROR, "could not set appropriate sndio parameters\n");
> + goto fail;
> + }
> +
> + s->buffer_size = par.round * par.bps *
> + (is_output ? par.pchan : par.rchan);
> +
> + s->buffer = av_malloc(s->buffer_size);
> + if (!s->buffer) {
> + av_log(s1, AV_LOG_ERROR, "could not allocate buffer\n");
> + goto fail;
> + }
> +
> + s->codec_id = par.le ? CODEC_ID_PCM_S16LE : CODEC_ID_PCM_S16BE;
> + s->channels = is_output ? par.pchan : par.rchan;
> + s->sample_rate = par.rate;
> + s->bps = par.bps;
> +
> + sio_onmove(hdl, movecb, s);
> +
> + if (!sio_start(hdl)) {
> + av_log(s1, AV_LOG_ERROR, "could not start sndio\n");
> + goto fail;
> + }
> +
> + s->hdl = hdl;
> +
> + return 0;
> +
> +fail:
> + if (s->buffer)
> + av_free(s->buffer);
> + if (hdl)
> + sio_close(hdl);
> + return AVERROR(EIO);
> +}
> +
> +int ff_sndio_close(AudioData *s)
> +{
> + if (s->buffer)
> + av_free(s->buffer);
> + if (s->hdl)
> + sio_close(s->hdl);
> + return 0;
> +}
> Index: libavdevice/sndio-dec.c
> ===================================================================
> --- libavdevice/sndio-dec.c (revision 0)
> +++ libavdevice/sndio-dec.c (revision 0)
[...]
> +static int audio_read_packet(AVFormatContext *s1, AVPacket *pkt)
> +{
> + AudioData *s = s1->priv_data;
> + int ret, bdelay;
> + int64_t cur_time;
> +
> + if ((ret=av_new_packet(pkt, s->buffer_size)) < 0)
nit: if ((ret = av_new_packet ...
[...]
> +AVInputFormat sndio_demuxer = {
> + "sndio",
> + NULL_IF_CONFIG_SMALL("sndio audio capture"),
> + sizeof(AudioData),
> + NULL,
> + audio_read_header,
> + audio_read_packet,
> + audio_read_close,
> + .flags = AVFMT_NOFILE,
> +};
Possibly always use designated inited fields, I mean:
.name = ...
.long_name = ...
.init = ...
.blah = ...
...
> Index: libavdevice/sndio-common.h
> ===================================================================
> --- libavdevice/sndio-common.h (revision 0)
> +++ libavdevice/sndio-common.h (revision 0)
[...]
> +#ifndef AVDEVICE_SNDIO_COMMON_H
> +#define AVDEVICE_SNDIO_COMMON_H
> +
> +#include <sndio.h>
> +#include "config.h"
> +#include "libavformat/avformat.h"
> +
> +/* XXX: we make the assumption that the soundcard accepts this format */
> +/* XXX: find better solution with "preinit" method, needed also in
> + other formats */
> +#if HAVE_BIGENDIAN
> +#define DEFAULT_CODEC_ID CODEC_ID_PCM_S16BE
> +#else
> +#define DEFAULT_CODEC_ID CODEC_ID_PCM_S16LE
> +#endif
possibly better not add a level of indirection, do this in the device
definition, also we may define a macro (e.g. in
libavformat/internal.h) for this if it is used in other parts of FFmpeg:
#if AV_HAVE_BIGENDIAN
# define CODEC_ID_NE(be, le) CODEC_ID_##be
#else
# define CODEC_ID_NE(be, le) CODEC_ID_##le
#endif
AVOutputFormat sndio_muxer = {
...
.default_codec = CODEC_ID_NE(PCM_S16BE, PCM_S16LE),
...
}
[...]
> +AVOutputFormat sndio_muxer = {
> + "sndio",
> + NULL_IF_CONFIG_SMALL("sndio audio playback"),
> + "",
> + "",
> + sizeof(AudioData),
> + DEFAULT_CODEC_ID,
> + CODEC_ID_NONE,
> + audio_write_header,
> + audio_write_packet,
> + audio_write_trailer,
> + .flags = AVFMT_NOFILE,
Same as before.
[...]
Regards.
--
FFmpeg = Furious and Foolish Miracolous Pacific Eretic Gorilla
More information about the ffmpeg-devel
mailing list