[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