avdevice: Apply a more consistent file naming scheme
authorDiego Biurrun <diego@biurrun.de>
Fri, 27 Mar 2015 11:40:23 +0000 (12:40 +0100)
committerDiego Biurrun <diego@biurrun.de>
Thu, 9 Apr 2015 14:40:12 +0000 (16:40 +0200)
25 files changed:
libavdevice/Makefile
libavdevice/alsa-audio-common.c [deleted file]
libavdevice/alsa-audio-dec.c [deleted file]
libavdevice/alsa-audio-enc.c [deleted file]
libavdevice/alsa-audio.h [deleted file]
libavdevice/alsa.c [new file with mode: 0644]
libavdevice/alsa.h [new file with mode: 0644]
libavdevice/alsa_dec.c [new file with mode: 0644]
libavdevice/alsa_enc.c [new file with mode: 0644]
libavdevice/jack.c [new file with mode: 0644]
libavdevice/jack_audio.c [deleted file]
libavdevice/oss.c [new file with mode: 0644]
libavdevice/oss.h [new file with mode: 0644]
libavdevice/oss_audio.c [deleted file]
libavdevice/oss_audio.h [deleted file]
libavdevice/oss_audio_dec.c [deleted file]
libavdevice/oss_audio_enc.c [deleted file]
libavdevice/oss_dec.c [new file with mode: 0644]
libavdevice/oss_enc.c [new file with mode: 0644]
libavdevice/sndio.c [new file with mode: 0644]
libavdevice/sndio.h [new file with mode: 0644]
libavdevice/sndio_common.c [deleted file]
libavdevice/sndio_common.h [deleted file]
libavdevice/sndio_dec.c
libavdevice/sndio_enc.c

index 2a21832..dfd56be 100644 (file)
@@ -7,19 +7,17 @@ OBJS    = alldevices.o                                                  \
           avdevice.o                                                    \
 
 # input/output devices
-OBJS-$(CONFIG_ALSA_INDEV)                += alsa-audio-common.o \
-                                            alsa-audio-dec.o
-OBJS-$(CONFIG_ALSA_OUTDEV)               += alsa-audio-common.o \
-                                            alsa-audio-enc.o
+OBJS-$(CONFIG_ALSA_INDEV)                += alsa_dec.o alsa.o
+OBJS-$(CONFIG_ALSA_OUTDEV)               += alsa_enc.o alsa.o
 OBJS-$(CONFIG_BKTR_INDEV)                += bktr.o
 OBJS-$(CONFIG_DV1394_INDEV)              += dv1394.o
 OBJS-$(CONFIG_FBDEV_INDEV)               += fbdev.o
-OBJS-$(CONFIG_JACK_INDEV)                += jack_audio.o timefilter.o
-OBJS-$(CONFIG_OSS_INDEV)                 += oss_audio.o oss_audio_dec.o
-OBJS-$(CONFIG_OSS_OUTDEV)                += oss_audio.o oss_audio_enc.o
+OBJS-$(CONFIG_JACK_INDEV)                += jack.o timefilter.o
+OBJS-$(CONFIG_OSS_INDEV)                 += oss_dec.o oss.o
+OBJS-$(CONFIG_OSS_OUTDEV)                += oss_enc.o oss.o
 OBJS-$(CONFIG_PULSE_INDEV)               += pulse.o
-OBJS-$(CONFIG_SNDIO_INDEV)               += sndio_common.o sndio_dec.o
-OBJS-$(CONFIG_SNDIO_OUTDEV)              += sndio_common.o sndio_enc.o
+OBJS-$(CONFIG_SNDIO_INDEV)               += sndio_dec.o sndio.o
+OBJS-$(CONFIG_SNDIO_OUTDEV)              += sndio_enc.o sndio.o
 OBJS-$(CONFIG_V4L2_INDEV)                += v4l2.o
 OBJS-$(CONFIG_VFWCAP_INDEV)              += vfwcap.o
 OBJS-$(CONFIG_X11GRAB_INDEV)             += x11grab.o
@@ -31,7 +29,7 @@ OBJS-$(CONFIG_LIBDC1394_INDEV)           += libdc1394.o
 
 OBJS-$(HAVE_LIBC_MSVCRT)                 += file_open.o
 
-SKIPHEADERS-$(HAVE_ALSA_ASOUNDLIB_H)     += alsa-audio.h
-SKIPHEADERS-$(HAVE_SNDIO_H)              += sndio_common.h
+SKIPHEADERS-$(HAVE_ALSA_ASOUNDLIB_H)     += alsa.h
+SKIPHEADERS-$(HAVE_SNDIO_H)              += sndio.h
 
 TESTPROGS = timefilter
diff --git a/libavdevice/alsa-audio-common.c b/libavdevice/alsa-audio-common.c
deleted file mode 100644 (file)
index 21f1594..0000000
+++ /dev/null
@@ -1,362 +0,0 @@
-/*
- * ALSA input and output
- * Copyright (c) 2007 Luca Abeni ( lucabe72 email it )
- * Copyright (c) 2007 Benoit Fouet ( benoit fouet free fr )
- *
- * This file is part of Libav.
- *
- * Libav 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.
- *
- * Libav 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 Libav; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-/**
- * @file
- * ALSA input and output: common code
- * @author Luca Abeni ( lucabe72 email it )
- * @author Benoit Fouet ( benoit fouet free fr )
- * @author Nicolas George ( nicolas george normalesup org )
- */
-
-#include <alsa/asoundlib.h>
-#include "libavformat/avformat.h"
-#include "libavutil/avassert.h"
-#include "libavutil/channel_layout.h"
-
-#include "alsa-audio.h"
-
-static av_cold snd_pcm_format_t codec_id_to_pcm_format(int codec_id)
-{
-    switch(codec_id) {
-        case AV_CODEC_ID_PCM_F64LE: return SND_PCM_FORMAT_FLOAT64_LE;
-        case AV_CODEC_ID_PCM_F64BE: return SND_PCM_FORMAT_FLOAT64_BE;
-        case AV_CODEC_ID_PCM_F32LE: return SND_PCM_FORMAT_FLOAT_LE;
-        case AV_CODEC_ID_PCM_F32BE: return SND_PCM_FORMAT_FLOAT_BE;
-        case AV_CODEC_ID_PCM_S32LE: return SND_PCM_FORMAT_S32_LE;
-        case AV_CODEC_ID_PCM_S32BE: return SND_PCM_FORMAT_S32_BE;
-        case AV_CODEC_ID_PCM_U32LE: return SND_PCM_FORMAT_U32_LE;
-        case AV_CODEC_ID_PCM_U32BE: return SND_PCM_FORMAT_U32_BE;
-        case AV_CODEC_ID_PCM_S24LE: return SND_PCM_FORMAT_S24_3LE;
-        case AV_CODEC_ID_PCM_S24BE: return SND_PCM_FORMAT_S24_3BE;
-        case AV_CODEC_ID_PCM_U24LE: return SND_PCM_FORMAT_U24_3LE;
-        case AV_CODEC_ID_PCM_U24BE: return SND_PCM_FORMAT_U24_3BE;
-        case AV_CODEC_ID_PCM_S16LE: return SND_PCM_FORMAT_S16_LE;
-        case AV_CODEC_ID_PCM_S16BE: return SND_PCM_FORMAT_S16_BE;
-        case AV_CODEC_ID_PCM_U16LE: return SND_PCM_FORMAT_U16_LE;
-        case AV_CODEC_ID_PCM_U16BE: return SND_PCM_FORMAT_U16_BE;
-        case AV_CODEC_ID_PCM_S8:    return SND_PCM_FORMAT_S8;
-        case AV_CODEC_ID_PCM_U8:    return SND_PCM_FORMAT_U8;
-        case AV_CODEC_ID_PCM_MULAW: return SND_PCM_FORMAT_MU_LAW;
-        case AV_CODEC_ID_PCM_ALAW:  return SND_PCM_FORMAT_A_LAW;
-        default:                 return SND_PCM_FORMAT_UNKNOWN;
-    }
-}
-
-#define REORDER_OUT_50(NAME, TYPE) \
-static void alsa_reorder_ ## NAME ## _out_50(const void *in_v, void *out_v, int n) \
-{ \
-    const TYPE *in = in_v; \
-    TYPE      *out = out_v; \
-\
-    while (n-- > 0) { \
-        out[0] = in[0]; \
-        out[1] = in[1]; \
-        out[2] = in[3]; \
-        out[3] = in[4]; \
-        out[4] = in[2]; \
-        in  += 5; \
-        out += 5; \
-    } \
-}
-
-#define REORDER_OUT_51(NAME, TYPE) \
-static void alsa_reorder_ ## NAME ## _out_51(const void *in_v, void *out_v, int n) \
-{ \
-    const TYPE *in = in_v; \
-    TYPE      *out = out_v; \
-\
-    while (n-- > 0) { \
-        out[0] = in[0]; \
-        out[1] = in[1]; \
-        out[2] = in[4]; \
-        out[3] = in[5]; \
-        out[4] = in[2]; \
-        out[5] = in[3]; \
-        in  += 6; \
-        out += 6; \
-    } \
-}
-
-#define REORDER_OUT_71(NAME, TYPE) \
-static void alsa_reorder_ ## NAME ## _out_71(const void *in_v, void *out_v, int n) \
-{ \
-    const TYPE *in = in_v; \
-    TYPE      *out = out_v; \
-\
-    while (n-- > 0) { \
-        out[0] = in[0]; \
-        out[1] = in[1]; \
-        out[2] = in[4]; \
-        out[3] = in[5]; \
-        out[4] = in[2]; \
-        out[5] = in[3]; \
-        out[6] = in[6]; \
-        out[7] = in[7]; \
-        in  += 8; \
-        out += 8; \
-    } \
-}
-
-REORDER_OUT_50(int8, int8_t)
-REORDER_OUT_51(int8, int8_t)
-REORDER_OUT_71(int8, int8_t)
-REORDER_OUT_50(int16, int16_t)
-REORDER_OUT_51(int16, int16_t)
-REORDER_OUT_71(int16, int16_t)
-REORDER_OUT_50(int32, int32_t)
-REORDER_OUT_51(int32, int32_t)
-REORDER_OUT_71(int32, int32_t)
-REORDER_OUT_50(f32, float)
-REORDER_OUT_51(f32, float)
-REORDER_OUT_71(f32, float)
-
-#define FORMAT_I8  0
-#define FORMAT_I16 1
-#define FORMAT_I32 2
-#define FORMAT_F32 3
-
-#define PICK_REORDER(layout)\
-switch(format) {\
-    case FORMAT_I8:  s->reorder_func = alsa_reorder_int8_out_ ##layout;  break;\
-    case FORMAT_I16: s->reorder_func = alsa_reorder_int16_out_ ##layout; break;\
-    case FORMAT_I32: s->reorder_func = alsa_reorder_int32_out_ ##layout; break;\
-    case FORMAT_F32: s->reorder_func = alsa_reorder_f32_out_ ##layout;   break;\
-}
-
-static av_cold int find_reorder_func(AlsaData *s, int codec_id, uint64_t layout, int out)
-{
-    int format;
-
-    /* reordering input is not currently supported */
-    if (!out)
-        return AVERROR(ENOSYS);
-
-    /* reordering is not needed for QUAD or 2_2 layout */
-    if (layout == AV_CH_LAYOUT_QUAD || layout == AV_CH_LAYOUT_2_2)
-        return 0;
-
-    switch (codec_id) {
-    case AV_CODEC_ID_PCM_S8:
-    case AV_CODEC_ID_PCM_U8:
-    case AV_CODEC_ID_PCM_ALAW:
-    case AV_CODEC_ID_PCM_MULAW: format = FORMAT_I8;  break;
-    case AV_CODEC_ID_PCM_S16LE:
-    case AV_CODEC_ID_PCM_S16BE:
-    case AV_CODEC_ID_PCM_U16LE:
-    case AV_CODEC_ID_PCM_U16BE: format = FORMAT_I16; break;
-    case AV_CODEC_ID_PCM_S32LE:
-    case AV_CODEC_ID_PCM_S32BE:
-    case AV_CODEC_ID_PCM_U32LE:
-    case AV_CODEC_ID_PCM_U32BE: format = FORMAT_I32; break;
-    case AV_CODEC_ID_PCM_F32LE:
-    case AV_CODEC_ID_PCM_F32BE: format = FORMAT_F32; break;
-    default:                 return AVERROR(ENOSYS);
-    }
-
-    if      (layout == AV_CH_LAYOUT_5POINT0_BACK || layout == AV_CH_LAYOUT_5POINT0)
-        PICK_REORDER(50)
-    else if (layout == AV_CH_LAYOUT_5POINT1_BACK || layout == AV_CH_LAYOUT_5POINT1)
-        PICK_REORDER(51)
-    else if (layout == AV_CH_LAYOUT_7POINT1)
-        PICK_REORDER(71)
-
-    return s->reorder_func ? 0 : AVERROR(ENOSYS);
-}
-
-av_cold int ff_alsa_open(AVFormatContext *ctx, snd_pcm_stream_t mode,
-                         unsigned int *sample_rate,
-                         int channels, enum AVCodecID *codec_id)
-{
-    AlsaData *s = ctx->priv_data;
-    const char *audio_device;
-    int res, flags = 0;
-    snd_pcm_format_t format;
-    snd_pcm_t *h;
-    snd_pcm_hw_params_t *hw_params;
-    snd_pcm_uframes_t buffer_size, period_size;
-    uint64_t layout = ctx->streams[0]->codec->channel_layout;
-
-    if (ctx->filename[0] == 0) audio_device = "default";
-    else                       audio_device = ctx->filename;
-
-    if (*codec_id == AV_CODEC_ID_NONE)
-        *codec_id = DEFAULT_CODEC_ID;
-    format = codec_id_to_pcm_format(*codec_id);
-    if (format == SND_PCM_FORMAT_UNKNOWN) {
-        av_log(ctx, AV_LOG_ERROR, "sample format 0x%04x is not supported\n", *codec_id);
-        return AVERROR(ENOSYS);
-    }
-    s->frame_size = av_get_bits_per_sample(*codec_id) / 8 * channels;
-
-    if (ctx->flags & AVFMT_FLAG_NONBLOCK) {
-        flags = SND_PCM_NONBLOCK;
-    }
-    res = snd_pcm_open(&h, audio_device, mode, flags);
-    if (res < 0) {
-        av_log(ctx, AV_LOG_ERROR, "cannot open audio device %s (%s)\n",
-               audio_device, snd_strerror(res));
-        return AVERROR(EIO);
-    }
-
-    res = snd_pcm_hw_params_malloc(&hw_params);
-    if (res < 0) {
-        av_log(ctx, AV_LOG_ERROR, "cannot allocate hardware parameter structure (%s)\n",
-               snd_strerror(res));
-        goto fail1;
-    }
-
-    res = snd_pcm_hw_params_any(h, hw_params);
-    if (res < 0) {
-        av_log(ctx, AV_LOG_ERROR, "cannot initialize hardware parameter structure (%s)\n",
-               snd_strerror(res));
-        goto fail;
-    }
-
-    res = snd_pcm_hw_params_set_access(h, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED);
-    if (res < 0) {
-        av_log(ctx, AV_LOG_ERROR, "cannot set access type (%s)\n",
-               snd_strerror(res));
-        goto fail;
-    }
-
-    res = snd_pcm_hw_params_set_format(h, hw_params, format);
-    if (res < 0) {
-        av_log(ctx, AV_LOG_ERROR, "cannot set sample format 0x%04x %d (%s)\n",
-               *codec_id, format, snd_strerror(res));
-        goto fail;
-    }
-
-    res = snd_pcm_hw_params_set_rate_near(h, hw_params, sample_rate, 0);
-    if (res < 0) {
-        av_log(ctx, AV_LOG_ERROR, "cannot set sample rate (%s)\n",
-               snd_strerror(res));
-        goto fail;
-    }
-
-    res = snd_pcm_hw_params_set_channels(h, hw_params, channels);
-    if (res < 0) {
-        av_log(ctx, AV_LOG_ERROR, "cannot set channel count to %d (%s)\n",
-               channels, snd_strerror(res));
-        goto fail;
-    }
-
-    snd_pcm_hw_params_get_buffer_size_max(hw_params, &buffer_size);
-    buffer_size = FFMIN(buffer_size, ALSA_BUFFER_SIZE_MAX);
-    /* TODO: maybe use ctx->max_picture_buffer somehow */
-    res = snd_pcm_hw_params_set_buffer_size_near(h, hw_params, &buffer_size);
-    if (res < 0) {
-        av_log(ctx, AV_LOG_ERROR, "cannot set ALSA buffer size (%s)\n",
-               snd_strerror(res));
-        goto fail;
-    }
-
-    snd_pcm_hw_params_get_period_size_min(hw_params, &period_size, NULL);
-    if (!period_size)
-        period_size = buffer_size / 4;
-    res = snd_pcm_hw_params_set_period_size_near(h, hw_params, &period_size, NULL);
-    if (res < 0) {
-        av_log(ctx, AV_LOG_ERROR, "cannot set ALSA period size (%s)\n",
-               snd_strerror(res));
-        goto fail;
-    }
-    s->period_size = period_size;
-
-    res = snd_pcm_hw_params(h, hw_params);
-    if (res < 0) {
-        av_log(ctx, AV_LOG_ERROR, "cannot set parameters (%s)\n",
-               snd_strerror(res));
-        goto fail;
-    }
-
-    snd_pcm_hw_params_free(hw_params);
-
-    if (channels > 2 && layout) {
-        if (find_reorder_func(s, *codec_id, layout, mode == SND_PCM_STREAM_PLAYBACK) < 0) {
-            char name[128];
-            av_get_channel_layout_string(name, sizeof(name), channels, layout);
-            av_log(ctx, AV_LOG_WARNING, "ALSA channel layout unknown or unimplemented for %s %s.\n",
-                   name, mode == SND_PCM_STREAM_PLAYBACK ? "playback" : "capture");
-        }
-        if (s->reorder_func) {
-            s->reorder_buf_size = buffer_size;
-            s->reorder_buf = av_malloc(s->reorder_buf_size * s->frame_size);
-            if (!s->reorder_buf)
-                goto fail1;
-        }
-    }
-
-    s->h = h;
-    return 0;
-
-fail:
-    snd_pcm_hw_params_free(hw_params);
-fail1:
-    snd_pcm_close(h);
-    return AVERROR(EIO);
-}
-
-av_cold int ff_alsa_close(AVFormatContext *s1)
-{
-    AlsaData *s = s1->priv_data;
-
-    av_freep(&s->reorder_buf);
-    snd_pcm_close(s->h);
-    return 0;
-}
-
-int ff_alsa_xrun_recover(AVFormatContext *s1, int err)
-{
-    AlsaData *s = s1->priv_data;
-    snd_pcm_t *handle = s->h;
-
-    av_log(s1, AV_LOG_WARNING, "ALSA buffer xrun.\n");
-    if (err == -EPIPE) {
-        err = snd_pcm_prepare(handle);
-        if (err < 0) {
-            av_log(s1, AV_LOG_ERROR, "cannot recover from underrun (snd_pcm_prepare failed: %s)\n", snd_strerror(err));
-
-            return AVERROR(EIO);
-        }
-    } else if (err == -ESTRPIPE) {
-        av_log(s1, AV_LOG_ERROR, "-ESTRPIPE... Unsupported!\n");
-
-        return -1;
-    }
-    return err;
-}
-
-int ff_alsa_extend_reorder_buf(AlsaData *s, int min_size)
-{
-    int size = s->reorder_buf_size;
-    void *r;
-
-    av_assert0(size != 0);
-    while (size < min_size)
-        size *= 2;
-    r = av_realloc(s->reorder_buf, size * s->frame_size);
-    if (!r)
-        return AVERROR(ENOMEM);
-    s->reorder_buf = r;
-    s->reorder_buf_size = size;
-    return 0;
-}
diff --git a/libavdevice/alsa-audio-dec.c b/libavdevice/alsa-audio-dec.c
deleted file mode 100644 (file)
index a6a814b..0000000
+++ /dev/null
@@ -1,178 +0,0 @@
-/*
- * ALSA input and output
- * Copyright (c) 2007 Luca Abeni ( lucabe72 email it )
- * Copyright (c) 2007 Benoit Fouet ( benoit fouet free fr )
- *
- * This file is part of Libav.
- *
- * Libav 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.
- *
- * Libav 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 Libav; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-/**
- * @file
- * ALSA input and output: input
- * @author Luca Abeni ( lucabe72 email it )
- * @author Benoit Fouet ( benoit fouet free fr )
- * @author Nicolas George ( nicolas george normalesup org )
- *
- * This avdevice decoder allows to capture audio from an ALSA (Advanced
- * Linux Sound Architecture) device.
- *
- * The filename parameter is the name of an ALSA PCM device capable of
- * capture, for example "default" or "plughw:1"; see the ALSA documentation
- * for naming conventions. The empty string is equivalent to "default".
- *
- * The capture period is set to the lower value available for the device,
- * which gives a low latency suitable for real-time capture.
- *
- * The PTS are an Unix time in microsecond.
- *
- * Due to a bug in the ALSA library
- * (https://bugtrack.alsa-project.org/alsa-bug/view.php?id=4308), this
- * decoder does not work with certain ALSA plugins, especially the dsnoop
- * plugin.
- */
-
-#include <alsa/asoundlib.h>
-
-#include "libavutil/internal.h"
-#include "libavutil/opt.h"
-
-#include "libavformat/avformat.h"
-#include "libavformat/internal.h"
-
-#include "alsa-audio.h"
-
-static av_cold int audio_read_header(AVFormatContext *s1)
-{
-    AlsaData *s = s1->priv_data;
-    AVStream *st;
-    int ret;
-    enum AVCodecID codec_id;
-    snd_pcm_sw_params_t *sw_params;
-
-    st = avformat_new_stream(s1, NULL);
-    if (!st) {
-        av_log(s1, AV_LOG_ERROR, "Cannot add stream\n");
-
-        return AVERROR(ENOMEM);
-    }
-    codec_id    = s1->audio_codec_id;
-
-    ret = ff_alsa_open(s1, SND_PCM_STREAM_CAPTURE, &s->sample_rate, s->channels,
-        &codec_id);
-    if (ret < 0) {
-        return AVERROR(EIO);
-    }
-
-    if (snd_pcm_type(s->h) != SND_PCM_TYPE_HW)
-        av_log(s1, AV_LOG_WARNING,
-               "capture with some ALSA plugins, especially dsnoop, "
-               "may hang.\n");
-
-    ret = snd_pcm_sw_params_malloc(&sw_params);
-    if (ret < 0) {
-        av_log(s1, AV_LOG_ERROR, "cannot allocate software parameters structure (%s)\n",
-               snd_strerror(ret));
-        goto fail;
-    }
-
-    snd_pcm_sw_params_current(s->h, sw_params);
-    snd_pcm_sw_params_set_tstamp_mode(s->h, sw_params, SND_PCM_TSTAMP_ENABLE);
-
-    ret = snd_pcm_sw_params(s->h, sw_params);
-    snd_pcm_sw_params_free(sw_params);
-    if (ret < 0) {
-        av_log(s1, AV_LOG_ERROR, "cannot install ALSA software parameters (%s)\n",
-               snd_strerror(ret));
-        goto fail;
-    }
-
-    /* take real parameters */
-    st->codec->codec_type  = AVMEDIA_TYPE_AUDIO;
-    st->codec->codec_id    = codec_id;
-    st->codec->sample_rate = s->sample_rate;
-    st->codec->channels    = s->channels;
-    avpriv_set_pts_info(st, 64, 1, 1000000);  /* 64 bits pts in us */
-
-    return 0;
-
-fail:
-    snd_pcm_close(s->h);
-    return AVERROR(EIO);
-}
-
-static int audio_read_packet(AVFormatContext *s1, AVPacket *pkt)
-{
-    AlsaData *s  = s1->priv_data;
-    AVStream *st = s1->streams[0];
-    int res;
-    snd_htimestamp_t timestamp;
-    snd_pcm_uframes_t ts_delay;
-
-    if (av_new_packet(pkt, s->period_size) < 0) {
-        return AVERROR(EIO);
-    }
-
-    while ((res = snd_pcm_readi(s->h, pkt->data, pkt->size / s->frame_size)) < 0) {
-        if (res == -EAGAIN) {
-            av_free_packet(pkt);
-
-            return AVERROR(EAGAIN);
-        }
-        if (ff_alsa_xrun_recover(s1, res) < 0) {
-            av_log(s1, AV_LOG_ERROR, "ALSA read error: %s\n",
-                   snd_strerror(res));
-            av_free_packet(pkt);
-
-            return AVERROR(EIO);
-        }
-    }
-
-    snd_pcm_htimestamp(s->h, &ts_delay, &timestamp);
-    ts_delay += res;
-    pkt->pts = timestamp.tv_sec * 1000000LL
-               + (timestamp.tv_nsec * st->codec->sample_rate
-                  - (int64_t)ts_delay * 1000000000LL + st->codec->sample_rate * 500LL)
-               / (st->codec->sample_rate * 1000LL);
-
-    pkt->size = res * s->frame_size;
-
-    return 0;
-}
-
-static const AVOption options[] = {
-    { "sample_rate", "", offsetof(AlsaData, sample_rate), AV_OPT_TYPE_INT, {.i64 = 48000}, 1, INT_MAX, AV_OPT_FLAG_DECODING_PARAM },
-    { "channels",    "", offsetof(AlsaData, channels),    AV_OPT_TYPE_INT, {.i64 = 2},     1, INT_MAX, AV_OPT_FLAG_DECODING_PARAM },
-    { NULL },
-};
-
-static const AVClass alsa_demuxer_class = {
-    .class_name     = "ALSA demuxer",
-    .item_name      = av_default_item_name,
-    .option         = options,
-    .version        = LIBAVUTIL_VERSION_INT,
-};
-
-AVInputFormat ff_alsa_demuxer = {
-    .name           = "alsa",
-    .long_name      = NULL_IF_CONFIG_SMALL("ALSA audio input"),
-    .priv_data_size = sizeof(AlsaData),
-    .read_header    = audio_read_header,
-    .read_packet    = audio_read_packet,
-    .read_close     = ff_alsa_close,
-    .flags          = AVFMT_NOFILE,
-    .priv_class     = &alsa_demuxer_class,
-};
diff --git a/libavdevice/alsa-audio-enc.c b/libavdevice/alsa-audio-enc.c
deleted file mode 100644 (file)
index db4f5e4..0000000
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * ALSA input and output
- * Copyright (c) 2007 Luca Abeni ( lucabe72 email it )
- * Copyright (c) 2007 Benoit Fouet ( benoit fouet free fr )
- *
- * This file is part of Libav.
- *
- * Libav 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.
- *
- * Libav 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 Libav; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-/**
- * @file
- * ALSA input and output: output
- * @author Luca Abeni ( lucabe72 email it )
- * @author Benoit Fouet ( benoit fouet free fr )
- *
- * This avdevice encoder allows to play audio to an ALSA (Advanced Linux
- * Sound Architecture) device.
- *
- * The filename parameter is the name of an ALSA PCM device capable of
- * capture, for example "default" or "plughw:1"; see the ALSA documentation
- * for naming conventions. The empty string is equivalent to "default".
- *
- * The playback period is set to the lower value available for the device,
- * which gives a low latency suitable for real-time playback.
- */
-
-#include <alsa/asoundlib.h>
-
-#include "libavutil/internal.h"
-
-#include "libavformat/avformat.h"
-
-#include "alsa-audio.h"
-
-static av_cold int audio_write_header(AVFormatContext *s1)
-{
-    AlsaData *s = s1->priv_data;
-    AVStream *st;
-    unsigned int sample_rate;
-    enum AVCodecID codec_id;
-    int res;
-
-    st = s1->streams[0];
-    sample_rate = st->codec->sample_rate;
-    codec_id    = st->codec->codec_id;
-    res = ff_alsa_open(s1, SND_PCM_STREAM_PLAYBACK, &sample_rate,
-        st->codec->channels, &codec_id);
-    if (sample_rate != st->codec->sample_rate) {
-        av_log(s1, AV_LOG_ERROR,
-               "sample rate %d not available, nearest is %d\n",
-               st->codec->sample_rate, sample_rate);
-        goto fail;
-    }
-
-    return res;
-
-fail:
-    snd_pcm_close(s->h);
-    return AVERROR(EIO);
-}
-
-static int audio_write_packet(AVFormatContext *s1, AVPacket *pkt)
-{
-    AlsaData *s = s1->priv_data;
-    int res;
-    int size     = pkt->size;
-    uint8_t *buf = pkt->data;
-
-    size /= s->frame_size;
-    if (s->reorder_func) {
-        if (size > s->reorder_buf_size)
-            if (ff_alsa_extend_reorder_buf(s, size))
-                return AVERROR(ENOMEM);
-        s->reorder_func(buf, s->reorder_buf, size);
-        buf = s->reorder_buf;
-    }
-    while ((res = snd_pcm_writei(s->h, buf, size)) < 0) {
-        if (res == -EAGAIN) {
-
-            return AVERROR(EAGAIN);
-        }
-
-        if (ff_alsa_xrun_recover(s1, res) < 0) {
-            av_log(s1, AV_LOG_ERROR, "ALSA write error: %s\n",
-                   snd_strerror(res));
-
-            return AVERROR(EIO);
-        }
-    }
-
-    return 0;
-}
-
-AVOutputFormat ff_alsa_muxer = {
-    .name           = "alsa",
-    .long_name      = NULL_IF_CONFIG_SMALL("ALSA audio output"),
-    .priv_data_size = sizeof(AlsaData),
-    .audio_codec    = DEFAULT_CODEC_ID,
-    .video_codec    = AV_CODEC_ID_NONE,
-    .write_header   = audio_write_header,
-    .write_packet   = audio_write_packet,
-    .write_trailer  = ff_alsa_close,
-    .flags          = AVFMT_NOFILE,
-};
diff --git a/libavdevice/alsa-audio.h b/libavdevice/alsa-audio.h
deleted file mode 100644 (file)
index 26eaee6..0000000
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * ALSA input and output
- * Copyright (c) 2007 Luca Abeni ( lucabe72 email it )
- * Copyright (c) 2007 Benoit Fouet ( benoit fouet free fr )
- *
- * This file is part of Libav.
- *
- * Libav 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.
- *
- * Libav 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 Libav; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-/**
- * @file
- * ALSA input and output: definitions and structures
- * @author Luca Abeni ( lucabe72 email it )
- * @author Benoit Fouet ( benoit fouet free fr )
- */
-
-#ifndef AVDEVICE_ALSA_AUDIO_H
-#define AVDEVICE_ALSA_AUDIO_H
-
-#include <alsa/asoundlib.h>
-#include "config.h"
-#include "libavformat/avformat.h"
-#include "libavutil/log.h"
-
-/* XXX: we make the assumption that the soundcard accepts this format */
-/* XXX: find better solution with "preinit" method, needed also in
-        other formats */
-#define DEFAULT_CODEC_ID AV_NE(AV_CODEC_ID_PCM_S16BE, AV_CODEC_ID_PCM_S16LE)
-
-#define ALSA_BUFFER_SIZE_MAX 32768
-
-typedef struct AlsaData {
-    AVClass *class;
-    snd_pcm_t *h;
-    int frame_size;  ///< preferred size for reads and writes
-    int period_size; ///< bytes per sample * channels
-    int sample_rate; ///< sample rate set by user
-    int channels;    ///< number of channels set by user
-    void (*reorder_func)(const void *, void *, int);
-    void *reorder_buf;
-    int reorder_buf_size; ///< in frames
-} AlsaData;
-
-/**
- * Open an ALSA PCM.
- *
- * @param s media file handle
- * @param mode either SND_PCM_STREAM_CAPTURE or SND_PCM_STREAM_PLAYBACK
- * @param sample_rate in: requested sample rate;
- *                    out: actually selected sample rate
- * @param channels number of channels
- * @param codec_id in: requested AVCodecID or AV_CODEC_ID_NONE;
- *                 out: actually selected AVCodecID, changed only if
- *                 AV_CODEC_ID_NONE was requested
- *
- * @return 0 if OK, AVERROR_xxx on error
- */
-int ff_alsa_open(AVFormatContext *s, snd_pcm_stream_t mode,
-                 unsigned int *sample_rate,
-                 int channels, enum AVCodecID *codec_id);
-
-/**
- * Close the ALSA PCM.
- *
- * @param s1 media file handle
- *
- * @return 0
- */
-int ff_alsa_close(AVFormatContext *s1);
-
-/**
- * Try to recover from ALSA buffer underrun.
- *
- * @param s1 media file handle
- * @param err error code reported by the previous ALSA call
- *
- * @return 0 if OK, AVERROR_xxx on error
- */
-int ff_alsa_xrun_recover(AVFormatContext *s1, int err);
-
-int ff_alsa_extend_reorder_buf(AlsaData *s, int size);
-
-#endif /* AVDEVICE_ALSA_AUDIO_H */
diff --git a/libavdevice/alsa.c b/libavdevice/alsa.c
new file mode 100644 (file)
index 0000000..6d68267
--- /dev/null
@@ -0,0 +1,362 @@
+/*
+ * ALSA input and output
+ * Copyright (c) 2007 Luca Abeni ( lucabe72 email it )
+ * Copyright (c) 2007 Benoit Fouet ( benoit fouet free fr )
+ *
+ * This file is part of Libav.
+ *
+ * Libav 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.
+ *
+ * Libav 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 Libav; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file
+ * ALSA input and output: common code
+ * @author Luca Abeni ( lucabe72 email it )
+ * @author Benoit Fouet ( benoit fouet free fr )
+ * @author Nicolas George ( nicolas george normalesup org )
+ */
+
+#include <alsa/asoundlib.h>
+#include "libavformat/avformat.h"
+#include "libavutil/avassert.h"
+#include "libavutil/channel_layout.h"
+
+#include "alsa.h"
+
+static av_cold snd_pcm_format_t codec_id_to_pcm_format(int codec_id)
+{
+    switch(codec_id) {
+        case AV_CODEC_ID_PCM_F64LE: return SND_PCM_FORMAT_FLOAT64_LE;
+        case AV_CODEC_ID_PCM_F64BE: return SND_PCM_FORMAT_FLOAT64_BE;
+        case AV_CODEC_ID_PCM_F32LE: return SND_PCM_FORMAT_FLOAT_LE;
+        case AV_CODEC_ID_PCM_F32BE: return SND_PCM_FORMAT_FLOAT_BE;
+        case AV_CODEC_ID_PCM_S32LE: return SND_PCM_FORMAT_S32_LE;
+        case AV_CODEC_ID_PCM_S32BE: return SND_PCM_FORMAT_S32_BE;
+        case AV_CODEC_ID_PCM_U32LE: return SND_PCM_FORMAT_U32_LE;
+        case AV_CODEC_ID_PCM_U32BE: return SND_PCM_FORMAT_U32_BE;
+        case AV_CODEC_ID_PCM_S24LE: return SND_PCM_FORMAT_S24_3LE;
+        case AV_CODEC_ID_PCM_S24BE: return SND_PCM_FORMAT_S24_3BE;
+        case AV_CODEC_ID_PCM_U24LE: return SND_PCM_FORMAT_U24_3LE;
+        case AV_CODEC_ID_PCM_U24BE: return SND_PCM_FORMAT_U24_3BE;
+        case AV_CODEC_ID_PCM_S16LE: return SND_PCM_FORMAT_S16_LE;
+        case AV_CODEC_ID_PCM_S16BE: return SND_PCM_FORMAT_S16_BE;
+        case AV_CODEC_ID_PCM_U16LE: return SND_PCM_FORMAT_U16_LE;
+        case AV_CODEC_ID_PCM_U16BE: return SND_PCM_FORMAT_U16_BE;
+        case AV_CODEC_ID_PCM_S8:    return SND_PCM_FORMAT_S8;
+        case AV_CODEC_ID_PCM_U8:    return SND_PCM_FORMAT_U8;
+        case AV_CODEC_ID_PCM_MULAW: return SND_PCM_FORMAT_MU_LAW;
+        case AV_CODEC_ID_PCM_ALAW:  return SND_PCM_FORMAT_A_LAW;
+        default:                 return SND_PCM_FORMAT_UNKNOWN;
+    }
+}
+
+#define REORDER_OUT_50(NAME, TYPE) \
+static void alsa_reorder_ ## NAME ## _out_50(const void *in_v, void *out_v, int n) \
+{ \
+    const TYPE *in = in_v; \
+    TYPE      *out = out_v; \
+\
+    while (n-- > 0) { \
+        out[0] = in[0]; \
+        out[1] = in[1]; \
+        out[2] = in[3]; \
+        out[3] = in[4]; \
+        out[4] = in[2]; \
+        in  += 5; \
+        out += 5; \
+    } \
+}
+
+#define REORDER_OUT_51(NAME, TYPE) \
+static void alsa_reorder_ ## NAME ## _out_51(const void *in_v, void *out_v, int n) \
+{ \
+    const TYPE *in = in_v; \
+    TYPE      *out = out_v; \
+\
+    while (n-- > 0) { \
+        out[0] = in[0]; \
+        out[1] = in[1]; \
+        out[2] = in[4]; \
+        out[3] = in[5]; \
+        out[4] = in[2]; \
+        out[5] = in[3]; \
+        in  += 6; \
+        out += 6; \
+    } \
+}
+
+#define REORDER_OUT_71(NAME, TYPE) \
+static void alsa_reorder_ ## NAME ## _out_71(const void *in_v, void *out_v, int n) \
+{ \
+    const TYPE *in = in_v; \
+    TYPE      *out = out_v; \
+\
+    while (n-- > 0) { \
+        out[0] = in[0]; \
+        out[1] = in[1]; \
+        out[2] = in[4]; \
+        out[3] = in[5]; \
+        out[4] = in[2]; \
+        out[5] = in[3]; \
+        out[6] = in[6]; \
+        out[7] = in[7]; \
+        in  += 8; \
+        out += 8; \
+    } \
+}
+
+REORDER_OUT_50(int8, int8_t)
+REORDER_OUT_51(int8, int8_t)
+REORDER_OUT_71(int8, int8_t)
+REORDER_OUT_50(int16, int16_t)
+REORDER_OUT_51(int16, int16_t)
+REORDER_OUT_71(int16, int16_t)
+REORDER_OUT_50(int32, int32_t)
+REORDER_OUT_51(int32, int32_t)
+REORDER_OUT_71(int32, int32_t)
+REORDER_OUT_50(f32, float)
+REORDER_OUT_51(f32, float)
+REORDER_OUT_71(f32, float)
+
+#define FORMAT_I8  0
+#define FORMAT_I16 1
+#define FORMAT_I32 2
+#define FORMAT_F32 3
+
+#define PICK_REORDER(layout)\
+switch(format) {\
+    case FORMAT_I8:  s->reorder_func = alsa_reorder_int8_out_ ##layout;  break;\
+    case FORMAT_I16: s->reorder_func = alsa_reorder_int16_out_ ##layout; break;\
+    case FORMAT_I32: s->reorder_func = alsa_reorder_int32_out_ ##layout; break;\
+    case FORMAT_F32: s->reorder_func = alsa_reorder_f32_out_ ##layout;   break;\
+}
+
+static av_cold int find_reorder_func(AlsaData *s, int codec_id, uint64_t layout, int out)
+{
+    int format;
+
+    /* reordering input is not currently supported */
+    if (!out)
+        return AVERROR(ENOSYS);
+
+    /* reordering is not needed for QUAD or 2_2 layout */
+    if (layout == AV_CH_LAYOUT_QUAD || layout == AV_CH_LAYOUT_2_2)
+        return 0;
+
+    switch (codec_id) {
+    case AV_CODEC_ID_PCM_S8:
+    case AV_CODEC_ID_PCM_U8:
+    case AV_CODEC_ID_PCM_ALAW:
+    case AV_CODEC_ID_PCM_MULAW: format = FORMAT_I8;  break;
+    case AV_CODEC_ID_PCM_S16LE:
+    case AV_CODEC_ID_PCM_S16BE:
+    case AV_CODEC_ID_PCM_U16LE:
+    case AV_CODEC_ID_PCM_U16BE: format = FORMAT_I16; break;
+    case AV_CODEC_ID_PCM_S32LE:
+    case AV_CODEC_ID_PCM_S32BE:
+    case AV_CODEC_ID_PCM_U32LE:
+    case AV_CODEC_ID_PCM_U32BE: format = FORMAT_I32; break;
+    case AV_CODEC_ID_PCM_F32LE:
+    case AV_CODEC_ID_PCM_F32BE: format = FORMAT_F32; break;
+    default:                 return AVERROR(ENOSYS);
+    }
+
+    if      (layout == AV_CH_LAYOUT_5POINT0_BACK || layout == AV_CH_LAYOUT_5POINT0)
+        PICK_REORDER(50)
+    else if (layout == AV_CH_LAYOUT_5POINT1_BACK || layout == AV_CH_LAYOUT_5POINT1)
+        PICK_REORDER(51)
+    else if (layout == AV_CH_LAYOUT_7POINT1)
+        PICK_REORDER(71)
+
+    return s->reorder_func ? 0 : AVERROR(ENOSYS);
+}
+
+av_cold int ff_alsa_open(AVFormatContext *ctx, snd_pcm_stream_t mode,
+                         unsigned int *sample_rate,
+                         int channels, enum AVCodecID *codec_id)
+{
+    AlsaData *s = ctx->priv_data;
+    const char *audio_device;
+    int res, flags = 0;
+    snd_pcm_format_t format;
+    snd_pcm_t *h;
+    snd_pcm_hw_params_t *hw_params;
+    snd_pcm_uframes_t buffer_size, period_size;
+    uint64_t layout = ctx->streams[0]->codec->channel_layout;
+
+    if (ctx->filename[0] == 0) audio_device = "default";
+    else                       audio_device = ctx->filename;
+
+    if (*codec_id == AV_CODEC_ID_NONE)
+        *codec_id = DEFAULT_CODEC_ID;
+    format = codec_id_to_pcm_format(*codec_id);
+    if (format == SND_PCM_FORMAT_UNKNOWN) {
+        av_log(ctx, AV_LOG_ERROR, "sample format 0x%04x is not supported\n", *codec_id);
+        return AVERROR(ENOSYS);
+    }
+    s->frame_size = av_get_bits_per_sample(*codec_id) / 8 * channels;
+
+    if (ctx->flags & AVFMT_FLAG_NONBLOCK) {
+        flags = SND_PCM_NONBLOCK;
+    }
+    res = snd_pcm_open(&h, audio_device, mode, flags);
+    if (res < 0) {
+        av_log(ctx, AV_LOG_ERROR, "cannot open audio device %s (%s)\n",
+               audio_device, snd_strerror(res));
+        return AVERROR(EIO);
+    }
+
+    res = snd_pcm_hw_params_malloc(&hw_params);
+    if (res < 0) {
+        av_log(ctx, AV_LOG_ERROR, "cannot allocate hardware parameter structure (%s)\n",
+               snd_strerror(res));
+        goto fail1;
+    }
+
+    res = snd_pcm_hw_params_any(h, hw_params);
+    if (res < 0) {
+        av_log(ctx, AV_LOG_ERROR, "cannot initialize hardware parameter structure (%s)\n",
+               snd_strerror(res));
+        goto fail;
+    }
+
+    res = snd_pcm_hw_params_set_access(h, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED);
+    if (res < 0) {
+        av_log(ctx, AV_LOG_ERROR, "cannot set access type (%s)\n",
+               snd_strerror(res));
+        goto fail;
+    }
+
+    res = snd_pcm_hw_params_set_format(h, hw_params, format);
+    if (res < 0) {
+        av_log(ctx, AV_LOG_ERROR, "cannot set sample format 0x%04x %d (%s)\n",
+               *codec_id, format, snd_strerror(res));
+        goto fail;
+    }
+
+    res = snd_pcm_hw_params_set_rate_near(h, hw_params, sample_rate, 0);
+    if (res < 0) {
+        av_log(ctx, AV_LOG_ERROR, "cannot set sample rate (%s)\n",
+               snd_strerror(res));
+        goto fail;
+    }
+
+    res = snd_pcm_hw_params_set_channels(h, hw_params, channels);
+    if (res < 0) {
+        av_log(ctx, AV_LOG_ERROR, "cannot set channel count to %d (%s)\n",
+               channels, snd_strerror(res));
+        goto fail;
+    }
+
+    snd_pcm_hw_params_get_buffer_size_max(hw_params, &buffer_size);
+    buffer_size = FFMIN(buffer_size, ALSA_BUFFER_SIZE_MAX);
+    /* TODO: maybe use ctx->max_picture_buffer somehow */
+    res = snd_pcm_hw_params_set_buffer_size_near(h, hw_params, &buffer_size);
+    if (res < 0) {
+        av_log(ctx, AV_LOG_ERROR, "cannot set ALSA buffer size (%s)\n",
+               snd_strerror(res));
+        goto fail;
+    }
+
+    snd_pcm_hw_params_get_period_size_min(hw_params, &period_size, NULL);
+    if (!period_size)
+        period_size = buffer_size / 4;
+    res = snd_pcm_hw_params_set_period_size_near(h, hw_params, &period_size, NULL);
+    if (res < 0) {
+        av_log(ctx, AV_LOG_ERROR, "cannot set ALSA period size (%s)\n",
+               snd_strerror(res));
+        goto fail;
+    }
+    s->period_size = period_size;
+
+    res = snd_pcm_hw_params(h, hw_params);
+    if (res < 0) {
+        av_log(ctx, AV_LOG_ERROR, "cannot set parameters (%s)\n",
+               snd_strerror(res));
+        goto fail;
+    }
+
+    snd_pcm_hw_params_free(hw_params);
+
+    if (channels > 2 && layout) {
+        if (find_reorder_func(s, *codec_id, layout, mode == SND_PCM_STREAM_PLAYBACK) < 0) {
+            char name[128];
+            av_get_channel_layout_string(name, sizeof(name), channels, layout);
+            av_log(ctx, AV_LOG_WARNING, "ALSA channel layout unknown or unimplemented for %s %s.\n",
+                   name, mode == SND_PCM_STREAM_PLAYBACK ? "playback" : "capture");
+        }
+        if (s->reorder_func) {
+            s->reorder_buf_size = buffer_size;
+            s->reorder_buf = av_malloc(s->reorder_buf_size * s->frame_size);
+            if (!s->reorder_buf)
+                goto fail1;
+        }
+    }
+
+    s->h = h;
+    return 0;
+
+fail:
+    snd_pcm_hw_params_free(hw_params);
+fail1:
+    snd_pcm_close(h);
+    return AVERROR(EIO);
+}
+
+av_cold int ff_alsa_close(AVFormatContext *s1)
+{
+    AlsaData *s = s1->priv_data;
+
+    av_freep(&s->reorder_buf);
+    snd_pcm_close(s->h);
+    return 0;
+}
+
+int ff_alsa_xrun_recover(AVFormatContext *s1, int err)
+{
+    AlsaData *s = s1->priv_data;
+    snd_pcm_t *handle = s->h;
+
+    av_log(s1, AV_LOG_WARNING, "ALSA buffer xrun.\n");
+    if (err == -EPIPE) {
+        err = snd_pcm_prepare(handle);
+        if (err < 0) {
+            av_log(s1, AV_LOG_ERROR, "cannot recover from underrun (snd_pcm_prepare failed: %s)\n", snd_strerror(err));
+
+            return AVERROR(EIO);
+        }
+    } else if (err == -ESTRPIPE) {
+        av_log(s1, AV_LOG_ERROR, "-ESTRPIPE... Unsupported!\n");
+
+        return -1;
+    }
+    return err;
+}
+
+int ff_alsa_extend_reorder_buf(AlsaData *s, int min_size)
+{
+    int size = s->reorder_buf_size;
+    void *r;
+
+    av_assert0(size != 0);
+    while (size < min_size)
+        size *= 2;
+    r = av_realloc(s->reorder_buf, size * s->frame_size);
+    if (!r)
+        return AVERROR(ENOMEM);
+    s->reorder_buf = r;
+    s->reorder_buf_size = size;
+    return 0;
+}
diff --git a/libavdevice/alsa.h b/libavdevice/alsa.h
new file mode 100644 (file)
index 0000000..590b354
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * ALSA input and output
+ * Copyright (c) 2007 Luca Abeni ( lucabe72 email it )
+ * Copyright (c) 2007 Benoit Fouet ( benoit fouet free fr )
+ *
+ * This file is part of Libav.
+ *
+ * Libav 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.
+ *
+ * Libav 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 Libav; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file
+ * ALSA input and output: definitions and structures
+ * @author Luca Abeni ( lucabe72 email it )
+ * @author Benoit Fouet ( benoit fouet free fr )
+ */
+
+#ifndef AVDEVICE_ALSA_H
+#define AVDEVICE_ALSA_H
+
+#include <alsa/asoundlib.h>
+#include "config.h"
+#include "libavformat/avformat.h"
+#include "libavutil/log.h"
+
+/* XXX: we make the assumption that the soundcard accepts this format */
+/* XXX: find better solution with "preinit" method, needed also in
+        other formats */
+#define DEFAULT_CODEC_ID AV_NE(AV_CODEC_ID_PCM_S16BE, AV_CODEC_ID_PCM_S16LE)
+
+#define ALSA_BUFFER_SIZE_MAX 32768
+
+typedef struct AlsaData {
+    AVClass *class;
+    snd_pcm_t *h;
+    int frame_size;  ///< preferred size for reads and writes
+    int period_size; ///< bytes per sample * channels
+    int sample_rate; ///< sample rate set by user
+    int channels;    ///< number of channels set by user
+    void (*reorder_func)(const void *, void *, int);
+    void *reorder_buf;
+    int reorder_buf_size; ///< in frames
+} AlsaData;
+
+/**
+ * Open an ALSA PCM.
+ *
+ * @param s media file handle
+ * @param mode either SND_PCM_STREAM_CAPTURE or SND_PCM_STREAM_PLAYBACK
+ * @param sample_rate in: requested sample rate;
+ *                    out: actually selected sample rate
+ * @param channels number of channels
+ * @param codec_id in: requested AVCodecID or AV_CODEC_ID_NONE;
+ *                 out: actually selected AVCodecID, changed only if
+ *                 AV_CODEC_ID_NONE was requested
+ *
+ * @return 0 if OK, AVERROR_xxx on error
+ */
+int ff_alsa_open(AVFormatContext *s, snd_pcm_stream_t mode,
+                 unsigned int *sample_rate,
+                 int channels, enum AVCodecID *codec_id);
+
+/**
+ * Close the ALSA PCM.
+ *
+ * @param s1 media file handle
+ *
+ * @return 0
+ */
+int ff_alsa_close(AVFormatContext *s1);
+
+/**
+ * Try to recover from ALSA buffer underrun.
+ *
+ * @param s1 media file handle
+ * @param err error code reported by the previous ALSA call
+ *
+ * @return 0 if OK, AVERROR_xxx on error
+ */
+int ff_alsa_xrun_recover(AVFormatContext *s1, int err);
+
+int ff_alsa_extend_reorder_buf(AlsaData *s, int size);
+
+#endif /* AVDEVICE_ALSA_H */
diff --git a/libavdevice/alsa_dec.c b/libavdevice/alsa_dec.c
new file mode 100644 (file)
index 0000000..2cc5b7d
--- /dev/null
@@ -0,0 +1,178 @@
+/*
+ * ALSA input and output
+ * Copyright (c) 2007 Luca Abeni ( lucabe72 email it )
+ * Copyright (c) 2007 Benoit Fouet ( benoit fouet free fr )
+ *
+ * This file is part of Libav.
+ *
+ * Libav 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.
+ *
+ * Libav 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 Libav; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file
+ * ALSA input and output: input
+ * @author Luca Abeni ( lucabe72 email it )
+ * @author Benoit Fouet ( benoit fouet free fr )
+ * @author Nicolas George ( nicolas george normalesup org )
+ *
+ * This avdevice decoder allows to capture audio from an ALSA (Advanced
+ * Linux Sound Architecture) device.
+ *
+ * The filename parameter is the name of an ALSA PCM device capable of
+ * capture, for example "default" or "plughw:1"; see the ALSA documentation
+ * for naming conventions. The empty string is equivalent to "default".
+ *
+ * The capture period is set to the lower value available for the device,
+ * which gives a low latency suitable for real-time capture.
+ *
+ * The PTS are an Unix time in microsecond.
+ *
+ * Due to a bug in the ALSA library
+ * (https://bugtrack.alsa-project.org/alsa-bug/view.php?id=4308), this
+ * decoder does not work with certain ALSA plugins, especially the dsnoop
+ * plugin.
+ */
+
+#include <alsa/asoundlib.h>
+
+#include "libavutil/internal.h"
+#include "libavutil/opt.h"
+
+#include "libavformat/avformat.h"
+#include "libavformat/internal.h"
+
+#include "alsa.h"
+
+static av_cold int audio_read_header(AVFormatContext *s1)
+{
+    AlsaData *s = s1->priv_data;
+    AVStream *st;
+    int ret;
+    enum AVCodecID codec_id;
+    snd_pcm_sw_params_t *sw_params;
+
+    st = avformat_new_stream(s1, NULL);
+    if (!st) {
+        av_log(s1, AV_LOG_ERROR, "Cannot add stream\n");
+
+        return AVERROR(ENOMEM);
+    }
+    codec_id    = s1->audio_codec_id;
+
+    ret = ff_alsa_open(s1, SND_PCM_STREAM_CAPTURE, &s->sample_rate, s->channels,
+        &codec_id);
+    if (ret < 0) {
+        return AVERROR(EIO);
+    }
+
+    if (snd_pcm_type(s->h) != SND_PCM_TYPE_HW)
+        av_log(s1, AV_LOG_WARNING,
+               "capture with some ALSA plugins, especially dsnoop, "
+               "may hang.\n");
+
+    ret = snd_pcm_sw_params_malloc(&sw_params);
+    if (ret < 0) {
+        av_log(s1, AV_LOG_ERROR, "cannot allocate software parameters structure (%s)\n",
+               snd_strerror(ret));
+        goto fail;
+    }
+
+    snd_pcm_sw_params_current(s->h, sw_params);
+    snd_pcm_sw_params_set_tstamp_mode(s->h, sw_params, SND_PCM_TSTAMP_ENABLE);
+
+    ret = snd_pcm_sw_params(s->h, sw_params);
+    snd_pcm_sw_params_free(sw_params);
+    if (ret < 0) {
+        av_log(s1, AV_LOG_ERROR, "cannot install ALSA software parameters (%s)\n",
+               snd_strerror(ret));
+        goto fail;
+    }
+
+    /* take real parameters */
+    st->codec->codec_type  = AVMEDIA_TYPE_AUDIO;
+    st->codec->codec_id    = codec_id;
+    st->codec->sample_rate = s->sample_rate;
+    st->codec->channels    = s->channels;
+    avpriv_set_pts_info(st, 64, 1, 1000000);  /* 64 bits pts in us */
+
+    return 0;
+
+fail:
+    snd_pcm_close(s->h);
+    return AVERROR(EIO);
+}
+
+static int audio_read_packet(AVFormatContext *s1, AVPacket *pkt)
+{
+    AlsaData *s  = s1->priv_data;
+    AVStream *st = s1->streams[0];
+    int res;
+    snd_htimestamp_t timestamp;
+    snd_pcm_uframes_t ts_delay;
+
+    if (av_new_packet(pkt, s->period_size) < 0) {
+        return AVERROR(EIO);
+    }
+
+    while ((res = snd_pcm_readi(s->h, pkt->data, pkt->size / s->frame_size)) < 0) {
+        if (res == -EAGAIN) {
+            av_free_packet(pkt);
+
+            return AVERROR(EAGAIN);
+        }
+        if (ff_alsa_xrun_recover(s1, res) < 0) {
+            av_log(s1, AV_LOG_ERROR, "ALSA read error: %s\n",
+                   snd_strerror(res));
+            av_free_packet(pkt);
+
+            return AVERROR(EIO);
+        }
+    }
+
+    snd_pcm_htimestamp(s->h, &ts_delay, &timestamp);
+    ts_delay += res;
+    pkt->pts = timestamp.tv_sec * 1000000LL
+               + (timestamp.tv_nsec * st->codec->sample_rate
+                  - (int64_t)ts_delay * 1000000000LL + st->codec->sample_rate * 500LL)
+               / (st->codec->sample_rate * 1000LL);
+
+    pkt->size = res * s->frame_size;
+
+    return 0;
+}
+
+static const AVOption options[] = {
+    { "sample_rate", "", offsetof(AlsaData, sample_rate), AV_OPT_TYPE_INT, {.i64 = 48000}, 1, INT_MAX, AV_OPT_FLAG_DECODING_PARAM },
+    { "channels",    "", offsetof(AlsaData, channels),    AV_OPT_TYPE_INT, {.i64 = 2},     1, INT_MAX, AV_OPT_FLAG_DECODING_PARAM },
+    { NULL },
+};
+
+static const AVClass alsa_demuxer_class = {
+    .class_name     = "ALSA demuxer",
+    .item_name      = av_default_item_name,
+    .option         = options,
+    .version        = LIBAVUTIL_VERSION_INT,
+};
+
+AVInputFormat ff_alsa_demuxer = {
+    .name           = "alsa",
+    .long_name      = NULL_IF_CONFIG_SMALL("ALSA audio input"),
+    .priv_data_size = sizeof(AlsaData),
+    .read_header    = audio_read_header,
+    .read_packet    = audio_read_packet,
+    .read_close     = ff_alsa_close,
+    .flags          = AVFMT_NOFILE,
+    .priv_class     = &alsa_demuxer_class,
+};
diff --git a/libavdevice/alsa_enc.c b/libavdevice/alsa_enc.c
new file mode 100644 (file)
index 0000000..30c1719
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ * ALSA input and output
+ * Copyright (c) 2007 Luca Abeni ( lucabe72 email it )
+ * Copyright (c) 2007 Benoit Fouet ( benoit fouet free fr )
+ *
+ * This file is part of Libav.
+ *
+ * Libav 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.
+ *
+ * Libav 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 Libav; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file
+ * ALSA input and output: output
+ * @author Luca Abeni ( lucabe72 email it )
+ * @author Benoit Fouet ( benoit fouet free fr )
+ *
+ * This avdevice encoder allows to play audio to an ALSA (Advanced Linux
+ * Sound Architecture) device.
+ *
+ * The filename parameter is the name of an ALSA PCM device capable of
+ * capture, for example "default" or "plughw:1"; see the ALSA documentation
+ * for naming conventions. The empty string is equivalent to "default".
+ *
+ * The playback period is set to the lower value available for the device,
+ * which gives a low latency suitable for real-time playback.
+ */
+
+#include <alsa/asoundlib.h>
+
+#include "libavutil/internal.h"
+
+#include "libavformat/avformat.h"
+
+#include "alsa.h"
+
+static av_cold int audio_write_header(AVFormatContext *s1)
+{
+    AlsaData *s = s1->priv_data;
+    AVStream *st;
+    unsigned int sample_rate;
+    enum AVCodecID codec_id;
+    int res;
+
+    st = s1->streams[0];
+    sample_rate = st->codec->sample_rate;
+    codec_id    = st->codec->codec_id;
+    res = ff_alsa_open(s1, SND_PCM_STREAM_PLAYBACK, &sample_rate,
+        st->codec->channels, &codec_id);
+    if (sample_rate != st->codec->sample_rate) {
+        av_log(s1, AV_LOG_ERROR,
+               "sample rate %d not available, nearest is %d\n",
+               st->codec->sample_rate, sample_rate);
+        goto fail;
+    }
+
+    return res;
+
+fail:
+    snd_pcm_close(s->h);
+    return AVERROR(EIO);
+}
+
+static int audio_write_packet(AVFormatContext *s1, AVPacket *pkt)
+{
+    AlsaData *s = s1->priv_data;
+    int res;
+    int size     = pkt->size;
+    uint8_t *buf = pkt->data;
+
+    size /= s->frame_size;
+    if (s->reorder_func) {
+        if (size > s->reorder_buf_size)
+            if (ff_alsa_extend_reorder_buf(s, size))
+                return AVERROR(ENOMEM);
+        s->reorder_func(buf, s->reorder_buf, size);
+        buf = s->reorder_buf;
+    }
+    while ((res = snd_pcm_writei(s->h, buf, size)) < 0) {
+        if (res == -EAGAIN) {
+
+            return AVERROR(EAGAIN);
+        }
+
+        if (ff_alsa_xrun_recover(s1, res) < 0) {
+            av_log(s1, AV_LOG_ERROR, "ALSA write error: %s\n",
+                   snd_strerror(res));
+
+            return AVERROR(EIO);
+        }
+    }
+
+    return 0;
+}
+
+AVOutputFormat ff_alsa_muxer = {
+    .name           = "alsa",
+    .long_name      = NULL_IF_CONFIG_SMALL("ALSA audio output"),
+    .priv_data_size = sizeof(AlsaData),
+    .audio_codec    = DEFAULT_CODEC_ID,
+    .video_codec    = AV_CODEC_ID_NONE,
+    .write_header   = audio_write_header,
+    .write_packet   = audio_write_packet,
+    .write_trailer  = ff_alsa_close,
+    .flags          = AVFMT_NOFILE,
+};
diff --git a/libavdevice/jack.c b/libavdevice/jack.c
new file mode 100644 (file)
index 0000000..fc5caa8
--- /dev/null
@@ -0,0 +1,353 @@
+/*
+ * JACK Audio Connection Kit input device
+ * Copyright (c) 2009 Samalyse
+ * Author: Olivier Guilyardi <olivier samalyse com>
+ *
+ * This file is part of Libav.
+ *
+ * Libav 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.
+ *
+ * Libav 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 Libav; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "config.h"
+#include <semaphore.h>
+#include <jack/jack.h>
+
+#include "libavutil/internal.h"
+#include "libavutil/log.h"
+#include "libavutil/fifo.h"
+#include "libavutil/opt.h"
+#include "libavutil/time.h"
+#include "libavcodec/avcodec.h"
+#include "libavformat/avformat.h"
+#include "libavformat/internal.h"
+#include "timefilter.h"
+
+/**
+ * Size of the internal FIFO buffers as a number of audio packets
+ */
+#define FIFO_PACKETS_NUM 16
+
+typedef struct JackData {
+    AVClass        *class;
+    jack_client_t * client;
+    int             activated;
+    sem_t           packet_count;
+    jack_nframes_t  sample_rate;
+    jack_nframes_t  buffer_size;
+    jack_port_t **  ports;
+    int             nports;
+    TimeFilter *    timefilter;
+    AVFifoBuffer *  new_pkts;
+    AVFifoBuffer *  filled_pkts;
+    int             pkt_xrun;
+    int             jack_xrun;
+} JackData;
+
+static int process_callback(jack_nframes_t nframes, void *arg)
+{
+    /* Warning: this function runs in realtime. One mustn't allocate memory here
+     * or do any other thing that could block. */
+
+    int i, j;
+    JackData *self = arg;
+    float * buffer;
+    jack_nframes_t latency, cycle_delay;
+    AVPacket pkt;
+    float *pkt_data;
+    double cycle_time;
+
+    if (!self->client)
+        return 0;
+
+    /* The approximate delay since the hardware interrupt as a number of frames */
+    cycle_delay = jack_frames_since_cycle_start(self->client);
+
+    /* Retrieve filtered cycle time */
+    cycle_time = ff_timefilter_update(self->timefilter,
+                                      av_gettime() / 1000000.0 - (double) cycle_delay / self->sample_rate,
+                                      self->buffer_size);
+
+    /* Check if an empty packet is available, and if there's enough space to send it back once filled */
+    if ((av_fifo_size(self->new_pkts) < sizeof(pkt)) || (av_fifo_space(self->filled_pkts) < sizeof(pkt))) {
+        self->pkt_xrun = 1;
+        return 0;
+    }
+
+    /* Retrieve empty (but allocated) packet */
+    av_fifo_generic_read(self->new_pkts, &pkt, sizeof(pkt), NULL);
+
+    pkt_data  = (float *) pkt.data;
+    latency   = 0;
+
+    /* Copy and interleave audio data from the JACK buffer into the packet */
+    for (i = 0; i < self->nports; i++) {
+    #if HAVE_JACK_PORT_GET_LATENCY_RANGE
+        jack_latency_range_t range;
+        jack_port_get_latency_range(self->ports[i], JackCaptureLatency, &range);
+        latency += range.max;
+    #else
+        latency += jack_port_get_total_latency(self->client, self->ports[i]);
+    #endif
+        buffer = jack_port_get_buffer(self->ports[i], self->buffer_size);
+        for (j = 0; j < self->buffer_size; j++)
+            pkt_data[j * self->nports + i] = buffer[j];
+    }
+
+    /* Timestamp the packet with the cycle start time minus the average latency */
+    pkt.pts = (cycle_time - (double) latency / (self->nports * self->sample_rate)) * 1000000.0;
+
+    /* Send the now filled packet back, and increase packet counter */
+    av_fifo_generic_write(self->filled_pkts, &pkt, sizeof(pkt), NULL);
+    sem_post(&self->packet_count);
+
+    return 0;
+}
+
+static void shutdown_callback(void *arg)
+{
+    JackData *self = arg;
+    self->client = NULL;
+}
+
+static int xrun_callback(void *arg)
+{
+    JackData *self = arg;
+    self->jack_xrun = 1;
+    ff_timefilter_reset(self->timefilter);
+    return 0;
+}
+
+static int supply_new_packets(JackData *self, AVFormatContext *context)
+{
+    AVPacket pkt;
+    int test, pkt_size = self->buffer_size * self->nports * sizeof(float);
+
+    /* Supply the process callback with new empty packets, by filling the new
+     * packets FIFO buffer with as many packets as possible. process_callback()
+     * can't do this by itself, because it can't allocate memory in realtime. */
+    while (av_fifo_space(self->new_pkts) >= sizeof(pkt)) {
+        if ((test = av_new_packet(&pkt, pkt_size)) < 0) {
+            av_log(context, AV_LOG_ERROR, "Could not create packet of size %d\n", pkt_size);
+            return test;
+        }
+        av_fifo_generic_write(self->new_pkts, &pkt, sizeof(pkt), NULL);
+    }
+    return 0;
+}
+
+static int start_jack(AVFormatContext *context)
+{
+    JackData *self = context->priv_data;
+    jack_status_t status;
+    int i, test;
+    double o, period;
+
+    /* Register as a JACK client, using the context filename as client name. */
+    self->client = jack_client_open(context->filename, JackNullOption, &status);
+    if (!self->client) {
+        av_log(context, AV_LOG_ERROR, "Unable to register as a JACK client\n");
+        return AVERROR(EIO);
+    }
+
+    sem_init(&self->packet_count, 0, 0);
+
+    self->sample_rate = jack_get_sample_rate(self->client);
+    self->ports       = av_malloc(self->nports * sizeof(*self->ports));
+    self->buffer_size = jack_get_buffer_size(self->client);
+
+    /* Register JACK ports */
+    for (i = 0; i < self->nports; i++) {
+        char str[16];
+        snprintf(str, sizeof(str), "input_%d", i + 1);
+        self->ports[i] = jack_port_register(self->client, str,
+                                            JACK_DEFAULT_AUDIO_TYPE,
+                                            JackPortIsInput, 0);
+        if (!self->ports[i]) {
+            av_log(context, AV_LOG_ERROR, "Unable to register port %s:%s\n",
+                   context->filename, str);
+            jack_client_close(self->client);
+            return AVERROR(EIO);
+        }
+    }
+
+    /* Register JACK callbacks */
+    jack_set_process_callback(self->client, process_callback, self);
+    jack_on_shutdown(self->client, shutdown_callback, self);
+    jack_set_xrun_callback(self->client, xrun_callback, self);
+
+    /* Create time filter */
+    period            = (double) self->buffer_size / self->sample_rate;
+    o                 = 2 * M_PI * 1.5 * period; /// bandwidth: 1.5Hz
+    self->timefilter  = ff_timefilter_new (1.0 / self->sample_rate, sqrt(2 * o), o * o);
+    if (!self->timefilter) {
+        jack_client_close(self->client);
+        return AVERROR(ENOMEM);
+    }
+
+    /* Create FIFO buffers */
+    self->filled_pkts = av_fifo_alloc(FIFO_PACKETS_NUM * sizeof(AVPacket));
+    /* New packets FIFO with one extra packet for safety against underruns */
+    self->new_pkts    = av_fifo_alloc((FIFO_PACKETS_NUM + 1) * sizeof(AVPacket));
+    if ((test = supply_new_packets(self, context))) {
+        jack_client_close(self->client);
+        return test;
+    }
+
+    return 0;
+
+}
+
+static void free_pkt_fifo(AVFifoBuffer *fifo)
+{
+    AVPacket pkt;
+    while (av_fifo_size(fifo)) {
+        av_fifo_generic_read(fifo, &pkt, sizeof(pkt), NULL);
+        av_free_packet(&pkt);
+    }
+    av_fifo_free(fifo);
+}
+
+static void stop_jack(JackData *self)
+{
+    if (self->client) {
+        if (self->activated)
+            jack_deactivate(self->client);
+        jack_client_close(self->client);
+    }
+    sem_destroy(&self->packet_count);
+    free_pkt_fifo(self->new_pkts);
+    free_pkt_fifo(self->filled_pkts);
+    av_freep(&self->ports);
+    ff_timefilter_destroy(self->timefilter);
+}
+
+static int audio_read_header(AVFormatContext *context)
+{
+    JackData *self = context->priv_data;
+    AVStream *stream;
+    int test;
+
+    if ((test = start_jack(context)))
+        return test;
+
+    stream = avformat_new_stream(context, NULL);
+    if (!stream) {
+        stop_jack(self);
+        return AVERROR(ENOMEM);
+    }
+
+    stream->codec->codec_type   = AVMEDIA_TYPE_AUDIO;
+#if HAVE_BIGENDIAN
+    stream->codec->codec_id     = AV_CODEC_ID_PCM_F32BE;
+#else
+    stream->codec->codec_id     = AV_CODEC_ID_PCM_F32LE;
+#endif
+    stream->codec->sample_rate  = self->sample_rate;
+    stream->codec->channels     = self->nports;
+
+    avpriv_set_pts_info(stream, 64, 1, 1000000);  /* 64 bits pts in us */
+    return 0;
+}
+
+static int audio_read_packet(AVFormatContext *context, AVPacket *pkt)
+{
+    JackData *self = context->priv_data;
+    struct timespec timeout = {0, 0};
+    int test;
+
+    /* Activate the JACK client on first packet read. Activating the JACK client
+     * means that process_callback() starts to get called at regular interval.
+     * If we activate it in audio_read_header(), we're actually reading audio data
+     * from the device before instructed to, and that may result in an overrun. */
+    if (!self->activated) {
+        if (!jack_activate(self->client)) {
+            self->activated = 1;
+            av_log(context, AV_LOG_INFO,
+                   "JACK client registered and activated (rate=%dHz, buffer_size=%d frames)\n",
+                   self->sample_rate, self->buffer_size);
+        } else {
+            av_log(context, AV_LOG_ERROR, "Unable to activate JACK client\n");
+            return AVERROR(EIO);
+        }
+    }
+
+    /* Wait for a packet coming back from process_callback(), if one isn't available yet */
+    timeout.tv_sec = av_gettime() / 1000000 + 2;
+    if (sem_timedwait(&self->packet_count, &timeout)) {
+        if (errno == ETIMEDOUT) {
+            av_log(context, AV_LOG_ERROR,
+                   "Input error: timed out when waiting for JACK process callback output\n");
+        } else {
+            char errbuf[128];
+            int ret = AVERROR(errno);
+            av_strerror(ret, errbuf, sizeof(errbuf));
+            av_log(context, AV_LOG_ERROR, "Error while waiting for audio packet: %s\n",
+                   errbuf);
+        }
+        if (!self->client)
+            av_log(context, AV_LOG_ERROR, "Input error: JACK server is gone\n");
+
+        return AVERROR(EIO);
+    }
+
+    if (self->pkt_xrun) {
+        av_log(context, AV_LOG_WARNING, "Audio packet xrun\n");
+        self->pkt_xrun = 0;
+    }
+
+    if (self->jack_xrun) {
+        av_log(context, AV_LOG_WARNING, "JACK xrun\n");
+        self->jack_xrun = 0;
+    }
+
+    /* Retrieve the packet filled with audio data by process_callback() */
+    av_fifo_generic_read(self->filled_pkts, pkt, sizeof(*pkt), NULL);
+
+    if ((test = supply_new_packets(self, context)))
+        return test;
+
+    return 0;
+}
+
+static int audio_read_close(AVFormatContext *context)
+{
+    JackData *self = context->priv_data;
+    stop_jack(self);
+    return 0;
+}
+
+#define OFFSET(x) offsetof(JackData, x)
+static const AVOption options[] = {
+    { "channels", "Number of audio channels.", OFFSET(nports), AV_OPT_TYPE_INT, { .i64 = 2 }, 1, INT_MAX, AV_OPT_FLAG_DECODING_PARAM },
+    { NULL },
+};
+
+static const AVClass jack_indev_class = {
+    .class_name     = "JACK indev",
+    .item_name      = av_default_item_name,
+    .option         = options,
+    .version        = LIBAVUTIL_VERSION_INT,
+};
+
+AVInputFormat ff_jack_demuxer = {
+    .name           = "jack",
+    .long_name      = NULL_IF_CONFIG_SMALL("JACK Audio Connection Kit"),
+    .priv_data_size = sizeof(JackData),
+    .read_header    = audio_read_header,
+    .read_packet    = audio_read_packet,
+    .read_close     = audio_read_close,
+    .flags          = AVFMT_NOFILE,
+    .priv_class     = &jack_indev_class,
+};
diff --git a/libavdevice/jack_audio.c b/libavdevice/jack_audio.c
deleted file mode 100644 (file)
index fc5caa8..0000000
+++ /dev/null
@@ -1,353 +0,0 @@
-/*
- * JACK Audio Connection Kit input device
- * Copyright (c) 2009 Samalyse
- * Author: Olivier Guilyardi <olivier samalyse com>
- *
- * This file is part of Libav.
- *
- * Libav 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.
- *
- * Libav 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 Libav; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include "config.h"
-#include <semaphore.h>
-#include <jack/jack.h>
-
-#include "libavutil/internal.h"
-#include "libavutil/log.h"
-#include "libavutil/fifo.h"
-#include "libavutil/opt.h"
-#include "libavutil/time.h"
-#include "libavcodec/avcodec.h"
-#include "libavformat/avformat.h"
-#include "libavformat/internal.h"
-#include "timefilter.h"
-
-/**
- * Size of the internal FIFO buffers as a number of audio packets
- */
-#define FIFO_PACKETS_NUM 16
-
-typedef struct JackData {
-    AVClass        *class;
-    jack_client_t * client;
-    int             activated;
-    sem_t           packet_count;
-    jack_nframes_t  sample_rate;
-    jack_nframes_t  buffer_size;
-    jack_port_t **  ports;
-    int             nports;
-    TimeFilter *    timefilter;
-    AVFifoBuffer *  new_pkts;
-    AVFifoBuffer *  filled_pkts;
-    int             pkt_xrun;
-    int             jack_xrun;
-} JackData;
-
-static int process_callback(jack_nframes_t nframes, void *arg)
-{
-    /* Warning: this function runs in realtime. One mustn't allocate memory here
-     * or do any other thing that could block. */
-
-    int i, j;
-    JackData *self = arg;
-    float * buffer;
-    jack_nframes_t latency, cycle_delay;
-    AVPacket pkt;
-    float *pkt_data;
-    double cycle_time;
-
-    if (!self->client)
-        return 0;
-
-    /* The approximate delay since the hardware interrupt as a number of frames */
-    cycle_delay = jack_frames_since_cycle_start(self->client);
-
-    /* Retrieve filtered cycle time */
-    cycle_time = ff_timefilter_update(self->timefilter,
-                                      av_gettime() / 1000000.0 - (double) cycle_delay / self->sample_rate,
-                                      self->buffer_size);
-
-    /* Check if an empty packet is available, and if there's enough space to send it back once filled */
-    if ((av_fifo_size(self->new_pkts) < sizeof(pkt)) || (av_fifo_space(self->filled_pkts) < sizeof(pkt))) {
-        self->pkt_xrun = 1;
-        return 0;
-    }
-
-    /* Retrieve empty (but allocated) packet */
-    av_fifo_generic_read(self->new_pkts, &pkt, sizeof(pkt), NULL);
-
-    pkt_data  = (float *) pkt.data;
-    latency   = 0;
-
-    /* Copy and interleave audio data from the JACK buffer into the packet */
-    for (i = 0; i < self->nports; i++) {
-    #if HAVE_JACK_PORT_GET_LATENCY_RANGE
-        jack_latency_range_t range;
-        jack_port_get_latency_range(self->ports[i], JackCaptureLatency, &range);
-        latency += range.max;
-    #else
-        latency += jack_port_get_total_latency(self->client, self->ports[i]);
-    #endif
-        buffer = jack_port_get_buffer(self->ports[i], self->buffer_size);
-        for (j = 0; j < self->buffer_size; j++)
-            pkt_data[j * self->nports + i] = buffer[j];
-    }
-
-    /* Timestamp the packet with the cycle start time minus the average latency */
-    pkt.pts = (cycle_time - (double) latency / (self->nports * self->sample_rate)) * 1000000.0;
-
-    /* Send the now filled packet back, and increase packet counter */
-    av_fifo_generic_write(self->filled_pkts, &pkt, sizeof(pkt), NULL);
-    sem_post(&self->packet_count);
-
-    return 0;
-}
-
-static void shutdown_callback(void *arg)
-{
-    JackData *self = arg;
-    self->client = NULL;
-}
-
-static int xrun_callback(void *arg)
-{
-    JackData *self = arg;
-    self->jack_xrun = 1;
-    ff_timefilter_reset(self->timefilter);
-    return 0;
-}
-
-static int supply_new_packets(JackData *self, AVFormatContext *context)
-{
-    AVPacket pkt;
-    int test, pkt_size = self->buffer_size * self->nports * sizeof(float);
-
-    /* Supply the process callback with new empty packets, by filling the new
-     * packets FIFO buffer with as many packets as possible. process_callback()
-     * can't do this by itself, because it can't allocate memory in realtime. */
-    while (av_fifo_space(self->new_pkts) >= sizeof(pkt)) {
-        if ((test = av_new_packet(&pkt, pkt_size)) < 0) {
-            av_log(context, AV_LOG_ERROR, "Could not create packet of size %d\n", pkt_size);
-            return test;
-        }
-        av_fifo_generic_write(self->new_pkts, &pkt, sizeof(pkt), NULL);
-    }
-    return 0;
-}
-
-static int start_jack(AVFormatContext *context)
-{
-    JackData *self = context->priv_data;
-    jack_status_t status;
-    int i, test;
-    double o, period;
-
-    /* Register as a JACK client, using the context filename as client name. */
-    self->client = jack_client_open(context->filename, JackNullOption, &status);
-    if (!self->client) {
-        av_log(context, AV_LOG_ERROR, "Unable to register as a JACK client\n");
-        return AVERROR(EIO);
-    }
-
-    sem_init(&self->packet_count, 0, 0);
-
-    self->sample_rate = jack_get_sample_rate(self->client);
-    self->ports       = av_malloc(self->nports * sizeof(*self->ports));
-    self->buffer_size = jack_get_buffer_size(self->client);
-
-    /* Register JACK ports */
-    for (i = 0; i < self->nports; i++) {
-        char str[16];
-        snprintf(str, sizeof(str), "input_%d", i + 1);
-        self->ports[i] = jack_port_register(self->client, str,
-                                            JACK_DEFAULT_AUDIO_TYPE,
-                                            JackPortIsInput, 0);
-        if (!self->ports[i]) {
-            av_log(context, AV_LOG_ERROR, "Unable to register port %s:%s\n",
-                   context->filename, str);
-            jack_client_close(self->client);
-            return AVERROR(EIO);
-        }
-    }
-
-    /* Register JACK callbacks */
-    jack_set_process_callback(self->client, process_callback, self);
-    jack_on_shutdown(self->client, shutdown_callback, self);
-    jack_set_xrun_callback(self->client, xrun_callback, self);
-
-    /* Create time filter */
-    period            = (double) self->buffer_size / self->sample_rate;
-    o                 = 2 * M_PI * 1.5 * period; /// bandwidth: 1.5Hz
-    self->timefilter  = ff_timefilter_new (1.0 / self->sample_rate, sqrt(2 * o), o * o);
-    if (!self->timefilter) {
-        jack_client_close(self->client);
-        return AVERROR(ENOMEM);
-    }
-
-    /* Create FIFO buffers */
-    self->filled_pkts = av_fifo_alloc(FIFO_PACKETS_NUM * sizeof(AVPacket));
-    /* New packets FIFO with one extra packet for safety against underruns */
-    self->new_pkts    = av_fifo_alloc((FIFO_PACKETS_NUM + 1) * sizeof(AVPacket));
-    if ((test = supply_new_packets(self, context))) {
-        jack_client_close(self->client);
-        return test;
-    }
-
-    return 0;
-
-}
-
-static void free_pkt_fifo(AVFifoBuffer *fifo)
-{
-    AVPacket pkt;
-    while (av_fifo_size(fifo)) {
-        av_fifo_generic_read(fifo, &pkt, sizeof(pkt), NULL);
-        av_free_packet(&pkt);
-    }
-    av_fifo_free(fifo);
-}
-
-static void stop_jack(JackData *self)
-{
-    if (self->client) {
-        if (self->activated)
-            jack_deactivate(self->client);
-        jack_client_close(self->client);
-    }
-    sem_destroy(&self->packet_count);
-    free_pkt_fifo(self->new_pkts);
-    free_pkt_fifo(self->filled_pkts);
-    av_freep(&self->ports);
-    ff_timefilter_destroy(self->timefilter);
-}
-
-static int audio_read_header(AVFormatContext *context)
-{
-    JackData *self = context->priv_data;
-    AVStream *stream;
-    int test;
-
-    if ((test = start_jack(context)))
-        return test;
-
-    stream = avformat_new_stream(context, NULL);
-    if (!stream) {
-        stop_jack(self);
-        return AVERROR(ENOMEM);
-    }
-
-    stream->codec->codec_type   = AVMEDIA_TYPE_AUDIO;
-#if HAVE_BIGENDIAN
-    stream->codec->codec_id     = AV_CODEC_ID_PCM_F32BE;
-#else
-    stream->codec->codec_id     = AV_CODEC_ID_PCM_F32LE;
-#endif
-    stream->codec->sample_rate  = self->sample_rate;
-    stream->codec->channels     = self->nports;
-
-    avpriv_set_pts_info(stream, 64, 1, 1000000);  /* 64 bits pts in us */
-    return 0;
-}
-
-static int audio_read_packet(AVFormatContext *context, AVPacket *pkt)
-{
-    JackData *self = context->priv_data;
-    struct timespec timeout = {0, 0};
-    int test;
-
-    /* Activate the JACK client on first packet read. Activating the JACK client
-     * means that process_callback() starts to get called at regular interval.
-     * If we activate it in audio_read_header(), we're actually reading audio data
-     * from the device before instructed to, and that may result in an overrun. */
-    if (!self->activated) {
-        if (!jack_activate(self->client)) {
-            self->activated = 1;
-            av_log(context, AV_LOG_INFO,
-                   "JACK client registered and activated (rate=%dHz, buffer_size=%d frames)\n",
-                   self->sample_rate, self->buffer_size);
-        } else {
-            av_log(context, AV_LOG_ERROR, "Unable to activate JACK client\n");
-            return AVERROR(EIO);
-        }
-    }
-
-    /* Wait for a packet coming back from process_callback(), if one isn't available yet */
-    timeout.tv_sec = av_gettime() / 1000000 + 2;
-    if (sem_timedwait(&self->packet_count, &timeout)) {
-        if (errno == ETIMEDOUT) {
-            av_log(context, AV_LOG_ERROR,
-                   "Input error: timed out when waiting for JACK process callback output\n");
-        } else {
-            char errbuf[128];
-            int ret = AVERROR(errno);
-            av_strerror(ret, errbuf, sizeof(errbuf));
-            av_log(context, AV_LOG_ERROR, "Error while waiting for audio packet: %s\n",
-                   errbuf);
-        }
-        if (!self->client)
-            av_log(context, AV_LOG_ERROR, "Input error: JACK server is gone\n");
-
-        return AVERROR(EIO);
-    }
-
-    if (self->pkt_xrun) {
-        av_log(context, AV_LOG_WARNING, "Audio packet xrun\n");
-        self->pkt_xrun = 0;
-    }
-
-    if (self->jack_xrun) {
-        av_log(context, AV_LOG_WARNING, "JACK xrun\n");
-        self->jack_xrun = 0;
-    }
-
-    /* Retrieve the packet filled with audio data by process_callback() */
-    av_fifo_generic_read(self->filled_pkts, pkt, sizeof(*pkt), NULL);
-
-    if ((test = supply_new_packets(self, context)))
-        return test;
-
-    return 0;
-}
-
-static int audio_read_close(AVFormatContext *context)
-{
-    JackData *self = context->priv_data;
-    stop_jack(self);
-    return 0;
-}
-
-#define OFFSET(x) offsetof(JackData, x)
-static const AVOption options[] = {
-    { "channels", "Number of audio channels.", OFFSET(nports), AV_OPT_TYPE_INT, { .i64 = 2 }, 1, INT_MAX, AV_OPT_FLAG_DECODING_PARAM },
-    { NULL },
-};
-
-static const AVClass jack_indev_class = {
-    .class_name     = "JACK indev",
-    .item_name      = av_default_item_name,
-    .option         = options,
-    .version        = LIBAVUTIL_VERSION_INT,
-};
-
-AVInputFormat ff_jack_demuxer = {
-    .name           = "jack",
-    .long_name      = NULL_IF_CONFIG_SMALL("JACK Audio Connection Kit"),
-    .priv_data_size = sizeof(JackData),
-    .read_header    = audio_read_header,
-    .read_packet    = audio_read_packet,
-    .read_close     = audio_read_close,
-    .flags          = AVFMT_NOFILE,
-    .priv_class     = &jack_indev_class,
-};
diff --git a/libavdevice/oss.c b/libavdevice/oss.c
new file mode 100644 (file)
index 0000000..eb8d454
--- /dev/null
@@ -0,0 +1,139 @@
+/*
+ * Linux audio play and grab interface
+ * Copyright (c) 2000, 2001 Fabrice Bellard
+ *
+ * This file is part of Libav.
+ *
+ * Libav 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.
+ *
+ * Libav 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 Libav; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "config.h"
+
+#include <string.h>
+
+#if HAVE_SOUNDCARD_H
+#include <soundcard.h>
+#else
+#include <sys/soundcard.h>
+#endif
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+
+#include "libavutil/log.h"
+
+#include "libavcodec/avcodec.h"
+
+#include "libavformat/avformat.h"
+
+#include "oss.h"
+
+int ff_oss_audio_open(AVFormatContext *s1, int is_output,
+                      const char *audio_device)
+{
+    OSSAudioData *s = s1->priv_data;
+    int audio_fd;
+    int tmp, err;
+    char *flip = getenv("AUDIO_FLIP_LEFT");
+    char errbuff[128];
+
+    if (is_output)
+        audio_fd = avpriv_open(audio_device, O_WRONLY);
+    else
+        audio_fd = avpriv_open(audio_device, O_RDONLY);
+    if (audio_fd < 0) {
+        av_log(s1, AV_LOG_ERROR, "%s: %s\n", audio_device, strerror(errno));
+        return AVERROR(EIO);
+    }
+
+    if (flip && *flip == '1') {
+        s->flip_left = 1;
+    }
+
+    /* non blocking mode */
+    if (!is_output)
+        fcntl(audio_fd, F_SETFL, O_NONBLOCK);
+
+    s->frame_size = OSS_AUDIO_BLOCK_SIZE;
+
+#define CHECK_IOCTL_ERROR(event)                                              \
+    if (err < 0) {                                                            \
+        av_strerror(AVERROR(errno), errbuff, sizeof(errbuff));                \
+        av_log(s1, AV_LOG_ERROR, #event ": %s\n", errbuff);                   \
+        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. */
+    (void) 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;
+        break;
+    case AFMT_S16_BE:
+        s->codec_id = AV_CODEC_ID_PCM_S16BE;
+        break;
+    default:
+        av_log(s1, AV_LOG_ERROR, "Soundcard does not support 16 bit sample format\n");
+        close(audio_fd);
+        return AVERROR(EIO);
+    }
+    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 */
+    s->fd = audio_fd;
+
+    return 0;
+ fail:
+    close(audio_fd);
+    return AVERROR(EIO);
+#undef CHECK_IOCTL_ERROR
+}
+
+int ff_oss_audio_close(OSSAudioData *s)
+{
+    close(s->fd);
+    return 0;
+}
diff --git a/libavdevice/oss.h b/libavdevice/oss.h
new file mode 100644 (file)
index 0000000..0fbe14b
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * This file is part of Libav.
+ *
+ * Libav 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.
+ *
+ * Libav 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 Libav; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AVDEVICE_OSS_H
+#define AVDEVICE_OSS_H
+
+#include "libavcodec/avcodec.h"
+
+#include "libavformat/avformat.h"
+
+#define OSS_AUDIO_BLOCK_SIZE 4096
+
+typedef struct OSSAudioData {
+    AVClass *class;
+    int fd;
+    int sample_rate;
+    int channels;
+    int frame_size; /* in bytes ! */
+    enum AVCodecID codec_id;
+    unsigned int flip_left : 1;
+    uint8_t buffer[OSS_AUDIO_BLOCK_SIZE];
+    int buffer_ptr;
+} OSSAudioData;
+
+int ff_oss_audio_open(AVFormatContext *s1, int is_output,
+                      const char *audio_device);
+
+int ff_oss_audio_close(OSSAudioData *s);
+
+#endif /* AVDEVICE_OSS_H */
diff --git a/libavdevice/oss_audio.c b/libavdevice/oss_audio.c
deleted file mode 100644 (file)
index 4feb937..0000000
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * Linux audio play and grab interface
- * Copyright (c) 2000, 2001 Fabrice Bellard
- *
- * This file is part of Libav.
- *
- * Libav 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.
- *
- * Libav 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 Libav; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include "config.h"
-
-#include <string.h>
-
-#if HAVE_SOUNDCARD_H
-#include <soundcard.h>
-#else
-#include <sys/soundcard.h>
-#endif
-
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/ioctl.h>
-
-#include "libavutil/log.h"
-
-#include "libavcodec/avcodec.h"
-
-#include "libavformat/avformat.h"
-
-#include "oss_audio.h"
-
-int ff_oss_audio_open(AVFormatContext *s1, int is_output,
-                      const char *audio_device)
-{
-    OSSAudioData *s = s1->priv_data;
-    int audio_fd;
-    int tmp, err;
-    char *flip = getenv("AUDIO_FLIP_LEFT");
-    char errbuff[128];
-
-    if (is_output)
-        audio_fd = avpriv_open(audio_device, O_WRONLY);
-    else
-        audio_fd = avpriv_open(audio_device, O_RDONLY);
-    if (audio_fd < 0) {
-        av_log(s1, AV_LOG_ERROR, "%s: %s\n", audio_device, strerror(errno));
-        return AVERROR(EIO);
-    }
-
-    if (flip && *flip == '1') {
-        s->flip_left = 1;
-    }
-
-    /* non blocking mode */
-    if (!is_output)
-        fcntl(audio_fd, F_SETFL, O_NONBLOCK);
-
-    s->frame_size = OSS_AUDIO_BLOCK_SIZE;
-
-#define CHECK_IOCTL_ERROR(event)                                              \
-    if (err < 0) {                                                            \
-        av_strerror(AVERROR(errno), errbuff, sizeof(errbuff));                \
-        av_log(s1, AV_LOG_ERROR, #event ": %s\n", errbuff);                   \
-        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. */
-    (void) 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;
-        break;
-    case AFMT_S16_BE:
-        s->codec_id = AV_CODEC_ID_PCM_S16BE;
-        break;
-    default:
-        av_log(s1, AV_LOG_ERROR, "Soundcard does not support 16 bit sample format\n");
-        close(audio_fd);
-        return AVERROR(EIO);
-    }
-    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 */
-    s->fd = audio_fd;
-
-    return 0;
- fail:
-    close(audio_fd);
-    return AVERROR(EIO);
-#undef CHECK_IOCTL_ERROR
-}
-
-int ff_oss_audio_close(OSSAudioData *s)
-{
-    close(s->fd);
-    return 0;
-}
diff --git a/libavdevice/oss_audio.h b/libavdevice/oss_audio.h
deleted file mode 100644 (file)
index 87ac4ad..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * This file is part of Libav.
- *
- * Libav 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.
- *
- * Libav 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 Libav; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#ifndef AVDEVICE_OSS_AUDIO_H
-#define AVDEVICE_OSS_AUDIO_H
-
-#include "libavcodec/avcodec.h"
-
-#include "libavformat/avformat.h"
-
-#define OSS_AUDIO_BLOCK_SIZE 4096
-
-typedef struct OSSAudioData {
-    AVClass *class;
-    int fd;
-    int sample_rate;
-    int channels;
-    int frame_size; /* in bytes ! */
-    enum AVCodecID codec_id;
-    unsigned int flip_left : 1;
-    uint8_t buffer[OSS_AUDIO_BLOCK_SIZE];
-    int buffer_ptr;
-} OSSAudioData;
-
-int ff_oss_audio_open(AVFormatContext *s1, int is_output,
-                      const char *audio_device);
-
-int ff_oss_audio_close(OSSAudioData *s);
-
-#endif /* AVDEVICE_OSS_AUDIO_H */
diff --git a/libavdevice/oss_audio_dec.c b/libavdevice/oss_audio_dec.c
deleted file mode 100644 (file)
index 601d91c..0000000
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * Linux audio play interface
- * Copyright (c) 2000, 2001 Fabrice Bellard
- *
- * This file is part of Libav.
- *
- * Libav 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.
- *
- * Libav 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 Libav; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include "config.h"
-
-#include <stdint.h>
-
-#if HAVE_SOUNDCARD_H
-#include <soundcard.h>
-#else
-#include <sys/soundcard.h>
-#endif
-
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/ioctl.h>
-
-#include "libavutil/internal.h"
-#include "libavutil/opt.h"
-#include "libavutil/time.h"
-
-#include "libavcodec/avcodec.h"
-
-#include "libavformat/avformat.h"
-#include "libavformat/internal.h"
-
-#include "oss_audio.h"
-
-static int audio_read_header(AVFormatContext *s1)
-{
-    OSSAudioData *s = s1->priv_data;
-    AVStream *st;
-    int ret;
-
-    st = avformat_new_stream(s1, NULL);
-    if (!st) {
-        return AVERROR(ENOMEM);
-    }
-
-    ret = ff_oss_audio_open(s1, 0, s1->filename);
-    if (ret < 0) {
-        return AVERROR(EIO);
-    }
-
-    /* take real parameters */
-    st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
-    st->codec->codec_id = s->codec_id;
-    st->codec->sample_rate = s->sample_rate;
-    st->codec->channels = s->channels;
-
-    avpriv_set_pts_info(st, 64, 1, 1000000);  /* 64 bits pts in us */
-    return 0;
-}
-
-static int audio_read_packet(AVFormatContext *s1, AVPacket *pkt)
-{
-    OSSAudioData *s = s1->priv_data;
-    int ret, bdelay;
-    int64_t cur_time;
-    struct audio_buf_info abufi;
-
-    if ((ret=av_new_packet(pkt, s->frame_size)) < 0)
-        return ret;
-
-    ret = read(s->fd, pkt->data, pkt->size);
-    if (ret <= 0){
-        av_free_packet(pkt);
-        pkt->size = 0;
-        if (ret<0)  return AVERROR(errno);
-        else        return AVERROR_EOF;
-    }
-    pkt->size = ret;
-
-    /* compute pts of the start of the packet */
-    cur_time = av_gettime();
-    bdelay = ret;
-    if (ioctl(s->fd, SNDCTL_DSP_GETISPACE, &abufi) == 0) {
-        bdelay += abufi.bytes;
-    }
-    /* subtract time represented by the number of bytes in the audio fifo */
-    cur_time -= (bdelay * 1000000LL) / (s->sample_rate * s->channels);
-
-    /* convert to wanted units */
-    pkt->pts = cur_time;
-
-    if (s->flip_left && s->channels == 2) {
-        int i;
-        short *p = (short *) pkt->data;
-
-        for (i = 0; i < ret; i += 4) {
-            *p = ~*p;
-            p += 2;
-        }
-    }
-    return 0;
-}
-
-static int audio_read_close(AVFormatContext *s1)
-{
-    OSSAudioData *s = s1->priv_data;
-
-    ff_oss_audio_close(s);
-    return 0;
-}
-
-static const AVOption options[] = {
-    { "sample_rate", "", offsetof(OSSAudioData, sample_rate), AV_OPT_TYPE_INT, {.i64 = 48000}, 1, INT_MAX, AV_OPT_FLAG_DECODING_PARAM },
-    { "channels",    "", offsetof(OSSAudioData, channels),    AV_OPT_TYPE_INT, {.i64 = 2},     1, INT_MAX, AV_OPT_FLAG_DECODING_PARAM },
-    { NULL },
-};
-
-static const AVClass oss_demuxer_class = {
-    .class_name     = "OSS demuxer",
-    .item_name      = av_default_item_name,
-    .option         = options,
-    .version        = LIBAVUTIL_VERSION_INT,
-};
-
-AVInputFormat ff_oss_demuxer = {
-    .name           = "oss",
-    .long_name      = NULL_IF_CONFIG_SMALL("OSS (Open Sound System) capture"),
-    .priv_data_size = sizeof(OSSAudioData),
-    .read_header    = audio_read_header,
-    .read_packet    = audio_read_packet,
-    .read_close     = audio_read_close,
-    .flags          = AVFMT_NOFILE,
-    .priv_class     = &oss_demuxer_class,
-};
diff --git a/libavdevice/oss_audio_enc.c b/libavdevice/oss_audio_enc.c
deleted file mode 100644 (file)
index 688982a..0000000
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Linux audio grab interface
- * Copyright (c) 2000, 2001 Fabrice Bellard
- *
- * This file is part of Libav.
- *
- * Libav 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.
- *
- * Libav 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 Libav; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include "config.h"
-
-#if HAVE_SOUNDCARD_H
-#include <soundcard.h>
-#else
-#include <sys/soundcard.h>
-#endif
-
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/ioctl.h>
-
-#include "libavutil/internal.h"
-
-#include "libavcodec/avcodec.h"
-
-#include "libavformat/avformat.h"
-#include "libavformat/internal.h"
-
-#include "oss_audio.h"
-
-static int audio_write_header(AVFormatContext *s1)
-{
-    OSSAudioData *s = s1->priv_data;
-    AVStream *st;
-    int ret;
-
-    st = s1->streams[0];
-    s->sample_rate = st->codec->sample_rate;
-    s->channels = st->codec->channels;
-    ret = ff_oss_audio_open(s1, 1, s1->filename);
-    if (ret < 0) {
-        return AVERROR(EIO);
-    } else {
-        return 0;
-    }
-}
-
-static int audio_write_packet(AVFormatContext *s1, AVPacket *pkt)
-{
-    OSSAudioData *s = s1->priv_data;
-    int len, ret;
-    int size= pkt->size;
-    uint8_t *buf= pkt->data;
-
-    while (size > 0) {
-        len = FFMIN(OSS_AUDIO_BLOCK_SIZE - s->buffer_ptr, size);
-        memcpy(s->buffer + s->buffer_ptr, buf, len);
-        s->buffer_ptr += len;
-        if (s->buffer_ptr >= OSS_AUDIO_BLOCK_SIZE) {
-            for(;;) {
-                ret = write(s->fd, s->buffer, OSS_AUDIO_BLOCK_SIZE);
-                if (ret > 0)
-                    break;
-                if (ret < 0 && (errno != EAGAIN && errno != EINTR))
-                    return AVERROR(EIO);
-            }
-            s->buffer_ptr = 0;
-        }
-        buf += len;
-        size -= len;
-    }
-    return 0;
-}
-
-static int audio_write_trailer(AVFormatContext *s1)
-{
-    OSSAudioData *s = s1->priv_data;
-
-    ff_oss_audio_close(s);
-    return 0;
-}
-
-AVOutputFormat ff_oss_muxer = {
-    .name           = "oss",
-    .long_name      = NULL_IF_CONFIG_SMALL("OSS (Open Sound System) playback"),
-    .priv_data_size = sizeof(OSSAudioData),
-    /* XXX: we make the assumption that the soundcard accepts this format */
-    /* XXX: find better solution with "preinit" method, needed also in
-       other formats */
-    .audio_codec    = AV_NE(AV_CODEC_ID_PCM_S16BE, AV_CODEC_ID_PCM_S16LE),
-    .video_codec    = AV_CODEC_ID_NONE,
-    .write_header   = audio_write_header,
-    .write_packet   = audio_write_packet,
-    .write_trailer  = audio_write_trailer,
-    .flags          = AVFMT_NOFILE,
-};
diff --git a/libavdevice/oss_dec.c b/libavdevice/oss_dec.c
new file mode 100644 (file)
index 0000000..3f786cc
--- /dev/null
@@ -0,0 +1,146 @@
+/*
+ * Linux audio play interface
+ * Copyright (c) 2000, 2001 Fabrice Bellard
+ *
+ * This file is part of Libav.
+ *
+ * Libav 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.
+ *
+ * Libav 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 Libav; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "config.h"
+
+#include <stdint.h>
+
+#if HAVE_SOUNDCARD_H
+#include <soundcard.h>
+#else
+#include <sys/soundcard.h>
+#endif
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+
+#include "libavutil/internal.h"
+#include "libavutil/opt.h"
+#include "libavutil/time.h"
+
+#include "libavcodec/avcodec.h"
+
+#include "libavformat/avformat.h"
+#include "libavformat/internal.h"
+
+#include "oss.h"
+
+static int audio_read_header(AVFormatContext *s1)
+{
+    OSSAudioData *s = s1->priv_data;
+    AVStream *st;
+    int ret;
+
+    st = avformat_new_stream(s1, NULL);
+    if (!st) {
+        return AVERROR(ENOMEM);
+    }
+
+    ret = ff_oss_audio_open(s1, 0, s1->filename);
+    if (ret < 0) {
+        return AVERROR(EIO);
+    }
+
+    /* take real parameters */
+    st->codec->codec_type = AVMEDIA_TYPE_AUDIO;
+    st->codec->codec_id = s->codec_id;
+    st->codec->sample_rate = s->sample_rate;
+    st->codec->channels = s->channels;
+
+    avpriv_set_pts_info(st, 64, 1, 1000000);  /* 64 bits pts in us */
+    return 0;
+}
+
+static int audio_read_packet(AVFormatContext *s1, AVPacket *pkt)
+{
+    OSSAudioData *s = s1->priv_data;
+    int ret, bdelay;
+    int64_t cur_time;
+    struct audio_buf_info abufi;
+
+    if ((ret=av_new_packet(pkt, s->frame_size)) < 0)
+        return ret;
+
+    ret = read(s->fd, pkt->data, pkt->size);
+    if (ret <= 0){
+        av_free_packet(pkt);
+        pkt->size = 0;
+        if (ret<0)  return AVERROR(errno);
+        else        return AVERROR_EOF;
+    }
+    pkt->size = ret;
+
+    /* compute pts of the start of the packet */
+    cur_time = av_gettime();
+    bdelay = ret;
+    if (ioctl(s->fd, SNDCTL_DSP_GETISPACE, &abufi) == 0) {
+        bdelay += abufi.bytes;
+    }
+    /* subtract time represented by the number of bytes in the audio fifo */
+    cur_time -= (bdelay * 1000000LL) / (s->sample_rate * s->channels);
+
+    /* convert to wanted units */
+    pkt->pts = cur_time;
+
+    if (s->flip_left && s->channels == 2) {
+        int i;
+        short *p = (short *) pkt->data;
+
+        for (i = 0; i < ret; i += 4) {
+            *p = ~*p;
+            p += 2;
+        }
+    }
+    return 0;
+}
+
+static int audio_read_close(AVFormatContext *s1)
+{
+    OSSAudioData *s = s1->priv_data;
+
+    ff_oss_audio_close(s);
+    return 0;
+}
+
+static const AVOption options[] = {
+    { "sample_rate", "", offsetof(OSSAudioData, sample_rate), AV_OPT_TYPE_INT, {.i64 = 48000}, 1, INT_MAX, AV_OPT_FLAG_DECODING_PARAM },
+    { "channels",    "", offsetof(OSSAudioData, channels),    AV_OPT_TYPE_INT, {.i64 = 2},     1, INT_MAX, AV_OPT_FLAG_DECODING_PARAM },
+    { NULL },
+};
+
+static const AVClass oss_demuxer_class = {
+    .class_name     = "OSS demuxer",
+    .item_name      = av_default_item_name,
+    .option         = options,
+    .version        = LIBAVUTIL_VERSION_INT,
+};
+
+AVInputFormat ff_oss_demuxer = {
+    .name           = "oss",
+    .long_name      = NULL_IF_CONFIG_SMALL("OSS (Open Sound System) capture"),
+    .priv_data_size = sizeof(OSSAudioData),
+    .read_header    = audio_read_header,
+    .read_packet    = audio_read_packet,
+    .read_close     = audio_read_close,
+    .flags          = AVFMT_NOFILE,
+    .priv_class     = &oss_demuxer_class,
+};
diff --git a/libavdevice/oss_enc.c b/libavdevice/oss_enc.c
new file mode 100644 (file)
index 0000000..2f07558
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ * Linux audio grab interface
+ * Copyright (c) 2000, 2001 Fabrice Bellard
+ *
+ * This file is part of Libav.
+ *
+ * Libav 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.
+ *
+ * Libav 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 Libav; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "config.h"
+
+#if HAVE_SOUNDCARD_H
+#include <soundcard.h>
+#else
+#include <sys/soundcard.h>
+#endif
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+
+#include "libavutil/internal.h"
+
+#include "libavcodec/avcodec.h"
+
+#include "libavformat/avformat.h"
+#include "libavformat/internal.h"
+
+#include "oss.h"
+
+static int audio_write_header(AVFormatContext *s1)
+{
+    OSSAudioData *s = s1->priv_data;
+    AVStream *st;
+    int ret;
+
+    st = s1->streams[0];
+    s->sample_rate = st->codec->sample_rate;
+    s->channels = st->codec->channels;
+    ret = ff_oss_audio_open(s1, 1, s1->filename);
+    if (ret < 0) {
+        return AVERROR(EIO);
+    } else {
+        return 0;
+    }
+}
+
+static int audio_write_packet(AVFormatContext *s1, AVPacket *pkt)
+{
+    OSSAudioData *s = s1->priv_data;
+    int len, ret;
+    int size= pkt->size;
+    uint8_t *buf= pkt->data;
+
+    while (size > 0) {
+        len = FFMIN(OSS_AUDIO_BLOCK_SIZE - s->buffer_ptr, size);
+        memcpy(s->buffer + s->buffer_ptr, buf, len);
+        s->buffer_ptr += len;
+        if (s->buffer_ptr >= OSS_AUDIO_BLOCK_SIZE) {
+            for(;;) {
+                ret = write(s->fd, s->buffer, OSS_AUDIO_BLOCK_SIZE);
+                if (ret > 0)
+                    break;
+                if (ret < 0 && (errno != EAGAIN && errno != EINTR))
+                    return AVERROR(EIO);
+            }
+            s->buffer_ptr = 0;
+        }
+        buf += len;
+        size -= len;
+    }
+    return 0;
+}
+
+static int audio_write_trailer(AVFormatContext *s1)
+{
+    OSSAudioData *s = s1->priv_data;
+
+    ff_oss_audio_close(s);
+    return 0;
+}
+
+AVOutputFormat ff_oss_muxer = {
+    .name           = "oss",
+    .long_name      = NULL_IF_CONFIG_SMALL("OSS (Open Sound System) playback"),
+    .priv_data_size = sizeof(OSSAudioData),
+    /* XXX: we make the assumption that the soundcard accepts this format */
+    /* XXX: find better solution with "preinit" method, needed also in
+       other formats */
+    .audio_codec    = AV_NE(AV_CODEC_ID_PCM_S16BE, AV_CODEC_ID_PCM_S16LE),
+    .video_codec    = AV_CODEC_ID_NONE,
+    .write_header   = audio_write_header,
+    .write_packet   = audio_write_packet,
+    .write_trailer  = audio_write_trailer,
+    .flags          = AVFMT_NOFILE,
+};
diff --git a/libavdevice/sndio.c b/libavdevice/sndio.c
new file mode 100644 (file)
index 0000000..739551b
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+ * sndio play and grab interface
+ * Copyright (c) 2010 Jacob Meuser
+ *
+ * This file is part of Libav.
+ *
+ * Libav 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.
+ *
+ * Libav 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 Libav; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <stdint.h>
+#include <sndio.h>
+
+#include "libavformat/avformat.h"
+
+#include "libavdevice/sndio.h"
+
+static inline void movecb(void *addr, int delta)
+{
+    SndioData *s = addr;
+
+    s->hwpos += delta * s->channels * s->bps;
+}
+
+av_cold int ff_sndio_open(AVFormatContext *s1, int is_output,
+                          const char *audio_device)
+{
+    SndioData *s = s1->priv_data;
+    struct sio_hdl *hdl;
+    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.rate = s->sample_rate;
+
+    if (!sio_setpar(hdl, &par) || !sio_getpar(hdl, &par)) {
+        av_log(s1, AV_LOG_ERROR, "Impossible to set sndio parameters, "
+               "channels: %d sample rate: %d\n", s->channels, s->sample_rate);
+        goto fail;
+    }
+
+    if (par.bits != 16 || par.sig != 1 ||
+        (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, "
+               "channels: %d sample rate: %d\n", s->channels, s->sample_rate);
+        goto fail;
+    }
+
+    s->buffer_size = par.round * par.bps *
+                     (is_output ? par.pchan : par.rchan);
+
+    if (is_output) {
+        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 ? AV_CODEC_ID_PCM_S16LE : AV_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:
+    av_freep(&s->buffer);
+
+    if (hdl)
+        sio_close(hdl);
+
+    return AVERROR(EIO);
+}
+
+int ff_sndio_close(SndioData *s)
+{
+    av_freep(&s->buffer);
+
+    if (s->hdl)
+        sio_close(s->hdl);
+
+    return 0;
+}
diff --git a/libavdevice/sndio.h b/libavdevice/sndio.h
new file mode 100644 (file)
index 0000000..cd5c55e
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * sndio play and grab interface
+ * Copyright (c) 2010 Jacob Meuser
+ *
+ * This file is part of Libav.
+ *
+ * Libav 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.
+ *
+ * Libav 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 Libav; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AVDEVICE_SNDIO_H
+#define AVDEVICE_SNDIO_H
+
+#include <stdint.h>
+#include <sndio.h>
+
+#include "libavformat/avformat.h"
+#include "libavutil/log.h"
+
+typedef struct SndioData {
+    AVClass *class;
+    struct sio_hdl *hdl;
+    enum AVCodecID codec_id;
+    int64_t hwpos;
+    int64_t softpos;
+    uint8_t *buffer;
+    int bps;
+    int buffer_size;
+    int buffer_offset;
+    int channels;
+    int sample_rate;
+} SndioData;
+
+int ff_sndio_open(AVFormatContext *s1, int is_output, const char *audio_device);
+int ff_sndio_close(SndioData *s);
+
+#endif /* AVDEVICE_SNDIO_H */
diff --git a/libavdevice/sndio_common.c b/libavdevice/sndio_common.c
deleted file mode 100644 (file)
index 1bea6c5..0000000
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * sndio play and grab interface
- * Copyright (c) 2010 Jacob Meuser
- *
- * This file is part of Libav.
- *
- * Libav 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.
- *
- * Libav 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 Libav; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include <stdint.h>
-#include <sndio.h>
-
-#include "libavformat/avformat.h"
-
-#include "sndio_common.h"
-
-static inline void movecb(void *addr, int delta)
-{
-    SndioData *s = addr;
-
-    s->hwpos += delta * s->channels * s->bps;
-}
-
-av_cold int ff_sndio_open(AVFormatContext *s1, int is_output,
-                          const char *audio_device)
-{
-    SndioData *s = s1->priv_data;
-    struct sio_hdl *hdl;
-    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.rate = s->sample_rate;
-
-    if (!sio_setpar(hdl, &par) || !sio_getpar(hdl, &par)) {
-        av_log(s1, AV_LOG_ERROR, "Impossible to set sndio parameters, "
-               "channels: %d sample rate: %d\n", s->channels, s->sample_rate);
-        goto fail;
-    }
-
-    if (par.bits != 16 || par.sig != 1 ||
-        (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, "
-               "channels: %d sample rate: %d\n", s->channels, s->sample_rate);
-        goto fail;
-    }
-
-    s->buffer_size = par.round * par.bps *
-                     (is_output ? par.pchan : par.rchan);
-
-    if (is_output) {
-        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 ? AV_CODEC_ID_PCM_S16LE : AV_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:
-    av_freep(&s->buffer);
-
-    if (hdl)
-        sio_close(hdl);
-
-    return AVERROR(EIO);
-}
-
-int ff_sndio_close(SndioData *s)
-{
-    av_freep(&s->buffer);
-
-    if (s->hdl)
-        sio_close(s->hdl);
-
-    return 0;
-}
diff --git a/libavdevice/sndio_common.h b/libavdevice/sndio_common.h
deleted file mode 100644 (file)
index 2f70213..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * sndio play and grab interface
- * Copyright (c) 2010 Jacob Meuser
- *
- * This file is part of Libav.
- *
- * Libav 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.
- *
- * Libav 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 Libav; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#ifndef AVDEVICE_SNDIO_COMMON_H
-#define AVDEVICE_SNDIO_COMMON_H
-
-#include <stdint.h>
-#include <sndio.h>
-
-#include "libavformat/avformat.h"
-#include "libavutil/log.h"
-
-typedef struct SndioData {
-    AVClass *class;
-    struct sio_hdl *hdl;
-    enum AVCodecID codec_id;
-    int64_t hwpos;
-    int64_t softpos;
-    uint8_t *buffer;
-    int bps;
-    int buffer_size;
-    int buffer_offset;
-    int channels;
-    int sample_rate;
-} SndioData;
-
-int ff_sndio_open(AVFormatContext *s1, int is_output, const char *audio_device);
-int ff_sndio_close(SndioData *s);
-
-#endif /* AVDEVICE_SNDIO_COMMON_H */
index 24c6d1e..7ebb8c3 100644 (file)
@@ -29,7 +29,7 @@
 #include "libavformat/avformat.h"
 #include "libavformat/internal.h"
 
-#include "sndio_common.h"
+#include "libavdevice/sndio.h"
 
 static av_cold int audio_read_header(AVFormatContext *s1)
 {
index 61ac398..fad3610 100644 (file)
@@ -26,7 +26,7 @@
 
 #include "libavformat/avformat.h"
 
-#include "sndio_common.h"
+#include "libavdevice/sndio.h"
 
 static av_cold int audio_write_header(AVFormatContext *s1)
 {