Merge commit '8d26c193fb42d08602ac93ece039d4718d029adc'
authorMichael Niedermayer <michaelni@gmx.at>
Thu, 9 Apr 2015 19:36:42 +0000 (21:36 +0200)
committerMichael Niedermayer <michaelni@gmx.at>
Thu, 9 Apr 2015 19:36:42 +0000 (21:36 +0200)
* commit '8d26c193fb42d08602ac93ece039d4718d029adc':
  avdevice: Apply a more consistent file naming scheme

Conflicts:
libavdevice/Makefile
libavdevice/alsa.h
libavdevice/alsa_dec.c
libavdevice/alsa_enc.c
libavdevice/sndio_enc.c

Merged-by: Michael Niedermayer <michaelni@gmx.at>
14 files changed:
1  2 
libavdevice/Makefile
libavdevice/alsa.c
libavdevice/alsa.h
libavdevice/alsa_dec.c
libavdevice/alsa_enc.c
libavdevice/jack.c
libavdevice/oss.c
libavdevice/oss.h
libavdevice/oss_dec.c
libavdevice/oss_enc.c
libavdevice/sndio.c
libavdevice/sndio.h
libavdevice/sndio_dec.c
libavdevice/sndio_enc.c

@@@ -7,45 -5,20 +7,43 @@@ HEADERS = avdevice.
  
  OBJS    = alldevices.o                                                  \
            avdevice.o                                                    \
 +          utils.o                                                       \
  
  # input/output devices
- OBJS-$(CONFIG_ALSA_INDEV)                += alsa-audio-common.o \
-                                             alsa-audio-dec.o timefilter.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_INDEV)                += alsa_dec.o alsa.o timefilter.o
+ OBJS-$(CONFIG_ALSA_OUTDEV)               += alsa_enc.o alsa.o
 +OBJS-$(CONFIG_AVFOUNDATION_INDEV)        += avfoundation.o
  OBJS-$(CONFIG_BKTR_INDEV)                += bktr.o
 +OBJS-$(CONFIG_CACA_OUTDEV)               += caca.o
 +OBJS-$(CONFIG_DECKLINK_OUTDEV)           += decklink_enc.o decklink_enc_c.o decklink_common.o
 +OBJS-$(CONFIG_DECKLINK_INDEV)            += decklink_dec.o decklink_dec_c.o decklink_common.o
 +OBJS-$(CONFIG_DSHOW_INDEV)               += dshow_crossbar.o dshow.o dshow_enummediatypes.o \
 +                                            dshow_enumpins.o dshow_filter.o \
 +                                            dshow_pin.o dshow_common.o
  OBJS-$(CONFIG_DV1394_INDEV)              += dv1394.o
 -OBJS-$(CONFIG_FBDEV_INDEV)               += fbdev.o
 +OBJS-$(CONFIG_FBDEV_INDEV)               += fbdev_dec.o \
 +                                            fbdev_common.o
 +OBJS-$(CONFIG_FBDEV_OUTDEV)              += fbdev_enc.o \
 +                                            fbdev_common.o
 +OBJS-$(CONFIG_GDIGRAB_INDEV)             += gdigrab.o
 +OBJS-$(CONFIG_IEC61883_INDEV)            += iec61883.o
- OBJS-$(CONFIG_JACK_INDEV)                += jack_audio.o timefilter.o
+ OBJS-$(CONFIG_JACK_INDEV)                += jack.o timefilter.o
 +OBJS-$(CONFIG_LAVFI_INDEV)               += lavfi.o
 +OBJS-$(CONFIG_OPENAL_INDEV)              += openal-dec.o
 +OBJS-$(CONFIG_OPENGL_OUTDEV)             += opengl_enc.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_OSS_INDEV)                 += oss_dec.o oss.o
+ OBJS-$(CONFIG_OSS_OUTDEV)                += oss_enc.o oss.o
 -OBJS-$(CONFIG_PULSE_INDEV)               += pulse.o
 +OBJS-$(CONFIG_PULSE_INDEV)               += pulse_audio_dec.o \
 +                                            pulse_audio_common.o timefilter.o
 +OBJS-$(CONFIG_PULSE_OUTDEV)              += pulse_audio_enc.o \
 +                                            pulse_audio_common.o
 +OBJS-$(CONFIG_QTKIT_INDEV)               += qtkit.o
 +OBJS-$(CONFIG_SDL_OUTDEV)                += sdl.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_V4L2_INDEV)                += v4l2.o v4l2-common.o timefilter.o
 +OBJS-$(CONFIG_V4L2_OUTDEV)               += v4l2enc.o v4l2-common.o
 +OBJS-$(CONFIG_V4L_INDEV)                 += v4l.o
  OBJS-$(CONFIG_VFWCAP_INDEV)              += vfwcap.o
  OBJS-$(CONFIG_X11GRAB_INDEV)             += x11grab.o
  OBJS-$(CONFIG_X11GRAB_XCB_INDEV)         += xcbgrab.o
@@@ -57,18 -29,7 +55,18 @@@ OBJS-$(CONFIG_LIBDC1394_INDEV
  
  OBJS-$(HAVE_LIBC_MSVCRT)                 += file_open.o
  
- SKIPHEADERS-$(HAVE_ALSA_ASOUNDLIB_H)     += alsa-audio.h
- SKIPHEADERS-$(HAVE_SNDIO_H)              += sndio_common.h
 +# Windows resource file
 +SLIBOBJS-$(HAVE_GNU_WINDRES)             += avdeviceres.o
 +
 +SKIPHEADERS-$(CONFIG_DECKLINK)           += decklink_enc.h decklink_dec.h \
 +                                            decklink_common.h decklink_common_c.h
 +SKIPHEADERS-$(CONFIG_DSHOW_INDEV)        += dshow_capture.h
 +SKIPHEADERS-$(CONFIG_FBDEV_INDEV)        += fbdev_common.h
 +SKIPHEADERS-$(CONFIG_FBDEV_OUTDEV)       += fbdev_common.h
 +SKIPHEADERS-$(CONFIG_LIBPULSE)           += pulse_audio_common.h
 +SKIPHEADERS-$(CONFIG_V4L2_INDEV)         += v4l2-common.h
 +SKIPHEADERS-$(CONFIG_V4L2_OUTDEV)        += v4l2-common.h
+ SKIPHEADERS-$(HAVE_ALSA_ASOUNDLIB_H)     += alsa.h
+ SKIPHEADERS-$(HAVE_SNDIO_H)              += sndio.h
  
  TESTPROGS = timefilter
index 0000000,6d68267..27a1655
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,362 +1,399 @@@
 - * This file is part of Libav.
+ /*
+  * ALSA input and output
+  * Copyright (c) 2007 Luca Abeni ( lucabe72 email it )
+  * Copyright (c) 2007 Benoit Fouet ( benoit fouet free fr )
+  *
 - * Libav is free software; you can redistribute it and/or
++ * This file is part of FFmpeg.
+  *
 - * Libav is distributed in the hope that it will be useful,
++ * FFmpeg is free software; you can redistribute it and/or
+  * modify it under the terms of the GNU Lesser General Public
+  * License as published by the Free Software Foundation; either
+  * version 2.1 of the License, or (at your option) any later version.
+  *
 - * License along with Libav; if not, write to the Free Software
++ * FFmpeg is distributed in the hope that it will be useful,
+  * but WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  * Lesser General Public License for more details.
+  *
+  * You should have received a copy of the GNU Lesser General Public
 -#include "libavformat/avformat.h"
++ * License along with FFmpeg; 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>
 -#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) { \
++#include "avdevice.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;
+     }
+ }
 -        in  += 5; \
 -        out += 5; \
 -    } \
 -}
++#define MAKE_REORDER_FUNC(NAME, TYPE, CHANNELS, LAYOUT, MAP)                \
++static void alsa_reorder_ ## NAME ## _ ## LAYOUT(const void *in_v,          \
++                                                 void *out_v,               \
++                                                 int n)                     \
++{                                                                           \
++    const TYPE *in = in_v;                                                  \
++    TYPE      *out = out_v;                                                 \
++                                                                            \
++    while (n-- > 0) {                                                       \
++        MAP                                                                 \
++        in  += CHANNELS;                                                    \
++        out += CHANNELS;                                                    \
++    }                                                                       \
++}
++
++#define MAKE_REORDER_FUNCS(CHANNELS, LAYOUT, MAP) \
++    MAKE_REORDER_FUNC(int8,  int8_t,  CHANNELS, LAYOUT, MAP) \
++    MAKE_REORDER_FUNC(int16, int16_t, CHANNELS, LAYOUT, MAP) \
++    MAKE_REORDER_FUNC(int32, int32_t, CHANNELS, LAYOUT, MAP) \
++    MAKE_REORDER_FUNC(f32,   float,   CHANNELS, LAYOUT, MAP)
++
++MAKE_REORDER_FUNCS(5, out_50, \
+         out[0] = in[0]; \
+         out[1] = in[1]; \
+         out[2] = in[3]; \
+         out[3] = in[4]; \
+         out[4] = in[2]; \
 -#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) { \
++        );
 -        in  += 6; \
 -        out += 6; \
 -    } \
 -}
++MAKE_REORDER_FUNCS(6, out_51, \
+         out[0] = in[0]; \
+         out[1] = in[1]; \
+         out[2] = in[4]; \
+         out[3] = in[5]; \
+         out[4] = in[2]; \
+         out[5] = in[3]; \
 -#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) { \
++        );
 -        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)
++MAKE_REORDER_FUNCS(8, out_71, \
+         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]; \
 -            s->reorder_buf = av_malloc(s->reorder_buf_size * s->frame_size);
++        );
+ #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;
 -    r = av_realloc(s->reorder_buf, size * s->frame_size);
++            s->reorder_buf = av_malloc_array(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);
++    if (CONFIG_ALSA_INDEV)
++        ff_timefilter_destroy(s->timefilter);
+     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_array(s->reorder_buf, size, s->frame_size);
+     if (!r)
+         return AVERROR(ENOMEM);
+     s->reorder_buf = r;
+     s->reorder_buf_size = size;
+     return 0;
+ }
++
++/* ported from alsa-utils/aplay.c */
++int ff_alsa_get_device_list(AVDeviceInfoList *device_list, snd_pcm_stream_t stream_type)
++{
++    int ret = 0;
++    void **hints, **n;
++    char *name = NULL, *descr = NULL, *io = NULL, *tmp;
++    AVDeviceInfo *new_device = NULL;
++    const char *filter = stream_type == SND_PCM_STREAM_PLAYBACK ? "Output" : "Input";
++
++    if (snd_device_name_hint(-1, "pcm", &hints) < 0)
++        return AVERROR_EXTERNAL;
++    n = hints;
++    while (*n && !ret) {
++        name = snd_device_name_get_hint(*n, "NAME");
++        descr = snd_device_name_get_hint(*n, "DESC");
++        io = snd_device_name_get_hint(*n, "IOID");
++        if (!io || !strcmp(io, filter)) {
++            new_device = av_mallocz(sizeof(AVDeviceInfo));
++            if (!new_device) {
++                ret = AVERROR(ENOMEM);
++                goto fail;
++            }
++            new_device->device_name = av_strdup(name);
++            if ((tmp = strrchr(descr, '\n')) && tmp[1])
++                new_device->device_description = av_strdup(&tmp[1]);
++            else
++                new_device->device_description = av_strdup(descr);
++            if (!new_device->device_description || !new_device->device_name) {
++                ret = AVERROR(ENOMEM);
++                goto fail;
++            }
++            if ((ret = av_dynarray_add_nofree(&device_list->devices,
++                                              &device_list->nb_devices, new_device)) < 0) {
++                goto fail;
++            }
++            if (!strcmp(new_device->device_name, "default"))
++                device_list->default_device = device_list->nb_devices - 1;
++            new_device = NULL;
++        }
++      fail:
++        free(io);
++        free(name);
++        free(descr);
++        n++;
++    }
++    if (new_device) {
++        av_free(new_device->device_description);
++        av_free(new_device->device_name);
++        av_free(new_device);
++    }
++    snd_device_name_free_hint(hints);
++    return ret;
++}
index 0000000,590b354..f8b7449
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,96 +1,104 @@@
 - * This file is part of Libav.
+ /*
+  * ALSA input and output
+  * Copyright (c) 2007 Luca Abeni ( lucabe72 email it )
+  * Copyright (c) 2007 Benoit Fouet ( benoit fouet free fr )
+  *
 - * Libav is free software; you can redistribute it and/or
++ * This file is part of FFmpeg.
+  *
 - * Libav is distributed in the hope that it will be useful,
++ * FFmpeg is free software; you can redistribute it and/or
+  * modify it under the terms of the GNU Lesser General Public
+  * License as published by the Free Software Foundation; either
+  * version 2.1 of the License, or (at your option) any later version.
+  *
 - * License along with Libav; if not, write to the Free Software
++ * FFmpeg is distributed in the hope that it will be useful,
+  * but WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  * Lesser General Public License for more details.
+  *
+  * You should have received a copy of the GNU Lesser General Public
 -#include "libavformat/avformat.h"
++ * License along with FFmpeg; 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"
 -#define ALSA_BUFFER_SIZE_MAX 32768
+ #include "libavutil/log.h"
++#include "timefilter.h"
++#include "avdevice.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)
 -    int frame_size;  ///< preferred size for reads and writes
 -    int period_size; ///< bytes per sample * channels
++typedef void (*ff_reorder_func)(const void *, void *, int);
++
++#define ALSA_BUFFER_SIZE_MAX 65536
+ typedef struct AlsaData {
+     AVClass *class;
+     snd_pcm_t *h;
++    int frame_size;  ///< bytes per sample * channels
++    int period_size; ///< preferred size for reads and writes, in frames
+     int sample_rate; ///< sample rate set by user
+     int channels;    ///< number of channels set by user
++    int last_period;
++    TimeFilter *timefilter;
+     void (*reorder_func)(const void *, void *, int);
+     void *reorder_buf;
+     int reorder_buf_size; ///< in frames
++    int64_t timestamp; ///< current timestamp, without latency applied.
+ } 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);
++int ff_alsa_get_device_list(AVDeviceInfoList *device_list, snd_pcm_stream_t stream_type);
++
+ #endif /* AVDEVICE_ALSA_H */
index 0000000,2cc5b7d..286af65
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,178 +1,168 @@@
 - * This file is part of Libav.
+ /*
+  * ALSA input and output
+  * Copyright (c) 2007 Luca Abeni ( lucabe72 email it )
+  * Copyright (c) 2007 Benoit Fouet ( benoit fouet free fr )
+  *
 - * Libav is free software; you can redistribute it and/or
++ * This file is part of FFmpeg.
+  *
 - * Libav is distributed in the hope that it will be useful,
++ * FFmpeg is free software; you can redistribute it and/or
+  * modify it under the terms of the GNU Lesser General Public
+  * License as published by the Free Software Foundation; either
+  * version 2.1 of the License, or (at your option) any later version.
+  *
 - * License along with Libav; if not, write to the Free Software
++ * FFmpeg is distributed in the hope that it will be useful,
+  * but WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  * Lesser General Public License for more details.
+  *
+  * You should have received a copy of the GNU Lesser General Public
 -#include "libavformat/avformat.h"
++ * License along with FFmpeg; 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/mathematics.h"
+ #include "libavutil/opt.h"
++#include "libavutil/time.h"
 -    snd_pcm_sw_params_t *sw_params;
+ #include "libavformat/internal.h"
++#include "avdevice.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;
 -    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;
 -    }
 -
+     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);
+     }
 -    AVStream *st = s1->streams[0];
+     /* 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;
++    st->codec->frame_size = s->frame_size;
+     avpriv_set_pts_info(st, 64, 1, 1000000);  /* 64 bits pts in us */
++    /* microseconds instead of seconds, MHz instead of Hz */
++    s->timefilter = ff_timefilter_new(1000000.0 / s->sample_rate,
++                                      s->period_size, 1.5E-6);
++    if (!s->timefilter)
++        goto fail;
+     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;
 -    snd_htimestamp_t timestamp;
 -    snd_pcm_uframes_t ts_delay;
+     int res;
 -    if (av_new_packet(pkt, s->period_size) < 0) {
++    int64_t dts;
++    snd_pcm_sframes_t delay = 0;
 -    while ((res = snd_pcm_readi(s->h, pkt->data, pkt->size / s->frame_size)) < 0) {
++    if (av_new_packet(pkt, s->period_size * s->frame_size) < 0) {
+         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);
++    while ((res = snd_pcm_readi(s->h, pkt->data, s->period_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);
+         }
++        ff_timefilter_reset(s->timefilter);
+     }
++    dts = av_gettime();
++    snd_pcm_delay(s->h, &delay);
++    dts -= av_rescale(delay + res, 1000000, s->sample_rate);
++    pkt->pts = ff_timefilter_update(s->timefilter, dts, s->last_period);
++    s->last_period = res;
+     pkt->size = res * s->frame_size;
+     return 0;
+ }
++static int audio_get_device_list(AVFormatContext *h, AVDeviceInfoList *device_list)
++{
++    return ff_alsa_get_device_list(device_list, SND_PCM_STREAM_CAPTURE);
++}
++
+ 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,
++    .category       = AV_CLASS_CATEGORY_DEVICE_AUDIO_INPUT,
+ };
+ 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,
++    .get_device_list = audio_get_device_list,
+     .flags          = AVFMT_NOFILE,
+     .priv_class     = &alsa_demuxer_class,
+ };
index 0000000,30c1719..fb428f0
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,117 +1,174 @@@
 - * This file is part of Libav.
+ /*
+  * ALSA input and output
+  * Copyright (c) 2007 Luca Abeni ( lucabe72 email it )
+  * Copyright (c) 2007 Benoit Fouet ( benoit fouet free fr )
+  *
 - * Libav is free software; you can redistribute it and/or
++ * This file is part of FFmpeg.
+  *
 - * Libav is distributed in the hope that it will be useful,
++ * FFmpeg is free software; you can redistribute it and/or
+  * modify it under the terms of the GNU Lesser General Public
+  * License as published by the Free Software Foundation; either
+  * version 2.1 of the License, or (at your option) any later version.
+  *
 - * License along with Libav; if not, write to the Free Software
++ * FFmpeg is distributed in the hope that it will be useful,
+  * but WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  * Lesser General Public License for more details.
+  *
+  * You should have received a copy of the GNU Lesser General Public
 -#include "libavformat/avformat.h"
++ * License along with FFmpeg; 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 "libavutil/time.h"
 -    AVStream *st;
++#include "libavformat/internal.h"
++#include "avdevice.h"
+ #include "alsa.h"
+ static av_cold int audio_write_header(AVFormatContext *s1)
+ {
+     AlsaData *s = s1->priv_data;
++    AVStream *st = NULL;
+     unsigned int sample_rate;
+     enum AVCodecID codec_id;
+     int res;
++    if (s1->nb_streams != 1 || s1->streams[0]->codec->codec_type != AVMEDIA_TYPE_AUDIO) {
++        av_log(s1, AV_LOG_ERROR, "Only a single audio stream is supported.\n");
++        return AVERROR(EINVAL);
++    }
+     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;
+     }
++    avpriv_set_pts_info(st, 64, 1, sample_rate);
+     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 (pkt->dts != AV_NOPTS_VALUE)
++        s->timestamp = pkt->dts;
++    s->timestamp += pkt->duration ? pkt->duration : 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;
+ }
++static int audio_write_frame(AVFormatContext *s1, int stream_index,
++                             AVFrame **frame, unsigned flags)
++{
++    AlsaData *s = s1->priv_data;
++    AVPacket pkt;
++
++    /* ff_alsa_open() should have accepted only supported formats */
++    if ((flags & AV_WRITE_UNCODED_FRAME_QUERY))
++        return av_sample_fmt_is_planar(s1->streams[stream_index]->codec->sample_fmt) ?
++               AVERROR(EINVAL) : 0;
++    /* set only used fields */
++    pkt.data     = (*frame)->data[0];
++    pkt.size     = (*frame)->nb_samples * s->frame_size;
++    pkt.dts      = (*frame)->pkt_dts;
++    pkt.duration = av_frame_get_pkt_duration(*frame);
++    return audio_write_packet(s1, &pkt);
++}
++
++static void
++audio_get_output_timestamp(AVFormatContext *s1, int stream,
++    int64_t *dts, int64_t *wall)
++{
++    AlsaData *s  = s1->priv_data;
++    snd_pcm_sframes_t delay = 0;
++    *wall = av_gettime();
++    snd_pcm_delay(s->h, &delay);
++    *dts = s->timestamp - delay;
++}
++
++static int audio_get_device_list(AVFormatContext *h, AVDeviceInfoList *device_list)
++{
++    return ff_alsa_get_device_list(device_list, SND_PCM_STREAM_PLAYBACK);
++}
++
++static const AVClass alsa_muxer_class = {
++    .class_name     = "ALSA muxer",
++    .item_name      = av_default_item_name,
++    .version        = LIBAVUTIL_VERSION_INT,
++    .category       = AV_CLASS_CATEGORY_DEVICE_AUDIO_OUTPUT,
++};
++
+ 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,
++    .write_uncoded_frame = audio_write_frame,
++    .get_device_list = audio_get_device_list,
++    .get_output_timestamp = audio_get_output_timestamp,
+     .flags          = AVFMT_NOFILE,
++    .priv_class     = &alsa_muxer_class,
+ };
index 0000000,fc5caa8..053dba7
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,353 +1,352 @@@
 - * This file is part of Libav.
+ /*
+  * JACK Audio Connection Kit input device
+  * Copyright (c) 2009 Samalyse
+  * Author: Olivier Guilyardi <olivier samalyse com>
+  *
 - * Libav is free software; you can redistribute it and/or
++ * This file is part of FFmpeg.
+  *
 - * Libav is distributed in the hope that it will be useful,
++ * FFmpeg is free software; you can redistribute it and/or
+  * modify it under the terms of the GNU Lesser General Public
+  * License as published by the Free Software Foundation; either
+  * version 2.1 of the License, or (at your option) any later version.
+  *
 - * License along with Libav; if not, write to the Free Software
++ * FFmpeg is distributed in the hope that it will be useful,
+  * but WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  * Lesser General Public License for more details.
+  *
+  * You should have received a copy of the GNU Lesser General Public
 -    double o, period;
++ * License along with FFmpeg; 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"
++#include "avdevice.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;
 -    self->ports       = av_malloc(self->nports * sizeof(*self->ports));
+     /* 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);
 -    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);
++    self->ports       = av_malloc_array(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 */
 -    self->filled_pkts = av_fifo_alloc(FIFO_PACKETS_NUM * sizeof(AVPacket));
++    self->timefilter  = ff_timefilter_new (1.0 / self->sample_rate, self->buffer_size, 1.5);
+     if (!self->timefilter) {
+         jack_client_close(self->client);
+         return AVERROR(ENOMEM);
+     }
+     /* Create FIFO buffers */
 -    self->new_pkts    = av_fifo_alloc((FIFO_PACKETS_NUM + 1) * sizeof(AVPacket));
++    self->filled_pkts = av_fifo_alloc_array(FIFO_PACKETS_NUM, sizeof(AVPacket));
+     /* New packets FIFO with one extra packet for safety against underruns */
 -static void free_pkt_fifo(AVFifoBuffer *fifo)
++    self->new_pkts    = av_fifo_alloc_array((FIFO_PACKETS_NUM + 1), sizeof(AVPacket));
+     if ((test = supply_new_packets(self, context))) {
+         jack_client_close(self->client);
+         return test;
+     }
+     return 0;
+ }
 -    while (av_fifo_size(fifo)) {
 -        av_fifo_generic_read(fifo, &pkt, sizeof(pkt), NULL);
++static void free_pkt_fifo(AVFifoBuffer **fifo)
+ {
+     AVPacket pkt;
 -    av_fifo_free(fifo);
++    while (av_fifo_size(*fifo)) {
++        av_fifo_generic_read(*fifo, &pkt, sizeof(pkt), NULL);
+         av_free_packet(&pkt);
+     }
 -    free_pkt_fifo(self->new_pkts);
 -    free_pkt_fifo(self->filled_pkts);
++    av_fifo_freep(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,
++    .category       = AV_CLASS_CATEGORY_DEVICE_AUDIO_INPUT,
+ };
+ 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,
+ };
index 0000000,eb8d454..d741128
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,139 +1,144 @@@
 - * This file is part of Libav.
+ /*
+  * Linux audio play and grab interface
+  * Copyright (c) 2000, 2001 Fabrice Bellard
+  *
 - * Libav is free software; you can redistribute it and/or
++ * This file is part of FFmpeg.
+  *
 - * Libav is distributed in the hope that it will be useful,
++ * FFmpeg is free software; you can redistribute it and/or
+  * modify it under the terms of the GNU Lesser General Public
+  * License as published by the Free Software Foundation; either
+  * version 2.1 of the License, or (at your option) any later version.
+  *
 - * License along with Libav; if not, write to the Free Software
++ * FFmpeg is distributed in the hope that it will be useful,
+  * but WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  * Lesser General Public License for more details.
+  *
+  * You should have received a copy of the GNU Lesser General Public
 -
 -#include "libavformat/avformat.h"
++ * License along with FFmpeg; 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
++#if HAVE_UNISTD_H
+ #include <unistd.h>
++#endif
+ #include <fcntl.h>
+ #include <sys/ioctl.h>
+ #include "libavutil/log.h"
+ #include "libavcodec/avcodec.h"
 -    char errbuff[128];
++#include "avdevice.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");
 -        av_log(s1, AV_LOG_ERROR, "%s: %s\n", audio_device, strerror(errno));
+     if (is_output)
+         audio_fd = avpriv_open(audio_device, O_WRONLY);
+     else
+         audio_fd = avpriv_open(audio_device, O_RDONLY);
+     if (audio_fd < 0) {
 -    if (!is_output)
 -        fcntl(audio_fd, F_SETFL, O_NONBLOCK);
++        av_log(s1, AV_LOG_ERROR, "%s: %s\n", audio_device, av_err2str(AVERROR(errno)));
+         return AVERROR(EIO);
+     }
+     if (flip && *flip == '1') {
+         s->flip_left = 1;
+     }
+     /* non blocking mode */
 -        av_strerror(AVERROR(errno), errbuff, sizeof(errbuff));                \
 -        av_log(s1, AV_LOG_ERROR, #event ": %s\n", errbuff);                   \
++    if (!is_output) {
++        if (fcntl(audio_fd, F_SETFL, O_NONBLOCK) < 0) {
++            av_log(s1, AV_LOG_WARNING, "%s: Could not enable non block mode (%s)\n", audio_device, av_err2str(AVERROR(errno)));
++        }
++    }
+     s->frame_size = OSS_AUDIO_BLOCK_SIZE;
+ #define CHECK_IOCTL_ERROR(event)                                              \
+     if (err < 0) {                                                            \
 -    (void) ioctl(audio_fd, SNDCTL_DSP_GETFMTS, &tmp);
++        av_log(s1, AV_LOG_ERROR, #event ": %s\n", av_err2str(AVERROR(errno)));\
+         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. */
++    err = ioctl(audio_fd, SNDCTL_DSP_GETFMTS, &tmp);
++    if (err < 0) {
++        av_log(s1, AV_LOG_WARNING, "SNDCTL_DSP_GETFMTS: %s\n", av_err2str(AVERROR(errno)));
++    }
+ #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;
+ }
index 0000000,0fbe14b..1f3f5e4
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,45 +1,45 @@@
 - * This file is part of Libav.
+ /*
 - * Libav is free software; you can redistribute it and/or
++ * This file is part of FFmpeg.
+  *
 - * Libav is distributed in the hope that it will be useful,
++ * FFmpeg is free software; you can redistribute it and/or
+  * modify it under the terms of the GNU Lesser General Public
+  * License as published by the Free Software Foundation; either
+  * version 2.1 of the License, or (at your option) any later version.
+  *
 - * License along with Libav; if not, write to the Free Software
++ * FFmpeg is distributed in the hope that it will be useful,
+  * but WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  * Lesser General Public License for more details.
+  *
+  * You should have received a copy of the GNU Lesser General Public
++ * License along with FFmpeg; if not, write to the Free Software
+  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+  */
+ #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 */
index 0000000,3f786cc..156d6ae
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,146 +1,149 @@@
 - * This file is part of Libav.
+ /*
+  * Linux audio play interface
+  * Copyright (c) 2000, 2001 Fabrice Bellard
+  *
 - * Libav is free software; you can redistribute it and/or
++ * This file is part of FFmpeg.
+  *
 - * Libav is distributed in the hope that it will be useful,
++ * FFmpeg is free software; you can redistribute it and/or
+  * modify it under the terms of the GNU Lesser General Public
+  * License as published by the Free Software Foundation; either
+  * version 2.1 of the License, or (at your option) any later version.
+  *
 - * License along with Libav; if not, write to the Free Software
++ * FFmpeg is distributed in the hope that it will be useful,
+  * but WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  * Lesser General Public License for more details.
+  *
+  * You should have received a copy of the GNU Lesser General Public
 -#include "libavformat/avformat.h"
++ * License along with FFmpeg; 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
++#if HAVE_UNISTD_H
+ #include <unistd.h>
++#endif
+ #include <fcntl.h>
+ #include <sys/ioctl.h>
+ #include "libavutil/internal.h"
+ #include "libavutil/opt.h"
+ #include "libavutil/time.h"
+ #include "libavcodec/avcodec.h"
++#include "avdevice.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,
++    .category       = AV_CLASS_CATEGORY_DEVICE_AUDIO_INPUT,
+ };
+ 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,
+ };
index 0000000,2f07558..3781eb5
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,108 +1,118 @@@
 - * This file is part of Libav.
+ /*
+  * Linux audio grab interface
+  * Copyright (c) 2000, 2001 Fabrice Bellard
+  *
 - * Libav is free software; you can redistribute it and/or
++ * This file is part of FFmpeg.
+  *
 - * Libav is distributed in the hope that it will be useful,
++ * FFmpeg is free software; you can redistribute it and/or
+  * modify it under the terms of the GNU Lesser General Public
+  * License as published by the Free Software Foundation; either
+  * version 2.1 of the License, or (at your option) any later version.
+  *
 - * License along with Libav; if not, write to the Free Software
++ * FFmpeg is distributed in the hope that it will be useful,
+  * but WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  * Lesser General Public License for more details.
+  *
+  * You should have received a copy of the GNU Lesser General Public
 -#include "libavformat/avformat.h"
++ * License along with FFmpeg; 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
++#if HAVE_UNISTD_H
+ #include <unistd.h>
++#endif
+ #include <fcntl.h>
+ #include <sys/ioctl.h>
+ #include "libavutil/internal.h"
+ #include "libavcodec/avcodec.h"
++#include "avdevice.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;
+ }
++static const AVClass oss_muxer_class = {
++    .class_name     = "OSS muxer",
++    .item_name      = av_default_item_name,
++    .version        = LIBAVUTIL_VERSION_INT,
++    .category       = AV_CLASS_CATEGORY_DEVICE_AUDIO_OUTPUT,
++};
++
+ 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,
++    .priv_class     = &oss_muxer_class,
+ };
index 0000000,739551b..46f2875
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,120 +1,120 @@@
 - * This file is part of Libav.
+ /*
+  * sndio play and grab interface
+  * Copyright (c) 2010 Jacob Meuser
+  *
 - * Libav is free software; you can redistribute it and/or
++ * This file is part of FFmpeg.
+  *
 - * Libav is distributed in the hope that it will be useful,
++ * FFmpeg is free software; you can redistribute it and/or
+  * modify it under the terms of the GNU Lesser General Public
+  * License as published by the Free Software Foundation; either
+  * version 2.1 of the License, or (at your option) any later version.
+  *
 - * License along with Libav; if not, write to the Free Software
++ * FFmpeg is distributed in the hope that it will be useful,
+  * but WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  * Lesser General Public License for more details.
+  *
+  * You should have received a copy of the GNU Lesser General Public
 -#include "libavformat/avformat.h"
++ * License along with FFmpeg; 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 "avdevice.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;
+ }
index 0000000,cd5c55e..54a5ec3
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,48 +1,48 @@@
 - * This file is part of Libav.
+ /*
+  * sndio play and grab interface
+  * Copyright (c) 2010 Jacob Meuser
+  *
 - * Libav is free software; you can redistribute it and/or
++ * This file is part of FFmpeg.
+  *
 - * Libav is distributed in the hope that it will be useful,
++ * FFmpeg is free software; you can redistribute it and/or
+  * modify it under the terms of the GNU Lesser General Public
+  * License as published by the Free Software Foundation; either
+  * version 2.1 of the License, or (at your option) any later version.
+  *
 - * License along with Libav; if not, write to the Free Software
++ * FFmpeg is distributed in the hope that it will be useful,
+  * but WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  * Lesser General Public License for more details.
+  *
+  * You should have received a copy of the GNU Lesser General Public
 -#include "libavformat/avformat.h"
++ * License along with FFmpeg; 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 "libavutil/log.h"
++#include "avdevice.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 */
Simple merge
@@@ -24,9 -24,9 +24,9 @@@
  
  #include "libavutil/internal.h"
  
 -#include "libavformat/avformat.h"
  
- #include "avdevice.h"
- #include "sndio_common.h"
++#include "libavdevice/avdevice.h"
+ #include "libavdevice/sndio.h"
  
  static av_cold int audio_write_header(AVFormatContext *s1)
  {