Merge commit 'e6153f173a49e5bfa70b0c04d2f82930533597b9'
authorMichael Niedermayer <michaelni@gmx.at>
Wed, 5 Sep 2012 12:26:01 +0000 (14:26 +0200)
committerMichael Niedermayer <michaelni@gmx.at>
Wed, 5 Sep 2012 12:33:32 +0000 (14:33 +0200)
* commit 'e6153f173a49e5bfa70b0c04d2f82930533597b9':
  avopt: Store defaults for AV_OPT_TYPE_INT in the i64 union member

Conflicts:
libavcodec/libopenjpegdec.c
libavcodec/libopenjpegenc.c
libavcodec/libx264.c
libavcodec/mpeg12enc.c
libavcodec/options_table.h
libavcodec/snowenc.c
libavcodec/tiffenc.c
libavdevice/v4l2.c
libavdevice/x11grab.c
libavfilter/af_amix.c
libavfilter/af_asyncts.c
libavfilter/af_join.c
libavfilter/buffersrc.c
libavfilter/src_movie.c
libavfilter/vf_delogo.c
libavfilter/vf_drawtext.c
libavformat/http.c
libavformat/img2dec.c
libavformat/img2enc.c
libavformat/movenc.c
libavformat/mpegenc.c
libavformat/mpegtsenc.c
libavformat/options_table.h
libavformat/segment.c

Merged-by: Michael Niedermayer <michaelni@gmx.at>
107 files changed:
1  2 
ffprobe.c
libavcodec/aacenc.c
libavcodec/ac3dec.c
libavcodec/apedec.c
libavcodec/cljr.c
libavcodec/dnxhdenc.c
libavcodec/ffv1.c
libavcodec/flacenc.c
libavcodec/g723_1.c
libavcodec/g726.c
libavcodec/libfdk-aacenc.c
libavcodec/libilbc.c
libavcodec/libmp3lame.c
libavcodec/libopencore-amr.c
libavcodec/libopenjpegdec.c
libavcodec/libopenjpegenc.c
libavcodec/libspeexenc.c
libavcodec/libtwolame.c
libavcodec/libvo-amrwbenc.c
libavcodec/libvpxenc.c
libavcodec/libx264.c
libavcodec/libxavs.c
libavcodec/mjpegdec.c
libavcodec/mpeg12enc.c
libavcodec/mpeg4videoenc.c
libavcodec/mpegvideo.h
libavcodec/mpegvideo_enc.c
libavcodec/options.c
libavcodec/options_table.h
libavcodec/pgssubdec.c
libavcodec/proresenc_kostya.c
libavcodec/rawdec.c
libavcodec/snowenc.c
libavcodec/tiffenc.c
libavdevice/alsa-audio-dec.c
libavdevice/bktr.c
libavdevice/caca.c
libavdevice/dshow.c
libavdevice/dv1394.c
libavdevice/iec61883.c
libavdevice/jack_audio.c
libavdevice/libcdio.c
libavdevice/libdc1394.c
libavdevice/openal-dec.c
libavdevice/oss_audio.c
libavdevice/pulse.c
libavdevice/sndio_dec.c
libavdevice/v4l.c
libavdevice/v4l2.c
libavdevice/x11grab.c
libavfilter/af_amerge.c
libavfilter/af_amix.c
libavfilter/af_asetnsamples.c
libavfilter/af_asyncts.c
libavfilter/af_join.c
libavfilter/af_silencedetect.c
libavfilter/asrc_aevalsrc.c
libavfilter/asrc_anullsrc.c
libavfilter/asrc_flite.c
libavfilter/avf_concat.c
libavfilter/avf_showwaves.c
libavfilter/buffersrc.c
libavfilter/src_movie.c
libavfilter/vf_delogo.c
libavfilter/vf_drawtext.c
libavfilter/vf_fade.c
libavfilter/vf_overlay.c
libavfilter/vsrc_cellauto.c
libavfilter/vsrc_life.c
libavfilter/vsrc_mandelbrot.c
libavfilter/vsrc_mptestsrc.c
libavfilter/vsrc_testsrc.c
libavformat/asfdec.c
libavformat/avidec.c
libavformat/bintext.c
libavformat/bluray.c
libavformat/cdxl.c
libavformat/flvdec.c
libavformat/g729dec.c
libavformat/gif.c
libavformat/gsmdec.c
libavformat/http.c
libavformat/img2dec.c
libavformat/img2enc.c
libavformat/latmenc.c
libavformat/libmodplug.c
libavformat/movenc.c
libavformat/mp3enc.c
libavformat/mpegenc.c
libavformat/mpegts.c
libavformat/mpegtsenc.c
libavformat/oggenc.c
libavformat/options_table.h
libavformat/pcmdec.c
libavformat/rtmpcrypt.c
libavformat/rtmphttp.c
libavformat/rtmpproto.c
libavformat/rtpenc.c
libavformat/rtsp.c
libavformat/sbgdec.c
libavformat/segment.c
libavformat/spdifenc.c
libavformat/tty.c
libavformat/wav.c
libavutil/opt.c
libswresample/swresample.c
libswscale/options.c

diff --cc ffprobe.c
index 3ec832f,0000000..5f2132d
mode 100644,000000..100644
--- /dev/null
+++ b/ffprobe.c
@@@ -1,2210 -1,0 +1,2210 @@@
-     { "noprint_wrappers", "do not print headers and footers", OFFSET(noprint_wrappers), AV_OPT_TYPE_INT, {.dbl=0}, 0, 1 },
-     { "nw",               "do not print headers and footers", OFFSET(noprint_wrappers), AV_OPT_TYPE_INT, {.dbl=0}, 0, 1 },
-     { "nokey",          "force no key printing",     OFFSET(nokey),          AV_OPT_TYPE_INT, {.dbl=0}, 0, 1 },
-     { "nk",             "force no key printing",     OFFSET(nokey),          AV_OPT_TYPE_INT, {.dbl=0}, 0, 1 },
 +/*
 + * Copyright (c) 2007-2010 Stefano Sabatini
 + *
 + * This file is part of FFmpeg.
 + *
 + * FFmpeg is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU Lesser General Public
 + * License as published by the Free Software Foundation; either
 + * version 2.1 of the License, or (at your option) any later version.
 + *
 + * FFmpeg is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 + * Lesser General Public License for more details.
 + *
 + * You should have received a copy of the GNU Lesser General Public
 + * License along with FFmpeg; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 + */
 +
 +/**
 + * @file
 + * simple media prober based on the FFmpeg libraries
 + */
 +
 +#include "config.h"
 +#include "version.h"
 +
 +#include "libavformat/avformat.h"
 +#include "libavcodec/avcodec.h"
 +#include "libavutil/avstring.h"
 +#include "libavutil/bprint.h"
 +#include "libavutil/opt.h"
 +#include "libavutil/pixdesc.h"
 +#include "libavutil/dict.h"
 +#include "libavutil/libm.h"
 +#include "libavutil/timecode.h"
 +#include "libavdevice/avdevice.h"
 +#include "libswscale/swscale.h"
 +#include "libswresample/swresample.h"
 +#include "libpostproc/postprocess.h"
 +#include "cmdutils.h"
 +
 +const char program_name[] = "ffprobe";
 +const int program_birth_year = 2007;
 +
 +static int do_count_frames = 0;
 +static int do_count_packets = 0;
 +static int do_read_frames  = 0;
 +static int do_read_packets = 0;
 +static int do_show_error   = 0;
 +static int do_show_format  = 0;
 +static int do_show_frames  = 0;
 +static AVDictionary *fmt_entries_to_show = NULL;
 +static int do_show_packets = 0;
 +static int do_show_streams = 0;
 +static int do_show_data    = 0;
 +static int do_show_program_version  = 0;
 +static int do_show_library_versions = 0;
 +
 +static int show_value_unit              = 0;
 +static int use_value_prefix             = 0;
 +static int use_byte_value_binary_prefix = 0;
 +static int use_value_sexagesimal_format = 0;
 +static int show_private_data            = 1;
 +
 +static char *print_format;
 +
 +static const OptionDef *options;
 +
 +/* FFprobe context */
 +static const char *input_filename;
 +static AVInputFormat *iformat = NULL;
 +
 +static const char *const binary_unit_prefixes [] = { "", "Ki", "Mi", "Gi", "Ti", "Pi" };
 +static const char *const decimal_unit_prefixes[] = { "", "K" , "M" , "G" , "T" , "P"  };
 +
 +static const char unit_second_str[]         = "s"    ;
 +static const char unit_hertz_str[]          = "Hz"   ;
 +static const char unit_byte_str[]           = "byte" ;
 +static const char unit_bit_per_second_str[] = "bit/s";
 +static uint64_t *nb_streams_packets;
 +static uint64_t *nb_streams_frames;
 +
 +void av_noreturn exit_program(int ret)
 +{
 +    av_dict_free(&fmt_entries_to_show);
 +    exit(ret);
 +}
 +
 +struct unit_value {
 +    union { double d; long long int i; } val;
 +    const char *unit;
 +};
 +
 +static char *value_string(char *buf, int buf_size, struct unit_value uv)
 +{
 +    double vald;
 +    int show_float = 0;
 +
 +    if (uv.unit == unit_second_str) {
 +        vald = uv.val.d;
 +        show_float = 1;
 +    } else {
 +        vald = uv.val.i;
 +    }
 +
 +    if (uv.unit == unit_second_str && use_value_sexagesimal_format) {
 +        double secs;
 +        int hours, mins;
 +        secs  = vald;
 +        mins  = (int)secs / 60;
 +        secs  = secs - mins * 60;
 +        hours = mins / 60;
 +        mins %= 60;
 +        snprintf(buf, buf_size, "%d:%02d:%09.6f", hours, mins, secs);
 +    } else {
 +        const char *prefix_string = "";
 +        int l;
 +
 +        if (use_value_prefix && vald > 1) {
 +            long long int index;
 +
 +            if (uv.unit == unit_byte_str && use_byte_value_binary_prefix) {
 +                index = (long long int) (log2(vald)) / 10;
 +                index = av_clip(index, 0, FF_ARRAY_ELEMS(binary_unit_prefixes) - 1);
 +                vald /= pow(2, index * 10);
 +                prefix_string = binary_unit_prefixes[index];
 +            } else {
 +                index = (long long int) (log10(vald)) / 3;
 +                index = av_clip(index, 0, FF_ARRAY_ELEMS(decimal_unit_prefixes) - 1);
 +                vald /= pow(10, index * 3);
 +                prefix_string = decimal_unit_prefixes[index];
 +            }
 +        }
 +
 +        if (show_float || (use_value_prefix && vald != (long long int)vald))
 +            l = snprintf(buf, buf_size, "%f", vald);
 +        else
 +            l = snprintf(buf, buf_size, "%lld", (long long int)vald);
 +        snprintf(buf+l, buf_size-l, "%s%s%s", *prefix_string || show_value_unit ? " " : "",
 +                 prefix_string, show_value_unit ? uv.unit : "");
 +    }
 +
 +    return buf;
 +}
 +
 +/* WRITERS API */
 +
 +typedef struct WriterContext WriterContext;
 +
 +#define WRITER_FLAG_DISPLAY_OPTIONAL_FIELDS 1
 +#define WRITER_FLAG_PUT_PACKETS_AND_FRAMES_IN_SAME_CHAPTER 2
 +
 +typedef struct Writer {
 +    int priv_size;                  ///< private size for the writer context
 +    const char *name;
 +
 +    int  (*init)  (WriterContext *wctx, const char *args, void *opaque);
 +    void (*uninit)(WriterContext *wctx);
 +
 +    void (*print_header)(WriterContext *ctx);
 +    void (*print_footer)(WriterContext *ctx);
 +
 +    void (*print_chapter_header)(WriterContext *wctx, const char *);
 +    void (*print_chapter_footer)(WriterContext *wctx, const char *);
 +    void (*print_section_header)(WriterContext *wctx, const char *);
 +    void (*print_section_footer)(WriterContext *wctx, const char *);
 +    void (*print_integer)       (WriterContext *wctx, const char *, long long int);
 +    void (*print_rational)      (WriterContext *wctx, AVRational *q, char *sep);
 +    void (*print_string)        (WriterContext *wctx, const char *, const char *);
 +    void (*show_tags)           (WriterContext *wctx, AVDictionary *dict);
 +    int flags;                  ///< a combination or WRITER_FLAG_*
 +} Writer;
 +
 +struct WriterContext {
 +    const AVClass *class;           ///< class of the writer
 +    const Writer *writer;           ///< the Writer of which this is an instance
 +    char *name;                     ///< name of this writer instance
 +    void *priv;                     ///< private data for use by the filter
 +    unsigned int nb_item;           ///< number of the item printed in the given section, starting at 0
 +    unsigned int nb_section;        ///< number of the section printed in the given section sequence, starting at 0
 +    unsigned int nb_section_packet; ///< number of the packet section in case we are in "packets_and_frames" section
 +    unsigned int nb_section_frame;  ///< number of the frame  section in case we are in "packets_and_frames" section
 +    unsigned int nb_section_packet_frame; ///< nb_section_packet or nb_section_frame according if is_packets_and_frames
 +    unsigned int nb_chapter;        ///< number of the chapter, starting at 0
 +
 +    int multiple_sections;          ///< tells if the current chapter can contain multiple sections
 +    int is_fmt_chapter;             ///< tells if the current chapter is "format", required by the print_format_entry option
 +    int is_packets_and_frames;      ///< tells if the current section is "packets_and_frames"
 +};
 +
 +static const char *writer_get_name(void *p)
 +{
 +    WriterContext *wctx = p;
 +    return wctx->writer->name;
 +}
 +
 +static const AVClass writer_class = {
 +    "Writer",
 +    writer_get_name,
 +    NULL,
 +    LIBAVUTIL_VERSION_INT,
 +};
 +
 +static void writer_close(WriterContext **wctx)
 +{
 +    if (!*wctx)
 +        return;
 +
 +    if ((*wctx)->writer->uninit)
 +        (*wctx)->writer->uninit(*wctx);
 +    av_freep(&((*wctx)->priv));
 +    av_freep(wctx);
 +}
 +
 +static int writer_open(WriterContext **wctx, const Writer *writer,
 +                       const char *args, void *opaque)
 +{
 +    int ret = 0;
 +
 +    if (!(*wctx = av_malloc(sizeof(WriterContext)))) {
 +        ret = AVERROR(ENOMEM);
 +        goto fail;
 +    }
 +
 +    if (!((*wctx)->priv = av_mallocz(writer->priv_size))) {
 +        ret = AVERROR(ENOMEM);
 +        goto fail;
 +    }
 +
 +    (*wctx)->class = &writer_class;
 +    (*wctx)->writer = writer;
 +    if ((*wctx)->writer->init)
 +        ret = (*wctx)->writer->init(*wctx, args, opaque);
 +    if (ret < 0)
 +        goto fail;
 +
 +    return 0;
 +
 +fail:
 +    writer_close(wctx);
 +    return ret;
 +}
 +
 +static inline void writer_print_header(WriterContext *wctx)
 +{
 +    if (wctx->writer->print_header)
 +        wctx->writer->print_header(wctx);
 +    wctx->nb_chapter = 0;
 +}
 +
 +static inline void writer_print_footer(WriterContext *wctx)
 +{
 +    if (wctx->writer->print_footer)
 +        wctx->writer->print_footer(wctx);
 +}
 +
 +static inline void writer_print_chapter_header(WriterContext *wctx,
 +                                               const char *chapter)
 +{
 +    wctx->nb_section =
 +    wctx->nb_section_packet = wctx->nb_section_frame =
 +    wctx->nb_section_packet_frame = 0;
 +    wctx->is_packets_and_frames = !strcmp(chapter, "packets_and_frames");
 +    wctx->multiple_sections = !strcmp(chapter, "packets") || !strcmp(chapter, "frames" ) ||
 +                              wctx->is_packets_and_frames ||
 +                              !strcmp(chapter, "streams") || !strcmp(chapter, "library_versions");
 +    wctx->is_fmt_chapter = !strcmp(chapter, "format");
 +
 +    if (wctx->writer->print_chapter_header)
 +        wctx->writer->print_chapter_header(wctx, chapter);
 +}
 +
 +static inline void writer_print_chapter_footer(WriterContext *wctx,
 +                                               const char *chapter)
 +{
 +    if (wctx->writer->print_chapter_footer)
 +        wctx->writer->print_chapter_footer(wctx, chapter);
 +    wctx->nb_chapter++;
 +}
 +
 +static inline void writer_print_section_header(WriterContext *wctx,
 +                                               const char *section)
 +{
 +    if (wctx->is_packets_and_frames)
 +        wctx->nb_section_packet_frame = !strcmp(section, "packet") ? wctx->nb_section_packet
 +                                                                   : wctx->nb_section_frame;
 +    if (wctx->writer->print_section_header)
 +        wctx->writer->print_section_header(wctx, section);
 +    wctx->nb_item = 0;
 +}
 +
 +static inline void writer_print_section_footer(WriterContext *wctx,
 +                                               const char *section)
 +{
 +    if (wctx->writer->print_section_footer)
 +        wctx->writer->print_section_footer(wctx, section);
 +    if (wctx->is_packets_and_frames) {
 +        if (!strcmp(section, "packet")) wctx->nb_section_packet++;
 +        else                            wctx->nb_section_frame++;
 +    }
 +    wctx->nb_section++;
 +}
 +
 +static inline void writer_print_integer(WriterContext *wctx,
 +                                        const char *key, long long int val)
 +{
 +    if (!wctx->is_fmt_chapter || !fmt_entries_to_show || av_dict_get(fmt_entries_to_show, key, NULL, 0)) {
 +        wctx->writer->print_integer(wctx, key, val);
 +        wctx->nb_item++;
 +    }
 +}
 +
 +static inline void writer_print_rational(WriterContext *wctx,
 +                                         const char *key, AVRational q, char sep)
 +{
 +    AVBPrint buf;
 +    av_bprint_init(&buf, 0, AV_BPRINT_SIZE_AUTOMATIC);
 +    av_bprintf(&buf, "%d%c%d", q.num, sep, q.den);
 +    wctx->writer->print_string(wctx, key, buf.str);
 +    wctx->nb_item++;
 +}
 +
 +static inline void writer_print_string(WriterContext *wctx,
 +                                       const char *key, const char *val, int opt)
 +{
 +    if (opt && !(wctx->writer->flags & WRITER_FLAG_DISPLAY_OPTIONAL_FIELDS))
 +        return;
 +    if (!wctx->is_fmt_chapter || !fmt_entries_to_show || av_dict_get(fmt_entries_to_show, key, NULL, 0)) {
 +        wctx->writer->print_string(wctx, key, val);
 +        wctx->nb_item++;
 +    }
 +}
 +
 +static void writer_print_time(WriterContext *wctx, const char *key,
 +                              int64_t ts, const AVRational *time_base, int is_duration)
 +{
 +    char buf[128];
 +
 +    if (!wctx->is_fmt_chapter || !fmt_entries_to_show || av_dict_get(fmt_entries_to_show, key, NULL, 0)) {
 +        if ((!is_duration && ts == AV_NOPTS_VALUE) || (is_duration && ts == 0)) {
 +            writer_print_string(wctx, key, "N/A", 1);
 +        } else {
 +            double d = ts * av_q2d(*time_base);
 +            value_string(buf, sizeof(buf), (struct unit_value){.val.d=d, .unit=unit_second_str});
 +            writer_print_string(wctx, key, buf, 0);
 +        }
 +    }
 +}
 +
 +static void writer_print_ts(WriterContext *wctx, const char *key, int64_t ts, int is_duration)
 +{
 +    if ((!is_duration && ts == AV_NOPTS_VALUE) || (is_duration && ts == 0)) {
 +        writer_print_string(wctx, key, "N/A", 1);
 +    } else {
 +        writer_print_integer(wctx, key, ts);
 +    }
 +}
 +
 +static inline void writer_show_tags(WriterContext *wctx, AVDictionary *dict)
 +{
 +    wctx->writer->show_tags(wctx, dict);
 +}
 +
 +static void writer_print_data(WriterContext *wctx, const char *name,
 +                              uint8_t *data, int size)
 +{
 +    AVBPrint bp;
 +    int offset = 0, l, i;
 +
 +    av_bprint_init(&bp, 0, AV_BPRINT_SIZE_UNLIMITED);
 +    av_bprintf(&bp, "\n");
 +    while (size) {
 +        av_bprintf(&bp, "%08x: ", offset);
 +        l = FFMIN(size, 16);
 +        for (i = 0; i < l; i++) {
 +            av_bprintf(&bp, "%02x", data[i]);
 +            if (i & 1)
 +                av_bprintf(&bp, " ");
 +        }
 +        av_bprint_chars(&bp, ' ', 41 - 2 * i - i / 2);
 +        for (i = 0; i < l; i++)
 +            av_bprint_chars(&bp, data[i] - 32U < 95 ? data[i] : '.', 1);
 +        av_bprintf(&bp, "\n");
 +        offset += l;
 +        data   += l;
 +        size   -= l;
 +    }
 +    writer_print_string(wctx, name, bp.str, 0);
 +    av_bprint_finalize(&bp, NULL);
 +}
 +
 +#define MAX_REGISTERED_WRITERS_NB 64
 +
 +static const Writer *registered_writers[MAX_REGISTERED_WRITERS_NB + 1];
 +
 +static int writer_register(const Writer *writer)
 +{
 +    static int next_registered_writer_idx = 0;
 +
 +    if (next_registered_writer_idx == MAX_REGISTERED_WRITERS_NB)
 +        return AVERROR(ENOMEM);
 +
 +    registered_writers[next_registered_writer_idx++] = writer;
 +    return 0;
 +}
 +
 +static const Writer *writer_get_by_name(const char *name)
 +{
 +    int i;
 +
 +    for (i = 0; registered_writers[i]; i++)
 +        if (!strcmp(registered_writers[i]->name, name))
 +            return registered_writers[i];
 +
 +    return NULL;
 +}
 +
 +
 +/* WRITERS */
 +
 +/* Default output */
 +
 +typedef struct DefaultContext {
 +    const AVClass *class;
 +    int nokey;
 +    int noprint_wrappers;
 +} DefaultContext;
 +
 +#define OFFSET(x) offsetof(DefaultContext, x)
 +
 +static const AVOption default_options[] = {
-     {"nokey",    "force no key printing", OFFSET(nokey),           AV_OPT_TYPE_INT,    {.dbl=0},    0,        1        },
-     {"nk",       "force no key printing", OFFSET(nokey),           AV_OPT_TYPE_INT,    {.dbl=0},    0,        1        },
++    { "noprint_wrappers", "do not print headers and footers", OFFSET(noprint_wrappers), AV_OPT_TYPE_INT, {.i64=0}, 0, 1 },
++    { "nw",               "do not print headers and footers", OFFSET(noprint_wrappers), AV_OPT_TYPE_INT, {.i64=0}, 0, 1 },
++    { "nokey",          "force no key printing",     OFFSET(nokey),          AV_OPT_TYPE_INT, {.i64=0}, 0, 1 },
++    { "nk",             "force no key printing",     OFFSET(nokey),          AV_OPT_TYPE_INT, {.i64=0}, 0, 1 },
 +    {NULL},
 +};
 +
 +static const char *default_get_name(void *ctx)
 +{
 +    return "default";
 +}
 +
 +static const AVClass default_class = {
 +    "DefaultContext",
 +    default_get_name,
 +    default_options
 +};
 +
 +static av_cold int default_init(WriterContext *wctx, const char *args, void *opaque)
 +{
 +    DefaultContext *def = wctx->priv;
 +    int err;
 +
 +    def->class = &default_class;
 +    av_opt_set_defaults(def);
 +
 +    if (args &&
 +        (err = (av_set_options_string(def, args, "=", ":"))) < 0)
 +        return err;
 +
 +    return 0;
 +}
 +
 +static void default_print_footer(WriterContext *wctx)
 +{
 +    DefaultContext *def = wctx->priv;
 +
 +    if (!def->noprint_wrappers)
 +        printf("\n");
 +}
 +
 +static void default_print_chapter_header(WriterContext *wctx, const char *chapter)
 +{
 +    DefaultContext *def = wctx->priv;
 +
 +    if (!def->noprint_wrappers && wctx->nb_chapter)
 +        printf("\n");
 +}
 +
 +/* lame uppercasing routine, assumes the string is lower case ASCII */
 +static inline char *upcase_string(char *dst, size_t dst_size, const char *src)
 +{
 +    int i;
 +    for (i = 0; src[i] && i < dst_size-1; i++)
 +        dst[i] = av_toupper(src[i]);
 +    dst[i] = 0;
 +    return dst;
 +}
 +
 +static void default_print_section_header(WriterContext *wctx, const char *section)
 +{
 +    DefaultContext *def = wctx->priv;
 +    char buf[32];
 +
 +    if (wctx->nb_section)
 +        printf("\n");
 +    if (!def->noprint_wrappers)
 +        printf("[%s]\n", upcase_string(buf, sizeof(buf), section));
 +}
 +
 +static void default_print_section_footer(WriterContext *wctx, const char *section)
 +{
 +    DefaultContext *def = wctx->priv;
 +    char buf[32];
 +
 +    if (!def->noprint_wrappers)
 +        printf("[/%s]", upcase_string(buf, sizeof(buf), section));
 +}
 +
 +static void default_print_str(WriterContext *wctx, const char *key, const char *value)
 +{
 +    DefaultContext *def = wctx->priv;
 +    if (!def->nokey)
 +        printf("%s=", key);
 +    printf("%s\n", value);
 +}
 +
 +static void default_print_int(WriterContext *wctx, const char *key, long long int value)
 +{
 +    DefaultContext *def = wctx->priv;
 +
 +    if (!def->nokey)
 +        printf("%s=", key);
 +    printf("%lld\n", value);
 +}
 +
 +static void default_show_tags(WriterContext *wctx, AVDictionary *dict)
 +{
 +    AVDictionaryEntry *tag = NULL;
 +    while ((tag = av_dict_get(dict, "", tag, AV_DICT_IGNORE_SUFFIX))) {
 +        if (!fmt_entries_to_show || (tag->key && av_dict_get(fmt_entries_to_show, tag->key, NULL, 0)))
 +            printf("TAG:");
 +        writer_print_string(wctx, tag->key, tag->value, 0);
 +    }
 +}
 +
 +static const Writer default_writer = {
 +    .name                  = "default",
 +    .priv_size             = sizeof(DefaultContext),
 +    .init                  = default_init,
 +    .print_footer          = default_print_footer,
 +    .print_chapter_header  = default_print_chapter_header,
 +    .print_section_header  = default_print_section_header,
 +    .print_section_footer  = default_print_section_footer,
 +    .print_integer         = default_print_int,
 +    .print_string          = default_print_str,
 +    .show_tags             = default_show_tags,
 +    .flags = WRITER_FLAG_DISPLAY_OPTIONAL_FIELDS,
 +};
 +
 +/* Compact output */
 +
 +/**
 + * Apply C-language-like string escaping.
 + */
 +static const char *c_escape_str(AVBPrint *dst, const char *src, const char sep, void *log_ctx)
 +{
 +    const char *p;
 +
 +    for (p = src; *p; p++) {
 +        switch (*p) {
 +        case '\b': av_bprintf(dst, "%s", "\\b");  break;
 +        case '\f': av_bprintf(dst, "%s", "\\f");  break;
 +        case '\n': av_bprintf(dst, "%s", "\\n");  break;
 +        case '\r': av_bprintf(dst, "%s", "\\r");  break;
 +        case '\\': av_bprintf(dst, "%s", "\\\\"); break;
 +        default:
 +            if (*p == sep)
 +                av_bprint_chars(dst, '\\', 1);
 +            av_bprint_chars(dst, *p, 1);
 +        }
 +    }
 +    return dst->str;
 +}
 +
 +/**
 + * Quote fields containing special characters, check RFC4180.
 + */
 +static const char *csv_escape_str(AVBPrint *dst, const char *src, const char sep, void *log_ctx)
 +{
 +    const char *p;
 +    int quote = 0;
 +
 +    /* check if input needs quoting */
 +    for (p = src; *p; p++)
 +        if (*p == '"' || *p == sep || *p == '\n' || *p == '\r')
 +            quote = 1;
 +
 +    if (quote)
 +        av_bprint_chars(dst, '\"', 1);
 +
 +    for (p = src; *p; p++) {
 +        if (*p == '"')
 +            av_bprint_chars(dst, '\"', 1);
 +        av_bprint_chars(dst, *p, 1);
 +    }
 +    if (quote)
 +        av_bprint_chars(dst, '\"', 1);
 +    return dst->str;
 +}
 +
 +static const char *none_escape_str(AVBPrint *dst, const char *src, const char sep, void *log_ctx)
 +{
 +    return src;
 +}
 +
 +typedef struct CompactContext {
 +    const AVClass *class;
 +    char *item_sep_str;
 +    char item_sep;
 +    int nokey;
 +    char *escape_mode_str;
 +    const char * (*escape_str)(AVBPrint *dst, const char *src, const char sep, void *log_ctx);
 +} CompactContext;
 +
 +#undef OFFSET
 +#define OFFSET(x) offsetof(CompactContext, x)
 +
 +static const AVOption compact_options[]= {
 +    {"item_sep", "set item separator",    OFFSET(item_sep_str),    AV_OPT_TYPE_STRING, {.str="|"},  CHAR_MIN, CHAR_MAX },
 +    {"s",        "set item separator",    OFFSET(item_sep_str),    AV_OPT_TYPE_STRING, {.str="|"},  CHAR_MIN, CHAR_MAX },
-     {"hierarchical", "specify if the section specification should be hierarchical", OFFSET(hierarchical), AV_OPT_TYPE_INT, {.dbl=1}, 0, 1 },
-     {"h",           "specify if the section specification should be hierarchical", OFFSET(hierarchical), AV_OPT_TYPE_INT, {.dbl=1}, 0, 1 },
++    {"nokey",    "force no key printing", OFFSET(nokey),           AV_OPT_TYPE_INT,    {.i64=0},    0,        1        },
++    {"nk",       "force no key printing", OFFSET(nokey),           AV_OPT_TYPE_INT,    {.i64=0},    0,        1        },
 +    {"escape",   "set escape mode",       OFFSET(escape_mode_str), AV_OPT_TYPE_STRING, {.str="c"},  CHAR_MIN, CHAR_MAX },
 +    {"e",        "set escape mode",       OFFSET(escape_mode_str), AV_OPT_TYPE_STRING, {.str="c"},  CHAR_MIN, CHAR_MAX },
 +    {NULL},
 +};
 +
 +static const char *compact_get_name(void *ctx)
 +{
 +    return "compact";
 +}
 +
 +static const AVClass compact_class = {
 +    "CompactContext",
 +    compact_get_name,
 +    compact_options
 +};
 +
 +static av_cold int compact_init(WriterContext *wctx, const char *args, void *opaque)
 +{
 +    CompactContext *compact = wctx->priv;
 +    int err;
 +
 +    compact->class = &compact_class;
 +    av_opt_set_defaults(compact);
 +
 +    if (args &&
 +        (err = (av_set_options_string(compact, args, "=", ":"))) < 0)
 +        return err;
 +    if (strlen(compact->item_sep_str) != 1) {
 +        av_log(wctx, AV_LOG_ERROR, "Item separator '%s' specified, but must contain a single character\n",
 +               compact->item_sep_str);
 +        return AVERROR(EINVAL);
 +    }
 +    compact->item_sep = compact->item_sep_str[0];
 +
 +    if      (!strcmp(compact->escape_mode_str, "none")) compact->escape_str = none_escape_str;
 +    else if (!strcmp(compact->escape_mode_str, "c"   )) compact->escape_str = c_escape_str;
 +    else if (!strcmp(compact->escape_mode_str, "csv" )) compact->escape_str = csv_escape_str;
 +    else {
 +        av_log(wctx, AV_LOG_ERROR, "Unknown escape mode '%s'\n", compact->escape_mode_str);
 +        return AVERROR(EINVAL);
 +    }
 +
 +    return 0;
 +}
 +
 +static av_cold void compact_uninit(WriterContext *wctx)
 +{
 +    CompactContext *compact = wctx->priv;
 +
 +    av_freep(&compact->item_sep_str);
 +    av_freep(&compact->escape_mode_str);
 +}
 +
 +static void compact_print_section_header(WriterContext *wctx, const char *section)
 +{
 +    CompactContext *compact = wctx->priv;
 +
 +    printf("%s%c", section, compact->item_sep);
 +}
 +
 +static void compact_print_section_footer(WriterContext *wctx, const char *section)
 +{
 +    printf("\n");
 +}
 +
 +static void compact_print_str(WriterContext *wctx, const char *key, const char *value)
 +{
 +    CompactContext *compact = wctx->priv;
 +    AVBPrint buf;
 +
 +    if (wctx->nb_item) printf("%c", compact->item_sep);
 +    if (!compact->nokey)
 +        printf("%s=", key);
 +    av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED);
 +    printf("%s", compact->escape_str(&buf, value, compact->item_sep, wctx));
 +    av_bprint_finalize(&buf, NULL);
 +}
 +
 +static void compact_print_int(WriterContext *wctx, const char *key, long long int value)
 +{
 +    CompactContext *compact = wctx->priv;
 +
 +    if (wctx->nb_item) printf("%c", compact->item_sep);
 +    if (!compact->nokey)
 +        printf("%s=", key);
 +    printf("%lld", value);
 +}
 +
 +static void compact_show_tags(WriterContext *wctx, AVDictionary *dict)
 +{
 +    CompactContext *compact = wctx->priv;
 +    AVDictionaryEntry *tag = NULL;
 +    AVBPrint buf;
 +
 +    av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED);
 +    while ((tag = av_dict_get(dict, "", tag, AV_DICT_IGNORE_SUFFIX))) {
 +        if (wctx->nb_item) printf("%c", compact->item_sep);
 +        if (!compact->nokey) {
 +            av_bprint_clear(&buf);
 +            printf("tag:%s=", compact->escape_str(&buf, tag->key, compact->item_sep, wctx));
 +        }
 +        av_bprint_clear(&buf);
 +        printf("%s", compact->escape_str(&buf, tag->value, compact->item_sep, wctx));
 +    }
 +    av_bprint_finalize(&buf, NULL);
 +}
 +
 +static const Writer compact_writer = {
 +    .name                 = "compact",
 +    .priv_size            = sizeof(CompactContext),
 +    .init                 = compact_init,
 +    .uninit               = compact_uninit,
 +    .print_section_header = compact_print_section_header,
 +    .print_section_footer = compact_print_section_footer,
 +    .print_integer        = compact_print_int,
 +    .print_string         = compact_print_str,
 +    .show_tags            = compact_show_tags,
 +    .flags = WRITER_FLAG_DISPLAY_OPTIONAL_FIELDS,
 +};
 +
 +/* CSV output */
 +
 +static av_cold int csv_init(WriterContext *wctx, const char *args, void *opaque)
 +{
 +    return compact_init(wctx, "item_sep=,:nokey=1:escape=csv", opaque);
 +}
 +
 +static const Writer csv_writer = {
 +    .name                 = "csv",
 +    .priv_size            = sizeof(CompactContext),
 +    .init                 = csv_init,
 +    .uninit               = compact_uninit,
 +    .print_section_header = compact_print_section_header,
 +    .print_section_footer = compact_print_section_footer,
 +    .print_integer        = compact_print_int,
 +    .print_string         = compact_print_str,
 +    .show_tags            = compact_show_tags,
 +    .flags = WRITER_FLAG_DISPLAY_OPTIONAL_FIELDS,
 +};
 +
 +/* Flat output */
 +
 +typedef struct FlatContext {
 +    const AVClass *class;
 +    const char *section, *chapter;
 +    const char *sep_str;
 +    char sep;
 +    int hierarchical;
 +} FlatContext;
 +
 +#undef OFFSET
 +#define OFFSET(x) offsetof(FlatContext, x)
 +
 +static const AVOption flat_options[]= {
 +    {"sep_char", "set separator",    OFFSET(sep_str),    AV_OPT_TYPE_STRING, {.str="."},  CHAR_MIN, CHAR_MAX },
 +    {"s",        "set separator",    OFFSET(sep_str),    AV_OPT_TYPE_STRING, {.str="."},  CHAR_MIN, CHAR_MAX },
-     {"hierarchical", "specify if the section specification should be hierarchical", OFFSET(hierarchical), AV_OPT_TYPE_INT, {.dbl=1}, 0, 1 },
-     {"h",           "specify if the section specification should be hierarchical", OFFSET(hierarchical), AV_OPT_TYPE_INT, {.dbl=1}, 0, 1 },
++    {"hierarchical", "specify if the section specification should be hierarchical", OFFSET(hierarchical), AV_OPT_TYPE_INT, {.i64=1}, 0, 1 },
++    {"h",           "specify if the section specification should be hierarchical", OFFSET(hierarchical), AV_OPT_TYPE_INT, {.i64=1}, 0, 1 },
 +    {NULL},
 +};
 +
 +static const char *flat_get_name(void *ctx)
 +{
 +    return "flat";
 +}
 +
 +static const AVClass flat_class = {
 +    "FlatContext",
 +    flat_get_name,
 +    flat_options
 +};
 +
 +static av_cold int flat_init(WriterContext *wctx, const char *args, void *opaque)
 +{
 +    FlatContext *flat = wctx->priv;
 +    int err;
 +
 +    flat->class = &flat_class;
 +    av_opt_set_defaults(flat);
 +
 +    if (args &&
 +        (err = (av_set_options_string(flat, args, "=", ":"))) < 0)
 +        return err;
 +    if (strlen(flat->sep_str) != 1) {
 +        av_log(wctx, AV_LOG_ERROR, "Item separator '%s' specified, but must contain a single character\n",
 +               flat->sep_str);
 +        return AVERROR(EINVAL);
 +    }
 +    flat->sep = flat->sep_str[0];
 +    return 0;
 +}
 +
 +static const char *flat_escape_key_str(AVBPrint *dst, const char *src, const char sep)
 +{
 +    const char *p;
 +
 +    for (p = src; *p; p++) {
 +        if (!((*p >= '0' && *p <= '9') ||
 +              (*p >= 'a' && *p <= 'z') ||
 +              (*p >= 'A' && *p <= 'Z')))
 +            av_bprint_chars(dst, '_', 1);
 +        else
 +            av_bprint_chars(dst, *p, 1);
 +    }
 +    return dst->str;
 +}
 +
 +static const char *flat_escape_value_str(AVBPrint *dst, const char *src)
 +{
 +    const char *p;
 +
 +    for (p = src; *p; p++) {
 +        switch (*p) {
 +        case '\n': av_bprintf(dst, "%s", "\\n");  break;
 +        case '\r': av_bprintf(dst, "%s", "\\r");  break;
 +        case '\\': av_bprintf(dst, "%s", "\\\\"); break;
 +        case '"':  av_bprintf(dst, "%s", "\\\""); break;
 +        case '`':  av_bprintf(dst, "%s", "\\`");  break;
 +        case '$':  av_bprintf(dst, "%s", "\\$");  break;
 +        default:   av_bprint_chars(dst, *p, 1);   break;
 +        }
 +    }
 +    return dst->str;
 +}
 +
 +static void flat_print_chapter_header(WriterContext *wctx, const char *chapter)
 +{
 +    FlatContext *flat = wctx->priv;
 +    flat->chapter = chapter;
 +}
 +
 +static void flat_print_section_header(WriterContext *wctx, const char *section)
 +{
 +    FlatContext *flat = wctx->priv;
 +    flat->section = section;
 +}
 +
 +static void flat_print_section(WriterContext *wctx)
 +{
 +    FlatContext *flat = wctx->priv;
 +    int n = wctx->is_packets_and_frames ? wctx->nb_section_packet_frame
 +                                        : wctx->nb_section;
 +
 +    if (flat->hierarchical && wctx->multiple_sections)
 +        printf("%s%c", flat->chapter, flat->sep);
 +    printf("%s%c", flat->section, flat->sep);
 +    if (wctx->multiple_sections)
 +        printf("%d%c", n, flat->sep);
 +}
 +
 +static void flat_print_int(WriterContext *wctx, const char *key, long long int value)
 +{
 +    flat_print_section(wctx);
 +    printf("%s=%lld\n", key, value);
 +}
 +
 +static void flat_print_str(WriterContext *wctx, const char *key, const char *value)
 +{
 +    FlatContext *flat = wctx->priv;
 +    AVBPrint buf;
 +
 +    flat_print_section(wctx);
 +    av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED);
 +    printf("%s=", flat_escape_key_str(&buf, key, flat->sep));
 +    av_bprint_clear(&buf);
 +    printf("\"%s\"\n", flat_escape_value_str(&buf, value));
 +    av_bprint_finalize(&buf, NULL);
 +}
 +
 +static void flat_show_tags(WriterContext *wctx, AVDictionary *dict)
 +{
 +    FlatContext *flat = wctx->priv;
 +    AVBPrint buf;
 +    AVDictionaryEntry *tag = NULL;
 +
 +    av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED);
 +    while ((tag = av_dict_get(dict, "", tag, AV_DICT_IGNORE_SUFFIX))) {
 +        flat_print_section(wctx);
 +        av_bprint_clear(&buf);
 +        printf("tags%c%s=", flat->sep, flat_escape_key_str(&buf, tag->key, flat->sep));
 +        av_bprint_clear(&buf);
 +        printf("\"%s\"\n", flat_escape_value_str(&buf, tag->value));
 +    }
 +    av_bprint_finalize(&buf, NULL);
 +}
 +
 +static const Writer flat_writer = {
 +    .name                  = "flat",
 +    .priv_size             = sizeof(FlatContext),
 +    .init                  = flat_init,
 +    .print_chapter_header  = flat_print_chapter_header,
 +    .print_section_header  = flat_print_section_header,
 +    .print_integer         = flat_print_int,
 +    .print_string          = flat_print_str,
 +    .show_tags             = flat_show_tags,
 +    .flags = WRITER_FLAG_DISPLAY_OPTIONAL_FIELDS|WRITER_FLAG_PUT_PACKETS_AND_FRAMES_IN_SAME_CHAPTER,
 +};
 +
 +/* INI format output */
 +
 +typedef struct {
 +    const AVClass *class;
 +    AVBPrint chapter_name, section_name;
 +    int hierarchical;
 +} INIContext;
 +
 +#undef OFFSET
 +#define OFFSET(x) offsetof(INIContext, x)
 +
 +static const AVOption ini_options[] = {
-     { "compact", "enable compact output", OFFSET(compact), AV_OPT_TYPE_INT, {.dbl=0}, 0, 1 },
-     { "c",       "enable compact output", OFFSET(compact), AV_OPT_TYPE_INT, {.dbl=0}, 0, 1 },
++    {"hierarchical", "specify if the section specification should be hierarchical", OFFSET(hierarchical), AV_OPT_TYPE_INT, {.i64=1}, 0, 1 },
++    {"h",           "specify if the section specification should be hierarchical", OFFSET(hierarchical), AV_OPT_TYPE_INT, {.i64=1}, 0, 1 },
 +    {NULL},
 +};
 +
 +static const char *ini_get_name(void *ctx)
 +{
 +    return "ini";
 +}
 +
 +static const AVClass ini_class = {
 +    "INIContext",
 +    ini_get_name,
 +    ini_options
 +};
 +
 +static av_cold int ini_init(WriterContext *wctx, const char *args, void *opaque)
 +{
 +    INIContext *ini = wctx->priv;
 +    int err;
 +
 +    av_bprint_init(&ini->chapter_name, 1, AV_BPRINT_SIZE_UNLIMITED);
 +    av_bprint_init(&ini->section_name, 1, AV_BPRINT_SIZE_UNLIMITED);
 +
 +    ini->class = &ini_class;
 +    av_opt_set_defaults(ini);
 +
 +    if (args && (err = av_set_options_string(ini, args, "=", ":")) < 0)
 +        return err;
 +
 +    return 0;
 +}
 +
 +static av_cold void ini_uninit(WriterContext *wctx)
 +{
 +    INIContext *ini = wctx->priv;
 +    av_bprint_finalize(&ini->chapter_name, NULL);
 +    av_bprint_finalize(&ini->section_name, NULL);
 +}
 +
 +static void ini_print_header(WriterContext *wctx)
 +{
 +    printf("# ffprobe output\n\n");
 +}
 +
 +static char *ini_escape_str(AVBPrint *dst, const char *src)
 +{
 +    int i = 0;
 +    char c = 0;
 +
 +    while (c = src[i++]) {
 +        switch (c) {
 +        case '\b': av_bprintf(dst, "%s", "\\b"); break;
 +        case '\f': av_bprintf(dst, "%s", "\\f"); break;
 +        case '\n': av_bprintf(dst, "%s", "\\n"); break;
 +        case '\r': av_bprintf(dst, "%s", "\\r"); break;
 +        case '\t': av_bprintf(dst, "%s", "\\t"); break;
 +        case '\\':
 +        case '#' :
 +        case '=' :
 +        case ':' : av_bprint_chars(dst, '\\', 1);
 +        default:
 +            if ((unsigned char)c < 32)
 +                av_bprintf(dst, "\\x00%02x", c & 0xff);
 +            else
 +                av_bprint_chars(dst, c, 1);
 +            break;
 +        }
 +    }
 +    return dst->str;
 +}
 +
 +static void ini_print_chapter_header(WriterContext *wctx, const char *chapter)
 +{
 +    INIContext *ini = wctx->priv;
 +
 +    av_bprint_clear(&ini->chapter_name);
 +    av_bprintf(&ini->chapter_name, "%s", chapter);
 +
 +    if (wctx->nb_chapter)
 +        printf("\n");
 +}
 +
 +static void ini_print_section_header(WriterContext *wctx, const char *section)
 +{
 +    INIContext *ini = wctx->priv;
 +    int n = wctx->is_packets_and_frames ? wctx->nb_section_packet_frame
 +                                        : wctx->nb_section;
 +    if (wctx->nb_section)
 +        printf("\n");
 +    av_bprint_clear(&ini->section_name);
 +
 +    if (ini->hierarchical && wctx->multiple_sections)
 +        av_bprintf(&ini->section_name, "%s.", ini->chapter_name.str);
 +    av_bprintf(&ini->section_name, "%s", section);
 +
 +    if (wctx->multiple_sections)
 +        av_bprintf(&ini->section_name, ".%d", n);
 +    printf("[%s]\n", ini->section_name.str);
 +}
 +
 +static void ini_print_str(WriterContext *wctx, const char *key, const char *value)
 +{
 +    AVBPrint buf;
 +
 +    av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED);
 +    printf("%s=", ini_escape_str(&buf, key));
 +    av_bprint_clear(&buf);
 +    printf("%s\n", ini_escape_str(&buf, value));
 +    av_bprint_finalize(&buf, NULL);
 +}
 +
 +static void ini_print_int(WriterContext *wctx, const char *key, long long int value)
 +{
 +    printf("%s=%lld\n", key, value);
 +}
 +
 +static void ini_show_tags(WriterContext *wctx, AVDictionary *dict)
 +{
 +    INIContext *ini = wctx->priv;
 +    AVDictionaryEntry *tag = NULL;
 +    int is_first = 1;
 +
 +    while ((tag = av_dict_get(dict, "", tag, AV_DICT_IGNORE_SUFFIX))) {
 +        if (is_first) {
 +            printf("\n[%s.tags]\n", ini->section_name.str);
 +            is_first = 0;
 +        }
 +        writer_print_string(wctx, tag->key, tag->value, 0);
 +    }
 +}
 +
 +static const Writer ini_writer = {
 +    .name                  = "ini",
 +    .priv_size             = sizeof(INIContext),
 +    .init                  = ini_init,
 +    .uninit                = ini_uninit,
 +    .print_header          = ini_print_header,
 +    .print_chapter_header  = ini_print_chapter_header,
 +    .print_section_header  = ini_print_section_header,
 +    .print_integer         = ini_print_int,
 +    .print_string          = ini_print_str,
 +    .show_tags             = ini_show_tags,
 +    .flags = WRITER_FLAG_DISPLAY_OPTIONAL_FIELDS|WRITER_FLAG_PUT_PACKETS_AND_FRAMES_IN_SAME_CHAPTER,
 +};
 +
 +/* JSON output */
 +
 +typedef struct {
 +    const AVClass *class;
 +    int indent_level;
 +    int compact;
 +    const char *item_sep, *item_start_end;
 +} JSONContext;
 +
 +#undef OFFSET
 +#define OFFSET(x) offsetof(JSONContext, x)
 +
 +static const AVOption json_options[]= {
-     {"fully_qualified", "specify if the output should be fully qualified", OFFSET(fully_qualified), AV_OPT_TYPE_INT, {.dbl=0},  0, 1 },
-     {"q",               "specify if the output should be fully qualified", OFFSET(fully_qualified), AV_OPT_TYPE_INT, {.dbl=0},  0, 1 },
-     {"xsd_strict",      "ensure that the output is XSD compliant",         OFFSET(xsd_strict),      AV_OPT_TYPE_INT, {.dbl=0},  0, 1 },
-     {"x",               "ensure that the output is XSD compliant",         OFFSET(xsd_strict),      AV_OPT_TYPE_INT, {.dbl=0},  0, 1 },
++    { "compact", "enable compact output", OFFSET(compact), AV_OPT_TYPE_INT, {.i64=0}, 0, 1 },
++    { "c",       "enable compact output", OFFSET(compact), AV_OPT_TYPE_INT, {.i64=0}, 0, 1 },
 +    { NULL }
 +};
 +
 +static const char *json_get_name(void *ctx)
 +{
 +    return "json";
 +}
 +
 +static const AVClass json_class = {
 +    "JSONContext",
 +    json_get_name,
 +    json_options
 +};
 +
 +static av_cold int json_init(WriterContext *wctx, const char *args, void *opaque)
 +{
 +    JSONContext *json = wctx->priv;
 +    int err;
 +
 +    json->class = &json_class;
 +    av_opt_set_defaults(json);
 +
 +    if (args &&
 +        (err = (av_set_options_string(json, args, "=", ":"))) < 0)
 +        return err;
 +
 +    json->item_sep       = json->compact ? ", " : ",\n";
 +    json->item_start_end = json->compact ? " "  : "\n";
 +
 +    return 0;
 +}
 +
 +static const char *json_escape_str(AVBPrint *dst, const char *src, void *log_ctx)
 +{
 +    static const char json_escape[] = {'"', '\\', '\b', '\f', '\n', '\r', '\t', 0};
 +    static const char json_subst[]  = {'"', '\\',  'b',  'f',  'n',  'r',  't', 0};
 +    const char *p;
 +
 +    for (p = src; *p; p++) {
 +        char *s = strchr(json_escape, *p);
 +        if (s) {
 +            av_bprint_chars(dst, '\\', 1);
 +            av_bprint_chars(dst, json_subst[s - json_escape], 1);
 +        } else if ((unsigned char)*p < 32) {
 +            av_bprintf(dst, "\\u00%02x", *p & 0xff);
 +        } else {
 +            av_bprint_chars(dst, *p, 1);
 +        }
 +    }
 +    return dst->str;
 +}
 +
 +static void json_print_header(WriterContext *wctx)
 +{
 +    JSONContext *json = wctx->priv;
 +    printf("{");
 +    json->indent_level++;
 +}
 +
 +static void json_print_footer(WriterContext *wctx)
 +{
 +    JSONContext *json = wctx->priv;
 +    json->indent_level--;
 +    printf("\n}\n");
 +}
 +
 +#define JSON_INDENT() printf("%*c", json->indent_level * 4, ' ')
 +
 +static void json_print_chapter_header(WriterContext *wctx, const char *chapter)
 +{
 +    JSONContext *json = wctx->priv;
 +    AVBPrint buf;
 +
 +    if (wctx->nb_chapter)
 +        printf(",");
 +    printf("\n");
 +    if (wctx->multiple_sections) {
 +        JSON_INDENT();
 +        av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED);
 +        printf("\"%s\": [\n", json_escape_str(&buf, chapter, wctx));
 +        av_bprint_finalize(&buf, NULL);
 +        json->indent_level++;
 +    }
 +}
 +
 +static void json_print_chapter_footer(WriterContext *wctx, const char *chapter)
 +{
 +    JSONContext *json = wctx->priv;
 +
 +    if (wctx->multiple_sections) {
 +        printf("\n");
 +        json->indent_level--;
 +        JSON_INDENT();
 +        printf("]");
 +    }
 +}
 +
 +static void json_print_section_header(WriterContext *wctx, const char *section)
 +{
 +    JSONContext *json = wctx->priv;
 +
 +    if (wctx->nb_section)
 +        printf(",\n");
 +    JSON_INDENT();
 +    if (!wctx->multiple_sections)
 +        printf("\"%s\": ", section);
 +    printf("{%s", json->item_start_end);
 +    json->indent_level++;
 +    /* this is required so the parser can distinguish between packets and frames */
 +    if (wctx->is_packets_and_frames) {
 +        if (!json->compact)
 +            JSON_INDENT();
 +        printf("\"type\": \"%s\"%s", section, json->item_sep);
 +    }
 +}
 +
 +static void json_print_section_footer(WriterContext *wctx, const char *section)
 +{
 +    JSONContext *json = wctx->priv;
 +
 +    printf("%s", json->item_start_end);
 +    json->indent_level--;
 +    if (!json->compact)
 +        JSON_INDENT();
 +    printf("}");
 +}
 +
 +static inline void json_print_item_str(WriterContext *wctx,
 +                                       const char *key, const char *value)
 +{
 +    AVBPrint buf;
 +
 +    av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED);
 +    printf("\"%s\":", json_escape_str(&buf, key,   wctx));
 +    av_bprint_clear(&buf);
 +    printf(" \"%s\"", json_escape_str(&buf, value, wctx));
 +    av_bprint_finalize(&buf, NULL);
 +}
 +
 +static void json_print_str(WriterContext *wctx, const char *key, const char *value)
 +{
 +    JSONContext *json = wctx->priv;
 +
 +    if (wctx->nb_item) printf("%s", json->item_sep);
 +    if (!json->compact)
 +        JSON_INDENT();
 +    json_print_item_str(wctx, key, value);
 +}
 +
 +static void json_print_int(WriterContext *wctx, const char *key, long long int value)
 +{
 +    JSONContext *json = wctx->priv;
 +    AVBPrint buf;
 +
 +    if (wctx->nb_item) printf("%s", json->item_sep);
 +    if (!json->compact)
 +        JSON_INDENT();
 +
 +    av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED);
 +    printf("\"%s\": %lld", json_escape_str(&buf, key, wctx), value);
 +    av_bprint_finalize(&buf, NULL);
 +}
 +
 +static void json_show_tags(WriterContext *wctx, AVDictionary *dict)
 +{
 +    JSONContext *json = wctx->priv;
 +    AVDictionaryEntry *tag = NULL;
 +    int is_first = 1;
 +    if (!dict)
 +        return;
 +    printf("%s", json->item_sep);
 +    if (!json->compact)
 +        JSON_INDENT();
 +    printf("\"tags\": {%s", json->item_start_end);
 +    json->indent_level++;
 +    while ((tag = av_dict_get(dict, "", tag, AV_DICT_IGNORE_SUFFIX))) {
 +        if (is_first) is_first = 0;
 +        else          printf("%s", json->item_sep);
 +        if (!json->compact)
 +            JSON_INDENT();
 +        json_print_item_str(wctx, tag->key, tag->value);
 +    }
 +    json->indent_level--;
 +    printf("%s", json->item_start_end);
 +    if (!json->compact)
 +        JSON_INDENT();
 +    printf("}");
 +}
 +
 +static const Writer json_writer = {
 +    .name                 = "json",
 +    .priv_size            = sizeof(JSONContext),
 +    .init                 = json_init,
 +    .print_header         = json_print_header,
 +    .print_footer         = json_print_footer,
 +    .print_chapter_header = json_print_chapter_header,
 +    .print_chapter_footer = json_print_chapter_footer,
 +    .print_section_header = json_print_section_header,
 +    .print_section_footer = json_print_section_footer,
 +    .print_integer        = json_print_int,
 +    .print_string         = json_print_str,
 +    .show_tags            = json_show_tags,
 +    .flags = WRITER_FLAG_PUT_PACKETS_AND_FRAMES_IN_SAME_CHAPTER,
 +};
 +
 +/* XML output */
 +
 +typedef struct {
 +    const AVClass *class;
 +    int within_tag;
 +    int indent_level;
 +    int fully_qualified;
 +    int xsd_strict;
 +} XMLContext;
 +
 +#undef OFFSET
 +#define OFFSET(x) offsetof(XMLContext, x)
 +
 +static const AVOption xml_options[] = {
++    {"fully_qualified", "specify if the output should be fully qualified", OFFSET(fully_qualified), AV_OPT_TYPE_INT, {.i64=0},  0, 1 },
++    {"q",               "specify if the output should be fully qualified", OFFSET(fully_qualified), AV_OPT_TYPE_INT, {.i64=0},  0, 1 },
++    {"xsd_strict",      "ensure that the output is XSD compliant",         OFFSET(xsd_strict),      AV_OPT_TYPE_INT, {.i64=0},  0, 1 },
++    {"x",               "ensure that the output is XSD compliant",         OFFSET(xsd_strict),      AV_OPT_TYPE_INT, {.i64=0},  0, 1 },
 +    {NULL},
 +};
 +
 +static const char *xml_get_name(void *ctx)
 +{
 +    return "xml";
 +}
 +
 +static const AVClass xml_class = {
 +    "XMLContext",
 +    xml_get_name,
 +    xml_options
 +};
 +
 +static av_cold int xml_init(WriterContext *wctx, const char *args, void *opaque)
 +{
 +    XMLContext *xml = wctx->priv;
 +    int err;
 +
 +    xml->class = &xml_class;
 +    av_opt_set_defaults(xml);
 +
 +    if (args &&
 +        (err = (av_set_options_string(xml, args, "=", ":"))) < 0)
 +        return err;
 +
 +    if (xml->xsd_strict) {
 +        xml->fully_qualified = 1;
 +#define CHECK_COMPLIANCE(opt, opt_name)                                 \
 +        if (opt) {                                                      \
 +            av_log(wctx, AV_LOG_ERROR,                                  \
 +                   "XSD-compliant output selected but option '%s' was selected, XML output may be non-compliant.\n" \
 +                   "You need to disable such option with '-no%s'\n", opt_name, opt_name); \
 +            return AVERROR(EINVAL);                                     \
 +        }
 +        CHECK_COMPLIANCE(show_private_data, "private");
 +        CHECK_COMPLIANCE(show_value_unit,   "unit");
 +        CHECK_COMPLIANCE(use_value_prefix,  "prefix");
 +
 +        if (do_show_frames && do_show_packets) {
 +            av_log(wctx, AV_LOG_ERROR,
 +                   "Interleaved frames and packets are not allowed in XSD. "
 +                   "Select only one between the -show_frames and the -show_packets options.\n");
 +            return AVERROR(EINVAL);
 +        }
 +    }
 +
 +    return 0;
 +}
 +
 +static const char *xml_escape_str(AVBPrint *dst, const char *src, void *log_ctx)
 +{
 +    const char *p;
 +
 +    for (p = src; *p; p++) {
 +        switch (*p) {
 +        case '&' : av_bprintf(dst, "%s", "&amp;");  break;
 +        case '<' : av_bprintf(dst, "%s", "&lt;");   break;
 +        case '>' : av_bprintf(dst, "%s", "&gt;");   break;
 +        case '\"': av_bprintf(dst, "%s", "&quot;"); break;
 +        case '\'': av_bprintf(dst, "%s", "&apos;"); break;
 +        default: av_bprint_chars(dst, *p, 1);
 +        }
 +    }
 +
 +    return dst->str;
 +}
 +
 +static void xml_print_header(WriterContext *wctx)
 +{
 +    XMLContext *xml = wctx->priv;
 +    const char *qual = " xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' "
 +        "xmlns:ffprobe='http://www.ffmpeg.org/schema/ffprobe' "
 +        "xsi:schemaLocation='http://www.ffmpeg.org/schema/ffprobe ffprobe.xsd'";
 +
 +    printf("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
 +    printf("<%sffprobe%s>\n",
 +           xml->fully_qualified ? "ffprobe:" : "",
 +           xml->fully_qualified ? qual : "");
 +
 +    xml->indent_level++;
 +}
 +
 +static void xml_print_footer(WriterContext *wctx)
 +{
 +    XMLContext *xml = wctx->priv;
 +
 +    xml->indent_level--;
 +    printf("</%sffprobe>\n", xml->fully_qualified ? "ffprobe:" : "");
 +}
 +
 +#define XML_INDENT() printf("%*c", xml->indent_level * 4, ' ')
 +
 +static void xml_print_chapter_header(WriterContext *wctx, const char *chapter)
 +{
 +    XMLContext *xml = wctx->priv;
 +
 +    if (wctx->nb_chapter)
 +        printf("\n");
 +    if (wctx->multiple_sections) {
 +        XML_INDENT(); printf("<%s>\n", chapter);
 +        xml->indent_level++;
 +    }
 +}
 +
 +static void xml_print_chapter_footer(WriterContext *wctx, const char *chapter)
 +{
 +    XMLContext *xml = wctx->priv;
 +
 +    if (wctx->multiple_sections) {
 +        xml->indent_level--;
 +        XML_INDENT(); printf("</%s>\n", chapter);
 +    }
 +}
 +
 +static void xml_print_section_header(WriterContext *wctx, const char *section)
 +{
 +    XMLContext *xml = wctx->priv;
 +
 +    XML_INDENT(); printf("<%s ", section);
 +    xml->within_tag = 1;
 +}
 +
 +static void xml_print_section_footer(WriterContext *wctx, const char *section)
 +{
 +    XMLContext *xml = wctx->priv;
 +
 +    if (xml->within_tag)
 +        printf("/>\n");
 +    else {
 +        XML_INDENT(); printf("</%s>\n", section);
 +    }
 +}
 +
 +static void xml_print_str(WriterContext *wctx, const char *key, const char *value)
 +{
 +    AVBPrint buf;
 +
 +    if (wctx->nb_item)
 +        printf(" ");
 +    av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED);
 +    printf("%s=\"%s\"", key, xml_escape_str(&buf, value, wctx));
 +    av_bprint_finalize(&buf, NULL);
 +}
 +
 +static void xml_print_int(WriterContext *wctx, const char *key, long long int value)
 +{
 +    if (wctx->nb_item)
 +        printf(" ");
 +    printf("%s=\"%lld\"", key, value);
 +}
 +
 +static void xml_show_tags(WriterContext *wctx, AVDictionary *dict)
 +{
 +    XMLContext *xml = wctx->priv;
 +    AVDictionaryEntry *tag = NULL;
 +    int is_first = 1;
 +    AVBPrint buf;
 +
 +    av_bprint_init(&buf, 1, AV_BPRINT_SIZE_UNLIMITED);
 +    xml->indent_level++;
 +    while ((tag = av_dict_get(dict, "", tag, AV_DICT_IGNORE_SUFFIX))) {
 +        if (is_first) {
 +            /* close section tag */
 +            printf(">\n");
 +            xml->within_tag = 0;
 +            is_first = 0;
 +        }
 +        XML_INDENT();
 +
 +        av_bprint_clear(&buf);
 +        printf("<tag key=\"%s\"", xml_escape_str(&buf, tag->key, wctx));
 +        av_bprint_clear(&buf);
 +        printf(" value=\"%s\"/>\n", xml_escape_str(&buf, tag->value, wctx));
 +    }
 +    av_bprint_finalize(&buf, NULL);
 +    xml->indent_level--;
 +}
 +
 +static Writer xml_writer = {
 +    .name                 = "xml",
 +    .priv_size            = sizeof(XMLContext),
 +    .init                 = xml_init,
 +    .print_header         = xml_print_header,
 +    .print_footer         = xml_print_footer,
 +    .print_chapter_header = xml_print_chapter_header,
 +    .print_chapter_footer = xml_print_chapter_footer,
 +    .print_section_header = xml_print_section_header,
 +    .print_section_footer = xml_print_section_footer,
 +    .print_integer        = xml_print_int,
 +    .print_string         = xml_print_str,
 +    .show_tags            = xml_show_tags,
 +    .flags = WRITER_FLAG_PUT_PACKETS_AND_FRAMES_IN_SAME_CHAPTER,
 +};
 +
 +static void writer_register_all(void)
 +{
 +    static int initialized;
 +
 +    if (initialized)
 +        return;
 +    initialized = 1;
 +
 +    writer_register(&default_writer);
 +    writer_register(&compact_writer);
 +    writer_register(&csv_writer);
 +    writer_register(&flat_writer);
 +    writer_register(&ini_writer);
 +    writer_register(&json_writer);
 +    writer_register(&xml_writer);
 +}
 +
 +#define print_fmt(k, f, ...) do {              \
 +    av_bprint_clear(&pbuf);                    \
 +    av_bprintf(&pbuf, f, __VA_ARGS__);         \
 +    writer_print_string(w, k, pbuf.str, 0);    \
 +} while (0)
 +
 +#define print_int(k, v)         writer_print_integer(w, k, v)
 +#define print_q(k, v, s)        writer_print_rational(w, k, v, s)
 +#define print_str(k, v)         writer_print_string(w, k, v, 0)
 +#define print_str_opt(k, v)     writer_print_string(w, k, v, 1)
 +#define print_time(k, v, tb)    writer_print_time(w, k, v, tb, 0)
 +#define print_ts(k, v)          writer_print_ts(w, k, v, 0)
 +#define print_duration_time(k, v, tb) writer_print_time(w, k, v, tb, 1)
 +#define print_duration_ts(k, v)       writer_print_ts(w, k, v, 1)
 +#define print_val(k, v, u)      writer_print_string(w, k, \
 +    value_string(val_str, sizeof(val_str), (struct unit_value){.val.i = v, .unit=u}), 0)
 +#define print_section_header(s) writer_print_section_header(w, s)
 +#define print_section_footer(s) writer_print_section_footer(w, s)
 +#define show_tags(metadata)     writer_show_tags(w, metadata)
 +
 +static void show_packet(WriterContext *w, AVFormatContext *fmt_ctx, AVPacket *pkt, int packet_idx)
 +{
 +    char val_str[128];
 +    AVStream *st = fmt_ctx->streams[pkt->stream_index];
 +    AVBPrint pbuf;
 +    const char *s;
 +
 +    av_bprint_init(&pbuf, 1, AV_BPRINT_SIZE_UNLIMITED);
 +
 +    print_section_header("packet");
 +    s = av_get_media_type_string(st->codec->codec_type);
 +    if (s) print_str    ("codec_type", s);
 +    else   print_str_opt("codec_type", "unknown");
 +    print_int("stream_index",     pkt->stream_index);
 +    print_ts  ("pts",             pkt->pts);
 +    print_time("pts_time",        pkt->pts, &st->time_base);
 +    print_ts  ("dts",             pkt->dts);
 +    print_time("dts_time",        pkt->dts, &st->time_base);
 +    print_duration_ts("duration",        pkt->duration);
 +    print_duration_time("duration_time", pkt->duration, &st->time_base);
 +    print_duration_ts("convergence_duration", pkt->convergence_duration);
 +    print_duration_time("convergence_duration_time", pkt->convergence_duration, &st->time_base);
 +    print_val("size",             pkt->size, unit_byte_str);
 +    if (pkt->pos != -1) print_fmt    ("pos", "%"PRId64, pkt->pos);
 +    else                print_str_opt("pos", "N/A");
 +    print_fmt("flags", "%c",      pkt->flags & AV_PKT_FLAG_KEY ? 'K' : '_');
 +    if (do_show_data)
 +        writer_print_data(w, "data", pkt->data, pkt->size);
 +    print_section_footer("packet");
 +
 +    av_bprint_finalize(&pbuf, NULL);
 +    fflush(stdout);
 +}
 +
 +static void show_frame(WriterContext *w, AVFrame *frame, AVStream *stream,
 +                       AVFormatContext *fmt_ctx)
 +{
 +    AVBPrint pbuf;
 +    const char *s;
 +
 +    av_bprint_init(&pbuf, 1, AV_BPRINT_SIZE_UNLIMITED);
 +
 +    print_section_header("frame");
 +
 +    s = av_get_media_type_string(stream->codec->codec_type);
 +    if (s) print_str    ("media_type", s);
 +    else   print_str_opt("media_type", "unknown");
 +    print_int("key_frame",              frame->key_frame);
 +    print_ts  ("pkt_pts",               frame->pkt_pts);
 +    print_time("pkt_pts_time",          frame->pkt_pts, &stream->time_base);
 +    print_ts  ("pkt_dts",               frame->pkt_dts);
 +    print_time("pkt_dts_time",          frame->pkt_dts, &stream->time_base);
 +    print_duration_ts  ("pkt_duration",      frame->pkt_duration);
 +    print_duration_time("pkt_duration_time", frame->pkt_duration, &stream->time_base);
 +    if (frame->pkt_pos != -1) print_fmt    ("pkt_pos", "%"PRId64, frame->pkt_pos);
 +    else                      print_str_opt("pkt_pos", "N/A");
 +
 +    switch (stream->codec->codec_type) {
 +        AVRational sar;
 +
 +    case AVMEDIA_TYPE_VIDEO:
 +        print_int("width",                  frame->width);
 +        print_int("height",                 frame->height);
 +        s = av_get_pix_fmt_name(frame->format);
 +        if (s) print_str    ("pix_fmt", s);
 +        else   print_str_opt("pix_fmt", "unknown");
 +        sar = av_guess_sample_aspect_ratio(fmt_ctx, stream, frame);
 +        if (sar.num) {
 +            print_q("sample_aspect_ratio", sar, ':');
 +        } else {
 +            print_str_opt("sample_aspect_ratio", "N/A");
 +        }
 +        print_fmt("pict_type",              "%c", av_get_picture_type_char(frame->pict_type));
 +        print_int("coded_picture_number",   frame->coded_picture_number);
 +        print_int("display_picture_number", frame->display_picture_number);
 +        print_int("interlaced_frame",       frame->interlaced_frame);
 +        print_int("top_field_first",        frame->top_field_first);
 +        print_int("repeat_pict",            frame->repeat_pict);
 +        print_int("reference",              frame->reference);
 +        break;
 +
 +    case AVMEDIA_TYPE_AUDIO:
 +        s = av_get_sample_fmt_name(frame->format);
 +        if (s) print_str    ("sample_fmt", s);
 +        else   print_str_opt("sample_fmt", "unknown");
 +        print_int("nb_samples",         frame->nb_samples);
 +        print_int("channels", av_frame_get_channels(frame));
 +        if (av_frame_get_channel_layout(frame)) {
 +            av_bprint_clear(&pbuf);
 +            av_bprint_channel_layout(&pbuf, av_frame_get_channels(frame),
 +                                     av_frame_get_channel_layout(frame));
 +            print_str    ("channel_layout", pbuf.str);
 +        } else
 +            print_str_opt("channel_layout", "unknown");
 +        break;
 +    }
 +    show_tags(av_frame_get_metadata(frame));
 +
 +    print_section_footer("frame");
 +
 +    av_bprint_finalize(&pbuf, NULL);
 +    fflush(stdout);
 +}
 +
 +static av_always_inline int process_frame(WriterContext *w,
 +                                          AVFormatContext *fmt_ctx,
 +                                          AVFrame *frame, AVPacket *pkt)
 +{
 +    AVCodecContext *dec_ctx = fmt_ctx->streams[pkt->stream_index]->codec;
 +    int ret = 0, got_frame = 0;
 +
 +    avcodec_get_frame_defaults(frame);
 +    if (dec_ctx->codec) {
 +        switch (dec_ctx->codec_type) {
 +        case AVMEDIA_TYPE_VIDEO:
 +            ret = avcodec_decode_video2(dec_ctx, frame, &got_frame, pkt);
 +            break;
 +
 +        case AVMEDIA_TYPE_AUDIO:
 +            ret = avcodec_decode_audio4(dec_ctx, frame, &got_frame, pkt);
 +            break;
 +        }
 +    }
 +
 +    if (ret < 0)
 +        return ret;
 +    ret = FFMIN(ret, pkt->size); /* guard against bogus return values */
 +    pkt->data += ret;
 +    pkt->size -= ret;
 +    if (got_frame) {
 +        nb_streams_frames[pkt->stream_index]++;
 +        if (do_show_frames)
 +            show_frame(w, frame, fmt_ctx->streams[pkt->stream_index], fmt_ctx);
 +    }
 +    return got_frame;
 +}
 +
 +static void read_packets(WriterContext *w, AVFormatContext *fmt_ctx)
 +{
 +    AVPacket pkt, pkt1;
 +    AVFrame frame;
 +    int i = 0;
 +
 +    av_init_packet(&pkt);
 +
 +    while (!av_read_frame(fmt_ctx, &pkt)) {
 +        if (do_read_packets) {
 +            if (do_show_packets)
 +                show_packet(w, fmt_ctx, &pkt, i++);
 +            nb_streams_packets[pkt.stream_index]++;
 +        }
 +        if (do_read_frames) {
 +            pkt1 = pkt;
 +            while (pkt1.size && process_frame(w, fmt_ctx, &frame, &pkt1) > 0);
 +        }
 +        av_free_packet(&pkt);
 +    }
 +    av_init_packet(&pkt);
 +    pkt.data = NULL;
 +    pkt.size = 0;
 +    //Flush remaining frames that are cached in the decoder
 +    for (i = 0; i < fmt_ctx->nb_streams; i++) {
 +        pkt.stream_index = i;
 +        if (do_read_frames)
 +            while (process_frame(w, fmt_ctx, &frame, &pkt) > 0);
 +    }
 +}
 +
 +static void show_stream(WriterContext *w, AVFormatContext *fmt_ctx, int stream_idx)
 +{
 +    AVStream *stream = fmt_ctx->streams[stream_idx];
 +    AVCodecContext *dec_ctx;
 +    const AVCodec *dec;
 +    char val_str[128];
 +    const char *s;
 +    AVRational sar, dar;
 +    AVBPrint pbuf;
 +
 +    av_bprint_init(&pbuf, 1, AV_BPRINT_SIZE_UNLIMITED);
 +
 +    print_section_header("stream");
 +
 +    print_int("index", stream->index);
 +
 +    if ((dec_ctx = stream->codec)) {
 +        const char *profile = NULL;
 +        if ((dec = dec_ctx->codec)) {
 +            print_str("codec_name",      dec->name);
 +            print_str("codec_long_name", dec->long_name);
 +        } else {
 +            print_str_opt("codec_name",      "unknown");
 +            print_str_opt("codec_long_name", "unknown");
 +        }
 +
 +        if (dec && (profile = av_get_profile_name(dec, dec_ctx->profile)))
 +            print_str("profile", profile);
 +        else
 +            print_str_opt("profile", "unknown");
 +
 +        s = av_get_media_type_string(dec_ctx->codec_type);
 +        if (s) print_str    ("codec_type", s);
 +        else   print_str_opt("codec_type", "unknown");
 +        print_q("codec_time_base", dec_ctx->time_base, '/');
 +
 +        /* print AVI/FourCC tag */
 +        av_get_codec_tag_string(val_str, sizeof(val_str), dec_ctx->codec_tag);
 +        print_str("codec_tag_string",    val_str);
 +        print_fmt("codec_tag", "0x%04x", dec_ctx->codec_tag);
 +
 +        switch (dec_ctx->codec_type) {
 +        case AVMEDIA_TYPE_VIDEO:
 +            print_int("width",        dec_ctx->width);
 +            print_int("height",       dec_ctx->height);
 +            print_int("has_b_frames", dec_ctx->has_b_frames);
 +            sar = av_guess_sample_aspect_ratio(fmt_ctx, stream, NULL);
 +            if (sar.den) {
 +                print_q("sample_aspect_ratio", sar, ':');
 +                av_reduce(&dar.num, &dar.den,
 +                          dec_ctx->width  * sar.num,
 +                          dec_ctx->height * sar.den,
 +                          1024*1024);
 +                print_q("display_aspect_ratio", dar, ':');
 +            } else {
 +                print_str_opt("sample_aspect_ratio", "N/A");
 +                print_str_opt("display_aspect_ratio", "N/A");
 +            }
 +            s = av_get_pix_fmt_name(dec_ctx->pix_fmt);
 +            if (s) print_str    ("pix_fmt", s);
 +            else   print_str_opt("pix_fmt", "unknown");
 +            print_int("level",   dec_ctx->level);
 +            if (dec_ctx->timecode_frame_start >= 0) {
 +                char tcbuf[AV_TIMECODE_STR_SIZE];
 +                av_timecode_make_mpeg_tc_string(tcbuf, dec_ctx->timecode_frame_start);
 +                print_str("timecode", tcbuf);
 +            } else {
 +                print_str_opt("timecode", "N/A");
 +            }
 +            break;
 +
 +        case AVMEDIA_TYPE_AUDIO:
 +            s = av_get_sample_fmt_name(dec_ctx->sample_fmt);
 +            if (s) print_str    ("sample_fmt", s);
 +            else   print_str_opt("sample_fmt", "unknown");
 +            print_val("sample_rate",     dec_ctx->sample_rate, unit_hertz_str);
 +            print_int("channels",        dec_ctx->channels);
 +            print_int("bits_per_sample", av_get_bits_per_sample(dec_ctx->codec_id));
 +            break;
 +        }
 +    } else {
 +        print_str_opt("codec_type", "unknown");
 +    }
 +    if (dec_ctx->codec && dec_ctx->codec->priv_class && show_private_data) {
 +        const AVOption *opt = NULL;
 +        while (opt = av_opt_next(dec_ctx->priv_data,opt)) {
 +            uint8_t *str;
 +            if (opt->flags) continue;
 +            if (av_opt_get(dec_ctx->priv_data, opt->name, 0, &str) >= 0) {
 +                print_str(opt->name, str);
 +                av_free(str);
 +            }
 +        }
 +    }
 +
 +    if (fmt_ctx->iformat->flags & AVFMT_SHOW_IDS) print_fmt    ("id", "0x%x", stream->id);
 +    else                                          print_str_opt("id", "N/A");
 +    print_q("r_frame_rate",   stream->r_frame_rate,   '/');
 +    print_q("avg_frame_rate", stream->avg_frame_rate, '/');
 +    print_q("time_base",      stream->time_base,      '/');
 +    print_time("start_time",    stream->start_time, &stream->time_base);
 +    print_time("duration",      stream->duration,   &stream->time_base);
 +    if (dec_ctx->bit_rate > 0) print_val    ("bit_rate", dec_ctx->bit_rate, unit_bit_per_second_str);
 +    else                       print_str_opt("bit_rate", "N/A");
 +    if (stream->nb_frames) print_fmt    ("nb_frames", "%"PRId64, stream->nb_frames);
 +    else                   print_str_opt("nb_frames", "N/A");
 +    if (nb_streams_frames[stream_idx])  print_fmt    ("nb_read_frames", "%"PRIu64, nb_streams_frames[stream_idx]);
 +    else                                print_str_opt("nb_read_frames", "N/A");
 +    if (nb_streams_packets[stream_idx]) print_fmt    ("nb_read_packets", "%"PRIu64, nb_streams_packets[stream_idx]);
 +    else                                print_str_opt("nb_read_packets", "N/A");
 +    if (do_show_data)
 +        writer_print_data(w, "extradata", dec_ctx->extradata,
 +                                          dec_ctx->extradata_size);
 +    show_tags(stream->metadata);
 +
 +    print_section_footer("stream");
 +    av_bprint_finalize(&pbuf, NULL);
 +    fflush(stdout);
 +}
 +
 +static void show_streams(WriterContext *w, AVFormatContext *fmt_ctx)
 +{
 +    int i;
 +    for (i = 0; i < fmt_ctx->nb_streams; i++)
 +        show_stream(w, fmt_ctx, i);
 +}
 +
 +static void show_format(WriterContext *w, AVFormatContext *fmt_ctx)
 +{
 +    char val_str[128];
 +    int64_t size = fmt_ctx->pb ? avio_size(fmt_ctx->pb) : -1;
 +
 +    print_section_header("format");
 +    print_str("filename",         fmt_ctx->filename);
 +    print_int("nb_streams",       fmt_ctx->nb_streams);
 +    print_str("format_name",      fmt_ctx->iformat->name);
 +    print_str("format_long_name", fmt_ctx->iformat->long_name);
 +    print_time("start_time",      fmt_ctx->start_time, &AV_TIME_BASE_Q);
 +    print_time("duration",        fmt_ctx->duration,   &AV_TIME_BASE_Q);
 +    if (size >= 0) print_val    ("size", size, unit_byte_str);
 +    else           print_str_opt("size", "N/A");
 +    if (fmt_ctx->bit_rate > 0) print_val    ("bit_rate", fmt_ctx->bit_rate, unit_bit_per_second_str);
 +    else                       print_str_opt("bit_rate", "N/A");
 +    show_tags(fmt_ctx->metadata);
 +    print_section_footer("format");
 +    fflush(stdout);
 +}
 +
 +static void show_error(WriterContext *w, int err)
 +{
 +    char errbuf[128];
 +    const char *errbuf_ptr = errbuf;
 +
 +    if (av_strerror(err, errbuf, sizeof(errbuf)) < 0)
 +        errbuf_ptr = strerror(AVUNERROR(err));
 +
 +    writer_print_chapter_header(w, "error");
 +    print_section_header("error");
 +    print_int("code", err);
 +    print_str("string", errbuf_ptr);
 +    print_section_footer("error");
 +    writer_print_chapter_footer(w, "error");
 +}
 +
 +static int open_input_file(AVFormatContext **fmt_ctx_ptr, const char *filename)
 +{
 +    int err, i;
 +    AVFormatContext *fmt_ctx = NULL;
 +    AVDictionaryEntry *t;
 +
 +    if ((err = avformat_open_input(&fmt_ctx, filename,
 +                                   iformat, &format_opts)) < 0) {
 +        print_error(filename, err);
 +        return err;
 +    }
 +    if ((t = av_dict_get(format_opts, "", NULL, AV_DICT_IGNORE_SUFFIX))) {
 +        av_log(NULL, AV_LOG_ERROR, "Option %s not found.\n", t->key);
 +        return AVERROR_OPTION_NOT_FOUND;
 +    }
 +
 +
 +    /* fill the streams in the format context */
 +    if ((err = avformat_find_stream_info(fmt_ctx, NULL)) < 0) {
 +        print_error(filename, err);
 +        return err;
 +    }
 +
 +    av_dump_format(fmt_ctx, 0, filename, 0);
 +
 +    /* bind a decoder to each input stream */
 +    for (i = 0; i < fmt_ctx->nb_streams; i++) {
 +        AVStream *stream = fmt_ctx->streams[i];
 +        AVCodec *codec;
 +
 +        if (stream->codec->codec_id == AV_CODEC_ID_PROBE) {
 +            av_log(NULL, AV_LOG_ERROR,
 +                   "Failed to probe codec for input stream %d\n",
 +                    stream->index);
 +        } else if (!(codec = avcodec_find_decoder(stream->codec->codec_id))) {
 +            av_log(NULL, AV_LOG_ERROR,
 +                    "Unsupported codec with id %d for input stream %d\n",
 +                    stream->codec->codec_id, stream->index);
 +        } else if (avcodec_open2(stream->codec, codec, NULL) < 0) {
 +            av_log(NULL, AV_LOG_ERROR, "Error while opening codec for input stream %d\n",
 +                   stream->index);
 +        }
 +    }
 +
 +    *fmt_ctx_ptr = fmt_ctx;
 +    return 0;
 +}
 +
 +static void close_input_file(AVFormatContext **ctx_ptr)
 +{
 +    int i;
 +    AVFormatContext *fmt_ctx = *ctx_ptr;
 +
 +    /* close decoder for each stream */
 +    for (i = 0; i < fmt_ctx->nb_streams; i++)
 +        if (fmt_ctx->streams[i]->codec->codec_id != AV_CODEC_ID_NONE)
 +            avcodec_close(fmt_ctx->streams[i]->codec);
 +
 +    avformat_close_input(ctx_ptr);
 +}
 +
 +#define PRINT_CHAPTER(name) do {                                        \
 +    if (do_show_ ## name) {                                             \
 +        writer_print_chapter_header(wctx, #name);                       \
 +        show_ ## name (wctx, fmt_ctx);                                  \
 +        writer_print_chapter_footer(wctx, #name);                       \
 +    }                                                                   \
 +} while (0)
 +
 +static int probe_file(WriterContext *wctx, const char *filename)
 +{
 +    AVFormatContext *fmt_ctx;
 +    int ret;
 +
 +    do_read_frames = do_show_frames || do_count_frames;
 +    do_read_packets = do_show_packets || do_count_packets;
 +
 +    ret = open_input_file(&fmt_ctx, filename);
 +    if (ret >= 0) {
 +        nb_streams_frames  = av_calloc(fmt_ctx->nb_streams, sizeof(*nb_streams_frames));
 +        nb_streams_packets = av_calloc(fmt_ctx->nb_streams, sizeof(*nb_streams_packets));
 +        if (do_read_frames || do_read_packets) {
 +            const char *chapter;
 +            if (do_show_frames && do_show_packets &&
 +                wctx->writer->flags & WRITER_FLAG_PUT_PACKETS_AND_FRAMES_IN_SAME_CHAPTER)
 +                chapter = "packets_and_frames";
 +            else if (do_show_packets && !do_show_frames)
 +                chapter = "packets";
 +            else // (!do_show_packets && do_show_frames)
 +                chapter = "frames";
 +            if (do_show_frames || do_show_packets)
 +                writer_print_chapter_header(wctx, chapter);
 +            read_packets(wctx, fmt_ctx);
 +            if (do_show_frames || do_show_packets)
 +                writer_print_chapter_footer(wctx, chapter);
 +        }
 +        PRINT_CHAPTER(streams);
 +        PRINT_CHAPTER(format);
 +        close_input_file(&fmt_ctx);
 +        av_freep(&nb_streams_frames);
 +        av_freep(&nb_streams_packets);
 +    }
 +    return ret;
 +}
 +
 +static void show_usage(void)
 +{
 +    av_log(NULL, AV_LOG_INFO, "Simple multimedia streams analyzer\n");
 +    av_log(NULL, AV_LOG_INFO, "usage: %s [OPTIONS] [INPUT_FILE]\n", program_name);
 +    av_log(NULL, AV_LOG_INFO, "\n");
 +}
 +
 +static void ffprobe_show_program_version(WriterContext *w)
 +{
 +    AVBPrint pbuf;
 +    av_bprint_init(&pbuf, 1, AV_BPRINT_SIZE_UNLIMITED);
 +
 +    writer_print_chapter_header(w, "program_version");
 +    print_section_header("program_version");
 +    print_str("version", FFMPEG_VERSION);
 +    print_fmt("copyright", "Copyright (c) %d-%d the FFmpeg developers",
 +              program_birth_year, this_year);
 +    print_str("build_date", __DATE__);
 +    print_str("build_time", __TIME__);
 +    print_str("compiler_ident", CC_IDENT);
 +    print_str("configuration", FFMPEG_CONFIGURATION);
 +    print_section_footer("program_version");
 +    writer_print_chapter_footer(w, "program_version");
 +
 +    av_bprint_finalize(&pbuf, NULL);
 +}
 +
 +#define SHOW_LIB_VERSION(libname, LIBNAME)                              \
 +    do {                                                                \
 +        if (CONFIG_##LIBNAME) {                                         \
 +            unsigned int version = libname##_version();                 \
 +            print_section_header("library_version");                    \
 +            print_str("name",    "lib" #libname);                       \
 +            print_int("major",   LIB##LIBNAME##_VERSION_MAJOR);         \
 +            print_int("minor",   LIB##LIBNAME##_VERSION_MINOR);         \
 +            print_int("micro",   LIB##LIBNAME##_VERSION_MICRO);         \
 +            print_int("version", version);                              \
 +            print_section_footer("library_version");                    \
 +        }                                                               \
 +    } while (0)
 +
 +static void ffprobe_show_library_versions(WriterContext *w)
 +{
 +    writer_print_chapter_header(w, "library_versions");
 +    SHOW_LIB_VERSION(avutil,     AVUTIL);
 +    SHOW_LIB_VERSION(avcodec,    AVCODEC);
 +    SHOW_LIB_VERSION(avformat,   AVFORMAT);
 +    SHOW_LIB_VERSION(avdevice,   AVDEVICE);
 +    SHOW_LIB_VERSION(avfilter,   AVFILTER);
 +    SHOW_LIB_VERSION(swscale,    SWSCALE);
 +    SHOW_LIB_VERSION(swresample, SWRESAMPLE);
 +    SHOW_LIB_VERSION(postproc,   POSTPROC);
 +    writer_print_chapter_footer(w, "library_versions");
 +}
 +
 +static int opt_format(void *optctx, const char *opt, const char *arg)
 +{
 +    iformat = av_find_input_format(arg);
 +    if (!iformat) {
 +        av_log(NULL, AV_LOG_ERROR, "Unknown input format: %s\n", arg);
 +        return AVERROR(EINVAL);
 +    }
 +    return 0;
 +}
 +
 +static int opt_show_format_entry(void *optctx, const char *opt, const char *arg)
 +{
 +    do_show_format = 1;
 +    av_dict_set(&fmt_entries_to_show, arg, "", 0);
 +    return 0;
 +}
 +
 +static void opt_input_file(void *optctx, const char *arg)
 +{
 +    if (input_filename) {
 +        av_log(NULL, AV_LOG_ERROR,
 +                "Argument '%s' provided as input filename, but '%s' was already specified.\n",
 +                arg, input_filename);
 +        exit(1);
 +    }
 +    if (!strcmp(arg, "-"))
 +        arg = "pipe:";
 +    input_filename = arg;
 +}
 +
 +static int opt_input_file_i(void *optctx, const char *opt, const char *arg)
 +{
 +    opt_input_file(optctx, arg);
 +    return 0;
 +}
 +
 +void show_help_default(const char *opt, const char *arg)
 +{
 +    av_log_set_callback(log_callback_help);
 +    show_usage();
 +    show_help_options(options, "Main options:", 0, 0, 0);
 +    printf("\n");
 +
 +    show_help_children(avformat_get_class(), AV_OPT_FLAG_DECODING_PARAM);
 +}
 +
 +static int opt_pretty(void *optctx, const char *opt, const char *arg)
 +{
 +    show_value_unit              = 1;
 +    use_value_prefix             = 1;
 +    use_byte_value_binary_prefix = 1;
 +    use_value_sexagesimal_format = 1;
 +    return 0;
 +}
 +
 +static int opt_show_versions(const char *opt, const char *arg)
 +{
 +    do_show_program_version  = 1;
 +    do_show_library_versions = 1;
 +    return 0;
 +}
 +
 +static const OptionDef real_options[] = {
 +#include "cmdutils_common_opts.h"
 +    { "f", HAS_ARG, {.func_arg = opt_format}, "force format", "format" },
 +    { "unit", OPT_BOOL, {&show_value_unit}, "show unit of the displayed values" },
 +    { "prefix", OPT_BOOL, {&use_value_prefix}, "use SI prefixes for the displayed values" },
 +    { "byte_binary_prefix", OPT_BOOL, {&use_byte_value_binary_prefix},
 +      "use binary prefixes for byte units" },
 +    { "sexagesimal", OPT_BOOL,  {&use_value_sexagesimal_format},
 +      "use sexagesimal format HOURS:MM:SS.MICROSECONDS for time units" },
 +    { "pretty", 0, {.func_arg = opt_pretty},
 +      "prettify the format of displayed values, make it more human readable" },
 +    { "print_format", OPT_STRING | HAS_ARG, {(void*)&print_format},
 +      "set the output printing format (available formats are: default, compact, csv, flat, ini, json, xml)", "format" },
 +    { "of", OPT_STRING | HAS_ARG, {(void*)&print_format}, "alias for -print_format", "format" },
 +    { "show_data",    OPT_BOOL, {(void*)&do_show_data}, "show packets data" },
 +    { "show_error",   OPT_BOOL, {(void*)&do_show_error} ,  "show probing error" },
 +    { "show_format",  OPT_BOOL, {&do_show_format} , "show format/container info" },
 +    { "show_frames",  OPT_BOOL, {(void*)&do_show_frames} , "show frames info" },
 +    { "show_format_entry", HAS_ARG, {.func_arg = opt_show_format_entry},
 +      "show a particular entry from the format/container info", "entry" },
 +    { "show_packets", OPT_BOOL, {&do_show_packets}, "show packets info" },
 +    { "show_streams", OPT_BOOL, {&do_show_streams}, "show streams info" },
 +    { "count_frames", OPT_BOOL, {(void*)&do_count_frames}, "count the number of frames per stream" },
 +    { "count_packets", OPT_BOOL, {(void*)&do_count_packets}, "count the number of packets per stream" },
 +    { "show_program_version",  OPT_BOOL, {(void*)&do_show_program_version},  "show ffprobe version" },
 +    { "show_library_versions", OPT_BOOL, {(void*)&do_show_library_versions}, "show library versions" },
 +    { "show_versions",         0, {(void*)&opt_show_versions}, "show program and library versions" },
 +    { "show_private_data", OPT_BOOL, {(void*)&show_private_data}, "show private data" },
 +    { "private",           OPT_BOOL, {(void*)&show_private_data}, "same as show_private_data" },
 +    { "default", HAS_ARG | OPT_AUDIO | OPT_VIDEO | OPT_EXPERT, {.func_arg = opt_default}, "generic catch all option", "" },
 +    { "i", HAS_ARG, {.func_arg = opt_input_file_i}, "read specified file", "input_file"},
 +    { NULL, },
 +};
 +
 +int main(int argc, char **argv)
 +{
 +    const Writer *w;
 +    WriterContext *wctx;
 +    char *buf;
 +    char *w_name = NULL, *w_args = NULL;
 +    int ret;
 +
 +    av_log_set_flags(AV_LOG_SKIP_REPEATED);
 +    options = real_options;
 +    parse_loglevel(argc, argv, options);
 +    av_register_all();
 +    avformat_network_init();
 +    init_opts();
 +#if CONFIG_AVDEVICE
 +    avdevice_register_all();
 +#endif
 +
 +    show_banner(argc, argv, options);
 +    parse_options(NULL, argc, argv, options, opt_input_file);
 +
 +    writer_register_all();
 +
 +    if (!print_format)
 +        print_format = av_strdup("default");
 +    w_name = av_strtok(print_format, "=", &buf);
 +    w_args = buf;
 +
 +    w = writer_get_by_name(w_name);
 +    if (!w) {
 +        av_log(NULL, AV_LOG_ERROR, "Unknown output format with name '%s'\n", w_name);
 +        ret = AVERROR(EINVAL);
 +        goto end;
 +    }
 +
 +    if ((ret = writer_open(&wctx, w, w_args, NULL)) >= 0) {
 +        writer_print_header(wctx);
 +
 +        if (do_show_program_version)
 +            ffprobe_show_program_version(wctx);
 +        if (do_show_library_versions)
 +            ffprobe_show_library_versions(wctx);
 +
 +        if (!input_filename &&
 +            ((do_show_format || do_show_streams || do_show_packets || do_show_error) ||
 +             (!do_show_program_version && !do_show_library_versions))) {
 +            show_usage();
 +            av_log(NULL, AV_LOG_ERROR, "You have to specify one input file.\n");
 +            av_log(NULL, AV_LOG_ERROR, "Use -h to get full help or, even better, run 'man %s'.\n", program_name);
 +            ret = AVERROR(EINVAL);
 +        } else if (input_filename) {
 +            ret = probe_file(wctx, input_filename);
 +            if (ret < 0 && do_show_error)
 +                show_error(wctx, ret);
 +        }
 +
 +        writer_print_footer(wctx);
 +        writer_close(&wctx);
 +    }
 +
 +end:
 +    av_freep(&print_format);
 +
 +    uninit_opts();
 +    av_dict_free(&fmt_entries_to_show);
 +
 +    avformat_network_deinit();
 +
 +    return ret;
 +}
@@@ -805,7 -806,6 +805,7 @@@ static const AVOption aacenc_options[] 
          {"auto",     "Selected by the Encoder", 0, AV_OPT_TYPE_CONST, {.i64 = -1 }, INT_MIN, INT_MAX, AACENC_FLAGS, "stereo_mode"},
          {"ms_off",   "Disable Mid/Side coding", 0, AV_OPT_TYPE_CONST, {.i64 =  0 }, INT_MIN, INT_MAX, AACENC_FLAGS, "stereo_mode"},
          {"ms_force", "Force Mid/Side for the whole frame if possible", 0, AV_OPT_TYPE_CONST, {.i64 =  1 }, INT_MIN, INT_MAX, AACENC_FLAGS, "stereo_mode"},
-     {"aac_coder", "", offsetof(AACEncContext, options.aac_coder), AV_OPT_TYPE_INT, {.dbl = 2}, 0, AAC_CODER_NB-1, AACENC_FLAGS},
++    {"aac_coder", "", offsetof(AACEncContext, options.aac_coder), AV_OPT_TYPE_INT, {.i64 = 2}, 0, AAC_CODER_NB-1, AACENC_FLAGS},
      {NULL}
  };
  
@@@ -1457,13 -1447,6 +1457,13 @@@ static av_cold int ac3_decode_end(AVCod
  #define PAR (AV_OPT_FLAG_DECODING_PARAM | AV_OPT_FLAG_AUDIO_PARAM)
  static const AVOption options[] = {
      { "drc_scale", "percentage of dynamic range compression to apply", OFFSET(drc_scale), AV_OPT_TYPE_FLOAT, {1.0}, 0.0, 1.0, PAR },
- {"dmix_mode", "Preferred Stereo Downmix Mode", OFFSET(preferred_stereo_downmix), AV_OPT_TYPE_INT, {.dbl = -1 }, -1, 2, 0, "dmix_mode"},
 +
++{"dmix_mode", "Preferred Stereo Downmix Mode", OFFSET(preferred_stereo_downmix), AV_OPT_TYPE_INT, {.i64 = -1 }, -1, 2, 0, "dmix_mode"},
 +{"ltrt_cmixlev",   "Lt/Rt Center Mix Level",   OFFSET(ltrt_center_mix_level),    AV_OPT_TYPE_FLOAT, {.dbl = -1.0 }, -1.0, 2.0, 0},
 +{"ltrt_surmixlev", "Lt/Rt Surround Mix Level", OFFSET(ltrt_surround_mix_level),  AV_OPT_TYPE_FLOAT, {.dbl = -1.0 }, -1.0, 2.0, 0},
 +{"loro_cmixlev",   "Lo/Ro Center Mix Level",   OFFSET(loro_center_mix_level),    AV_OPT_TYPE_FLOAT, {.dbl = -1.0 }, -1.0, 2.0, 0},
 +{"loro_surmixlev", "Lo/Ro Surround Mix Level", OFFSET(loro_surround_mix_level),  AV_OPT_TYPE_FLOAT, {.dbl = -1.0 }, -1.0, 2.0, 0},
 +
      { NULL},
  };
  
Simple merge
@@@ -182,20 -168,6 +182,20 @@@ static int encode_frame(AVCodecContext 
      return 0;
  }
  
-     { "dither_type",   "Dither type",   OFFSET(dither_type),        AV_OPT_TYPE_INT, { .dbl=1 }, 0, 2, VE},
 +#define OFFSET(x) offsetof(CLJRContext, x)
 +#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
 +static const AVOption options[] = {
++    { "dither_type",   "Dither type",   OFFSET(dither_type),        AV_OPT_TYPE_INT, { .i64=1 }, 0, 2, VE},
 +    { NULL },
 +};
 +
 +static const AVClass class = {
 +    .class_name = "cljr encoder",
 +    .item_name  = av_default_item_name,
 +    .option     = options,
 +    .version    = LIBAVUTIL_VERSION_INT,
 +};
 +
  AVCodec ff_cljr_encoder = {
      .name           = "cljr",
      .type           = AVMEDIA_TYPE_VIDEO,
  #define DNX10BIT_QMAT_SHIFT 18 // The largest value that will not lead to overflow for 10bit samples.
  
  static const AVOption options[]={
-     {"nitris_compat", "encode with Avid Nitris compatibility", offsetof(DNXHDEncContext, nitris_compat), AV_OPT_TYPE_INT, {.dbl = 0}, 0, 1, VE},
+     {"nitris_compat", "encode with Avid Nitris compatibility", offsetof(DNXHDEncContext, nitris_compat), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, VE},
  {NULL}
  };
 -static const AVClass class = { "dnxhd", av_default_item_name, options, LIBAVUTIL_VERSION_INT };
 +
 +static const AVClass class = {
 +    .class_name = "dnxhd",
 +    .item_name  = av_default_item_name,
 +    .option     = options,
 +    .version    = LIBAVUTIL_VERSION_INT,
 +};
  
  #define LAMBDA_FRAC_BITS 10
  
@@@ -2154,26 -1749,6 +2154,26 @@@ AVCodec ff_ffv1_decoder = 
  };
  
  #if CONFIG_FFV1_ENCODER
-     { "slicecrc",        "Protect slices with CRCs",               OFFSET(ec),              AV_OPT_TYPE_INT, {-1}, -1, 1, VE},
 +
 +#define OFFSET(x) offsetof(FFV1Context, x)
 +#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
 +static const AVOption options[] = {
++    { "slicecrc",        "Protect slices with CRCs",               OFFSET(ec),              AV_OPT_TYPE_INT, {.i64 = -1}, -1, 1, VE},
 +{NULL}
 +};
 +
 +static const AVClass class = {
 +    .class_name = "ffv1 encoder",
 +    .item_name  = av_default_item_name,
 +    .option     = options,
 +    .version    = LIBAVUTIL_VERSION_INT,
 +};
 +
 +static const AVCodecDefault ffv1_defaults[] = {
 +    { "coder",                "-1" },
 +    { NULL },
 +};
 +
  AVCodec ff_ffv1_encoder = {
      .name           = "ffv1",
      .type           = AVMEDIA_TYPE_VIDEO,
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
@@@ -396,7 -432,8 +396,7 @@@ static av_cold int libopenjpeg_decode_c
  #define VD AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM
  
  static const AVOption options[] = {
-     { "lowqual", "Limit the number of layers used for decoding",    OFFSET(lowqual), AV_OPT_TYPE_INT, { 0 }, 0, INT_MAX, VD },
+     { "lowqual", "Limit the number of layers used for decoding",    OFFSET(lowqual), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, VD },
 -    { "lowres",  "Lower the decoding resolution by a power of two", OFFSET(lowres),  AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, VD },
      { NULL },
  };
  
@@@ -455,11 -397,11 +455,11 @@@ static const AVOption options[] = 
      { "rpcl",          NULL,                0,                     AV_OPT_TYPE_CONST, { .i64 = RPCL        }, 0,         0,           VE, "prog_order"  },
      { "pcrl",          NULL,                0,                     AV_OPT_TYPE_CONST, { .i64 = PCRL        }, 0,         0,           VE, "prog_order"  },
      { "cprl",          NULL,                0,                     AV_OPT_TYPE_CONST, { .i64 = CPRL        }, 0,         0,           VE, "prog_order"  },
-     { "numresolution", NULL,                OFFSET(numresolution), AV_OPT_TYPE_INT,   { 6           }, 1,         INT_MAX,     VE                },
-     { "numlayers",     NULL,                OFFSET(numlayers),     AV_OPT_TYPE_INT,   { 1           }, 1,         10,          VE                },
-     { "disto_alloc",   NULL,                OFFSET(disto_alloc),   AV_OPT_TYPE_INT,   { 1           }, 0,         1,           VE                },
-     { "fixed_alloc",   NULL,                OFFSET(fixed_alloc),   AV_OPT_TYPE_INT,   { 0           }, 0,         1,           VE                },
-     { "fixed_quality", NULL,                OFFSET(fixed_quality), AV_OPT_TYPE_INT,   { 0           }, 0,         1,           VE                },
 -    { "numresolution", NULL,                OFFSET(numresolution), AV_OPT_TYPE_INT,   { .i64 = 6           }, 1,         10,          VE },
 -    { "numlayers",     NULL,                OFFSET(numlayers),     AV_OPT_TYPE_INT,   { .i64 = 1           }, 1,         10,          VE },
 -    { "disto_alloc",   NULL,                OFFSET(disto_alloc),   AV_OPT_TYPE_INT,   { .i64 = 1           }, 0,         1,           VE },
 -    { "fixed_alloc",   NULL,                OFFSET(fixed_alloc),   AV_OPT_TYPE_INT,   { .i64 = 0           }, 0,         1,           VE },
 -    { "fixed_quality", NULL,                OFFSET(fixed_quality), AV_OPT_TYPE_INT,   { .i64 = 0           }, 0,         1,           VE },
++    { "numresolution", NULL,                OFFSET(numresolution), AV_OPT_TYPE_INT,   { .i64 = 6           }, 1,         INT_MAX,     VE                },
++    { "numlayers",     NULL,                OFFSET(numlayers),     AV_OPT_TYPE_INT,   { .i64 = 1           }, 1,         10,          VE                },
++    { "disto_alloc",   NULL,                OFFSET(disto_alloc),   AV_OPT_TYPE_INT,   { .i64 = 1           }, 0,         1,           VE                },
++    { "fixed_alloc",   NULL,                OFFSET(fixed_alloc),   AV_OPT_TYPE_INT,   { .i64 = 0           }, 0,         1,           VE                },
++    { "fixed_quality", NULL,                OFFSET(fixed_quality), AV_OPT_TYPE_INT,   { .i64 = 0           }, 0,         1,           VE                },
      { NULL },
  };
  
Simple merge
index dce7dce,0000000..b57fbc9
mode 100644,000000..100644
--- /dev/null
@@@ -1,196 -1,0 +1,196 @@@
-     { "mode",         "Mpeg Mode", OFFSET(mode), AV_OPT_TYPE_INT, { TWOLAME_AUTO_MODE }, TWOLAME_AUTO_MODE, TWOLAME_MONO, AE, "mode"},
 +/*
 + * Interface to libtwolame for mp2 encoding
 + * Copyright (c) 2012 Paul B Mahol
 + *
 + * This file is part of FFmpeg.
 + *
 + * FFmpeg is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU Lesser General Public
 + * License as published by the Free Software Foundation; either
 + * version 2.1 of the License, or (at your option) any later version.
 + *
 + * FFmpeg is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 + * Lesser General Public License for more details.
 + *
 + * You should have received a copy of the GNU Lesser General Public
 + * License along with FFmpeg; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 + */
 +
 +/**
 + * @file
 + * Interface to libtwolame for mp2 encoding.
 + */
 +
 +#include <twolame.h>
 +
 +#include "libavutil/opt.h"
 +#include "avcodec.h"
 +#include "internal.h"
 +#include "mpegaudio.h"
 +
 +typedef struct TWOLAMEContext {
 +    AVClass  *class;
 +    int      mode;
 +    int      psymodel;
 +    int      energy;
 +    int      error_protection;
 +    int      copyright;
 +    int      original;
 +
 +    twolame_options *glopts;
 +    int64_t  next_pts;
 +} TWOLAMEContext;
 +
 +static av_cold int twolame_encode_close(AVCodecContext *avctx)
 +{
 +    TWOLAMEContext *s = avctx->priv_data;
 +    twolame_close(&s->glopts);
 +    return 0;
 +}
 +
 +static av_cold int twolame_encode_init(AVCodecContext *avctx)
 +{
 +    TWOLAMEContext *s = avctx->priv_data;
 +    int ret;
 +
 +    avctx->frame_size = TWOLAME_SAMPLES_PER_FRAME;
 +
 +    s->glopts = twolame_init();
 +    if (!s->glopts)
 +        return AVERROR(ENOMEM);
 +
 +    twolame_set_verbosity(s->glopts, 0);
 +    twolame_set_mode(s->glopts, s->mode);
 +    twolame_set_psymodel(s->glopts, s->psymodel);
 +    twolame_set_energy_levels(s->glopts, s->energy);
 +    twolame_set_error_protection(s->glopts, s->error_protection);
 +
 +    twolame_set_num_channels(s->glopts, avctx->channels);
 +    twolame_set_in_samplerate(s->glopts, avctx->sample_rate);
 +    twolame_set_out_samplerate(s->glopts, avctx->sample_rate);
 +    if (avctx->flags & CODEC_FLAG_QSCALE || !avctx->bit_rate) {
 +        twolame_set_VBR(s->glopts, TRUE);
 +        twolame_set_VBR_level(s->glopts, avctx->global_quality);
 +        av_log(avctx, AV_LOG_WARNING, "VBR mode is experimental!\n");
 +    } else {
 +        twolame_set_bitrate(s->glopts, avctx->bit_rate / 1000);
 +    }
 +
 +    if ((ret = twolame_init_params(s->glopts)))
 +        goto error;
 +
 +    return 0;
 +error:
 +    twolame_encode_close(avctx);
 +    return ret;
 +}
 +
 +static int twolame_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
 +                                const AVFrame *frame, int *got_packet_ptr)
 +{
 +    TWOLAMEContext *s = avctx->priv_data;
 +    int ret;
 +
 +    if ((ret = ff_alloc_packet2(avctx, avpkt, MPA_MAX_CODED_FRAME_SIZE)))
 +        return ret;
 +
 +    if (frame) {
 +        switch (avctx->sample_fmt) {
 +        case AV_SAMPLE_FMT_FLT:
 +            ret = twolame_encode_buffer_float32_interleaved(s->glopts,
 +                                        frame->data[0],
 +                                        frame->nb_samples,
 +                                        avpkt->data, avpkt->size);
 +            break;
 +        case AV_SAMPLE_FMT_FLTP:
 +            ret = twolame_encode_buffer_float32(s->glopts,
 +                                        frame->data[0], frame->data[1],
 +                                        frame->nb_samples,
 +                                        avpkt->data, avpkt->size);
 +            break;
 +        case AV_SAMPLE_FMT_S16:
 +            ret = twolame_encode_buffer_interleaved(s->glopts,
 +                                        frame->data[0],
 +                                        frame->nb_samples,
 +                                        avpkt->data, avpkt->size);
 +            break;
 +        case AV_SAMPLE_FMT_S16P:
 +            ret = twolame_encode_buffer(s->glopts,
 +                                        frame->data[0], frame->data[1],
 +                                        frame->nb_samples,
 +                                        avpkt->data, avpkt->size);
 +            break;
 +        default:
 +            return AVERROR_BUG;
 +        }
 +    } else {
 +        ret = twolame_encode_flush(s->glopts, avpkt->data, avpkt->size);
 +    }
 +
 +    if (ret > 0) {
 +        avpkt->duration = ff_samples_to_time_base(avctx, avctx->frame_size);
 +        if (frame) {
 +            if (frame->pts != AV_NOPTS_VALUE)
 +                avpkt->pts  = frame->pts;
 +        } else {
 +            avpkt->pts = s->next_pts;
 +        }
 +        if (avpkt->pts != AV_NOPTS_VALUE)
 +            s->next_pts = avpkt->pts + avpkt->duration;
 +
 +        avpkt->size     = ret;
 +        *got_packet_ptr = 1;
 +        return 0;
 +    }
 +
 +    return ret;
 +}
 +
 +#define OFFSET(x) offsetof(TWOLAMEContext, x)
 +#define AE AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
 +static const AVOption options[] = {
-     { "psymodel",    "Psychoacoustic Model",  OFFSET(psymodel), AV_OPT_TYPE_INT, { 3 }, -1, 4, AE},
-     { "energy_levels","enable energy levels", OFFSET(energy),   AV_OPT_TYPE_INT, { 0 },  0, 1, AE},
-     { "error_protection","enable CRC error protection", OFFSET(error_protection), AV_OPT_TYPE_INT, { 0 },  0, 1, AE},
-     { "copyright",    "set MPEG Audio Copyright flag",  OFFSET(copyright), AV_OPT_TYPE_INT, { 0 },  0, 1, AE},
-     { "original",     "set MPEG Audio Original flag",   OFFSET(original),  AV_OPT_TYPE_INT, { 0 },  0, 1, AE},
++    { "mode",         "Mpeg Mode", OFFSET(mode), AV_OPT_TYPE_INT, { .i64 = TWOLAME_AUTO_MODE }, TWOLAME_AUTO_MODE, TWOLAME_MONO, AE, "mode"},
 +    { "auto",         NULL,         0, AV_OPT_TYPE_CONST, { .i64 = TWOLAME_AUTO_MODE },          0, 0, AE, "mode" },
 +    { "stereo",       NULL,         0, AV_OPT_TYPE_CONST, { .i64 = TWOLAME_STEREO },             0, 0, AE, "mode" },
 +    { "joint_stereo", NULL,         0, AV_OPT_TYPE_CONST, { .i64 = TWOLAME_JOINT_STEREO },       0, 0, AE, "mode" },
 +    { "dual_channel", NULL,         0, AV_OPT_TYPE_CONST, { .i64 = TWOLAME_DUAL_CHANNEL },       0, 0, AE, "mode" },
 +    { "mono",         NULL,         0, AV_OPT_TYPE_CONST, { .i64 = TWOLAME_MONO },               0, 0, AE, "mode" },
++    { "psymodel",    "Psychoacoustic Model",  OFFSET(psymodel), AV_OPT_TYPE_INT, { .i64 = 3 }, -1, 4, AE},
++    { "energy_levels","enable energy levels", OFFSET(energy),   AV_OPT_TYPE_INT, { .i64 = 0 },  0, 1, AE},
++    { "error_protection","enable CRC error protection", OFFSET(error_protection), AV_OPT_TYPE_INT, { .i64 = 0 },  0, 1, AE},
++    { "copyright",    "set MPEG Audio Copyright flag",  OFFSET(copyright), AV_OPT_TYPE_INT, { .i64 = 0 },  0, 1, AE},
++    { "original",     "set MPEG Audio Original flag",   OFFSET(original),  AV_OPT_TYPE_INT, { .i64 = 0 },  0, 1, AE},
 +    { NULL },
 +};
 +
 +static const AVClass libtwolame_class = {
 +    .class_name = "libtwolame encoder",
 +    .item_name  = av_default_item_name,
 +    .option     = options,
 +    .version    = LIBAVUTIL_VERSION_INT,
 +};
 +
 +AVCodec ff_libtwolame_encoder = {
 +    .name                  = "libtwolame",
 +    .type                  = AVMEDIA_TYPE_AUDIO,
 +    .id                    = AV_CODEC_ID_MP2,
 +    .priv_data_size        = sizeof(TWOLAMEContext),
 +    .init                  = twolame_encode_init,
 +    .encode2               = twolame_encode_frame,
 +    .close                 = twolame_encode_close,
 +    .capabilities          = CODEC_CAP_DELAY,
 +    .sample_fmts           = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_FLT,
 +                                                             AV_SAMPLE_FMT_FLTP,
 +                                                             AV_SAMPLE_FMT_S16,
 +                                                             AV_SAMPLE_FMT_S16P,
 +                                                             AV_SAMPLE_FMT_NONE },
 +    .channel_layouts       = (const uint64_t[]) { AV_CH_LAYOUT_MONO,
 +                                                  AV_CH_LAYOUT_STEREO,
 +                                                  0 },
 +    .supported_samplerates = (const int[]){ 16000, 22050, 24000, 32000, 44100, 48000, 0 },
 +    .long_name             = NULL_IF_CONFIG_SMALL("libtwolame MP2 (MPEG audio layer 2)"),
 +    .priv_class            = &libtwolame_class,
 +};
Simple merge
@@@ -585,7 -546,6 +585,7 @@@ static const AVOption options[] = 
      { "good",            NULL, 0, AV_OPT_TYPE_CONST, {.i64 = VPX_DL_GOOD_QUALITY}, 0, 0, VE, "quality"},
      { "realtime",        NULL, 0, AV_OPT_TYPE_CONST, {.i64 = VPX_DL_REALTIME},     0, 0, VE, "quality"},
      { "error-resilient", "Error resilience configuration", OFFSET(error_resilient), AV_OPT_TYPE_FLAGS, {.i64 = 0}, INT_MIN, INT_MAX, VE, "er"},
-     { "max-intra-rate",  "Maximum I-frame bitrate (pct) 0=unlimited",  OFFSET(max_intra_rate),  AV_OPT_TYPE_INT,  {-1}, -1,      INT_MAX, VE},
++    { "max-intra-rate",  "Maximum I-frame bitrate (pct) 0=unlimited",  OFFSET(max_intra_rate),  AV_OPT_TYPE_INT,  {.i64 = -1}, -1,      INT_MAX, VE},
  #ifdef VPX_ERROR_RESILIENT_DEFAULT
      { "default",         "Improve resiliency against losses of whole frames", 0, AV_OPT_TYPE_CONST, {.i64 = VPX_ERROR_RESILIENT_DEFAULT}, 0, 0, VE, "er"},
      { "partitions",      "The frame partitions are independently decodable "
                           "though earlier partitions have been lost. Note that intra predicition"
                           " is still done over the partition boundary.",       0, AV_OPT_TYPE_CONST, {.i64 = VPX_ERROR_RESILIENT_PARTITIONS}, 0, 0, VE, "er"},
  #endif
- {"speed", "", offsetof(VP8Context, cpu_used), AV_OPT_TYPE_INT, {.dbl = 3}, -16, 16, VE},
- {"quality", "", offsetof(VP8Context, deadline), AV_OPT_TYPE_INT, {.dbl = VPX_DL_GOOD_QUALITY}, INT_MIN, INT_MAX, VE, "quality"},
 -    { NULL }
++{"speed", "", offsetof(VP8Context, cpu_used), AV_OPT_TYPE_INT, {.i64 = 3}, -16, 16, VE},
++{"quality", "", offsetof(VP8Context, deadline), AV_OPT_TYPE_INT, {.i64 = VPX_DL_GOOD_QUALITY}, INT_MIN, INT_MAX, VE, "quality"},
 +{"vp8flags", "", offsetof(VP8Context, flags), FF_OPT_TYPE_FLAGS, {.dbl = 0}, 0, UINT_MAX, VE, "flags"},
 +{"error_resilient", "enable error resilience", 0, FF_OPT_TYPE_CONST, {.dbl = VP8F_ERROR_RESILIENT}, INT_MIN, INT_MAX, VE, "flags"},
 +{"altref", "enable use of alternate reference frames (VP8/2-pass only)", 0, FF_OPT_TYPE_CONST, {.dbl = VP8F_AUTO_ALT_REF}, INT_MIN, INT_MAX, VE, "flags"},
- {"arnr_max_frames", "altref noise reduction max frame count", offsetof(VP8Context, arnr_max_frames), AV_OPT_TYPE_INT, {.dbl = 0}, 0, 15, VE},
- {"arnr_strength", "altref noise reduction filter strength", offsetof(VP8Context, arnr_strength), AV_OPT_TYPE_INT, {.dbl = 3}, 0, 6, VE},
- {"arnr_type", "altref noise reduction filter type", offsetof(VP8Context, arnr_type), AV_OPT_TYPE_INT, {.dbl = 3}, 1, 3, VE},
- {"rc_lookahead", "Number of frames to look ahead for alternate reference frame selection", offsetof(VP8Context, lag_in_frames), AV_OPT_TYPE_INT, {.dbl = 25}, 0, 25, VE},
- {"crf", "Select the quality for constant quality mode", offsetof(VP8Context, crf), AV_OPT_TYPE_INT, {.dbl = 0}, 0, 63, VE},
++{"arnr_max_frames", "altref noise reduction max frame count", offsetof(VP8Context, arnr_max_frames), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 15, VE},
++{"arnr_strength", "altref noise reduction filter strength", offsetof(VP8Context, arnr_strength), AV_OPT_TYPE_INT, {.i64 = 3}, 0, 6, VE},
++{"arnr_type", "altref noise reduction filter type", offsetof(VP8Context, arnr_type), AV_OPT_TYPE_INT, {.i64 = 3}, 1, 3, VE},
++{"rc_lookahead", "Number of frames to look ahead for alternate reference frame selection", offsetof(VP8Context, lag_in_frames), AV_OPT_TYPE_INT, {.i64 = 25}, 0, 25, VE},
++{"crf", "Select the quality for constant quality mode", offsetof(VP8Context, crf), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 63, VE},
 +{NULL}
  };
  
  static const AVClass class = {
@@@ -565,15 -478,11 +565,15 @@@ static const AVOption options[] = 
      { "preset",        "Set the encoding preset (cf. x264 --fullhelp)",   OFFSET(preset),        AV_OPT_TYPE_STRING, { .str = "medium" }, 0, 0, VE},
      { "tune",          "Tune the encoding params (cf. x264 --fullhelp)",  OFFSET(tune),          AV_OPT_TYPE_STRING, { 0 }, 0, 0, VE},
      { "profile",       "Set profile restrictions (cf. x264 --fullhelp) ", OFFSET(profile),       AV_OPT_TYPE_STRING, { 0 }, 0, 0, VE},
-     { "fastfirstpass", "Use fast settings when encoding first pass",      OFFSET(fastfirstpass), AV_OPT_TYPE_INT,    { 1 }, 0, 1, VE},
+     { "fastfirstpass", "Use fast settings when encoding first pass",      OFFSET(fastfirstpass), AV_OPT_TYPE_INT,    { .i64 = 1 }, 0, 1, VE},
 +    {"level", "Specify level (as defined by Annex A)", OFFSET(level), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, VE},
 +    {"passlogfile", "Filename for 2 pass stats", OFFSET(stats), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, VE},
 +    {"wpredp", "Weighted prediction for P-frames", OFFSET(wpredp), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, VE},
 +    {"x264opts", "x264 options", OFFSET(x264opts), AV_OPT_TYPE_STRING, {.str=NULL}, 0, 0, VE},
      { "crf",           "Select the quality for constant quality mode",    OFFSET(crf),           AV_OPT_TYPE_FLOAT,  {-1 }, -1, FLT_MAX, VE },
      { "crf_max",       "In CRF mode, prevents VBV from lowering quality beyond this point.",OFFSET(crf_max), AV_OPT_TYPE_FLOAT, {-1 }, -1, FLT_MAX, VE },
-     { "qp",            "Constant quantization parameter rate control method",OFFSET(cqp),        AV_OPT_TYPE_INT,    {-1 }, -1, INT_MAX, VE },
-     { "aq-mode",       "AQ method",                                       OFFSET(aq_mode),       AV_OPT_TYPE_INT,    {-1 }, -1, INT_MAX, VE, "aq_mode"},
+     { "qp",            "Constant quantization parameter rate control method",OFFSET(cqp),        AV_OPT_TYPE_INT,    { .i64 = -1 }, -1, INT_MAX, VE },
+     { "aq-mode",       "AQ method",                                       OFFSET(aq_mode),       AV_OPT_TYPE_INT,    { .i64 = -1 }, -1, INT_MAX, VE, "aq_mode"},
      { "none",          NULL,                              0, AV_OPT_TYPE_CONST, {.i64 = X264_AQ_NONE},         INT_MIN, INT_MAX, VE, "aq_mode" },
      { "variance",      "Variance AQ (complexity mask)",   0, AV_OPT_TYPE_CONST, {.i64 = X264_AQ_VARIANCE},     INT_MIN, INT_MAX, VE, "aq_mode" },
      { "autovariance",  "Auto-variance AQ (experimental)", 0, AV_OPT_TYPE_CONST, {.i64 = X264_AQ_AUTOVARIANCE}, INT_MIN, INT_MAX, VE, "aq_mode" },
Simple merge
Simple merge
@@@ -931,10 -921,9 +931,10 @@@ static void mpeg1_encode_block(MpegEncC
  #define OFFSET(x) offsetof(MpegEncContext, x)
  #define VE AV_OPT_FLAG_ENCODING_PARAM | AV_OPT_FLAG_VIDEO_PARAM
  #define COMMON_OPTS\
-     { "intra_vlc",           "Use MPEG-2 intra VLC table.",       OFFSET(intra_vlc_format),    AV_OPT_TYPE_INT, { 0 }, 0, 1, VE },\
-     { "drop_frame_timecode", "Timecode is in drop frame format.", OFFSET(drop_frame_timecode), AV_OPT_TYPE_INT, { 0 }, 0, 1, VE}, \
-     { "scan_offset",         "Reserve space for SVCD scan offset user data.", OFFSET(scan_offset), AV_OPT_TYPE_INT, { 0 }, 0, 1, VE },
 +    { "gop_timecode",        "MPEG GOP Timecode in hh:mm:ss[:;.]ff format", OFFSET(tc_opt_str), AV_OPT_TYPE_STRING, {.str=NULL}, CHAR_MIN, CHAR_MAX, VE },\
+     { "intra_vlc",           "Use MPEG-2 intra VLC table.",       OFFSET(intra_vlc_format),    AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE },\
+     { "drop_frame_timecode", "Timecode is in drop frame format.", OFFSET(drop_frame_timecode), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE}, \
+     { "scan_offset",         "Reserve space for SVCD scan offset user data.", OFFSET(scan_offset), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE },
  
  static const AVOption mpeg1_options[] = {
      COMMON_OPTS
Simple merge
Simple merge
Simple merge
@@@ -242,53 -198,3 +242,53 @@@ const AVClass *avcodec_get_class(void
  {
      return &av_codec_context_class;
  }
- {"width", "", FOFFSET(width), AV_OPT_TYPE_INT, {.dbl = 0 }, 0, INT_MAX, 0},
- {"height", "", FOFFSET(height), AV_OPT_TYPE_INT, {.dbl = 0 }, 0, INT_MAX, 0},
- {"format", "", FOFFSET(format), AV_OPT_TYPE_INT, {.dbl = -1 }, 0, INT_MAX, 0},
 +
 +#define FOFFSET(x) offsetof(AVFrame,x)
 +
 +static const AVOption frame_options[]={
 +{"best_effort_timestamp", "", FOFFSET(best_effort_timestamp), AV_OPT_TYPE_INT64, {.i64 = AV_NOPTS_VALUE }, INT64_MIN, INT64_MAX, 0},
 +{"pkt_pos", "", FOFFSET(pkt_pos), AV_OPT_TYPE_INT64, {.i64 = -1 }, INT64_MIN, INT64_MAX, 0},
 +{"sample_aspect_ratio", "", FOFFSET(sample_aspect_ratio), AV_OPT_TYPE_RATIONAL, {.dbl = 0 }, 0, INT_MAX, 0},
- {"sample_rate", "", FOFFSET(sample_rate), AV_OPT_TYPE_INT, {.dbl = 0 }, 0, INT_MAX, 0},
++{"width", "", FOFFSET(width), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, INT_MAX, 0},
++{"height", "", FOFFSET(height), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, INT_MAX, 0},
++{"format", "", FOFFSET(format), AV_OPT_TYPE_INT, {.i64 = -1 }, 0, INT_MAX, 0},
 +{"channel_layout", "", FOFFSET(channel_layout), AV_OPT_TYPE_INT64, {.i64 = 0 }, 0, INT64_MAX, 0},
- {"x", "", SROFFSET(x), AV_OPT_TYPE_INT, {.dbl = 0 }, 0, INT_MAX, 0},
- {"y", "", SROFFSET(y), AV_OPT_TYPE_INT, {.dbl = 0 }, 0, INT_MAX, 0},
- {"w", "", SROFFSET(w), AV_OPT_TYPE_INT, {.dbl = 0 }, 0, INT_MAX, 0},
- {"h", "", SROFFSET(h), AV_OPT_TYPE_INT, {.dbl = 0 }, 0, INT_MAX, 0},
- {"type", "", SROFFSET(type), AV_OPT_TYPE_INT, {.dbl = 0 }, 0, INT_MAX, 0},
- {"forced", "", SROFFSET(forced), AV_OPT_TYPE_INT, {.dbl = 0}, 0, 1, 0},
++{"sample_rate", "", FOFFSET(sample_rate), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, INT_MAX, 0},
 +{NULL},
 +};
 +
 +static const AVClass av_frame_class = {
 +    .class_name              = "AVFrame",
 +    .item_name               = NULL,
 +    .option                  = frame_options,
 +    .version                 = LIBAVUTIL_VERSION_INT,
 +};
 +
 +const AVClass *avcodec_get_frame_class(void)
 +{
 +    return &av_frame_class;
 +}
 +
 +#define SROFFSET(x) offsetof(AVSubtitleRect,x)
 +
 +static const AVOption subtitle_rect_options[]={
++{"x", "", SROFFSET(x), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, INT_MAX, 0},
++{"y", "", SROFFSET(y), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, INT_MAX, 0},
++{"w", "", SROFFSET(w), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, INT_MAX, 0},
++{"h", "", SROFFSET(h), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, INT_MAX, 0},
++{"type", "", SROFFSET(type), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, INT_MAX, 0},
++{"forced", "", SROFFSET(forced), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, 0},
 +{NULL},
 +};
 +
 +static const AVClass av_subtitle_rect_class = {
 +    .class_name             = "AVSubtitleRect",
 +    .item_name              = NULL,
 +    .option                 = subtitle_rect_options,
 +    .version                = LIBAVUTIL_VERSION_INT,
 +};
 +
 +const AVClass *avcodec_get_subtitle_rect_class(void)
 +{
 +    return &av_subtitle_rect_class;
 +}
  #define AV_CODEC_DEFAULT_BITRATE 200*1000
  
  static const AVOption options[]={
- {"b", "set bitrate (in bits/s)", OFFSET(bit_rate), AV_OPT_TYPE_INT, {.dbl = AV_CODEC_DEFAULT_BITRATE }, INT_MIN, INT_MAX, A|V|E},
- {"ab", "set bitrate (in bits/s)", OFFSET(bit_rate), AV_OPT_TYPE_INT, {.dbl = 128*1000 }, INT_MIN, INT_MAX, A|E},
 -{"b", "set bitrate (in bits/s)", OFFSET(bit_rate), AV_OPT_TYPE_INT, {.i64 = AV_CODEC_DEFAULT_BITRATE }, INT_MIN, INT_MAX, V|A|E},
++{"b", "set bitrate (in bits/s)", OFFSET(bit_rate), AV_OPT_TYPE_INT, {.i64 = AV_CODEC_DEFAULT_BITRATE }, INT_MIN, INT_MAX, A|V|E},
++{"ab", "set bitrate (in bits/s)", OFFSET(bit_rate), AV_OPT_TYPE_INT, {.i64 = 128*1000 }, INT_MIN, INT_MAX, A|E},
  {"bt", "Set video bitrate tolerance (in bits/s). In 1-pass mode, bitrate tolerance specifies how far "
         "ratecontrol is willing to deviate from the target average bitrate value. This is not related "
         "to min/max bitrate. Lowering tolerance too much has an adverse effect on quality.",
-        OFFSET(bit_rate_tolerance), AV_OPT_TYPE_INT, {.dbl = AV_CODEC_DEFAULT_BITRATE*20 }, 1, INT_MAX, V|E},
+        OFFSET(bit_rate_tolerance), AV_OPT_TYPE_INT, {.i64 = AV_CODEC_DEFAULT_BITRATE*20 }, 1, INT_MAX, V|E},
 -{"flags", NULL, OFFSET(flags), AV_OPT_TYPE_FLAGS, {.i64 = DEFAULT }, 0, UINT_MAX, V|A|E|D, "flags"},
 +{"flags", NULL, OFFSET(flags), AV_OPT_TYPE_FLAGS, {.i64 = DEFAULT }, 0, UINT_MAX, V|A|S|E|D, "flags"},
  {"mv4", "use four motion vector by macroblock (mpeg4)", 0, AV_OPT_TYPE_CONST, {.i64 = CODEC_FLAG_4MV }, INT_MIN, INT_MAX, V|E, "flags"},
  {"qpel", "use 1/4 pel motion compensation", 0, AV_OPT_TYPE_CONST, {.i64 = CODEC_FLAG_QPEL }, INT_MIN, INT_MAX, V|E, "flags"},
  {"loop", "use loop filter", 0, AV_OPT_TYPE_CONST, {.i64 = CODEC_FLAG_LOOP_FILTER }, INT_MIN, INT_MAX, V|E, "flags"},
  #endif
  {"noout", "skip bitstream encoding", 0, AV_OPT_TYPE_CONST, {.i64 = CODEC_FLAG2_NO_OUTPUT }, INT_MIN, INT_MAX, V|E, "flags2"},
  {"local_header", "place global headers at every keyframe instead of in extradata", 0, AV_OPT_TYPE_CONST, {.i64 = CODEC_FLAG2_LOCAL_HEADER }, INT_MIN, INT_MAX, V|E, "flags2"},
 +{"chunks", "Frame data might be split into multiple chunks", 0, AV_OPT_TYPE_CONST, {.i64 = CODEC_FLAG2_CHUNKS }, INT_MIN, INT_MAX, V|D, "flags2"},
 +{"showall", "Show all frames before the first keyframe", 0, AV_OPT_TYPE_CONST, {.i64 = CODEC_FLAG2_SHOW_ALL }, INT_MIN, INT_MAX, V|D, "flags2"},
  #if FF_API_SUB_ID
- {"sub_id", NULL, OFFSET(sub_id), AV_OPT_TYPE_INT, {.dbl = DEFAULT }, INT_MIN, INT_MAX},
+ {"sub_id", NULL, OFFSET(sub_id), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX},
  #endif
- {"me_method", "set motion estimation method", OFFSET(me_method), AV_OPT_TYPE_INT, {.dbl = ME_EPZS }, INT_MIN, INT_MAX, V|E, "me_method"},
+ {"me_method", "set motion estimation method", OFFSET(me_method), AV_OPT_TYPE_INT, {.i64 = ME_EPZS }, INT_MIN, INT_MAX, V|E, "me_method"},
  {"zero", "zero motion estimation (fastest)", 0, AV_OPT_TYPE_CONST, {.i64 = ME_ZERO }, INT_MIN, INT_MAX, V|E, "me_method" },
  {"full", "full motion estimation (slowest)", 0, AV_OPT_TYPE_CONST, {.i64 = ME_FULL }, INT_MIN, INT_MAX, V|E, "me_method" },
  {"epzs", "EPZS motion estimation (default)", 0, AV_OPT_TYPE_CONST, {.i64 = ME_EPZS }, INT_MIN, INT_MAX, V|E, "me_method" },
            "Recommended range for default rc_eq: 0.0-1.0",
            OFFSET(qcompress), AV_OPT_TYPE_FLOAT, {.dbl = 0.5 }, -FLT_MAX, FLT_MAX, V|E},
  {"qblur", "video quantizer scale blur (VBR)", OFFSET(qblur), AV_OPT_TYPE_FLOAT, {.dbl = 0.5 }, -1, FLT_MAX, V|E},
- {"qmin", "min video quantizer scale (VBR)", OFFSET(qmin), AV_OPT_TYPE_INT, {.dbl = 2 }, -1, 69, V|E},
- {"qmax", "max video quantizer scale (VBR)", OFFSET(qmax), AV_OPT_TYPE_INT, {.dbl = 31 }, -1, 1024, V|E},
- {"qdiff", "max difference between the quantizer scale (VBR)", OFFSET(max_qdiff), AV_OPT_TYPE_INT, {.dbl = 3 }, INT_MIN, INT_MAX, V|E},
- {"bf", "use 'frames' B frames", OFFSET(max_b_frames), AV_OPT_TYPE_INT, {.dbl = DEFAULT }, -1, FF_MAX_B_FRAMES, V|E},
+ {"qmin", "min video quantizer scale (VBR)", OFFSET(qmin), AV_OPT_TYPE_INT, {.i64 = 2 }, -1, 69, V|E},
 -{"qmax", "max video quantizer scale (VBR)", OFFSET(qmax), AV_OPT_TYPE_INT, {.i64 = 31 }, -1, 69, V|E},
++{"qmax", "max video quantizer scale (VBR)", OFFSET(qmax), AV_OPT_TYPE_INT, {.i64 = 31 }, -1, 1024, V|E},
+ {"qdiff", "max difference between the quantizer scale (VBR)", OFFSET(max_qdiff), AV_OPT_TYPE_INT, {.i64 = 3 }, INT_MIN, INT_MAX, V|E},
+ {"bf", "use 'frames' B frames", OFFSET(max_b_frames), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, -1, FF_MAX_B_FRAMES, V|E},
  {"b_qfactor", "qp factor between p and b frames", OFFSET(b_quant_factor), AV_OPT_TYPE_FLOAT, {.dbl = 1.25 }, -FLT_MAX, FLT_MAX, V|E},
- {"rc_strategy", "ratecontrol method", OFFSET(rc_strategy), AV_OPT_TYPE_INT, {.dbl = DEFAULT }, INT_MIN, INT_MAX, V|E},
- {"b_strategy", "strategy to choose between I/P/B-frames", OFFSET(b_frame_strategy), AV_OPT_TYPE_INT, {.dbl = 0 }, INT_MIN, INT_MAX, V|E},
- {"ps", "rtp payload size in bytes", OFFSET(rtp_payload_size), AV_OPT_TYPE_INT, {.dbl = DEFAULT }, INT_MIN, INT_MAX, V|E},
- {"mv_bits", NULL, OFFSET(mv_bits), AV_OPT_TYPE_INT, {.dbl = DEFAULT }, INT_MIN, INT_MAX},
- {"header_bits", NULL, OFFSET(header_bits), AV_OPT_TYPE_INT, {.dbl = DEFAULT }, INT_MIN, INT_MAX},
- {"i_tex_bits", NULL, OFFSET(i_tex_bits), AV_OPT_TYPE_INT, {.dbl = DEFAULT }, INT_MIN, INT_MAX},
- {"p_tex_bits", NULL, OFFSET(p_tex_bits), AV_OPT_TYPE_INT, {.dbl = DEFAULT }, INT_MIN, INT_MAX},
- {"i_count", NULL, OFFSET(i_count), AV_OPT_TYPE_INT, {.dbl = DEFAULT }, INT_MIN, INT_MAX},
- {"p_count", NULL, OFFSET(p_count), AV_OPT_TYPE_INT, {.dbl = DEFAULT }, INT_MIN, INT_MAX},
- {"skip_count", NULL, OFFSET(skip_count), AV_OPT_TYPE_INT, {.dbl = DEFAULT }, INT_MIN, INT_MAX},
- {"misc_bits", NULL, OFFSET(misc_bits), AV_OPT_TYPE_INT, {.dbl = DEFAULT }, INT_MIN, INT_MAX},
- {"frame_bits", NULL, OFFSET(frame_bits), AV_OPT_TYPE_INT, {.dbl = DEFAULT }, INT_MIN, INT_MAX},
- {"codec_tag", NULL, OFFSET(codec_tag), AV_OPT_TYPE_INT, {.dbl = DEFAULT }, INT_MIN, INT_MAX},
+ {"rc_strategy", "ratecontrol method", OFFSET(rc_strategy), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E},
+ {"b_strategy", "strategy to choose between I/P/B-frames", OFFSET(b_frame_strategy), AV_OPT_TYPE_INT, {.i64 = 0 }, INT_MIN, INT_MAX, V|E},
+ {"ps", "rtp payload size in bytes", OFFSET(rtp_payload_size), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E},
+ {"mv_bits", NULL, OFFSET(mv_bits), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX},
+ {"header_bits", NULL, OFFSET(header_bits), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX},
+ {"i_tex_bits", NULL, OFFSET(i_tex_bits), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX},
+ {"p_tex_bits", NULL, OFFSET(p_tex_bits), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX},
+ {"i_count", NULL, OFFSET(i_count), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX},
+ {"p_count", NULL, OFFSET(p_count), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX},
+ {"skip_count", NULL, OFFSET(skip_count), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX},
+ {"misc_bits", NULL, OFFSET(misc_bits), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX},
+ {"frame_bits", NULL, OFFSET(frame_bits), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX},
+ {"codec_tag", NULL, OFFSET(codec_tag), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX},
  {"bug", "workaround not auto detected encoder bugs", OFFSET(workaround_bugs), AV_OPT_TYPE_FLAGS, {.i64 = FF_BUG_AUTODETECT }, INT_MIN, INT_MAX, V|D, "bug"},
  {"autodetect", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_BUG_AUTODETECT }, INT_MIN, INT_MAX, V|D, "bug"},
  {"old_msmpeg4", "some old lavc generated msmpeg4v3 files (no autodetection)", 0, AV_OPT_TYPE_CONST, {.i64 = FF_BUG_OLD_MSMPEG4 }, INT_MIN, INT_MAX, V|D, "bug"},
  {"experimental", "allow non standardized experimental things", 0, AV_OPT_TYPE_CONST, {.i64 = FF_COMPLIANCE_EXPERIMENTAL }, INT_MIN, INT_MAX, V|D|E, "strict"},
  {"b_qoffset", "qp offset between P and B frames", OFFSET(b_quant_offset), AV_OPT_TYPE_FLOAT, {.dbl = 1.25 }, -FLT_MAX, FLT_MAX, V|E},
  {"err_detect", "set error detection flags", OFFSET(err_recognition), AV_OPT_TYPE_FLAGS, {.i64 = AV_EF_CRCCHECK }, INT_MIN, INT_MAX, A|V|D, "err_detect"},
 -{"crccheck", "verify embedded CRCs", 0, AV_OPT_TYPE_CONST, {.i64 = AV_EF_CRCCHECK }, INT_MIN, INT_MAX, V|D, "err_detect"},
 -{"bitstream", "detect bitstream specification deviations", 0, AV_OPT_TYPE_CONST, {.i64 = AV_EF_BITSTREAM }, INT_MIN, INT_MAX, V|D, "err_detect"},
 -{"buffer", "detect improper bitstream length", 0, AV_OPT_TYPE_CONST, {.i64 = AV_EF_BUFFER }, INT_MIN, INT_MAX, V|D, "err_detect"},
 -{"explode", "abort decoding on minor error detection", 0, AV_OPT_TYPE_CONST, {.i64 = AV_EF_EXPLODE }, INT_MIN, INT_MAX, V|D, "err_detect"},
 +{"crccheck", "verify embedded CRCs", 0, AV_OPT_TYPE_CONST, {.i64 = AV_EF_CRCCHECK }, INT_MIN, INT_MAX, A|V|D, "err_detect"},
 +{"bitstream", "detect bitstream specification deviations", 0, AV_OPT_TYPE_CONST, {.i64 = AV_EF_BITSTREAM }, INT_MIN, INT_MAX, A|V|D, "err_detect"},
 +{"buffer", "detect improper bitstream length", 0, AV_OPT_TYPE_CONST, {.i64 = AV_EF_BUFFER }, INT_MIN, INT_MAX, A|V|D, "err_detect"},
 +{"explode", "abort decoding on minor error detection", 0, AV_OPT_TYPE_CONST, {.i64 = AV_EF_EXPLODE }, INT_MIN, INT_MAX, A|V|D, "err_detect"},
 +{"careful",    "consider things that violate the spec and have not been seen in the wild as errors", 0, AV_OPT_TYPE_CONST, {.i64 = AV_EF_CAREFUL }, INT_MIN, INT_MAX, A|V|D, "err_detect"},
 +{"compliant",  "consider all spec non compliancies as errors", 0, AV_OPT_TYPE_CONST, {.i64 = AV_EF_COMPLIANT }, INT_MIN, INT_MAX, A|V|D, "err_detect"},
 +{"aggressive", "consider things that a sane encoder should not do as an error", 0, AV_OPT_TYPE_CONST, {.i64 = AV_EF_AGGRESSIVE }, INT_MIN, INT_MAX, A|V|D, "err_detect"},
- {"has_b_frames", NULL, OFFSET(has_b_frames), AV_OPT_TYPE_INT, {.dbl = DEFAULT }, INT_MIN, INT_MAX},
- {"block_align", NULL, OFFSET(block_align), AV_OPT_TYPE_INT, {.dbl = DEFAULT }, INT_MIN, INT_MAX},
- {"mpeg_quant", "use MPEG quantizers instead of H.263", OFFSET(mpeg_quant), AV_OPT_TYPE_INT, {.dbl = DEFAULT }, INT_MIN, INT_MAX, V|E},
+ {"has_b_frames", NULL, OFFSET(has_b_frames), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX},
+ {"block_align", NULL, OFFSET(block_align), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX},
+ {"mpeg_quant", "use MPEG quantizers instead of H.263", OFFSET(mpeg_quant), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E},
  {"stats_out", NULL, OFFSET(stats_out), AV_OPT_TYPE_STRING, {.str = NULL}, CHAR_MIN, CHAR_MAX},
  {"qsquish", "how to keep quantizer between qmin and qmax (0 = clip, 1 = use differentiable function)", OFFSET(rc_qsquish), AV_OPT_TYPE_FLOAT, {.dbl = DEFAULT }, 0, 99, V|E},
  {"rc_qmod_amp", "experimental quantizer modulation", OFFSET(rc_qmod_amp), AV_OPT_TYPE_FLOAT, {.dbl = DEFAULT }, -FLT_MAX, FLT_MAX, V|E},
  {"dts_96_24", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_PROFILE_DTS_96_24 }, INT_MIN, INT_MAX, A|E, "profile"},
  {"dts_hd_hra", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_PROFILE_DTS_HD_HRA }, INT_MIN, INT_MAX, A|E, "profile"},
  {"dts_hd_ma", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_PROFILE_DTS_HD_MA }, INT_MIN, INT_MAX, A|E, "profile"},
- {"level", NULL, OFFSET(level), AV_OPT_TYPE_INT, {.dbl = FF_LEVEL_UNKNOWN }, INT_MIN, INT_MAX, V|A|E, "level"},
+ {"level", NULL, OFFSET(level), AV_OPT_TYPE_INT, {.i64 = FF_LEVEL_UNKNOWN }, INT_MIN, INT_MAX, V|A|E, "level"},
  {"unknown", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_LEVEL_UNKNOWN }, INT_MIN, INT_MAX, V|A|E, "level"},
- {"lowres", "decode at 1= 1/2, 2=1/4, 3=1/8 resolutions", OFFSET(lowres), AV_OPT_TYPE_INT, {.dbl = 0 }, 0, INT_MAX, V|A|D},
- {"skip_threshold", "frame skip threshold", OFFSET(frame_skip_threshold), AV_OPT_TYPE_INT, {.dbl = DEFAULT }, INT_MIN, INT_MAX, V|E},
- {"skip_factor", "frame skip factor", OFFSET(frame_skip_factor), AV_OPT_TYPE_INT, {.dbl = DEFAULT }, INT_MIN, INT_MAX, V|E},
- {"skip_exp", "frame skip exponent", OFFSET(frame_skip_exp), AV_OPT_TYPE_INT, {.dbl = DEFAULT }, INT_MIN, INT_MAX, V|E},
- {"skipcmp", "frame skip compare function", OFFSET(frame_skip_cmp), AV_OPT_TYPE_INT, {.dbl = FF_CMP_DCTMAX }, INT_MIN, INT_MAX, V|E, "cmp_func"},
++{"lowres", "decode at 1= 1/2, 2=1/4, 3=1/8 resolutions", OFFSET(lowres), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, INT_MAX, V|A|D},
+ {"skip_threshold", "frame skip threshold", OFFSET(frame_skip_threshold), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E},
+ {"skip_factor", "frame skip factor", OFFSET(frame_skip_factor), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E},
+ {"skip_exp", "frame skip exponent", OFFSET(frame_skip_exp), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E},
+ {"skipcmp", "frame skip compare function", OFFSET(frame_skip_cmp), AV_OPT_TYPE_INT, {.i64 = FF_CMP_DCTMAX }, INT_MIN, INT_MAX, V|E, "cmp_func"},
  {"border_mask", "increases the quantizer for macroblocks close to borders", OFFSET(border_masking), AV_OPT_TYPE_FLOAT, {.dbl = DEFAULT }, -FLT_MAX, FLT_MAX, V|E},
- {"mblmin", "min macroblock lagrange factor (VBR)", OFFSET(mb_lmin), AV_OPT_TYPE_INT, {.dbl = FF_QP2LAMBDA * 2 }, 1, FF_LAMBDA_MAX, V|E},
- {"mblmax", "max macroblock lagrange factor (VBR)", OFFSET(mb_lmax), AV_OPT_TYPE_INT, {.dbl = FF_QP2LAMBDA * 31 }, 1, FF_LAMBDA_MAX, V|E},
- {"mepc", "motion estimation bitrate penalty compensation (1.0 = 256)", OFFSET(me_penalty_compensation), AV_OPT_TYPE_INT, {.dbl = 256 }, INT_MIN, INT_MAX, V|E},
- {"skip_loop_filter", NULL, OFFSET(skip_loop_filter), AV_OPT_TYPE_INT, {.dbl = AVDISCARD_DEFAULT }, INT_MIN, INT_MAX, V|D, "avdiscard"},
- {"skip_idct"       , NULL, OFFSET(skip_idct)       , AV_OPT_TYPE_INT, {.dbl = AVDISCARD_DEFAULT }, INT_MIN, INT_MAX, V|D, "avdiscard"},
- {"skip_frame"      , NULL, OFFSET(skip_frame)      , AV_OPT_TYPE_INT, {.dbl = AVDISCARD_DEFAULT }, INT_MIN, INT_MAX, V|D, "avdiscard"},
+ {"mblmin", "min macroblock lagrange factor (VBR)", OFFSET(mb_lmin), AV_OPT_TYPE_INT, {.i64 = FF_QP2LAMBDA * 2 }, 1, FF_LAMBDA_MAX, V|E},
+ {"mblmax", "max macroblock lagrange factor (VBR)", OFFSET(mb_lmax), AV_OPT_TYPE_INT, {.i64 = FF_QP2LAMBDA * 31 }, 1, FF_LAMBDA_MAX, V|E},
+ {"mepc", "motion estimation bitrate penalty compensation (1.0 = 256)", OFFSET(me_penalty_compensation), AV_OPT_TYPE_INT, {.i64 = 256 }, INT_MIN, INT_MAX, V|E},
+ {"skip_loop_filter", NULL, OFFSET(skip_loop_filter), AV_OPT_TYPE_INT, {.i64 = AVDISCARD_DEFAULT }, INT_MIN, INT_MAX, V|D, "avdiscard"},
+ {"skip_idct"       , NULL, OFFSET(skip_idct)       , AV_OPT_TYPE_INT, {.i64 = AVDISCARD_DEFAULT }, INT_MIN, INT_MAX, V|D, "avdiscard"},
+ {"skip_frame"      , NULL, OFFSET(skip_frame)      , AV_OPT_TYPE_INT, {.i64 = AVDISCARD_DEFAULT }, INT_MIN, INT_MAX, V|D, "avdiscard"},
  {"none"            , NULL, 0, AV_OPT_TYPE_CONST, {.i64 = AVDISCARD_NONE    }, INT_MIN, INT_MAX, V|D, "avdiscard"},
  {"default"         , NULL, 0, AV_OPT_TYPE_CONST, {.i64 = AVDISCARD_DEFAULT }, INT_MIN, INT_MAX, V|D, "avdiscard"},
  {"noref"           , NULL, 0, AV_OPT_TYPE_CONST, {.i64 = AVDISCARD_NONREF  }, INT_MIN, INT_MAX, V|D, "avdiscard"},
  {"bidir"           , NULL, 0, AV_OPT_TYPE_CONST, {.i64 = AVDISCARD_BIDIR   }, INT_MIN, INT_MAX, V|D, "avdiscard"},
  {"nokey"           , NULL, 0, AV_OPT_TYPE_CONST, {.i64 = AVDISCARD_NONKEY  }, INT_MIN, INT_MAX, V|D, "avdiscard"},
  {"all"             , NULL, 0, AV_OPT_TYPE_CONST, {.i64 = AVDISCARD_ALL     }, INT_MIN, INT_MAX, V|D, "avdiscard"},
- {"bidir_refine", "refine the two motion vectors used in bidirectional macroblocks", OFFSET(bidir_refine), AV_OPT_TYPE_INT, {.dbl = 1 }, 0, 4, V|E},
- {"brd_scale", "downscales frames for dynamic B-frame decision", OFFSET(brd_scale), AV_OPT_TYPE_INT, {.dbl = DEFAULT }, 0, 10, V|E},
- {"keyint_min", "minimum interval between IDR-frames", OFFSET(keyint_min), AV_OPT_TYPE_INT, {.dbl = 25 }, INT_MIN, INT_MAX, V|E},
- {"refs", "reference frames to consider for motion compensation", OFFSET(refs), AV_OPT_TYPE_INT, {.dbl = 1 }, INT_MIN, INT_MAX, V|E},
- {"chromaoffset", "chroma qp offset from luma", OFFSET(chromaoffset), AV_OPT_TYPE_INT, {.dbl = DEFAULT }, INT_MIN, INT_MAX, V|E},
- {"trellis", "rate-distortion optimal quantization", OFFSET(trellis), AV_OPT_TYPE_INT, {.dbl = DEFAULT }, INT_MIN, INT_MAX, V|A|E},
+ {"bidir_refine", "refine the two motion vectors used in bidirectional macroblocks", OFFSET(bidir_refine), AV_OPT_TYPE_INT, {.i64 = 1 }, 0, 4, V|E},
+ {"brd_scale", "downscales frames for dynamic B-frame decision", OFFSET(brd_scale), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, 0, 10, V|E},
 -{"keyint_min", "minimum interval between IDR-frames (x264)", OFFSET(keyint_min), AV_OPT_TYPE_INT, {.i64 = 25 }, INT_MIN, INT_MAX, V|E},
 -{"refs", "reference frames to consider for motion compensation (Snow)", OFFSET(refs), AV_OPT_TYPE_INT, {.i64 = 1 }, INT_MIN, INT_MAX, V|E},
++{"keyint_min", "minimum interval between IDR-frames", OFFSET(keyint_min), AV_OPT_TYPE_INT, {.i64 = 25 }, INT_MIN, INT_MAX, V|E},
++{"refs", "reference frames to consider for motion compensation", OFFSET(refs), AV_OPT_TYPE_INT, {.i64 = 1 }, INT_MIN, INT_MAX, V|E},
+ {"chromaoffset", "chroma qp offset from luma", OFFSET(chromaoffset), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E},
+ {"trellis", "rate-distortion optimal quantization", OFFSET(trellis), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|A|E},
  #if FF_API_MPV_GLOBAL_OPTS
  {"skiprd", "Deprecated, use mpegvideo private options instead", 0, AV_OPT_TYPE_CONST, {.i64 = CODEC_FLAG2_SKIP_RD }, INT_MIN, INT_MAX, V|E, "flags2"},
  #endif
  {"em", "Emergency",          0, AV_OPT_TYPE_CONST, {.i64 = AV_AUDIO_SERVICE_TYPE_EMERGENCY },         INT_MIN, INT_MAX, A|E, "audio_service_type"},
  {"vo", "Voice Over",         0, AV_OPT_TYPE_CONST, {.i64 = AV_AUDIO_SERVICE_TYPE_VOICE_OVER },        INT_MIN, INT_MAX, A|E, "audio_service_type"},
  {"ka", "Karaoke",            0, AV_OPT_TYPE_CONST, {.i64 = AV_AUDIO_SERVICE_TYPE_KARAOKE },           INT_MIN, INT_MAX, A|E, "audio_service_type"},
- {"request_sample_fmt", "sample format audio decoders should prefer", OFFSET(request_sample_fmt), AV_OPT_TYPE_INT, {.dbl = AV_SAMPLE_FMT_NONE }, AV_SAMPLE_FMT_NONE, AV_SAMPLE_FMT_NB-1, A|D, "request_sample_fmt"},
 -{"request_sample_fmt", NULL, OFFSET(request_sample_fmt), AV_OPT_TYPE_INT, {.i64 = AV_SAMPLE_FMT_NONE }, AV_SAMPLE_FMT_NONE, AV_SAMPLE_FMT_NB-1, A|D, "request_sample_fmt"},
++{"request_sample_fmt", "sample format audio decoders should prefer", OFFSET(request_sample_fmt), AV_OPT_TYPE_INT, {.i64 = AV_SAMPLE_FMT_NONE }, AV_SAMPLE_FMT_NONE, AV_SAMPLE_FMT_NB-1, A|D, "request_sample_fmt"},
  {"u8" , "8-bit unsigned integer", 0, AV_OPT_TYPE_CONST, {.i64 = AV_SAMPLE_FMT_U8  }, INT_MIN, INT_MAX, A|D, "request_sample_fmt"},
  {"s16", "16-bit signed integer",  0, AV_OPT_TYPE_CONST, {.i64 = AV_SAMPLE_FMT_S16 }, INT_MIN, INT_MAX, A|D, "request_sample_fmt"},
  {"s32", "32-bit signed integer",  0, AV_OPT_TYPE_CONST, {.i64 = AV_SAMPLE_FMT_S32 }, INT_MIN, INT_MAX, A|D, "request_sample_fmt"},
@@@ -508,20 -468,6 +508,20 @@@ static int decode(AVCodecContext *avctx
      return buf_size;
  }
  
-     {"forced_subs_only", "Only show forced subtitles", OFFSET(forced_subs_only), AV_OPT_TYPE_INT, {.dbl = 0}, 0, 1, SD},
 +#define OFFSET(x) offsetof(PGSSubContext, x)
 +#define SD AV_OPT_FLAG_SUBTITLE_PARAM | AV_OPT_FLAG_DECODING_PARAM
 +static const AVOption options[] = {
++    {"forced_subs_only", "Only show forced subtitles", OFFSET(forced_subs_only), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, SD},
 +    { NULL },
 +};
 +
 +static const AVClass pgsdec_class = {
 +    .class_name = "PGS subtitle decoder",
 +    .item_name  = av_default_item_name,
 +    .option     = options,
 +    .version    = LIBAVUTIL_VERSION_INT,
 +};
 +
  AVCodec ff_pgssub_decoder = {
      .name           = "pgssub",
      .type           = AVMEDIA_TYPE_SUBTITLE,
Simple merge
@@@ -40,23 -37,9 +40,23 @@@ typedef struct RawVideoContext 
      int             length;  /* number of bytes in buffer */
      int flip;
      AVFrame pic;             ///< AVCodecContext.coded_frame
 +    int tff;
  } RawVideoContext;
  
- {"top", "top field first", offsetof(RawVideoContext, tff), AV_OPT_TYPE_INT, {.dbl = -1}, -1, 1, AV_OPT_FLAG_DECODING_PARAM|AV_OPT_FLAG_VIDEO_PARAM},
 +static const AVOption options[]={
++{"top", "top field first", offsetof(RawVideoContext, tff), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 1, AV_OPT_FLAG_DECODING_PARAM|AV_OPT_FLAG_VIDEO_PARAM},
 +{NULL}
 +};
 +
 +static const AVClass class = {
 +    .class_name = "rawdec",
 +    .option     = options,
 +    .version    = LIBAVUTIL_VERSION_INT,
 +};
 +
  static const PixelFormatTag pix_fmt_bps_avi[] = {
 +    { PIX_FMT_MONOWHITE, 1 },
 +    { PIX_FMT_PAL8,    2 },
      { PIX_FMT_PAL8,    4 },
      { PIX_FMT_PAL8,    8 },
      { PIX_FMT_RGB444, 12 },
@@@ -1926,8 -1914,7 +1926,8 @@@ static av_cold int encode_end(AVCodecCo
  #define OFFSET(x) offsetof(SnowContext, x)
  #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
  static const AVOption options[] = {
-     { "memc_only",      "Only do ME/MC (I frames -> ref, P frame -> ME+MC).",   OFFSET(memc_only), AV_OPT_TYPE_INT, { 0 }, 0, 1, VE },
-     { "no_bitstream",   "Skip final bitstream writeout.",                    OFFSET(no_bitstream), AV_OPT_TYPE_INT, { 0 }, 0, 1, VE },
+     { "memc_only",      "Only do ME/MC (I frames -> ref, P frame -> ME+MC).",   OFFSET(memc_only), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE },
++    { "no_bitstream",   "Skip final bitstream writeout.",                    OFFSET(no_bitstream), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE },
      { NULL },
  };
  
@@@ -493,8 -450,7 +493,8 @@@ static av_cold int encode_close(AVCodec
  #define OFFSET(x) offsetof(TiffEncoderContext, x)
  #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
  static const AVOption options[] = {
-     {"dpi", "set the image resolution (in dpi)", OFFSET(dpi), AV_OPT_TYPE_INT, {.dbl = 72}, 1, 0x10000, AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_ENCODING_PARAM},
-     { "compression_algo", NULL, OFFSET(compr), AV_OPT_TYPE_INT, {TIFF_PACKBITS}, TIFF_RAW, TIFF_DEFLATE, VE, "compression_algo" },
++    {"dpi", "set the image resolution (in dpi)", OFFSET(dpi), AV_OPT_TYPE_INT, {.i64 = 72}, 1, 0x10000, AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_ENCODING_PARAM},
+     { "compression_algo", NULL, OFFSET(compr), AV_OPT_TYPE_INT, {.i64 = TIFF_PACKBITS}, TIFF_RAW, TIFF_DEFLATE, VE, "compression_algo" },
      { "packbits", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = TIFF_PACKBITS}, 0, 0, VE, "compression_algo" },
      { "raw",      NULL, 0, AV_OPT_TYPE_CONST, {.i64 = TIFF_RAW},      0, 0, VE, "compression_algo" },
      { "lzw",      NULL, 0, AV_OPT_TYPE_CONST, {.i64 = TIFF_LZW},      0, 0, VE, "compression_algo" },
Simple merge
Simple merge
index 74de809,0000000..c47906e
mode 100644,000000..100644
--- /dev/null
@@@ -1,240 -1,0 +1,240 @@@
-     { "list_drivers", "list available drivers",  OFFSET(list_drivers), AV_OPT_TYPE_INT, {.dbl=0}, 0, 1, ENC, "list_drivers" },
 +/*
 + * Copyright (c) 2012 Paul B Mahol
 + *
 + * This file is part of FFmpeg.
 + *
 + * FFmpeg is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU Lesser General Public
 + * License as published by the Free Software Foundation; either
 + * version 2.1 of the License, or (at your option) any later version.
 + *
 + * FFmpeg is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 + * Lesser General Public License for more details.
 + *
 + * You should have received a copy of the GNU Lesser General Public
 + * License along with FFmpeg; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 + */
 +
 +#include <caca.h>
 +#include "libavutil/opt.h"
 +#include "libavutil/pixdesc.h"
 +#include "avdevice.h"
 +
 +typedef struct CACAContext {
 +    AVClass         *class;
 +    AVFormatContext *ctx;
 +    char            *window_title;
 +    int             window_width,  window_height;
 +
 +    caca_canvas_t   *canvas;
 +    caca_display_t  *display;
 +    caca_dither_t   *dither;
 +
 +    char            *algorithm, *antialias;
 +    char            *charset, *color;
 +    char            *driver;
 +
 +    char            *list_dither;
 +    int             list_drivers;
 +} CACAContext;
 +
 +static int caca_write_trailer(AVFormatContext *s)
 +{
 +    CACAContext *c = s->priv_data;
 +
 +    av_freep(&c->window_title);
 +
 +    if (c->display) {
 +        caca_free_display(c->display);
 +        c->display = NULL;
 +    }
 +    if (c->dither) {
 +        caca_free_dither(c->dither);
 +        c->dither = NULL;
 +    }
 +    if (c->canvas) {
 +        caca_free_canvas(c->canvas);
 +        c->canvas = NULL;
 +    }
 +    return 0;
 +}
 +
 +static void list_drivers(CACAContext *c)
 +{
 +    const char *const *drivers = caca_get_display_driver_list();
 +    int i;
 +
 +    av_log(c->ctx, AV_LOG_INFO, "Available drivers:\n");
 +    for (i = 0; drivers[i]; i += 2)
 +        av_log(c->ctx, AV_LOG_INFO, "%s : %s\n", drivers[i], drivers[i + 1]);
 +}
 +
 +#define DEFINE_LIST_DITHER(thing, thing_str)                                 \
 +static void list_dither_## thing(CACAContext *c)                         \
 +{                                                                            \
 +    const char *const *thing = caca_get_dither_## thing ##_list(c->dither);  \
 +    int i;                                                                   \
 +                                                                             \
 +    av_log(c->ctx, AV_LOG_INFO, "Available %s:\n", thing_str);               \
 +    for (i = 0; thing[i]; i += 2)                                            \
 +        av_log(c->ctx, AV_LOG_INFO, "%s : %s\n", thing[i], thing[i + 1]);    \
 +}
 +
 +DEFINE_LIST_DITHER(color, "colors");
 +DEFINE_LIST_DITHER(charset, "charsets");
 +DEFINE_LIST_DITHER(algorithm, "algorithms");
 +DEFINE_LIST_DITHER(antialias, "antialias");
 +
 +static int caca_write_header(AVFormatContext *s)
 +{
 +    CACAContext *c = s->priv_data;
 +    AVStream *st = s->streams[0];
 +    AVCodecContext *encctx = st->codec;
 +    int ret, bpp;
 +
 +    c->ctx = s;
 +    if (c->list_drivers) {
 +        list_drivers(c);
 +        return AVERROR_EXIT;
 +    }
 +    if (c->list_dither) {
 +        if (!strcmp(c->list_dither, "colors")) {
 +            list_dither_color(c);
 +        } else if (!strcmp(c->list_dither, "charsets")) {
 +            list_dither_charset(c);
 +        } else if (!strcmp(c->list_dither, "algorithms")) {
 +            list_dither_algorithm(c);
 +        } else if (!strcmp(c->list_dither, "antialiases")) {
 +            list_dither_antialias(c);
 +        } else {
 +            av_log(s, AV_LOG_ERROR,
 +                   "Invalid argument '%s', for 'list_dither' option\n"
 +                   "Argument must be one of 'algorithms, 'antialiases', 'charsets', 'colors'\n",
 +                   c->list_dither);
 +            return AVERROR(EINVAL);
 +        }
 +        return AVERROR_EXIT;
 +    }
 +
 +    if (   s->nb_streams > 1
 +        || encctx->codec_type != AVMEDIA_TYPE_VIDEO
 +        || encctx->codec_id   != AV_CODEC_ID_RAWVIDEO) {
 +        av_log(s, AV_LOG_ERROR, "Only supports one rawvideo stream\n");
 +        return AVERROR(EINVAL);
 +    }
 +
 +    if (encctx->pix_fmt != PIX_FMT_RGB24) {
 +        av_log(s, AV_LOG_ERROR,
 +               "Unsupported pixel format '%s', choose rgb24\n",
 +               av_get_pix_fmt_name(encctx->pix_fmt));
 +        return AVERROR(EINVAL);
 +    }
 +
 +    c->canvas = caca_create_canvas(c->window_width, c->window_height);
 +    if (!c->canvas) {
 +        av_log(s, AV_LOG_ERROR, "Failed to create canvas\n");
 +        ret = AVERROR(errno);
 +        goto fail;
 +    }
 +
 +    bpp = av_get_bits_per_pixel(&av_pix_fmt_descriptors[encctx->pix_fmt]);
 +    c->dither = caca_create_dither(bpp, encctx->width, encctx->height,
 +                                   bpp / 8 * encctx->width,
 +                                   0x0000ff, 0x00ff00, 0xff0000, 0);
 +    if (!c->dither) {
 +        av_log(s, AV_LOG_ERROR, "Failed to create dither\n");
 +        ret =  AVERROR(errno);
 +        goto fail;
 +    }
 +
 +#define CHECK_DITHER_OPT(opt)                                           \
 +    if (caca_set_dither_##opt(c->dither, c->opt) < 0)  {                \
 +        ret = AVERROR(errno);                                           \
 +        av_log(s, AV_LOG_ERROR, "Failed to set value '%s' for option '%s'\n", \
 +               c->opt, #opt);                                           \
 +        goto fail;                                                      \
 +    }
 +    CHECK_DITHER_OPT(algorithm);
 +    CHECK_DITHER_OPT(antialias);
 +    CHECK_DITHER_OPT(charset);
 +    CHECK_DITHER_OPT(color);
 +
 +    c->display = caca_create_display_with_driver(c->canvas, c->driver);
 +    if (!c->display) {
 +        av_log(s, AV_LOG_ERROR, "Failed to create display\n");
 +        list_drivers(c);
 +        ret = AVERROR(errno);
 +        goto fail;
 +    }
 +
 +    if (!c->window_width || !c->window_height) {
 +        c->window_width  = caca_get_canvas_width(c->canvas);
 +        c->window_height = caca_get_canvas_height(c->canvas);
 +    }
 +
 +    if (!c->window_title)
 +        c->window_title = av_strdup(s->filename);
 +    caca_set_display_title(c->display, c->window_title);
 +    caca_set_display_time(c->display, av_rescale_q(1, st->codec->time_base, AV_TIME_BASE_Q));
 +
 +    return 0;
 +
 +fail:
 +    caca_write_trailer(s);
 +    return ret;
 +}
 +
 +static int caca_write_packet(AVFormatContext *s, AVPacket *pkt)
 +{
 +    CACAContext *c = s->priv_data;
 +
 +    caca_dither_bitmap(c->canvas, 0, 0, c->window_width, c->window_height, c->dither, pkt->data);
 +    caca_refresh_display(c->display);
 +
 +    return 0;
 +}
 +
 +#define OFFSET(x) offsetof(CACAContext,x)
 +#define ENC AV_OPT_FLAG_ENCODING_PARAM
 +
 +static const AVOption options[] = {
 +    { "window_size",  "set window forced size",  OFFSET(window_width), AV_OPT_TYPE_IMAGE_SIZE, {.str = NULL }, 0, 0, ENC},
 +    { "window_title", "set window title",        OFFSET(window_title), AV_OPT_TYPE_STRING,     {.str = NULL }, 0, 0, ENC },
 +    { "driver",       "set display driver",      OFFSET(driver),    AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, ENC },
 +    { "algorithm",    "set dithering algorithm", OFFSET(algorithm), AV_OPT_TYPE_STRING, {.str = "default" }, 0, 0, ENC },
 +    { "antialias",    "set antialias method",    OFFSET(antialias), AV_OPT_TYPE_STRING, {.str = "default" }, 0, 0, ENC },
 +    { "charset",      "set charset used to render output", OFFSET(charset), AV_OPT_TYPE_STRING, {.str = "default" }, 0, 0, ENC },
 +    { "color",        "set color used to render output",   OFFSET(color),   AV_OPT_TYPE_STRING, {.str = "default" }, 0, 0, ENC },
++    { "list_drivers", "list available drivers",  OFFSET(list_drivers), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, ENC, "list_drivers" },
 +    { "true",         NULL, 0, AV_OPT_TYPE_CONST, {.i64 = 1}, 0, 0, ENC, "list_drivers" },
 +    { "false",        NULL, 0, AV_OPT_TYPE_CONST, {.i64 = 0}, 0, 0, ENC, "list_drivers" },
 +    { "list_dither", "list available dither options", OFFSET(list_dither), AV_OPT_TYPE_STRING, {.dbl=0}, 0, 1, ENC, "list_dither" },
 +    { "algorithms",   NULL, 0, AV_OPT_TYPE_CONST, {.str = "algorithms"}, 0, 0, ENC, "list_dither" },
 +    { "antialiases",  NULL, 0, AV_OPT_TYPE_CONST, {.str = "antialiases"},0, 0, ENC, "list_dither" },
 +    { "charsets",     NULL, 0, AV_OPT_TYPE_CONST, {.str = "charsets"},   0, 0, ENC, "list_dither" },
 +    { "colors",       NULL, 0, AV_OPT_TYPE_CONST, {.str = "colors"},     0, 0, ENC, "list_dither" },
 +    { NULL },
 +};
 +
 +static const AVClass caca_class = {
 +    .class_name = "caca_outdev",
 +    .item_name  = av_default_item_name,
 +    .option     = options,
 +    .version    = LIBAVUTIL_VERSION_INT,
 +};
 +
 +AVOutputFormat ff_caca_muxer = {
 +    .name           = "caca",
 +    .long_name      = NULL_IF_CONFIG_SMALL("caca (color ASCII art) output device"),
 +    .priv_data_size = sizeof(CACAContext),
 +    .audio_codec    = AV_CODEC_ID_NONE,
 +    .video_codec    = AV_CODEC_ID_RAWVIDEO,
 +    .write_header   = caca_write_header,
 +    .write_packet   = caca_write_packet,
 +    .write_trailer  = caca_write_trailer,
 +    .flags          = AVFMT_NOFILE,
 +    .priv_class     = &caca_class,
 +};
index 48bab37,0000000..43af028
mode 100644,000000..100644
--- /dev/null
@@@ -1,1025 -1,0 +1,1025 @@@
-     { "sample_rate", "set audio sample rate", OFFSET(sample_rate), AV_OPT_TYPE_INT, {.dbl = 0}, 0, INT_MAX, DEC },
-     { "sample_size", "set audio sample size", OFFSET(sample_size), AV_OPT_TYPE_INT, {.dbl = 0}, 0, 16, DEC },
-     { "channels", "set number of audio channels, such as 1 or 2", OFFSET(channels), AV_OPT_TYPE_INT, {.dbl = 0}, 0, INT_MAX, DEC },
-     { "list_devices", "list available devices", OFFSET(list_devices), AV_OPT_TYPE_INT, {.dbl=0}, 0, 1, DEC, "list_devices" },
 +/*
 + * Directshow capture interface
 + * Copyright (c) 2010 Ramiro Polla
 + *
 + * This file is part of FFmpeg.
 + *
 + * FFmpeg is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU Lesser General Public
 + * License as published by the Free Software Foundation; either
 + * version 2.1 of the License, or (at your option) any later version.
 + *
 + * FFmpeg is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 + * Lesser General Public License for more details.
 + *
 + * You should have received a copy of the GNU Lesser General Public
 + * License along with FFmpeg; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 + */
 +
 +#include "libavutil/parseutils.h"
 +#include "libavutil/opt.h"
 +#include "libavformat/internal.h"
 +#include "avdevice.h"
 +#include "dshow_capture.h"
 +
 +struct dshow_ctx {
 +    const AVClass *class;
 +
 +    IGraphBuilder *graph;
 +
 +    char *device_name[2];
 +    int video_device_number;
 +    int audio_device_number;
 +
 +    int   list_options;
 +    int   list_devices;
 +    int   audio_buffer_size;
 +
 +    IBaseFilter *device_filter[2];
 +    IPin        *device_pin[2];
 +    libAVFilter *capture_filter[2];
 +    libAVPin    *capture_pin[2];
 +
 +    HANDLE mutex;
 +    HANDLE event;
 +    AVPacketList *pktl;
 +
 +    int64_t curbufsize;
 +    unsigned int video_frame_num;
 +
 +    IMediaControl *control;
 +
 +    char *video_size;
 +    char *framerate;
 +
 +    int requested_width;
 +    int requested_height;
 +    AVRational requested_framerate;
 +
 +    int sample_rate;
 +    int sample_size;
 +    int channels;
 +};
 +
 +static enum PixelFormat dshow_pixfmt(DWORD biCompression, WORD biBitCount)
 +{
 +    switch(biCompression) {
 +    case MKTAG('U', 'Y', 'V', 'Y'):
 +        return PIX_FMT_UYVY422;
 +    case MKTAG('Y', 'U', 'Y', '2'):
 +        return PIX_FMT_YUYV422;
 +    case MKTAG('I', '4', '2', '0'):
 +        return PIX_FMT_YUV420P;
 +    case BI_BITFIELDS:
 +    case BI_RGB:
 +        switch(biBitCount) { /* 1-8 are untested */
 +            case 1:
 +                return PIX_FMT_MONOWHITE;
 +            case 4:
 +                return PIX_FMT_RGB4;
 +            case 8:
 +                return PIX_FMT_RGB8;
 +            case 16:
 +                return PIX_FMT_RGB555;
 +            case 24:
 +                return PIX_FMT_BGR24;
 +            case 32:
 +                return PIX_FMT_RGB32;
 +        }
 +    }
 +    return PIX_FMT_NONE;
 +}
 +
 +static enum AVCodecID dshow_codecid(DWORD biCompression)
 +{
 +    switch(biCompression) {
 +    case MKTAG('d', 'v', 's', 'd'):
 +        return AV_CODEC_ID_DVVIDEO;
 +    case MKTAG('M', 'J', 'P', 'G'):
 +    case MKTAG('m', 'j', 'p', 'g'):
 +        return AV_CODEC_ID_MJPEG;
 +    }
 +    return AV_CODEC_ID_NONE;
 +}
 +
 +static int
 +dshow_read_close(AVFormatContext *s)
 +{
 +    struct dshow_ctx *ctx = s->priv_data;
 +    AVPacketList *pktl;
 +
 +    if (ctx->control) {
 +        IMediaControl_Stop(ctx->control);
 +        IMediaControl_Release(ctx->control);
 +    }
 +
 +    if (ctx->graph) {
 +        IEnumFilters *fenum;
 +        int r;
 +        r = IGraphBuilder_EnumFilters(ctx->graph, &fenum);
 +        if (r == S_OK) {
 +            IBaseFilter *f;
 +            IEnumFilters_Reset(fenum);
 +            while (IEnumFilters_Next(fenum, 1, &f, NULL) == S_OK) {
 +                if (IGraphBuilder_RemoveFilter(ctx->graph, f) == S_OK)
 +                    IEnumFilters_Reset(fenum); /* When a filter is removed,
 +                                                * the list must be reset. */
 +                IBaseFilter_Release(f);
 +            }
 +            IEnumFilters_Release(fenum);
 +        }
 +        IGraphBuilder_Release(ctx->graph);
 +    }
 +
 +    if (ctx->capture_pin[VideoDevice])
 +        libAVPin_Release(ctx->capture_pin[VideoDevice]);
 +    if (ctx->capture_pin[AudioDevice])
 +        libAVPin_Release(ctx->capture_pin[AudioDevice]);
 +    if (ctx->capture_filter[VideoDevice])
 +        libAVFilter_Release(ctx->capture_filter[VideoDevice]);
 +    if (ctx->capture_filter[AudioDevice])
 +        libAVFilter_Release(ctx->capture_filter[AudioDevice]);
 +
 +    if (ctx->device_pin[VideoDevice])
 +        IPin_Release(ctx->device_pin[VideoDevice]);
 +    if (ctx->device_pin[AudioDevice])
 +        IPin_Release(ctx->device_pin[AudioDevice]);
 +    if (ctx->device_filter[VideoDevice])
 +        IBaseFilter_Release(ctx->device_filter[VideoDevice]);
 +    if (ctx->device_filter[AudioDevice])
 +        IBaseFilter_Release(ctx->device_filter[AudioDevice]);
 +
 +    if (ctx->device_name[0])
 +        av_free(ctx->device_name[0]);
 +    if (ctx->device_name[1])
 +        av_free(ctx->device_name[1]);
 +
 +    if(ctx->mutex)
 +        CloseHandle(ctx->mutex);
 +    if(ctx->event)
 +        CloseHandle(ctx->event);
 +
 +    pktl = ctx->pktl;
 +    while (pktl) {
 +        AVPacketList *next = pktl->next;
 +        av_destruct_packet(&pktl->pkt);
 +        av_free(pktl);
 +        pktl = next;
 +    }
 +
 +    return 0;
 +}
 +
 +static char *dup_wchar_to_utf8(wchar_t *w)
 +{
 +    char *s = NULL;
 +    int l = WideCharToMultiByte(CP_UTF8, 0, w, -1, 0, 0, 0, 0);
 +    s = av_malloc(l);
 +    if (s)
 +        WideCharToMultiByte(CP_UTF8, 0, w, -1, s, l, 0, 0);
 +    return s;
 +}
 +
 +static int shall_we_drop(AVFormatContext *s)
 +{
 +    struct dshow_ctx *ctx = s->priv_data;
 +    const uint8_t dropscore[] = {62, 75, 87, 100};
 +    const int ndropscores = FF_ARRAY_ELEMS(dropscore);
 +    unsigned int buffer_fullness = (ctx->curbufsize*100)/s->max_picture_buffer;
 +
 +    if(dropscore[++ctx->video_frame_num%ndropscores] <= buffer_fullness) {
 +        av_log(s, AV_LOG_ERROR,
 +              "real-time buffer %d%% full! frame dropped!\n", buffer_fullness);
 +        return 1;
 +    }
 +
 +    return 0;
 +}
 +
 +static void
 +callback(void *priv_data, int index, uint8_t *buf, int buf_size, int64_t time)
 +{
 +    AVFormatContext *s = priv_data;
 +    struct dshow_ctx *ctx = s->priv_data;
 +    AVPacketList **ppktl, *pktl_next;
 +
 +//    dump_videohdr(s, vdhdr);
 +
 +    WaitForSingleObject(ctx->mutex, INFINITE);
 +
 +    if(shall_we_drop(s))
 +        goto fail;
 +
 +    pktl_next = av_mallocz(sizeof(AVPacketList));
 +    if(!pktl_next)
 +        goto fail;
 +
 +    if(av_new_packet(&pktl_next->pkt, buf_size) < 0) {
 +        av_free(pktl_next);
 +        goto fail;
 +    }
 +
 +    pktl_next->pkt.stream_index = index;
 +    pktl_next->pkt.pts = time;
 +    memcpy(pktl_next->pkt.data, buf, buf_size);
 +
 +    for(ppktl = &ctx->pktl ; *ppktl ; ppktl = &(*ppktl)->next);
 +    *ppktl = pktl_next;
 +
 +    ctx->curbufsize += buf_size;
 +
 +    SetEvent(ctx->event);
 +    ReleaseMutex(ctx->mutex);
 +
 +    return;
 +fail:
 +    ReleaseMutex(ctx->mutex);
 +    return;
 +}
 +
 +/**
 + * Cycle through available devices using the device enumerator devenum,
 + * retrieve the device with type specified by devtype and return the
 + * pointer to the object found in *pfilter.
 + * If pfilter is NULL, list all device names.
 + */
 +static int
 +dshow_cycle_devices(AVFormatContext *avctx, ICreateDevEnum *devenum,
 +                    enum dshowDeviceType devtype, IBaseFilter **pfilter)
 +{
 +    struct dshow_ctx *ctx = avctx->priv_data;
 +    IBaseFilter *device_filter = NULL;
 +    IEnumMoniker *classenum = NULL;
 +    IMoniker *m = NULL;
 +    const char *device_name = ctx->device_name[devtype];
 +    int skip = (devtype == VideoDevice) ? ctx->video_device_number
 +                                        : ctx->audio_device_number;
 +    int r;
 +
 +    const GUID *device_guid[2] = { &CLSID_VideoInputDeviceCategory,
 +                                   &CLSID_AudioInputDeviceCategory };
 +    const char *devtypename = (devtype == VideoDevice) ? "video" : "audio";
 +
 +    r = ICreateDevEnum_CreateClassEnumerator(devenum, device_guid[devtype],
 +                                             (IEnumMoniker **) &classenum, 0);
 +    if (r != S_OK) {
 +        av_log(avctx, AV_LOG_ERROR, "Could not enumerate %s devices.\n",
 +               devtypename);
 +        return AVERROR(EIO);
 +    }
 +
 +    while (!device_filter && IEnumMoniker_Next(classenum, 1, &m, NULL) == S_OK) {
 +        IPropertyBag *bag = NULL;
 +        char *buf = NULL;
 +        VARIANT var;
 +
 +        r = IMoniker_BindToStorage(m, 0, 0, &IID_IPropertyBag, (void *) &bag);
 +        if (r != S_OK)
 +            goto fail1;
 +
 +        var.vt = VT_BSTR;
 +        r = IPropertyBag_Read(bag, L"FriendlyName", &var, NULL);
 +        if (r != S_OK)
 +            goto fail1;
 +
 +        buf = dup_wchar_to_utf8(var.bstrVal);
 +
 +        if (pfilter) {
 +            if (strcmp(device_name, buf))
 +                goto fail1;
 +
 +            if (!skip--)
 +                IMoniker_BindToObject(m, 0, 0, &IID_IBaseFilter, (void *) &device_filter);
 +        } else {
 +            av_log(avctx, AV_LOG_INFO, " \"%s\"\n", buf);
 +        }
 +
 +fail1:
 +        if (buf)
 +            av_free(buf);
 +        if (bag)
 +            IPropertyBag_Release(bag);
 +        IMoniker_Release(m);
 +    }
 +
 +    IEnumMoniker_Release(classenum);
 +
 +    if (pfilter) {
 +        if (!device_filter) {
 +            av_log(avctx, AV_LOG_ERROR, "Could not find %s device.\n",
 +                   devtypename);
 +            return AVERROR(EIO);
 +        }
 +        *pfilter = device_filter;
 +    }
 +
 +    return 0;
 +}
 +
 +/**
 + * Cycle through available formats using the specified pin,
 + * try to set parameters specified through AVOptions and if successful
 + * return 1 in *pformat_set.
 + * If pformat_set is NULL, list all pin capabilities.
 + */
 +static void
 +dshow_cycle_formats(AVFormatContext *avctx, enum dshowDeviceType devtype,
 +                    IPin *pin, int *pformat_set)
 +{
 +    struct dshow_ctx *ctx = avctx->priv_data;
 +    IAMStreamConfig *config = NULL;
 +    AM_MEDIA_TYPE *type = NULL;
 +    int format_set = 0;
 +    void *caps = NULL;
 +    int i, n, size;
 +
 +    if (IPin_QueryInterface(pin, &IID_IAMStreamConfig, (void **) &config) != S_OK)
 +        return;
 +    if (IAMStreamConfig_GetNumberOfCapabilities(config, &n, &size) != S_OK)
 +        goto end;
 +
 +    caps = av_malloc(size);
 +    if (!caps)
 +        goto end;
 +
 +    for (i = 0; i < n && !format_set; i++) {
 +        IAMStreamConfig_GetStreamCaps(config, i, &type, (void *) caps);
 +
 +#if DSHOWDEBUG
 +        ff_print_AM_MEDIA_TYPE(type);
 +#endif
 +
 +        if (devtype == VideoDevice) {
 +            VIDEO_STREAM_CONFIG_CAPS *vcaps = caps;
 +            BITMAPINFOHEADER *bih;
 +            int64_t *fr;
 +#if DSHOWDEBUG
 +            ff_print_VIDEO_STREAM_CONFIG_CAPS(vcaps);
 +#endif
 +            if (IsEqualGUID(&type->formattype, &FORMAT_VideoInfo)) {
 +                VIDEOINFOHEADER *v = (void *) type->pbFormat;
 +                fr = &v->AvgTimePerFrame;
 +                bih = &v->bmiHeader;
 +            } else if (IsEqualGUID(&type->formattype, &FORMAT_VideoInfo2)) {
 +                VIDEOINFOHEADER2 *v = (void *) type->pbFormat;
 +                fr = &v->AvgTimePerFrame;
 +                bih = &v->bmiHeader;
 +            } else {
 +                goto next;
 +            }
 +            if (!pformat_set) {
 +                av_log(avctx, AV_LOG_INFO, "  min s=%ldx%ld fps=%g max s=%ldx%ld fps=%g\n",
 +                       vcaps->MinOutputSize.cx, vcaps->MinOutputSize.cy,
 +                       1e7 / vcaps->MaxFrameInterval,
 +                       vcaps->MaxOutputSize.cx, vcaps->MaxOutputSize.cy,
 +                       1e7 / vcaps->MinFrameInterval);
 +                continue;
 +            }
 +            if (ctx->framerate) {
 +                int64_t framerate = ((int64_t) ctx->requested_framerate.den*10000000)
 +                                            /  ctx->requested_framerate.num;
 +                if (framerate > vcaps->MaxFrameInterval ||
 +                    framerate < vcaps->MinFrameInterval)
 +                    goto next;
 +                *fr = framerate;
 +            }
 +            if (ctx->video_size) {
 +                if (ctx->requested_width  > vcaps->MaxOutputSize.cx ||
 +                    ctx->requested_width  < vcaps->MinOutputSize.cx ||
 +                    ctx->requested_height > vcaps->MaxOutputSize.cy ||
 +                    ctx->requested_height < vcaps->MinOutputSize.cy)
 +                    goto next;
 +                bih->biWidth  = ctx->requested_width;
 +                bih->biHeight = ctx->requested_height;
 +            }
 +        } else {
 +            AUDIO_STREAM_CONFIG_CAPS *acaps = caps;
 +            WAVEFORMATEX *fx;
 +#if DSHOWDEBUG
 +            ff_print_AUDIO_STREAM_CONFIG_CAPS(acaps);
 +#endif
 +            if (IsEqualGUID(&type->formattype, &FORMAT_WaveFormatEx)) {
 +                fx = (void *) type->pbFormat;
 +            } else {
 +                goto next;
 +            }
 +            if (!pformat_set) {
 +                av_log(avctx, AV_LOG_INFO, "  min ch=%lu bits=%lu rate=%6lu max ch=%lu bits=%lu rate=%6lu\n",
 +                       acaps->MinimumChannels, acaps->MinimumBitsPerSample, acaps->MinimumSampleFrequency,
 +                       acaps->MaximumChannels, acaps->MaximumBitsPerSample, acaps->MaximumSampleFrequency);
 +                continue;
 +            }
 +            if (ctx->sample_rate) {
 +                if (ctx->sample_rate > acaps->MaximumSampleFrequency ||
 +                    ctx->sample_rate < acaps->MinimumSampleFrequency)
 +                    goto next;
 +                fx->nSamplesPerSec = ctx->sample_rate;
 +            }
 +            if (ctx->sample_size) {
 +                if (ctx->sample_size > acaps->MaximumBitsPerSample ||
 +                    ctx->sample_size < acaps->MinimumBitsPerSample)
 +                    goto next;
 +                fx->wBitsPerSample = ctx->sample_size;
 +            }
 +            if (ctx->channels) {
 +                if (ctx->channels > acaps->MaximumChannels ||
 +                    ctx->channels < acaps->MinimumChannels)
 +                    goto next;
 +                fx->nChannels = ctx->channels;
 +            }
 +        }
 +        if (IAMStreamConfig_SetFormat(config, type) != S_OK)
 +            goto next;
 +        format_set = 1;
 +next:
 +        if (type->pbFormat)
 +            CoTaskMemFree(type->pbFormat);
 +        CoTaskMemFree(type);
 +    }
 +end:
 +    IAMStreamConfig_Release(config);
 +    if (caps)
 +        av_free(caps);
 +    if (pformat_set)
 +        *pformat_set = format_set;
 +}
 +
 +/**
 + * Set audio device buffer size in milliseconds (which can directly impact
 + * latency, depending on the device).
 + */
 +static int
 +dshow_set_audio_buffer_size(AVFormatContext *avctx, IPin *pin)
 +{
 +    struct dshow_ctx *ctx = avctx->priv_data;
 +    IAMBufferNegotiation *buffer_negotiation = NULL;
 +    ALLOCATOR_PROPERTIES props = { -1, -1, -1, -1 };
 +    IAMStreamConfig *config = NULL;
 +    AM_MEDIA_TYPE *type = NULL;
 +    int ret = AVERROR(EIO);
 +
 +    if (IPin_QueryInterface(pin, &IID_IAMStreamConfig, (void **) &config) != S_OK)
 +        goto end;
 +    if (IAMStreamConfig_GetFormat(config, &type) != S_OK)
 +        goto end;
 +    if (!IsEqualGUID(&type->formattype, &FORMAT_WaveFormatEx))
 +        goto end;
 +
 +    props.cbBuffer = (((WAVEFORMATEX *) type->pbFormat)->nAvgBytesPerSec)
 +                   * ctx->audio_buffer_size / 1000;
 +
 +    if (IPin_QueryInterface(pin, &IID_IAMBufferNegotiation, (void **) &buffer_negotiation) != S_OK)
 +        goto end;
 +    if (IAMBufferNegotiation_SuggestAllocatorProperties(buffer_negotiation, &props) != S_OK)
 +        goto end;
 +
 +    ret = 0;
 +
 +end:
 +    if (buffer_negotiation)
 +        IAMBufferNegotiation_Release(buffer_negotiation);
 +    if (type) {
 +        if (type->pbFormat)
 +            CoTaskMemFree(type->pbFormat);
 +        CoTaskMemFree(type);
 +    }
 +    if (config)
 +        IAMStreamConfig_Release(config);
 +
 +    return ret;
 +}
 +
 +/**
 + * Cycle through available pins using the device_filter device, of type
 + * devtype, retrieve the first output pin and return the pointer to the
 + * object found in *ppin.
 + * If ppin is NULL, cycle through all pins listing audio/video capabilities.
 + */
 +static int
 +dshow_cycle_pins(AVFormatContext *avctx, enum dshowDeviceType devtype,
 +                 IBaseFilter *device_filter, IPin **ppin)
 +{
 +    struct dshow_ctx *ctx = avctx->priv_data;
 +    IEnumPins *pins = 0;
 +    IPin *device_pin = NULL;
 +    IPin *pin;
 +    int r;
 +
 +    const GUID *mediatype[2] = { &MEDIATYPE_Video, &MEDIATYPE_Audio };
 +    const char *devtypename = (devtype == VideoDevice) ? "video" : "audio";
 +
 +    int set_format = (devtype == VideoDevice && (ctx->video_size || ctx->framerate))
 +                  || (devtype == AudioDevice && (ctx->channels || ctx->sample_rate));
 +    int format_set = 0;
 +
 +    r = IBaseFilter_EnumPins(device_filter, &pins);
 +    if (r != S_OK) {
 +        av_log(avctx, AV_LOG_ERROR, "Could not enumerate pins.\n");
 +        return AVERROR(EIO);
 +    }
 +
 +    if (!ppin) {
 +        av_log(avctx, AV_LOG_INFO, "DirectShow %s device options\n",
 +               devtypename);
 +    }
 +    while (!device_pin && IEnumPins_Next(pins, 1, &pin, NULL) == S_OK) {
 +        IKsPropertySet *p = NULL;
 +        IEnumMediaTypes *types = NULL;
 +        PIN_INFO info = {0};
 +        AM_MEDIA_TYPE *type;
 +        GUID category;
 +        DWORD r2;
 +
 +        IPin_QueryPinInfo(pin, &info);
 +        IBaseFilter_Release(info.pFilter);
 +
 +        if (info.dir != PINDIR_OUTPUT)
 +            goto next;
 +        if (IPin_QueryInterface(pin, &IID_IKsPropertySet, (void **) &p) != S_OK)
 +            goto next;
 +        if (IKsPropertySet_Get(p, &AMPROPSETID_Pin, AMPROPERTY_PIN_CATEGORY,
 +                               NULL, 0, &category, sizeof(GUID), &r2) != S_OK)
 +            goto next;
 +        if (!IsEqualGUID(&category, &PIN_CATEGORY_CAPTURE))
 +            goto next;
 +
 +        if (!ppin) {
 +            char *buf = dup_wchar_to_utf8(info.achName);
 +            av_log(avctx, AV_LOG_INFO, " Pin \"%s\"\n", buf);
 +            av_free(buf);
 +            dshow_cycle_formats(avctx, devtype, pin, NULL);
 +            goto next;
 +        }
 +        if (set_format) {
 +            dshow_cycle_formats(avctx, devtype, pin, &format_set);
 +            if (!format_set) {
 +                goto next;
 +            }
 +        }
 +        if (devtype == AudioDevice && ctx->audio_buffer_size) {
 +            if (dshow_set_audio_buffer_size(avctx, pin) < 0)
 +                goto next;
 +        }
 +
 +        if (IPin_EnumMediaTypes(pin, &types) != S_OK)
 +            goto next;
 +
 +        IEnumMediaTypes_Reset(types);
 +        while (!device_pin && IEnumMediaTypes_Next(types, 1, &type, NULL) == S_OK) {
 +            if (IsEqualGUID(&type->majortype, mediatype[devtype])) {
 +                device_pin = pin;
 +                goto next;
 +            }
 +            CoTaskMemFree(type);
 +        }
 +
 +next:
 +        if (types)
 +            IEnumMediaTypes_Release(types);
 +        if (p)
 +            IKsPropertySet_Release(p);
 +        if (device_pin != pin)
 +            IPin_Release(pin);
 +    }
 +
 +    IEnumPins_Release(pins);
 +
 +    if (ppin) {
 +        if (set_format && !format_set) {
 +            av_log(avctx, AV_LOG_ERROR, "Could not set %s options\n", devtypename);
 +            return AVERROR(EIO);
 +        }
 +        if (!device_pin) {
 +            av_log(avctx, AV_LOG_ERROR,
 +                "Could not find output pin from %s capture device.\n", devtypename);
 +            return AVERROR(EIO);
 +        }
 +        *ppin = device_pin;
 +    }
 +
 +    return 0;
 +}
 +
 +/**
 + * List options for device with type devtype.
 + *
 + * @param devenum device enumerator used for accessing the device
 + */
 +static int
 +dshow_list_device_options(AVFormatContext *avctx, ICreateDevEnum *devenum,
 +                          enum dshowDeviceType devtype)
 +{
 +    struct dshow_ctx *ctx = avctx->priv_data;
 +    IBaseFilter *device_filter = NULL;
 +    int r;
 +
 +    if ((r = dshow_cycle_devices(avctx, devenum, devtype, &device_filter)) < 0)
 +        return r;
 +    ctx->device_filter[devtype] = device_filter;
 +    if ((r = dshow_cycle_pins(avctx, devtype, device_filter, NULL)) < 0)
 +        return r;
 +
 +    return 0;
 +}
 +
 +static int
 +dshow_open_device(AVFormatContext *avctx, ICreateDevEnum *devenum,
 +                  enum dshowDeviceType devtype)
 +{
 +    struct dshow_ctx *ctx = avctx->priv_data;
 +    IBaseFilter *device_filter = NULL;
 +    IGraphBuilder *graph = ctx->graph;
 +    IPin *device_pin = NULL;
 +    libAVPin *capture_pin = NULL;
 +    libAVFilter *capture_filter = NULL;
 +    int ret = AVERROR(EIO);
 +    int r;
 +
 +    const wchar_t *filter_name[2] = { L"Audio capture filter", L"Video capture filter" };
 +
 +    if ((r = dshow_cycle_devices(avctx, devenum, devtype, &device_filter)) < 0) {
 +        ret = r;
 +        goto error;
 +    }
 +
 +    ctx->device_filter [devtype] = device_filter;
 +
 +    r = IGraphBuilder_AddFilter(graph, device_filter, NULL);
 +    if (r != S_OK) {
 +        av_log(avctx, AV_LOG_ERROR, "Could not add device filter to graph.\n");
 +        goto error;
 +    }
 +
 +    if ((r = dshow_cycle_pins(avctx, devtype, device_filter, &device_pin)) < 0) {
 +        ret = r;
 +        goto error;
 +    }
 +    ctx->device_pin[devtype] = device_pin;
 +
 +    capture_filter = libAVFilter_Create(avctx, callback, devtype);
 +    if (!capture_filter) {
 +        av_log(avctx, AV_LOG_ERROR, "Could not create grabber filter.\n");
 +        goto error;
 +    }
 +    ctx->capture_filter[devtype] = capture_filter;
 +
 +    r = IGraphBuilder_AddFilter(graph, (IBaseFilter *) capture_filter,
 +                                filter_name[devtype]);
 +    if (r != S_OK) {
 +        av_log(avctx, AV_LOG_ERROR, "Could not add capture filter to graph\n");
 +        goto error;
 +    }
 +
 +    libAVPin_AddRef(capture_filter->pin);
 +    capture_pin = capture_filter->pin;
 +    ctx->capture_pin[devtype] = capture_pin;
 +
 +    r = IGraphBuilder_ConnectDirect(graph, device_pin, (IPin *) capture_pin, NULL);
 +    if (r != S_OK) {
 +        av_log(avctx, AV_LOG_ERROR, "Could not connect pins\n");
 +        goto error;
 +    }
 +
 +    ret = 0;
 +
 +error:
 +    return ret;
 +}
 +
 +static enum AVCodecID waveform_codec_id(enum AVSampleFormat sample_fmt)
 +{
 +    switch (sample_fmt) {
 +    case AV_SAMPLE_FMT_U8:  return AV_CODEC_ID_PCM_U8;
 +    case AV_SAMPLE_FMT_S16: return AV_CODEC_ID_PCM_S16LE;
 +    case AV_SAMPLE_FMT_S32: return AV_CODEC_ID_PCM_S32LE;
 +    default:                return AV_CODEC_ID_NONE; /* Should never happen. */
 +    }
 +}
 +
 +static enum AVSampleFormat sample_fmt_bits_per_sample(int bits)
 +{
 +    switch (bits) {
 +    case 8:  return AV_SAMPLE_FMT_U8;
 +    case 16: return AV_SAMPLE_FMT_S16;
 +    case 32: return AV_SAMPLE_FMT_S32;
 +    default: return AV_SAMPLE_FMT_NONE; /* Should never happen. */
 +    }
 +}
 +
 +static int
 +dshow_add_device(AVFormatContext *avctx,
 +                 enum dshowDeviceType devtype)
 +{
 +    struct dshow_ctx *ctx = avctx->priv_data;
 +    AM_MEDIA_TYPE type;
 +    AVCodecContext *codec;
 +    AVStream *st;
 +    int ret = AVERROR(EIO);
 +
 +    st = avformat_new_stream(avctx, NULL);
 +    if (!st) {
 +        ret = AVERROR(ENOMEM);
 +        goto error;
 +    }
 +    st->id = devtype;
 +
 +    ctx->capture_filter[devtype]->stream_index = st->index;
 +
 +    libAVPin_ConnectionMediaType(ctx->capture_pin[devtype], &type);
 +
 +    codec = st->codec;
 +    if (devtype == VideoDevice) {
 +        BITMAPINFOHEADER *bih = NULL;
 +        AVRational time_base;
 +
 +        if (IsEqualGUID(&type.formattype, &FORMAT_VideoInfo)) {
 +            VIDEOINFOHEADER *v = (void *) type.pbFormat;
 +            time_base = (AVRational) { v->AvgTimePerFrame, 10000000 };
 +            bih = &v->bmiHeader;
 +        } else if (IsEqualGUID(&type.formattype, &FORMAT_VideoInfo2)) {
 +            VIDEOINFOHEADER2 *v = (void *) type.pbFormat;
 +            time_base = (AVRational) { v->AvgTimePerFrame, 10000000 };
 +            bih = &v->bmiHeader;
 +        }
 +        if (!bih) {
 +            av_log(avctx, AV_LOG_ERROR, "Could not get media type.\n");
 +            goto error;
 +        }
 +
 +        codec->time_base  = time_base;
 +        codec->codec_type = AVMEDIA_TYPE_VIDEO;
 +        codec->width      = bih->biWidth;
 +        codec->height     = bih->biHeight;
 +        codec->pix_fmt    = dshow_pixfmt(bih->biCompression, bih->biBitCount);
 +        if (codec->pix_fmt == PIX_FMT_NONE) {
 +            codec->codec_id = dshow_codecid(bih->biCompression);
 +            if (codec->codec_id == AV_CODEC_ID_NONE) {
 +                av_log(avctx, AV_LOG_ERROR, "Unknown compression type. "
 +                                 "Please report verbose (-v 9) debug information.\n");
 +                dshow_read_close(avctx);
 +                return AVERROR_PATCHWELCOME;
 +            }
 +            codec->bits_per_coded_sample = bih->biBitCount;
 +        } else {
 +            codec->codec_id = AV_CODEC_ID_RAWVIDEO;
 +            if (bih->biCompression == BI_RGB || bih->biCompression == BI_BITFIELDS) {
 +                codec->bits_per_coded_sample = bih->biBitCount;
 +                codec->extradata = av_malloc(9 + FF_INPUT_BUFFER_PADDING_SIZE);
 +                if (codec->extradata) {
 +                    codec->extradata_size = 9;
 +                    memcpy(codec->extradata, "BottomUp", 9);
 +                }
 +            }
 +        }
 +    } else {
 +        WAVEFORMATEX *fx = NULL;
 +
 +        if (IsEqualGUID(&type.formattype, &FORMAT_WaveFormatEx)) {
 +            fx = (void *) type.pbFormat;
 +        }
 +        if (!fx) {
 +            av_log(avctx, AV_LOG_ERROR, "Could not get media type.\n");
 +            goto error;
 +        }
 +
 +        codec->codec_type  = AVMEDIA_TYPE_AUDIO;
 +        codec->sample_fmt  = sample_fmt_bits_per_sample(fx->wBitsPerSample);
 +        codec->codec_id    = waveform_codec_id(codec->sample_fmt);
 +        codec->sample_rate = fx->nSamplesPerSec;
 +        codec->channels    = fx->nChannels;
 +    }
 +
 +    avpriv_set_pts_info(st, 64, 1, 10000000);
 +
 +    ret = 0;
 +
 +error:
 +    return ret;
 +}
 +
 +static int parse_device_name(AVFormatContext *avctx)
 +{
 +    struct dshow_ctx *ctx = avctx->priv_data;
 +    char **device_name = ctx->device_name;
 +    char *name = av_strdup(avctx->filename);
 +    char *tmp = name;
 +    int ret = 1;
 +    char *type;
 +
 +    while ((type = strtok(tmp, "="))) {
 +        char *token = strtok(NULL, ":");
 +        tmp = NULL;
 +
 +        if        (!strcmp(type, "video")) {
 +            device_name[0] = token;
 +        } else if (!strcmp(type, "audio")) {
 +            device_name[1] = token;
 +        } else {
 +            device_name[0] = NULL;
 +            device_name[1] = NULL;
 +            break;
 +        }
 +    }
 +
 +    if (!device_name[0] && !device_name[1]) {
 +        ret = 0;
 +    } else {
 +        if (device_name[0])
 +            device_name[0] = av_strdup(device_name[0]);
 +        if (device_name[1])
 +            device_name[1] = av_strdup(device_name[1]);
 +    }
 +
 +    av_free(name);
 +    return ret;
 +}
 +
 +static int dshow_read_header(AVFormatContext *avctx)
 +{
 +    struct dshow_ctx *ctx = avctx->priv_data;
 +    IGraphBuilder *graph = NULL;
 +    ICreateDevEnum *devenum = NULL;
 +    IMediaControl *control = NULL;
 +    int ret = AVERROR(EIO);
 +    int r;
 +
 +    if (!ctx->list_devices && !parse_device_name(avctx)) {
 +        av_log(avctx, AV_LOG_ERROR, "Malformed dshow input string.\n");
 +        goto error;
 +    }
 +
 +    if (ctx->video_size) {
 +        r = av_parse_video_size(&ctx->requested_width, &ctx->requested_height, ctx->video_size);
 +        if (r < 0) {
 +            av_log(avctx, AV_LOG_ERROR, "Could not parse video size '%s'.\n", ctx->video_size);
 +            goto error;
 +        }
 +    }
 +    if (ctx->framerate) {
 +        r = av_parse_video_rate(&ctx->requested_framerate, ctx->framerate);
 +        if (r < 0) {
 +            av_log(avctx, AV_LOG_ERROR, "Could not parse framerate '%s'.\n", ctx->framerate);
 +            goto error;
 +        }
 +    }
 +
 +    CoInitialize(0);
 +
 +    r = CoCreateInstance(&CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,
 +                         &IID_IGraphBuilder, (void **) &graph);
 +    if (r != S_OK) {
 +        av_log(avctx, AV_LOG_ERROR, "Could not create capture graph.\n");
 +        goto error;
 +    }
 +    ctx->graph = graph;
 +
 +    r = CoCreateInstance(&CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,
 +                         &IID_ICreateDevEnum, (void **) &devenum);
 +    if (r != S_OK) {
 +        av_log(avctx, AV_LOG_ERROR, "Could not enumerate system devices.\n");
 +        goto error;
 +    }
 +
 +    if (ctx->list_devices) {
 +        av_log(avctx, AV_LOG_INFO, "DirectShow video devices\n");
 +        dshow_cycle_devices(avctx, devenum, VideoDevice, NULL);
 +        av_log(avctx, AV_LOG_INFO, "DirectShow audio devices\n");
 +        dshow_cycle_devices(avctx, devenum, AudioDevice, NULL);
 +        ret = AVERROR_EXIT;
 +        goto error;
 +    }
 +    if (ctx->list_options) {
 +        if (ctx->device_name[VideoDevice])
 +            dshow_list_device_options(avctx, devenum, VideoDevice);
 +        if (ctx->device_name[AudioDevice])
 +            dshow_list_device_options(avctx, devenum, AudioDevice);
 +        ret = AVERROR_EXIT;
 +        goto error;
 +    }
 +
 +    if (ctx->device_name[VideoDevice]) {
 +        ret = dshow_open_device(avctx, devenum, VideoDevice);
 +        if (ret < 0)
 +            goto error;
 +        ret = dshow_add_device(avctx, VideoDevice);
 +        if (ret < 0)
 +            goto error;
 +    }
 +    if (ctx->device_name[AudioDevice]) {
 +        ret = dshow_open_device(avctx, devenum, AudioDevice);
 +        if (ret < 0)
 +            goto error;
 +        ret = dshow_add_device(avctx, AudioDevice);
 +        if (ret < 0)
 +            goto error;
 +    }
 +
 +    ctx->mutex = CreateMutex(NULL, 0, NULL);
 +    if (!ctx->mutex) {
 +        av_log(avctx, AV_LOG_ERROR, "Could not create Mutex\n");
 +        goto error;
 +    }
 +    ctx->event = CreateEvent(NULL, 1, 0, NULL);
 +    if (!ctx->event) {
 +        av_log(avctx, AV_LOG_ERROR, "Could not create Event\n");
 +        goto error;
 +    }
 +
 +    r = IGraphBuilder_QueryInterface(graph, &IID_IMediaControl, (void **) &control);
 +    if (r != S_OK) {
 +        av_log(avctx, AV_LOG_ERROR, "Could not get media control.\n");
 +        goto error;
 +    }
 +    ctx->control = control;
 +
 +    r = IMediaControl_Run(control);
 +    if (r == S_FALSE) {
 +        OAFilterState pfs;
 +        r = IMediaControl_GetState(control, 0, &pfs);
 +    }
 +    if (r != S_OK) {
 +        av_log(avctx, AV_LOG_ERROR, "Could not run filter\n");
 +        goto error;
 +    }
 +
 +    ret = 0;
 +
 +error:
 +
 +    if (ret < 0)
 +        dshow_read_close(avctx);
 +
 +    if (devenum)
 +        ICreateDevEnum_Release(devenum);
 +
 +    return ret;
 +}
 +
 +static int dshow_read_packet(AVFormatContext *s, AVPacket *pkt)
 +{
 +    struct dshow_ctx *ctx = s->priv_data;
 +    AVPacketList *pktl = NULL;
 +
 +    while (!pktl) {
 +        WaitForSingleObject(ctx->mutex, INFINITE);
 +        pktl = ctx->pktl;
 +        if (pktl) {
 +            *pkt = pktl->pkt;
 +            ctx->pktl = ctx->pktl->next;
 +            av_free(pktl);
 +            ctx->curbufsize -= pkt->size;
 +        }
 +        ResetEvent(ctx->event);
 +        ReleaseMutex(ctx->mutex);
 +        if (!pktl) {
 +            if (s->flags & AVFMT_FLAG_NONBLOCK) {
 +                return AVERROR(EAGAIN);
 +            } else {
 +                WaitForSingleObject(ctx->event, INFINITE);
 +            }
 +        }
 +    }
 +
 +    return pkt->size;
 +}
 +
 +#define OFFSET(x) offsetof(struct dshow_ctx, x)
 +#define DEC AV_OPT_FLAG_DECODING_PARAM
 +static const AVOption options[] = {
 +    { "video_size", "set video size given a string such as 640x480 or hd720.", OFFSET(video_size), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC },
 +    { "framerate", "set video frame rate", OFFSET(framerate), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC },
-     { "list_options", "list available options for specified device", OFFSET(list_options), AV_OPT_TYPE_INT, {.dbl=0}, 0, 1, DEC, "list_options" },
++    { "sample_rate", "set audio sample rate", OFFSET(sample_rate), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, DEC },
++    { "sample_size", "set audio sample size", OFFSET(sample_size), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 16, DEC },
++    { "channels", "set number of audio channels, such as 1 or 2", OFFSET(channels), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, DEC },
++    { "list_devices", "list available devices", OFFSET(list_devices), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, DEC, "list_devices" },
 +    { "true", "", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, DEC, "list_devices" },
 +    { "false", "", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, DEC, "list_devices" },
-     { "video_device_number", "set video device number for devices with same name (starts at 0)", OFFSET(video_device_number), AV_OPT_TYPE_INT, {.dbl = 0}, 0, INT_MAX, DEC },
-     { "audio_device_number", "set audio device number for devices with same name (starts at 0)", OFFSET(audio_device_number), AV_OPT_TYPE_INT, {.dbl = 0}, 0, INT_MAX, DEC },
-     { "audio_buffer_size", "set audio device buffer latency size in milliseconds (default is the device's default)", OFFSET(audio_buffer_size), AV_OPT_TYPE_INT, {.dbl = 0}, 0, INT_MAX, DEC },
++    { "list_options", "list available options for specified device", OFFSET(list_options), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, DEC, "list_options" },
 +    { "true", "", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, DEC, "list_options" },
 +    { "false", "", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, DEC, "list_options" },
++    { "video_device_number", "set video device number for devices with same name (starts at 0)", OFFSET(video_device_number), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, DEC },
++    { "audio_device_number", "set audio device number for devices with same name (starts at 0)", OFFSET(audio_device_number), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, DEC },
++    { "audio_buffer_size", "set audio device buffer latency size in milliseconds (default is the device's default)", OFFSET(audio_buffer_size), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, DEC },
 +    { NULL },
 +};
 +
 +static const AVClass dshow_class = {
 +    .class_name = "DirectShow indev",
 +    .item_name  = av_default_item_name,
 +    .option     = options,
 +    .version    = LIBAVUTIL_VERSION_INT,
 +};
 +
 +AVInputFormat ff_dshow_demuxer = {
 +    .name           = "dshow",
 +    .long_name      = NULL_IF_CONFIG_SMALL("DirectShow capture"),
 +    .priv_data_size = sizeof(struct dshow_ctx),
 +    .read_header    = dshow_read_header,
 +    .read_packet    = dshow_read_packet,
 +    .read_close     = dshow_read_close,
 +    .flags          = AVFMT_NOFILE,
 +    .priv_class     = &dshow_class,
 +};
Simple merge
index f21499b,0000000..8c9a39f
mode 100644,000000..100644
--- /dev/null
@@@ -1,466 -1,0 +1,466 @@@
-     { "dvtype", "override autodetection of DV/HDV", offsetof(struct iec61883_data, type), AV_OPT_TYPE_INT, {.dbl = IEC61883_AUTO}, IEC61883_AUTO, IEC61883_HDV, AV_OPT_FLAG_DECODING_PARAM, "dvtype" },
 +/*
 + * Copyright (c) 2012 Georg Lippitsch <georg.lippitsch@gmx.at>
 + *
 + * This file is part of FFmpeg.
 + *
 + * FFmpeg is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU Lesser General Public
 + * License as published by the Free Software Foundation; either
 + * version 2.1 of the License, or (at your option) any later version.
 + *
 + * FFmpeg is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 + * Lesser General Public License for more details.
 + *
 + * You should have received a copy of the GNU Lesser General Public
 + * License along with FFmpeg; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 + */
 +
 +/**
 + * @file
 + * libiec61883 interface
 + */
 +
 +#include <sys/poll.h>
 +#include <libraw1394/raw1394.h>
 +#include <libavc1394/avc1394.h>
 +#include <libavc1394/rom1394.h>
 +#include <libiec61883/iec61883.h>
 +#include "libavformat/dv.h"
 +#include "libavformat/mpegts.h"
 +#include "libavutil/opt.h"
 +#include "avdevice.h"
 +
 +#define THREADS HAVE_PTHREADS
 +
 +#if THREADS
 +#include <pthread.h>
 +#endif
 +
 +#define MOTDCT_SPEC_ID      0x00005068
 +#define IEC61883_AUTO       0
 +#define IEC61883_DV         1
 +#define IEC61883_HDV        2
 +
 +/**
 + * For DV, one packet corresponds exactly to one frame.
 + * For HDV, these are MPEG2 transport stream packets.
 + * The queue is implemented as linked list.
 + */
 +typedef struct DVPacket {
 +    uint8_t *buf;                       ///< actual buffer data
 +    int len;                            ///< size of buffer allocated
 +    struct DVPacket *next;              ///< next DVPacket
 +} DVPacket;
 +
 +struct iec61883_data {
 +    AVClass *class;
 +    raw1394handle_t raw1394;            ///< handle for libraw1394
 +    iec61883_dv_fb_t iec61883_dv;       ///< handle for libiec61883 when used with DV
 +    iec61883_mpeg2_t iec61883_mpeg2;    ///< handle for libiec61883 when used with HDV
 +
 +    DVDemuxContext *dv_demux;           ///< generic DV muxing/demuxing context
 +    MpegTSContext *mpeg_demux;          ///< generic HDV muxing/demuxing context
 +
 +    DVPacket *queue_first;              ///< first element of packet queue
 +    DVPacket *queue_last;               ///< last element of packet queue
 +
 +    int packets;                        ///< Number of packets queued
 +    int max_packets;                    ///< Max. number of packets in queue
 +
 +    int bandwidth;                      ///< returned by libiec61883
 +    int channel;                        ///< returned by libiec61883
 +    int input_port;                     ///< returned by libiec61883
 +    int type;                           ///< Stream type, to distinguish DV/HDV
 +    int node;                           ///< returned by libiec61883
 +    int output_port;                    ///< returned by libiec61883
 +    int thread_loop;                    ///< Condition for thread while-loop
 +    int receiving;                      ///< True as soon data from device available
 +    int receive_error;                  ///< Set in receive task in case of error
 +    int eof;                            ///< True as soon as no more data available
 +
 +    struct pollfd raw1394_poll;         ///< to poll for new data from libraw1394
 +
 +    /** Parse function for DV/HDV differs, so this is set before packets arrive */
 +    int (*parse_queue)(struct iec61883_data *dv, AVPacket *pkt);
 +
 +#if THREADS
 +    pthread_t receive_task_thread;
 +    pthread_mutex_t mutex;
 +    pthread_cond_t cond;
 +#endif
 +};
 +
 +static int iec61883_callback(unsigned char *data, int length,
 +                             int complete, void *callback_data)
 +{
 +    struct iec61883_data *dv = callback_data;
 +    DVPacket *packet;
 +    int ret;
 +
 +#ifdef THREADS
 +    pthread_mutex_lock(&dv->mutex);
 +#endif
 +
 +    if (dv->packets >= dv->max_packets) {
 +        av_log(NULL, AV_LOG_ERROR, "DV packet queue overrun, dropping.\n");
 +        ret = 0;
 +        goto exit;
 +    }
 +
 +    packet = av_mallocz(sizeof(*packet));
 +    if (!packet) {
 +        ret = -1;
 +        goto exit;
 +    }
 +
 +    packet->buf = av_malloc(length);
 +    if (!packet->buf) {
 +        ret = -1;
 +        goto exit;
 +    }
 +    packet->len = length;
 +
 +    memcpy(packet->buf, data, length);
 +
 +    if (dv->queue_first) {
 +        dv->queue_last->next = packet;
 +        dv->queue_last = packet;
 +    } else {
 +        dv->queue_first = packet;
 +        dv->queue_last = packet;
 +    }
 +    dv->packets++;
 +
 +    ret = 0;
 +
 +exit:
 +#ifdef THREADS
 +    pthread_cond_signal(&dv->cond);
 +    pthread_mutex_unlock(&dv->mutex);
 +#endif
 +    return ret;
 +}
 +
 +static void *iec61883_receive_task(void *opaque)
 +{
 +    struct iec61883_data *dv = (struct iec61883_data *)opaque;
 +    int result;
 +
 +#ifdef THREADS
 +    while (dv->thread_loop)
 +#endif
 +    {
 +        while ((result = poll(&dv->raw1394_poll, 1, 200)) < 0) {
 +            if (!(errno == EAGAIN || errno == EINTR)) {
 +                av_log(NULL, AV_LOG_ERROR, "Raw1394 poll error occurred.\n");
 +                dv->receive_error = AVERROR(EIO);
 +                return NULL;
 +            }
 +        }
 +        if (result > 0 && ((dv->raw1394_poll.revents & POLLIN)
 +                           || (dv->raw1394_poll.revents & POLLPRI))) {
 +            dv->receiving = 1;
 +            raw1394_loop_iterate(dv->raw1394);
 +        } else if (dv->receiving) {
 +            av_log(NULL, AV_LOG_ERROR, "No more input data available\n");
 +#ifdef THREADS
 +            pthread_mutex_lock(&dv->mutex);
 +            dv->eof = 1;
 +            pthread_cond_signal(&dv->cond);
 +            pthread_mutex_unlock(&dv->mutex);
 +#else
 +            dv->eof = 1;
 +#endif
 +            return NULL;
 +        }
 +    }
 +
 +    return NULL;
 +}
 +
 +static int iec61883_parse_queue_dv(struct iec61883_data *dv, AVPacket *pkt)
 +{
 +    DVPacket *packet;
 +    int size;
 +
 +    size = avpriv_dv_get_packet(dv->dv_demux, pkt);
 +    if (size > 0)
 +        return size;
 +
 +    packet = dv->queue_first;
 +    if (!packet)
 +        return -1;
 +
 +    size = avpriv_dv_produce_packet(dv->dv_demux, pkt,
 +                                    packet->buf, packet->len, -1);
 +    pkt->destruct = av_destruct_packet;
 +    dv->queue_first = packet->next;
 +    av_free(packet);
 +    dv->packets--;
 +
 +    if (size > 0)
 +        return size;
 +
 +    return -1;
 +}
 +
 +static int iec61883_parse_queue_hdv(struct iec61883_data *dv, AVPacket *pkt)
 +{
 +    DVPacket *packet;
 +    int size;
 +
 +    while (dv->queue_first) {
 +        packet = dv->queue_first;
 +        size = ff_mpegts_parse_packet(dv->mpeg_demux, pkt, packet->buf,
 +                                      packet->len);
 +        dv->queue_first = packet->next;
 +        av_free(packet->buf);
 +        av_free(packet);
 +        dv->packets--;
 +
 +        if (size > 0)
 +            return size;
 +    }
 +
 +    return -1;
 +}
 +
 +static int iec61883_read_header(AVFormatContext *context)
 +{
 +    struct iec61883_data *dv = context->priv_data;
 +    struct raw1394_portinfo pinf[16];
 +    rom1394_directory rom_dir;
 +    char *endptr;
 +    int inport;
 +    int nb_ports;
 +    int port = -1;
 +    int response;
 +    int i, j = 0;
 +
 +    dv->input_port = -1;
 +    dv->output_port = -1;
 +    dv->channel = -1;
 +
 +    dv->raw1394 = raw1394_new_handle();
 +
 +    if (!dv->raw1394) {
 +        av_log(context, AV_LOG_ERROR, "Failed to open IEEE1394 interface.\n");
 +        return AVERROR(EIO);
 +    }
 +
 +    if ((nb_ports = raw1394_get_port_info(dv->raw1394, pinf, 16)) < 0) {
 +        av_log(context, AV_LOG_ERROR, "Failed to get number of IEEE1394 ports.\n");
 +        goto fail;
 +    }
 +
 +    inport = strtol(context->filename, &endptr, 10);
 +    if (endptr != context->filename && *endptr == '\0') {
 +        av_log(context, AV_LOG_INFO, "Selecting IEEE1394 port: %d\n", inport);
 +        j = inport;
 +        nb_ports = inport + 1;
 +    } else if (strcmp(context->filename, "auto")) {
 +        av_log(context, AV_LOG_ERROR, "Invalid input \"%s\", you should specify "
 +               "\"auto\" for auto-detection, or the port number.\n", context->filename);
 +        goto fail;
 +    }
 +
 +    /* Select first AV/C tape recorder player node */
 +
 +    for (; j < nb_ports && port==-1; ++j) {
 +        if (raw1394_set_port(dv->raw1394, j)) {
 +            av_log(context, AV_LOG_ERROR, "Failed setting IEEE1394 port.\n");
 +            goto fail;
 +        }
 +        for (i=0; i<raw1394_get_nodecount(dv->raw1394); ++i) {
 +            if (rom1394_get_directory(dv->raw1394, i, &rom_dir) < 0)
 +                continue;
 +            if (((rom1394_get_node_type(&rom_dir) == ROM1394_NODE_TYPE_AVC) &&
 +                 avc1394_check_subunit_type(dv->raw1394, i, AVC1394_SUBUNIT_TYPE_VCR)) ||
 +                (rom_dir.unit_spec_id == MOTDCT_SPEC_ID)) {
 +                rom1394_free_directory(&rom_dir);
 +                dv->node = i;
 +                port = j;
 +                break;
 +            }
 +            rom1394_free_directory(&rom_dir);
 +        }
 +    }
 +
 +    if (port == -1) {
 +        av_log(context, AV_LOG_ERROR, "No AV/C devices found.\n");
 +        goto fail;
 +    }
 +
 +    /* Find out if device is DV or HDV */
 +
 +    if (dv->type == IEC61883_AUTO) {
 +        response = avc1394_transaction(dv->raw1394, dv->node,
 +                                       AVC1394_CTYPE_STATUS |
 +                                       AVC1394_SUBUNIT_TYPE_TAPE_RECORDER |
 +                                       AVC1394_SUBUNIT_ID_0 |
 +                                       AVC1394_VCR_COMMAND_OUTPUT_SIGNAL_MODE |
 +                                       0xFF, 2);
 +        response = AVC1394_GET_OPERAND0(response);
 +        dv->type = (response == 0x10 || response == 0x90 || response == 0x1A || response == 0x9A) ?
 +            IEC61883_HDV : IEC61883_DV;
 +    }
 +
 +    /* Connect to device, and do initialization */
 +
 +    dv->channel = iec61883_cmp_connect(dv->raw1394, dv->node, &dv->output_port,
 +                                       raw1394_get_local_id(dv->raw1394),
 +                                       &dv->input_port, &dv->bandwidth);
 +
 +    if (dv->channel < 0)
 +        dv->channel = 63;
 +
 +    if (!dv->max_packets)
 +        dv->max_packets = 100;
 +
 +    if (dv->type == IEC61883_HDV) {
 +
 +        /* Init HDV receive */
 +
 +        avformat_new_stream(context, NULL);
 +
 +        dv->mpeg_demux = ff_mpegts_parse_open(context);
 +        if (!dv->mpeg_demux)
 +            goto fail;
 +
 +        dv->parse_queue = iec61883_parse_queue_hdv;
 +
 +        dv->iec61883_mpeg2 = iec61883_mpeg2_recv_init(dv->raw1394,
 +                                                      (iec61883_mpeg2_recv_t)iec61883_callback,
 +                                                      dv);
 +
 +        dv->max_packets *= 766;
 +    } else {
 +
 +        /* Init DV receive */
 +
 +        dv->dv_demux = avpriv_dv_init_demux(context);
 +        if (!dv->dv_demux)
 +            goto fail;
 +
 +        dv->parse_queue = iec61883_parse_queue_dv;
 +
 +        dv->iec61883_dv = iec61883_dv_fb_init(dv->raw1394, iec61883_callback, dv);
 +    }
 +
 +    dv->raw1394_poll.fd = raw1394_get_fd(dv->raw1394);
 +    dv->raw1394_poll.events = POLLIN | POLLERR | POLLHUP | POLLPRI;
 +
 +    /* Actually start receiving */
 +
 +    if (dv->type == IEC61883_HDV)
 +        iec61883_mpeg2_recv_start(dv->iec61883_mpeg2, dv->channel);
 +    else
 +        iec61883_dv_fb_start(dv->iec61883_dv, dv->channel);
 +
 +#if THREADS
 +    dv->thread_loop = 1;
 +    pthread_mutex_init(&dv->mutex, NULL);
 +    pthread_cond_init(&dv->cond, NULL);
 +    pthread_create(&dv->receive_task_thread, NULL, iec61883_receive_task, dv);
 +#endif
 +
 +    return 0;
 +
 +fail:
 +    raw1394_destroy_handle(dv->raw1394);
 +    return AVERROR(EIO);
 +}
 +
 +static int iec61883_read_packet(AVFormatContext *context, AVPacket *pkt)
 +{
 +    struct iec61883_data *dv = context->priv_data;
 +    int size;
 +
 +    /**
 +     * Try to parse frames from queue
 +     */
 +
 +#ifdef THREADS
 +    pthread_mutex_lock(&dv->mutex);
 +    while ((size = dv->parse_queue(dv, pkt)) == -1)
 +        if (!dv->eof)
 +            pthread_cond_wait(&dv->cond, &dv->mutex);
 +        else
 +            break;
 +    pthread_mutex_unlock(&dv->mutex);
 +#else
 +    int result;
 +    while ((size = dv->parse_queue(dv, pkt)) == -1) {
 +        iec61883_receive_task((void *)dv);
 +        if (dv->receive_error)
 +            return dv->receive_error;
 +    }
 +#endif
 +
 +    return size;
 +}
 +
 +static int iec61883_close(AVFormatContext *context)
 +{
 +    struct iec61883_data *dv = context->priv_data;
 +
 +#if THREADS
 +    dv->thread_loop = 0;
 +    pthread_join(dv->receive_task_thread, NULL);
 +    pthread_cond_destroy(&dv->cond);
 +    pthread_mutex_destroy(&dv->mutex);
 +#endif
 +
 +    if (dv->type == IEC61883_HDV) {
 +        iec61883_mpeg2_recv_stop(dv->iec61883_mpeg2);
 +        iec61883_mpeg2_close(dv->iec61883_mpeg2);
 +        ff_mpegts_parse_close(dv->mpeg_demux);
 +    } else {
 +        iec61883_dv_fb_stop(dv->iec61883_dv);
 +        iec61883_dv_fb_close(dv->iec61883_dv);
 +    }
 +    while (dv->queue_first) {
 +        DVPacket *packet = dv->queue_first;
 +        dv->queue_first = packet->next;
 +        av_free(packet->buf);
 +        av_free(packet);
 +    }
 +
 +    iec61883_cmp_disconnect(dv->raw1394, dv->node, dv->output_port,
 +                            raw1394_get_local_id(dv->raw1394),
 +                            dv->input_port, dv->channel, dv->bandwidth);
 +
 +    raw1394_destroy_handle(dv->raw1394);
 +
 +    return 0;
 +}
 +
 +static const AVOption options[] = {
-     { "dvbuffer", "set queue buffer size (in packets)", offsetof(struct iec61883_data, max_packets), AV_OPT_TYPE_INT, {.dbl = 0}, 0, INT_MAX, AV_OPT_FLAG_DECODING_PARAM },
++    { "dvtype", "override autodetection of DV/HDV", offsetof(struct iec61883_data, type), AV_OPT_TYPE_INT, {.i64 = IEC61883_AUTO}, IEC61883_AUTO, IEC61883_HDV, AV_OPT_FLAG_DECODING_PARAM, "dvtype" },
 +    { "auto",   "auto detect DV/HDV", 0, AV_OPT_TYPE_CONST, {.i64 = IEC61883_AUTO}, 0, 0, AV_OPT_FLAG_DECODING_PARAM, "dvtype" },
 +    { "dv",     "force device being treated as DV device", 0, AV_OPT_TYPE_CONST, {.i64 = IEC61883_DV},   0, 0, AV_OPT_FLAG_DECODING_PARAM, "dvtype" },
 +    { "hdv" ,   "force device being treated as HDV device", 0, AV_OPT_TYPE_CONST, {.i64 = IEC61883_HDV},  0, 0, AV_OPT_FLAG_DECODING_PARAM, "dvtype" },
++    { "dvbuffer", "set queue buffer size (in packets)", offsetof(struct iec61883_data, max_packets), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, AV_OPT_FLAG_DECODING_PARAM },
 +    { NULL },
 +};
 +
 +static const AVClass iec61883_class = {
 +    .class_name = "iec61883 indev",
 +    .item_name  = av_default_item_name,
 +    .option     = options,
 +    .version    = LIBAVUTIL_VERSION_INT,
 +};
 +
 +AVInputFormat ff_iec61883_demuxer = {
 +    .name           = "iec61883",
 +    .long_name      = NULL_IF_CONFIG_SMALL("libiec61883 (new DV1394) A/V input device"),
 +    .priv_data_size = sizeof(struct iec61883_data),
 +    .read_header    = iec61883_read_header,
 +    .read_packet    = iec61883_read_packet,
 +    .read_close     = iec61883_close,
 +    .flags          = AVFMT_NOFILE,
 +    .priv_class     = &iec61883_class,
 +};
Simple merge
Simple merge
Simple merge
index a2f4ea1,0000000..6069edc
mode 100644,000000..100644
--- /dev/null
@@@ -1,251 -1,0 +1,251 @@@
-     {"channels", "set number of channels",     OFFSET(channels),     AV_OPT_TYPE_INT, {.dbl=2},     1, 2,      AV_OPT_FLAG_DECODING_PARAM },
-     {"sample_rate", "set sample rate",         OFFSET(sample_rate),  AV_OPT_TYPE_INT, {.dbl=44100}, 1, 192000, AV_OPT_FLAG_DECODING_PARAM },
-     {"sample_size", "set sample size",         OFFSET(sample_size),  AV_OPT_TYPE_INT, {.dbl=16},    8, 16,     AV_OPT_FLAG_DECODING_PARAM },
-     {"list_devices", "list available devices", OFFSET(list_devices), AV_OPT_TYPE_INT, {.dbl=0},     0, 1,      AV_OPT_FLAG_DECODING_PARAM, "list_devices"  },
 +/*
 + * Copyright (c) 2011 Jonathan Baldwin
 + *
 + * This file is part of FFmpeg.
 + *
 + * Permission to use, copy, modify, and/or distribute this software for any
 + * purpose with or without fee is hereby granted, provided that the above
 + * copyright notice and this permission notice appear in all copies.
 + *
 + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
 + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
 + * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
 + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
 + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
 + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 + * PERFORMANCE OF THIS SOFTWARE.
 + */
 +
 +/**
 + * @file
 + * OpenAL 1.1 capture device for libavdevice
 + **/
 +
 +#include <AL/al.h>
 +#include <AL/alc.h>
 +
 +#include "libavutil/opt.h"
 +#include "libavformat/internal.h"
 +#include "avdevice.h"
 +
 +typedef struct {
 +    AVClass *class;
 +    /** OpenAL capture device context. **/
 +    ALCdevice *device;
 +    /** The number of channels in the captured audio. **/
 +    int channels;
 +    /** The sample rate (in Hz) of the captured audio. **/
 +    int sample_rate;
 +    /** The sample size (in bits) of the captured audio. **/
 +    int sample_size;
 +    /** The OpenAL sample format of the captured audio. **/
 +    ALCenum sample_format;
 +    /** The number of bytes between two consecutive samples of the same channel/component. **/
 +    ALCint sample_step;
 +    /** If true, print a list of capture devices on this system and exit. **/
 +    int list_devices;
 +} al_data;
 +
 +typedef struct {
 +    ALCenum al_fmt;
 +    enum AVCodecID codec_id;
 +    int channels;
 +} al_format_info;
 +
 +#define LOWEST_AL_FORMAT FFMIN(FFMIN(AL_FORMAT_MONO8,AL_FORMAT_MONO16),FFMIN(AL_FORMAT_STEREO8,AL_FORMAT_STEREO16))
 +
 +/**
 + * Get information about an AL_FORMAT value.
 + * @param al_fmt the AL_FORMAT value to find information about.
 + * @return A pointer to a structure containing information about the AL_FORMAT value.
 + */
 +static inline al_format_info* get_al_format_info(ALCenum al_fmt)
 +{
 +    static al_format_info info_table[] = {
 +        [AL_FORMAT_MONO8-LOWEST_AL_FORMAT]    = {AL_FORMAT_MONO8, AV_CODEC_ID_PCM_U8, 1},
 +        [AL_FORMAT_MONO16-LOWEST_AL_FORMAT]   = {AL_FORMAT_MONO16, AV_NE (AV_CODEC_ID_PCM_S16BE, AV_CODEC_ID_PCM_S16LE), 1},
 +        [AL_FORMAT_STEREO8-LOWEST_AL_FORMAT]  = {AL_FORMAT_STEREO8, AV_CODEC_ID_PCM_U8, 2},
 +        [AL_FORMAT_STEREO16-LOWEST_AL_FORMAT] = {AL_FORMAT_STEREO16, AV_NE (AV_CODEC_ID_PCM_S16BE, AV_CODEC_ID_PCM_S16LE), 2},
 +    };
 +
 +    return &info_table[al_fmt-LOWEST_AL_FORMAT];
 +}
 +
 +/**
 + * Get the OpenAL error code, translated into an av/errno error code.
 + * @param device The ALC device to check for errors.
 + * @param error_msg_ret A pointer to a char* in which to return the error message, or NULL if desired.
 + * @return The error code, or 0 if there is no error.
 + */
 +static inline int al_get_error(ALCdevice *device, const char** error_msg_ret)
 +{
 +    ALCenum error = alcGetError(device);
 +    if (error_msg_ret)
 +        *error_msg_ret = (const char*) alcGetString(device, error);
 +    switch (error) {
 +    case ALC_NO_ERROR:
 +        return 0;
 +    case ALC_INVALID_DEVICE:
 +        return AVERROR(ENODEV);
 +        break;
 +    case ALC_INVALID_CONTEXT:
 +    case ALC_INVALID_ENUM:
 +    case ALC_INVALID_VALUE:
 +        return AVERROR(EINVAL);
 +        break;
 +    case ALC_OUT_OF_MEMORY:
 +        return AVERROR(ENOMEM);
 +        break;
 +    default:
 +        return AVERROR(EIO);
 +    }
 +}
 +
 +/**
 + * Print out a list of OpenAL capture devices on this system.
 + */
 +static inline void print_al_capture_devices(void *log_ctx)
 +{
 +    const char *devices;
 +
 +    if (!(devices = alcGetString(NULL, ALC_CAPTURE_DEVICE_SPECIFIER)))
 +        return;
 +
 +    av_log(log_ctx, AV_LOG_INFO, "List of OpenAL capture devices on this system:\n");
 +
 +    for (; *devices != '\0'; devices += strlen(devices) + 1)
 +        av_log(log_ctx, AV_LOG_INFO, "  %s\n", devices);
 +}
 +
 +static int read_header(AVFormatContext *ctx)
 +{
 +    al_data *ad = ctx->priv_data;
 +    static const ALCenum sample_formats[2][2] = {
 +        { AL_FORMAT_MONO8,  AL_FORMAT_STEREO8  },
 +        { AL_FORMAT_MONO16, AL_FORMAT_STEREO16 }
 +    };
 +    int error = 0;
 +    const char *error_msg;
 +    AVStream *st = NULL;
 +    AVCodecContext *codec = NULL;
 +
 +    if (ad->list_devices) {
 +        print_al_capture_devices(ctx);
 +        return AVERROR_EXIT;
 +    }
 +
 +    ad->sample_format = sample_formats[ad->sample_size/8-1][ad->channels-1];
 +
 +    /* Open device for capture */
 +    ad->device =
 +        alcCaptureOpenDevice(ctx->filename[0] ? ctx->filename : NULL,
 +                             ad->sample_rate,
 +                             ad->sample_format,
 +                             ad->sample_rate); /* Maximum 1 second of sample data to be read at once */
 +
 +    if (error = al_get_error(ad->device, &error_msg)) goto fail;
 +
 +    /* Create stream */
 +    if (!(st = avformat_new_stream(ctx, NULL))) {
 +        error = AVERROR(ENOMEM);
 +        goto fail;
 +    }
 +
 +    /* We work in microseconds */
 +    avpriv_set_pts_info(st, 64, 1, 1000000);
 +
 +    /* Set codec parameters */
 +    codec = st->codec;
 +    codec->codec_type = AVMEDIA_TYPE_AUDIO;
 +    codec->sample_rate = ad->sample_rate;
 +    codec->channels = get_al_format_info(ad->sample_format)->channels;
 +    codec->codec_id = get_al_format_info(ad->sample_format)->codec_id;
 +
 +    /* This is needed to read the audio data */
 +    ad->sample_step = (av_get_bits_per_sample(get_al_format_info(ad->sample_format)->codec_id) *
 +                       get_al_format_info(ad->sample_format)->channels) / 8;
 +
 +    /* Finally, start the capture process */
 +    alcCaptureStart(ad->device);
 +
 +    return 0;
 +
 +fail:
 +    /* Handle failure */
 +    if (ad->device)
 +        alcCaptureCloseDevice(ad->device);
 +    if (error_msg)
 +        av_log(ctx, AV_LOG_ERROR, "Cannot open device: %s\n", error_msg);
 +    return error;
 +}
 +
 +static int read_packet(AVFormatContext* ctx, AVPacket *pkt)
 +{
 +    al_data *ad = ctx->priv_data;
 +    int error=0;
 +    const char *error_msg;
 +    ALCint nb_samples;
 +
 +    /* Get number of samples available */
 +    alcGetIntegerv(ad->device, ALC_CAPTURE_SAMPLES, (ALCsizei) sizeof(ALCint), &nb_samples);
 +    if (error = al_get_error(ad->device, &error_msg)) goto fail;
 +
 +    /* Create a packet of appropriate size */
 +    av_new_packet(pkt, nb_samples*ad->sample_step);
 +    pkt->pts = av_gettime();
 +
 +    /* Fill the packet with the available samples */
 +    alcCaptureSamples(ad->device, pkt->data, nb_samples);
 +    if (error = al_get_error(ad->device, &error_msg)) goto fail;
 +
 +    return pkt->size;
 +fail:
 +    /* Handle failure */
 +    if (pkt->data)
 +        av_destruct_packet(pkt);
 +    if (error_msg)
 +        av_log(ctx, AV_LOG_ERROR, "Error: %s\n", error_msg);
 +    return error;
 +}
 +
 +static int read_close(AVFormatContext* ctx)
 +{
 +    al_data *ad = ctx->priv_data;
 +
 +    if (ad->device) {
 +        alcCaptureStop(ad->device);
 +        alcCaptureCloseDevice(ad->device);
 +    }
 +    return 0;
 +}
 +
 +#define OFFSET(x) offsetof(al_data, x)
 +
 +static const AVOption options[] = {
++    {"channels", "set number of channels",     OFFSET(channels),     AV_OPT_TYPE_INT, {.i64=2},     1, 2,      AV_OPT_FLAG_DECODING_PARAM },
++    {"sample_rate", "set sample rate",         OFFSET(sample_rate),  AV_OPT_TYPE_INT, {.i64=44100}, 1, 192000, AV_OPT_FLAG_DECODING_PARAM },
++    {"sample_size", "set sample size",         OFFSET(sample_size),  AV_OPT_TYPE_INT, {.i64=16},    8, 16,     AV_OPT_FLAG_DECODING_PARAM },
++    {"list_devices", "list available devices", OFFSET(list_devices), AV_OPT_TYPE_INT, {.i64=0},     0, 1,      AV_OPT_FLAG_DECODING_PARAM, "list_devices"  },
 +    {"true",  "", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, AV_OPT_FLAG_DECODING_PARAM, "list_devices" },
 +    {"false", "", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, AV_OPT_FLAG_DECODING_PARAM, "list_devices" },
 +    {NULL},
 +};
 +
 +static const AVClass class = {
 +    .class_name = "openal",
 +    .item_name = av_default_item_name,
 +    .option = options,
 +    .version = LIBAVUTIL_VERSION_INT
 +};
 +
 +AVInputFormat ff_openal_demuxer = {
 +    .name = "openal",
 +    .long_name = NULL_IF_CONFIG_SMALL("OpenAL audio capture device"),
 +    .priv_data_size = sizeof(al_data),
 +    .read_probe = NULL,
 +    .read_header = read_header,
 +    .read_packet = read_packet,
 +    .read_close = read_close,
 +    .flags = AVFMT_NOFILE,
 +    .priv_class = &class
 +};
Simple merge
@@@ -162,12 -162,12 +162,12 @@@ static av_cold int pulse_close(AVFormat
  
  static const AVOption options[] = {
      { "server",        "pulse server name",                              OFFSET(server),        AV_OPT_TYPE_STRING, {.str = NULL},     0, 0, D },
 -    { "name",          "application name",                               OFFSET(name),          AV_OPT_TYPE_STRING, {.str = "libav"},  0, 0, D },
 +    { "name",          "application name",                               OFFSET(name),          AV_OPT_TYPE_STRING, {.str = LIBAVFORMAT_IDENT},  0, 0, D },
      { "stream_name",   "stream description",                             OFFSET(stream_name),   AV_OPT_TYPE_STRING, {.str = "record"}, 0, 0, D },
-     { "sample_rate",   "sample rate in Hz",                              OFFSET(sample_rate),   AV_OPT_TYPE_INT,    {.dbl = 48000},    1, INT_MAX, D },
-     { "channels",      "number of audio channels",                       OFFSET(channels),      AV_OPT_TYPE_INT,    {.dbl = 2},        1, INT_MAX, D },
-     { "frame_size",    "number of bytes per frame",                      OFFSET(frame_size),    AV_OPT_TYPE_INT,    {.dbl = 1024},     1, INT_MAX, D },
-     { "fragment_size", "buffering size, affects latency and cpu usage",  OFFSET(fragment_size), AV_OPT_TYPE_INT,    {.dbl = -1},      -1, INT_MAX, D },
+     { "sample_rate",   "sample rate in Hz",                              OFFSET(sample_rate),   AV_OPT_TYPE_INT,    {.i64 = 48000},    1, INT_MAX, D },
+     { "channels",      "number of audio channels",                       OFFSET(channels),      AV_OPT_TYPE_INT,    {.i64 = 2},        1, INT_MAX, D },
+     { "frame_size",    "number of bytes per frame",                      OFFSET(frame_size),    AV_OPT_TYPE_INT,    {.i64 = 1024},     1, INT_MAX, D },
+     { "fragment_size", "buffering size, affects latency and cpu usage",  OFFSET(fragment_size), AV_OPT_TYPE_INT,    {.i64 = -1},      -1, INT_MAX, D },
      { NULL },
  };
  
Simple merge
index df48cb9,0000000..3d75110
mode 100644,000000..100644
--- /dev/null
@@@ -1,363 -1,0 +1,363 @@@
-     { "standard", "", offsetof(VideoData, standard), AV_OPT_TYPE_INT, {.dbl = VIDEO_MODE_NTSC}, VIDEO_MODE_PAL, VIDEO_MODE_NTSC, AV_OPT_FLAG_DECODING_PARAM, "standard" },
 +/*
 + * Linux video grab interface
 + * Copyright (c) 2000,2001 Fabrice Bellard
 + *
 + * This file is part of FFmpeg.
 + *
 + * FFmpeg is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU Lesser General Public
 + * License as published by the Free Software Foundation; either
 + * version 2.1 of the License, or (at your option) any later version.
 + *
 + * FFmpeg is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 + * Lesser General Public License for more details.
 + *
 + * You should have received a copy of the GNU Lesser General Public
 + * License along with FFmpeg; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 + */
 +
 +#include "avdevice.h"
 +
 +#undef __STRICT_ANSI__ //workaround due to broken kernel headers
 +#include "config.h"
 +#include "libavutil/rational.h"
 +#include "libavutil/imgutils.h"
 +#include "libavutil/log.h"
 +#include "libavutil/opt.h"
 +#include "libavformat/internal.h"
 +#include "libavcodec/dsputil.h"
 +#include <unistd.h>
 +#include <fcntl.h>
 +#include <sys/ioctl.h>
 +#include <sys/mman.h>
 +#include <sys/time.h>
 +#define _LINUX_TIME_H 1
 +#include <linux/videodev.h>
 +#include <time.h>
 +#include "avdevice.h"
 +
 +typedef struct {
 +    AVClass *class;
 +    int fd;
 +    int frame_format; /* see VIDEO_PALETTE_xxx */
 +    int use_mmap;
 +    AVRational time_base;
 +    int64_t time_frame;
 +    int frame_size;
 +    struct video_capability video_cap;
 +    struct video_audio audio_saved;
 +    struct video_window video_win;
 +    uint8_t *video_buf;
 +    struct video_mbuf gb_buffers;
 +    struct video_mmap gb_buf;
 +    int gb_frame;
 +    int standard;
 +} VideoData;
 +
 +static const struct {
 +    int palette;
 +    int depth;
 +    enum PixelFormat pix_fmt;
 +} video_formats [] = {
 +    {.palette = VIDEO_PALETTE_YUV420P, .depth = 12, .pix_fmt = PIX_FMT_YUV420P },
 +    {.palette = VIDEO_PALETTE_YUV422,  .depth = 16, .pix_fmt = PIX_FMT_YUYV422 },
 +    {.palette = VIDEO_PALETTE_UYVY,    .depth = 16, .pix_fmt = PIX_FMT_UYVY422 },
 +    {.palette = VIDEO_PALETTE_YUYV,    .depth = 16, .pix_fmt = PIX_FMT_YUYV422 },
 +    /* NOTE: v4l uses BGR24, not RGB24 */
 +    {.palette = VIDEO_PALETTE_RGB24,   .depth = 24, .pix_fmt = PIX_FMT_BGR24   },
 +    {.palette = VIDEO_PALETTE_RGB565,  .depth = 16, .pix_fmt = PIX_FMT_BGR565  },
 +    {.palette = VIDEO_PALETTE_GREY,    .depth = 8,  .pix_fmt = PIX_FMT_GRAY8   },
 +};
 +
 +
 +static int grab_read_header(AVFormatContext *s1, AVFormatParameters *ap)
 +{
 +    VideoData *s = s1->priv_data;
 +    AVStream *st;
 +    int video_fd;
 +    int desired_palette, desired_depth;
 +    struct video_tuner tuner;
 +    struct video_audio audio;
 +    struct video_picture pict;
 +    int j;
 +    int vformat_num = FF_ARRAY_ELEMS(video_formats);
 +
 +    av_log(s1, AV_LOG_WARNING, "V4L input device is deprecated and will be removed in the next release.");
 +
 +    if (ap->time_base.den <= 0) {
 +        av_log(s1, AV_LOG_ERROR, "Wrong time base (%d)\n", ap->time_base.den);
 +        return -1;
 +    }
 +    s->time_base = ap->time_base;
 +
 +    s->video_win.width = ap->width;
 +    s->video_win.height = ap->height;
 +
 +    st = avformat_new_stream(s1, NULL);
 +    if (!st)
 +        return AVERROR(ENOMEM);
 +    avpriv_set_pts_info(st, 64, 1, 1000000); /* 64 bits pts in us */
 +
 +    video_fd = open(s1->filename, O_RDWR);
 +    if (video_fd < 0) {
 +        av_log(s1, AV_LOG_ERROR, "%s: %s\n", s1->filename, strerror(errno));
 +        goto fail;
 +    }
 +
 +    if (ioctl(video_fd, VIDIOCGCAP, &s->video_cap) < 0) {
 +        av_log(s1, AV_LOG_ERROR, "VIDIOCGCAP: %s\n", strerror(errno));
 +        goto fail;
 +    }
 +
 +    if (!(s->video_cap.type & VID_TYPE_CAPTURE)) {
 +        av_log(s1, AV_LOG_ERROR, "Fatal: grab device does not handle capture\n");
 +        goto fail;
 +    }
 +
 +    /* no values set, autodetect them */
 +    if (s->video_win.width <= 0 || s->video_win.height <= 0) {
 +        if (ioctl(video_fd, VIDIOCGWIN, &s->video_win, sizeof(s->video_win)) < 0) {
 +            av_log(s1, AV_LOG_ERROR, "VIDIOCGWIN: %s\n", strerror(errno));
 +            goto fail;
 +        }
 +    }
 +
 +    if(av_image_check_size(s->video_win.width, s->video_win.height, 0, s1) < 0)
 +        return -1;
 +
 +    desired_palette = -1;
 +    desired_depth = -1;
 +    for (j = 0; j < vformat_num; j++) {
 +        if (ap->pix_fmt == video_formats[j].pix_fmt) {
 +            desired_palette = video_formats[j].palette;
 +            desired_depth = video_formats[j].depth;
 +            break;
 +        }
 +    }
 +
 +    /* set tv standard */
 +    if (!ioctl(video_fd, VIDIOCGTUNER, &tuner)) {
 +        tuner.mode = s->standard;
 +        ioctl(video_fd, VIDIOCSTUNER, &tuner);
 +    }
 +
 +    /* unmute audio */
 +    audio.audio = 0;
 +    ioctl(video_fd, VIDIOCGAUDIO, &audio);
 +    memcpy(&s->audio_saved, &audio, sizeof(audio));
 +    audio.flags &= ~VIDEO_AUDIO_MUTE;
 +    ioctl(video_fd, VIDIOCSAUDIO, &audio);
 +
 +    ioctl(video_fd, VIDIOCGPICT, &pict);
 +    av_dlog(s1, "v4l: colour=%d hue=%d brightness=%d constrast=%d whiteness=%d\n",
 +            pict.colour, pict.hue, pict.brightness, pict.contrast, pict.whiteness);
 +    /* try to choose a suitable video format */
 +    pict.palette = desired_palette;
 +    pict.depth= desired_depth;
 +    if (desired_palette == -1 || ioctl(video_fd, VIDIOCSPICT, &pict) < 0) {
 +        for (j = 0; j < vformat_num; j++) {
 +            pict.palette = video_formats[j].palette;
 +            pict.depth = video_formats[j].depth;
 +            if (-1 != ioctl(video_fd, VIDIOCSPICT, &pict))
 +                break;
 +        }
 +        if (j >= vformat_num)
 +            goto fail1;
 +    }
 +
 +    if (ioctl(video_fd, VIDIOCGMBUF, &s->gb_buffers) < 0) {
 +        /* try to use read based access */
 +        int val;
 +
 +        s->video_win.x = 0;
 +        s->video_win.y = 0;
 +        s->video_win.chromakey = -1;
 +        s->video_win.flags = 0;
 +
 +        if (ioctl(video_fd, VIDIOCSWIN, s->video_win) < 0) {
 +            av_log(s1, AV_LOG_ERROR, "VIDIOCSWIN: %s\n", strerror(errno));
 +            goto fail;
 +        }
 +
 +        s->frame_format = pict.palette;
 +
 +        val = 1;
 +        if (ioctl(video_fd, VIDIOCCAPTURE, &val) < 0) {
 +            av_log(s1, AV_LOG_ERROR, "VIDIOCCAPTURE: %s\n", strerror(errno));
 +            goto fail;
 +        }
 +
 +        s->time_frame = av_gettime() * s->time_base.den / s->time_base.num;
 +        s->use_mmap = 0;
 +    } else {
 +        s->video_buf = mmap(0, s->gb_buffers.size, PROT_READ|PROT_WRITE, MAP_SHARED, video_fd, 0);
 +        if ((unsigned char*)-1 == s->video_buf) {
 +            s->video_buf = mmap(0, s->gb_buffers.size, PROT_READ|PROT_WRITE, MAP_PRIVATE, video_fd, 0);
 +            if ((unsigned char*)-1 == s->video_buf) {
 +                av_log(s1, AV_LOG_ERROR, "mmap: %s\n", strerror(errno));
 +                goto fail;
 +            }
 +        }
 +        s->gb_frame = 0;
 +        s->time_frame = av_gettime() * s->time_base.den / s->time_base.num;
 +
 +        /* start to grab the first frame */
 +        s->gb_buf.frame = s->gb_frame % s->gb_buffers.frames;
 +        s->gb_buf.height = s->video_win.height;
 +        s->gb_buf.width = s->video_win.width;
 +        s->gb_buf.format = pict.palette;
 +
 +        if (ioctl(video_fd, VIDIOCMCAPTURE, &s->gb_buf) < 0) {
 +            if (errno != EAGAIN) {
 +            fail1:
 +                av_log(s1, AV_LOG_ERROR, "VIDIOCMCAPTURE: %s\n", strerror(errno));
 +            } else {
 +                av_log(s1, AV_LOG_ERROR, "Fatal: grab device does not receive any video signal\n");
 +            }
 +            goto fail;
 +        }
 +        for (j = 1; j < s->gb_buffers.frames; j++) {
 +          s->gb_buf.frame = j;
 +          ioctl(video_fd, VIDIOCMCAPTURE, &s->gb_buf);
 +        }
 +        s->frame_format = s->gb_buf.format;
 +        s->use_mmap = 1;
 +    }
 +
 +    for (j = 0; j < vformat_num; j++) {
 +        if (s->frame_format == video_formats[j].palette) {
 +            s->frame_size = s->video_win.width * s->video_win.height * video_formats[j].depth / 8;
 +            st->codec->pix_fmt = video_formats[j].pix_fmt;
 +            break;
 +        }
 +    }
 +
 +    if (j >= vformat_num)
 +        goto fail;
 +
 +    s->fd = video_fd;
 +
 +    st->codec->codec_type = AVMEDIA_TYPE_VIDEO;
 +    st->codec->codec_id = AV_CODEC_ID_RAWVIDEO;
 +    st->codec->width = s->video_win.width;
 +    st->codec->height = s->video_win.height;
 +    st->codec->time_base = s->time_base;
 +    st->codec->bit_rate = s->frame_size * 1/av_q2d(st->codec->time_base) * 8;
 +
 +    return 0;
 + fail:
 +    if (video_fd >= 0)
 +        close(video_fd);
 +    return AVERROR(EIO);
 +}
 +
 +static int v4l_mm_read_picture(VideoData *s, uint8_t *buf)
 +{
 +    uint8_t *ptr;
 +
 +    while (ioctl(s->fd, VIDIOCSYNC, &s->gb_frame) < 0 &&
 +           (errno == EAGAIN || errno == EINTR));
 +
 +    ptr = s->video_buf + s->gb_buffers.offsets[s->gb_frame];
 +    memcpy(buf, ptr, s->frame_size);
 +
 +    /* Setup to capture the next frame */
 +    s->gb_buf.frame = s->gb_frame;
 +    if (ioctl(s->fd, VIDIOCMCAPTURE, &s->gb_buf) < 0) {
 +        if (errno == EAGAIN)
 +            av_log(NULL, AV_LOG_ERROR, "Cannot Sync\n");
 +        else
 +            av_log(NULL, AV_LOG_ERROR, "VIDIOCMCAPTURE: %s\n", strerror(errno));
 +        return AVERROR(EIO);
 +    }
 +
 +    /* This is now the grabbing frame */
 +    s->gb_frame = (s->gb_frame + 1) % s->gb_buffers.frames;
 +
 +    return s->frame_size;
 +}
 +
 +static int grab_read_packet(AVFormatContext *s1, AVPacket *pkt)
 +{
 +    VideoData *s = s1->priv_data;
 +    int64_t curtime, delay;
 +    struct timespec ts;
 +
 +    /* Calculate the time of the next frame */
 +    s->time_frame += INT64_C(1000000);
 +
 +    /* wait based on the frame rate */
 +    for(;;) {
 +        curtime = av_gettime();
 +        delay = s->time_frame * s->time_base.num / s->time_base.den - curtime;
 +        if (delay <= 0) {
 +            if (delay < INT64_C(-1000000) * s->time_base.num / s->time_base.den) {
 +                /* printf("grabbing is %d frames late (dropping)\n", (int) -(delay / 16666)); */
 +                s->time_frame += INT64_C(1000000);
 +            }
 +            break;
 +        }
 +        ts.tv_sec = delay / 1000000;
 +        ts.tv_nsec = (delay % 1000000) * 1000;
 +        nanosleep(&ts, NULL);
 +    }
 +
 +    if (av_new_packet(pkt, s->frame_size) < 0)
 +        return AVERROR(EIO);
 +
 +    pkt->pts = curtime;
 +
 +    /* read one frame */
 +    if (s->use_mmap) {
 +        return v4l_mm_read_picture(s, pkt->data);
 +    } else {
 +        if (read(s->fd, pkt->data, pkt->size) != pkt->size)
 +            return AVERROR(EIO);
 +        return s->frame_size;
 +    }
 +}
 +
 +static int grab_read_close(AVFormatContext *s1)
 +{
 +    VideoData *s = s1->priv_data;
 +
 +    if (s->use_mmap)
 +        munmap(s->video_buf, s->gb_buffers.size);
 +
 +    /* mute audio. we must force it because the BTTV driver does not
 +       return its state correctly */
 +    s->audio_saved.flags |= VIDEO_AUDIO_MUTE;
 +    ioctl(s->fd, VIDIOCSAUDIO, &s->audio_saved);
 +
 +    close(s->fd);
 +    return 0;
 +}
 +
 +static const AVOption options[] = {
++    { "standard", "", offsetof(VideoData, standard), AV_OPT_TYPE_INT, {.i64 = VIDEO_MODE_NTSC}, VIDEO_MODE_PAL, VIDEO_MODE_NTSC, AV_OPT_FLAG_DECODING_PARAM, "standard" },
 +    { "PAL",   "", 0, AV_OPT_TYPE_CONST, {.i64 = VIDEO_MODE_PAL},   0, 0, AV_OPT_FLAG_DECODING_PARAM, "standard" },
 +    { "SECAM", "", 0, AV_OPT_TYPE_CONST, {.i64 = VIDEO_MODE_SECAM}, 0, 0, AV_OPT_FLAG_DECODING_PARAM, "standard" },
 +    { "NTSC",  "", 0, AV_OPT_TYPE_CONST, {.i64 = VIDEO_MODE_NTSC},  0, 0, AV_OPT_FLAG_DECODING_PARAM, "standard" },
 +    { NULL },
 +};
 +
 +static const AVClass v4l_class = {
 +    .class_name = "V4L indev",
 +    .item_name  = av_default_item_name,
 +    .option     = options,
 +    .version    = LIBAVUTIL_VERSION_INT,
 +};
 +
 +AVInputFormat ff_v4l_demuxer = {
 +    .name           = "video4linux,v4l",
 +    .long_name      = NULL_IF_CONFIG_SMALL("Video4Linux device grab"),
 +    .priv_data_size = sizeof(VideoData),
 +    .read_header    = grab_read_header,
 +    .read_packet    = grab_read_packet,
 +    .read_close     = grab_read_close,
 +    .flags          = AVFMT_NOFILE,
 +    .priv_class     = &v4l_class,
 +};
@@@ -920,11 -824,10 +920,11 @@@ static int v4l2_read_close(AVFormatCont
  
  #define OFFSET(x) offsetof(struct video_data, x)
  #define DEC AV_OPT_FLAG_DECODING_PARAM
 +
  static const AVOption options[] = {
      { "standard",     "TV standard, used only by analog frame grabber",            OFFSET(standard),     AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0,       DEC },
-     { "channel",      "TV channel, used only by frame grabber",                    OFFSET(channel),      AV_OPT_TYPE_INT,    {.dbl = 0 },    0, INT_MAX, DEC },
+     { "channel",      "TV channel, used only by frame grabber",                    OFFSET(channel),      AV_OPT_TYPE_INT,    {.i64 = 0 },    0, INT_MAX, DEC },
 -    { "video_size",   "A string describing frame size, such as 640x480 or hd720.", OFFSET(video_size),   AV_OPT_TYPE_STRING, {.str = NULL},  0, 0,       DEC },
 +    { "video_size",   "A string describing frame size, such as 640x480 or hd720.", OFFSET(width),        AV_OPT_TYPE_IMAGE_SIZE, {.str = NULL},  0, 0,       DEC },
      { "pixel_format", "Preferred pixel format",                                    OFFSET(pixel_format), AV_OPT_TYPE_STRING, {.str = NULL},  0, 0,       DEC },
      { "input_format", "Preferred pixel format (for raw video) or codec name",      OFFSET(pixel_format), AV_OPT_TYPE_STRING, {.str = NULL},  0, 0,       DEC },
      { "framerate",    "",                                                          OFFSET(framerate),    AV_OPT_TYPE_STRING, {.str = NULL},  0, 0,       DEC },
      { "all",          "Show all available formats",                                OFFSET(list_format),  AV_OPT_TYPE_CONST,  {.i64 = V4L_ALLFORMATS  },    0, INT_MAX, DEC, "list_formats" },
      { "raw",          "Show only non-compressed formats",                          OFFSET(list_format),  AV_OPT_TYPE_CONST,  {.i64 = V4L_RAWFORMATS  },    0, INT_MAX, DEC, "list_formats" },
      { "compressed",   "Show only compressed formats",                              OFFSET(list_format),  AV_OPT_TYPE_CONST,  {.i64 = V4L_COMPFORMATS },    0, INT_MAX, DEC, "list_formats" },
-     { "timestamps",   "Kind of timestamps for grabbed frames",                     OFFSET(ts_mode),      AV_OPT_TYPE_INT,    {.dbl = 0 }, 0, 2, DEC, "timestamps" },
++    { "timestamps",   "Kind of timestamps for grabbed frames",                     OFFSET(ts_mode),      AV_OPT_TYPE_INT,    {.i64 = 0 }, 0, 2, DEC, "timestamps" },
 +    { "default",      "Use timestamps from the kernel",                            OFFSET(ts_mode),      AV_OPT_TYPE_CONST,  {.i64 = V4L_TS_DEFAULT  }, 0, 2, DEC, "timestamps" },
 +    { "abs",          "Use absolute timestamps (wall clock)",                      OFFSET(ts_mode),      AV_OPT_TYPE_CONST,  {.i64 = V4L_TS_ABS      }, 0, 2, DEC, "timestamps" },
 +    { "mono2abs",     "Force conversion from monotonic to absolute timestamps",    OFFSET(ts_mode),      AV_OPT_TYPE_CONST,  {.i64 = V4L_TS_MONO2ABS }, 0, 2, DEC, "timestamps" },
-     { "ts",           "Kind of timestamps for grabbed frames",                     OFFSET(ts_mode),      AV_OPT_TYPE_INT,    {.dbl = 0 }, 0, 2, DEC, "timestamps" },
++    { "ts",           "Kind of timestamps for grabbed frames",                     OFFSET(ts_mode),      AV_OPT_TYPE_INT,    {.i64 = 0 }, 0, 2, DEC, "timestamps" },
      { NULL },
  };
  
@@@ -586,16 -585,13 +586,16 @@@ x11grab_read_close(AVFormatContext *s1
  #define OFFSET(x) offsetof(struct x11grab, x)
  #define DEC AV_OPT_FLAG_DECODING_PARAM
  static const AVOption options[] = {
-     { "draw_mouse", "draw the mouse pointer", OFFSET(draw_mouse), AV_OPT_TYPE_INT, {1}, 0, 1, DEC },
 -    { "video_size", "A string describing frame size, such as 640x480 or hd720.", OFFSET(video_size), AV_OPT_TYPE_STRING, {.str = "vga"}, 0, 0, DEC },
 -    { "framerate", "", OFFSET(framerate), AV_OPT_TYPE_STRING, {.str = "ntsc"}, 0, 0, DEC },
 -    { "draw_mouse", "Draw the mouse pointer.", OFFSET(draw_mouse), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 1, DEC },
 -    { "follow_mouse", "Move the grabbing region when the mouse pointer reaches within specified amount of pixels to the edge of region.",
 -      OFFSET(follow_mouse), AV_OPT_TYPE_INT, { .i64 = 0 }, -1, INT_MAX, DEC, "follow_mouse" },
 -    { "centered", "Keep the mouse pointer at the center of grabbing region when following.", 0, AV_OPT_TYPE_CONST, { .i64 = -1 }, INT_MIN, INT_MAX, DEC, "follow_mouse" },
 -    { "show_region", "Show the grabbing region.", OFFSET(show_region), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, DEC },
++    { "draw_mouse", "draw the mouse pointer", OFFSET(draw_mouse), AV_OPT_TYPE_INT, {.i64 = 1}, 0, 1, DEC },
 +
 +    { "follow_mouse", "move the grabbing region when the mouse pointer reaches within specified amount of pixels to the edge of region",
-       OFFSET(follow_mouse), AV_OPT_TYPE_INT, {0}, -1, INT_MAX, DEC, "follow_mouse" },
++      OFFSET(follow_mouse), AV_OPT_TYPE_INT, {.i64 = 0}, -1, INT_MAX, DEC, "follow_mouse" },
 +    { "centered",     "keep the mouse pointer at the center of grabbing region when following",
 +      0, AV_OPT_TYPE_CONST, {.i64 = -1}, INT_MIN, INT_MAX, DEC, "follow_mouse" },
 +
 +    { "framerate",  "set video frame rate",      OFFSET(framerate),   AV_OPT_TYPE_STRING,     {.str = "ntsc"}, 0, 0, DEC },
-     { "show_region", "show the grabbing region", OFFSET(show_region), AV_OPT_TYPE_INT,        {0}, 0, 1, DEC },
++    { "show_region", "show the grabbing region", OFFSET(show_region), AV_OPT_TYPE_INT,        {.i64 = 0}, 0, 1, DEC },
 +    { "video_size",  "set video frame size",     OFFSET(width),       AV_OPT_TYPE_IMAGE_SIZE, {.str = "vga"}, 0, 0, DEC },
      { NULL },
  };
  
index 1b29e88,0000000..542f8a6
mode 100644,000000..100644
--- /dev/null
@@@ -1,339 -1,0 +1,339 @@@
-       AV_OPT_TYPE_INT, { .dbl = 2 }, 2, SWR_CH_MAX, FLAGS },
 +/*
 + * Copyright (c) 2011 Nicolas George <nicolas.george@normalesup.org>
 + *
 + * This file is part of FFmpeg.
 + *
 + * FFmpeg is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU Lesser General Public
 + * License as published by the Free Software Foundation; either
 + * version 2.1 of the License, or (at your option) any later version.
 + *
 + * FFmpeg is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 + * GNU Lesser General Public License for more details.
 + *
 + * You should have received a copy of the GNU Lesser General Public
 + * License along with FFmpeg; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 + */
 +
 +/**
 + * @file
 + * Audio merging filter
 + */
 +
 +#include "libavutil/audioconvert.h"
 +#include "libavutil/bprint.h"
 +#include "libavutil/opt.h"
 +#include "libswresample/swresample.h" // only for SWR_CH_MAX
 +#include "avfilter.h"
 +#include "audio.h"
 +#include "bufferqueue.h"
 +#include "internal.h"
 +
 +typedef struct {
 +    const AVClass *class;
 +    int nb_inputs;
 +    int route[SWR_CH_MAX]; /**< channels routing, see copy_samples */
 +    int bps;
 +    struct amerge_input {
 +        struct FFBufQueue queue;
 +        int nb_ch;         /**< number of channels for the input */
 +        int nb_samples;
 +        int pos;
 +    } *in;
 +} AMergeContext;
 +
 +#define OFFSET(x) offsetof(AMergeContext, x)
 +#define FLAGS AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
 +
 +static const AVOption amerge_options[] = {
 +    { "inputs", "specify the number of inputs", OFFSET(nb_inputs),
++      AV_OPT_TYPE_INT, { .i64 = 2 }, 2, SWR_CH_MAX, FLAGS },
 +    {0}
 +};
 +
 +AVFILTER_DEFINE_CLASS(amerge);
 +
 +static av_cold void uninit(AVFilterContext *ctx)
 +{
 +    AMergeContext *am = ctx->priv;
 +    int i;
 +
 +    for (i = 0; i < am->nb_inputs; i++)
 +        ff_bufqueue_discard_all(&am->in[i].queue);
 +    av_freep(&am->in);
 +}
 +
 +static int query_formats(AVFilterContext *ctx)
 +{
 +    AMergeContext *am = ctx->priv;
 +    int64_t inlayout[SWR_CH_MAX], outlayout = 0;
 +    AVFilterFormats *formats;
 +    AVFilterChannelLayouts *layouts;
 +    int i, overlap = 0, nb_ch = 0;
 +
 +    for (i = 0; i < am->nb_inputs; i++) {
 +        if (!ctx->inputs[i]->in_channel_layouts ||
 +            !ctx->inputs[i]->in_channel_layouts->nb_channel_layouts) {
 +            av_log(ctx, AV_LOG_ERROR,
 +                   "No channel layout for input %d\n", i + 1);
 +            return AVERROR(EINVAL);
 +        }
 +        inlayout[i] = ctx->inputs[i]->in_channel_layouts->channel_layouts[0];
 +        if (ctx->inputs[i]->in_channel_layouts->nb_channel_layouts > 1) {
 +            char buf[256];
 +            av_get_channel_layout_string(buf, sizeof(buf), 0, inlayout[i]);
 +            av_log(ctx, AV_LOG_INFO, "Using \"%s\" for input %d\n", buf, i + 1);
 +        }
 +        am->in[i].nb_ch = av_get_channel_layout_nb_channels(inlayout[i]);
 +        if (outlayout & inlayout[i])
 +            overlap++;
 +        outlayout |= inlayout[i];
 +        nb_ch += am->in[i].nb_ch;
 +    }
 +    if (nb_ch > SWR_CH_MAX) {
 +        av_log(ctx, AV_LOG_ERROR, "Too many channels (max %d)\n", SWR_CH_MAX);
 +        return AVERROR(EINVAL);
 +    }
 +    if (overlap) {
 +        av_log(ctx, AV_LOG_WARNING,
 +               "Inputs overlap: output layout will be meaningless\n");
 +        for (i = 0; i < nb_ch; i++)
 +            am->route[i] = i;
 +        outlayout = av_get_default_channel_layout(nb_ch);
 +        if (!outlayout)
 +            outlayout = ((int64_t)1 << nb_ch) - 1;
 +    } else {
 +        int *route[SWR_CH_MAX];
 +        int c, out_ch_number = 0;
 +
 +        route[0] = am->route;
 +        for (i = 1; i < am->nb_inputs; i++)
 +            route[i] = route[i - 1] + am->in[i - 1].nb_ch;
 +        for (c = 0; c < 64; c++)
 +            for (i = 0; i < am->nb_inputs; i++)
 +                if ((inlayout[i] >> c) & 1)
 +                    *(route[i]++) = out_ch_number++;
 +    }
 +    formats = ff_make_format_list(ff_packed_sample_fmts_array);
 +    ff_set_common_formats(ctx, formats);
 +    for (i = 0; i < am->nb_inputs; i++) {
 +        layouts = NULL;
 +        ff_add_channel_layout(&layouts, inlayout[i]);
 +        ff_channel_layouts_ref(layouts, &ctx->inputs[i]->out_channel_layouts);
 +    }
 +    layouts = NULL;
 +    ff_add_channel_layout(&layouts, outlayout);
 +    ff_channel_layouts_ref(layouts, &ctx->outputs[0]->in_channel_layouts);
 +    ff_set_common_samplerates(ctx, ff_all_samplerates());
 +    return 0;
 +}
 +
 +static int config_output(AVFilterLink *outlink)
 +{
 +    AVFilterContext *ctx = outlink->src;
 +    AMergeContext *am = ctx->priv;
 +    AVBPrint bp;
 +    int i;
 +
 +    for (i = 1; i < am->nb_inputs; i++) {
 +        if (ctx->inputs[i]->sample_rate != ctx->inputs[0]->sample_rate) {
 +            av_log(ctx, AV_LOG_ERROR,
 +                   "Inputs must have the same sample rate "
 +                   "%d for in%d vs %d\n",
 +                   ctx->inputs[i]->sample_rate, i, ctx->inputs[0]->sample_rate);
 +            return AVERROR(EINVAL);
 +        }
 +    }
 +    am->bps = av_get_bytes_per_sample(ctx->outputs[0]->format);
 +    outlink->sample_rate = ctx->inputs[0]->sample_rate;
 +    outlink->time_base   = ctx->inputs[0]->time_base;
 +
 +    av_bprint_init(&bp, 0, 1);
 +    for (i = 0; i < am->nb_inputs; i++) {
 +        av_bprintf(&bp, "%sin%d:", i ? " + " : "", i);
 +        av_bprint_channel_layout(&bp, -1, ctx->inputs[i]->channel_layout);
 +    }
 +    av_bprintf(&bp, " -> out:");
 +    av_bprint_channel_layout(&bp, -1, ctx->outputs[0]->channel_layout);
 +    av_log(ctx, AV_LOG_VERBOSE, "%s\n", bp.str);
 +
 +    return 0;
 +}
 +
 +static int request_frame(AVFilterLink *outlink)
 +{
 +    AVFilterContext *ctx = outlink->src;
 +    AMergeContext *am = ctx->priv;
 +    int i, ret;
 +
 +    for (i = 0; i < am->nb_inputs; i++)
 +        if (!am->in[i].nb_samples)
 +            if ((ret = ff_request_frame(ctx->inputs[i])) < 0)
 +                return ret;
 +    return 0;
 +}
 +
 +/**
 + * Copy samples from several input streams to one output stream.
 + * @param nb_inputs number of inputs
 + * @param in        inputs; used only for the nb_ch field;
 + * @param route     routing values;
 + *                  input channel i goes to output channel route[i];
 + *                  i <  in[0].nb_ch are the channels from the first output;
 + *                  i >= in[0].nb_ch are the channels from the second output
 + * @param ins       pointer to the samples of each inputs, in packed format;
 + *                  will be left at the end of the copied samples
 + * @param outs      pointer to the samples of the output, in packet format;
 + *                  must point to a buffer big enough;
 + *                  will be left at the end of the copied samples
 + * @param ns        number of samples to copy
 + * @param bps       bytes per sample
 + */
 +static inline void copy_samples(int nb_inputs, struct amerge_input in[],
 +                                int *route, uint8_t *ins[],
 +                                uint8_t **outs, int ns, int bps)
 +{
 +    int *route_cur;
 +    int i, c, nb_ch = 0;
 +
 +    for (i = 0; i < nb_inputs; i++)
 +        nb_ch += in[i].nb_ch;
 +    while (ns--) {
 +        route_cur = route;
 +        for (i = 0; i < nb_inputs; i++) {
 +            for (c = 0; c < in[i].nb_ch; c++) {
 +                memcpy((*outs) + bps * *(route_cur++), ins[i], bps);
 +                ins[i] += bps;
 +            }
 +        }
 +        *outs += nb_ch * bps;
 +    }
 +}
 +
 +static int filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamples)
 +{
 +    AVFilterContext *ctx = inlink->dst;
 +    AMergeContext *am = ctx->priv;
 +    AVFilterLink *const outlink = ctx->outputs[0];
 +    int input_number;
 +    int nb_samples, ns, i;
 +    AVFilterBufferRef *outbuf, *inbuf[SWR_CH_MAX];
 +    uint8_t *ins[SWR_CH_MAX], *outs;
 +
 +    for (input_number = 0; input_number < am->nb_inputs; input_number++)
 +        if (inlink == ctx->inputs[input_number])
 +            break;
 +    av_assert1(input_number < am->nb_inputs);
 +    ff_bufqueue_add(ctx, &am->in[input_number].queue, insamples);
 +    am->in[input_number].nb_samples += insamples->audio->nb_samples;
 +    nb_samples = am->in[0].nb_samples;
 +    for (i = 1; i < am->nb_inputs; i++)
 +        nb_samples = FFMIN(nb_samples, am->in[i].nb_samples);
 +    if (!nb_samples)
 +        return 0;
 +
 +    outbuf = ff_get_audio_buffer(ctx->outputs[0], AV_PERM_WRITE, nb_samples);
 +    outs = outbuf->data[0];
 +    for (i = 0; i < am->nb_inputs; i++) {
 +        inbuf[i] = ff_bufqueue_peek(&am->in[i].queue, 0);
 +        ins[i] = inbuf[i]->data[0] +
 +                 am->in[i].pos * am->in[i].nb_ch * am->bps;
 +    }
 +    avfilter_copy_buffer_ref_props(outbuf, inbuf[0]);
 +    outbuf->pts = inbuf[0]->pts == AV_NOPTS_VALUE ? AV_NOPTS_VALUE :
 +                  inbuf[0]->pts +
 +                  av_rescale_q(am->in[0].pos,
 +                               (AVRational){ 1, ctx->inputs[0]->sample_rate },
 +                               ctx->outputs[0]->time_base);
 +
 +    outbuf->audio->nb_samples     = nb_samples;
 +    outbuf->audio->channel_layout = outlink->channel_layout;
 +
 +    while (nb_samples) {
 +        ns = nb_samples;
 +        for (i = 0; i < am->nb_inputs; i++)
 +            ns = FFMIN(ns, inbuf[i]->audio->nb_samples - am->in[i].pos);
 +        /* Unroll the most common sample formats: speed +~350% for the loop,
 +           +~13% overall (including two common decoders) */
 +        switch (am->bps) {
 +            case 1:
 +                copy_samples(am->nb_inputs, am->in, am->route, ins, &outs, ns, 1);
 +                break;
 +            case 2:
 +                copy_samples(am->nb_inputs, am->in, am->route, ins, &outs, ns, 2);
 +                break;
 +            case 4:
 +                copy_samples(am->nb_inputs, am->in, am->route, ins, &outs, ns, 4);
 +                break;
 +            default:
 +                copy_samples(am->nb_inputs, am->in, am->route, ins, &outs, ns, am->bps);
 +                break;
 +        }
 +
 +        nb_samples -= ns;
 +        for (i = 0; i < am->nb_inputs; i++) {
 +            am->in[i].nb_samples -= ns;
 +            am->in[i].pos += ns;
 +            if (am->in[i].pos == inbuf[i]->audio->nb_samples) {
 +                am->in[i].pos = 0;
 +                avfilter_unref_buffer(inbuf[i]);
 +                ff_bufqueue_get(&am->in[i].queue);
 +                inbuf[i] = ff_bufqueue_peek(&am->in[i].queue, 0);
 +                ins[i] = inbuf[i] ? inbuf[i]->data[0] : NULL;
 +            }
 +        }
 +    }
 +    return ff_filter_samples(ctx->outputs[0], outbuf);
 +}
 +
 +static av_cold int init(AVFilterContext *ctx, const char *args)
 +{
 +    AMergeContext *am = ctx->priv;
 +    int ret, i;
 +    char name[16];
 +
 +    am->class = &amerge_class;
 +    av_opt_set_defaults(am);
 +    ret = av_set_options_string(am, args, "=", ":");
 +    if (ret < 0) {
 +        av_log(ctx, AV_LOG_ERROR, "Error parsing options: '%s'\n", args);
 +        return ret;
 +    }
 +    am->in = av_calloc(am->nb_inputs, sizeof(*am->in));
 +    if (!am->in)
 +        return AVERROR(ENOMEM);
 +    for (i = 0; i < am->nb_inputs; i++) {
 +        AVFilterPad pad = {
 +            .name             = name,
 +            .type             = AVMEDIA_TYPE_AUDIO,
 +            .filter_samples   = filter_samples,
 +            .min_perms        = AV_PERM_READ | AV_PERM_PRESERVE,
 +        };
 +        snprintf(name, sizeof(name), "in%d", i);
 +        ff_insert_inpad(ctx, i, &pad);
 +    }
 +    return 0;
 +}
 +
 +AVFilter avfilter_af_amerge = {
 +    .name          = "amerge",
 +    .description   = NULL_IF_CONFIG_SMALL("Merge two audio streams into "
 +                                          "a single multi-channel stream."),
 +    .priv_size     = sizeof(AMergeContext),
 +    .init          = init,
 +    .uninit        = uninit,
 +    .query_formats = query_formats,
 +
 +    .inputs    = (const AVFilterPad[]) { { .name = NULL } },
 +    .outputs   = (const AVFilterPad[]) {
 +        { .name             = "default",
 +          .type             = AVMEDIA_TYPE_AUDIO,
 +          .config_props     = config_output,
 +          .request_frame    = request_frame, },
 +        { .name = NULL }
 +    },
 +    .priv_class = &amerge_class,
 +};
@@@ -174,18 -174,17 +174,18 @@@ typedef struct MixContext 
  
  #define OFFSET(x) offsetof(MixContext, x)
  #define A AV_OPT_FLAG_AUDIO_PARAM
 -static const AVOption options[] = {
 +#define F AV_OPT_FLAG_FILTERING_PARAM
 +static const AVOption amix_options[] = {
      { "inputs", "Number of inputs.",
-             OFFSET(nb_inputs), AV_OPT_TYPE_INT, { 2 }, 1, 32, A|F },
 -            OFFSET(nb_inputs), AV_OPT_TYPE_INT, { .i64 = 2 }, 1, 32, A },
++            OFFSET(nb_inputs), AV_OPT_TYPE_INT, { .i64 = 2 }, 1, 32, A|F },
      { "duration", "How to determine the end-of-stream.",
-             OFFSET(duration_mode), AV_OPT_TYPE_INT, { DURATION_LONGEST }, 0,  2, A|F, "duration" },
 -            OFFSET(duration_mode), AV_OPT_TYPE_INT, { .i64 = DURATION_LONGEST }, 0,  2, A, "duration" },
 -        { "longest",  "Duration of longest input.",  0, AV_OPT_TYPE_CONST, { .i64 = DURATION_LONGEST  }, INT_MIN, INT_MAX, A, "duration" },
 -        { "shortest", "Duration of shortest input.", 0, AV_OPT_TYPE_CONST, { .i64 = DURATION_SHORTEST }, INT_MIN, INT_MAX, A, "duration" },
 -        { "first",    "Duration of first input.",    0, AV_OPT_TYPE_CONST, { .i64 = DURATION_FIRST    }, INT_MIN, INT_MAX, A, "duration" },
++            OFFSET(duration_mode), AV_OPT_TYPE_INT, { .i64 = DURATION_LONGEST }, 0,  2, A|F, "duration" },
 +        { "longest",  "Duration of longest input.",  0, AV_OPT_TYPE_CONST, { .i64 = DURATION_LONGEST  }, INT_MIN, INT_MAX, A|F, "duration" },
 +        { "shortest", "Duration of shortest input.", 0, AV_OPT_TYPE_CONST, { .i64 = DURATION_SHORTEST }, INT_MIN, INT_MAX, A|F, "duration" },
 +        { "first",    "Duration of first input.",    0, AV_OPT_TYPE_CONST, { .i64 = DURATION_FIRST    }, INT_MIN, INT_MAX, A|F, "duration" },
      { "dropout_transition", "Transition time, in seconds, for volume "
                              "renormalization when an input stream ends.",
 -            OFFSET(dropout_transition), AV_OPT_TYPE_FLOAT, { 2.0 }, 0, INT_MAX, A },
 +            OFFSET(dropout_transition), AV_OPT_TYPE_FLOAT, { 2.0 }, 0, INT_MAX, A|F },
      { NULL },
  };
  
index 465f837,0000000..467af76
mode 100644,000000..100644
--- /dev/null
@@@ -1,205 -1,0 +1,205 @@@
- { "pad", "pad last frame with zeros", OFFSET(pad), AV_OPT_TYPE_INT, {.dbl=1}, 0, 1, FLAGS },
- { "p",   "pad last frame with zeros", OFFSET(pad), AV_OPT_TYPE_INT, {.dbl=1}, 0, 1, FLAGS },
- { "nb_out_samples", "set the number of per-frame output samples", OFFSET(nb_out_samples), AV_OPT_TYPE_INT, {.dbl=1024}, 1, INT_MAX, FLAGS },
- { "n",              "set the number of per-frame output samples", OFFSET(nb_out_samples), AV_OPT_TYPE_INT, {.dbl=1024}, 1, INT_MAX, FLAGS },
 +/*
 + * Copyright (c) 2012 Andrey Utkin
 + * Copyright (c) 2012 Stefano Sabatini
 + *
 + * This file is part of FFmpeg.
 + *
 + * FFmpeg is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU Lesser General Public
 + * License as published by the Free Software Foundation; either
 + * version 2.1 of the License, or (at your option) any later version.
 + *
 + * FFmpeg is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 + * Lesser General Public License for more details.
 + *
 + * You should have received a copy of the GNU Lesser General Public
 + * License along with FFmpeg; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 + */
 +
 +/**
 + * @file
 + * Filter that changes number of samples on single output operation
 + */
 +
 +#include "libavutil/audio_fifo.h"
 +#include "libavutil/audioconvert.h"
 +#include "libavutil/avassert.h"
 +#include "libavutil/opt.h"
 +#include "avfilter.h"
 +#include "audio.h"
 +#include "internal.h"
 +#include "formats.h"
 +
 +typedef struct {
 +    const AVClass *class;
 +    int nb_out_samples;  ///< how many samples to output
 +    AVAudioFifo *fifo;   ///< samples are queued here
 +    int64_t next_out_pts;
 +    int req_fullfilled;
 +    int pad;
 +} ASNSContext;
 +
 +#define OFFSET(x) offsetof(ASNSContext, x)
 +#define FLAGS AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
 +
 +static const AVOption asetnsamples_options[] = {
++{ "pad", "pad last frame with zeros", OFFSET(pad), AV_OPT_TYPE_INT, {.i64=1}, 0, 1, FLAGS },
++{ "p",   "pad last frame with zeros", OFFSET(pad), AV_OPT_TYPE_INT, {.i64=1}, 0, 1, FLAGS },
++{ "nb_out_samples", "set the number of per-frame output samples", OFFSET(nb_out_samples), AV_OPT_TYPE_INT, {.i64=1024}, 1, INT_MAX, FLAGS },
++{ "n",              "set the number of per-frame output samples", OFFSET(nb_out_samples), AV_OPT_TYPE_INT, {.i64=1024}, 1, INT_MAX, FLAGS },
 +{ NULL }
 +};
 +
 +AVFILTER_DEFINE_CLASS(asetnsamples);
 +
 +static av_cold int init(AVFilterContext *ctx, const char *args)
 +{
 +    ASNSContext *asns = ctx->priv;
 +    int err;
 +
 +    asns->class = &asetnsamples_class;
 +    av_opt_set_defaults(asns);
 +
 +    if ((err = av_set_options_string(asns, args, "=", ":")) < 0)
 +        return err;
 +
 +    asns->next_out_pts = AV_NOPTS_VALUE;
 +    av_log(ctx, AV_LOG_VERBOSE, "nb_out_samples:%d pad:%d\n", asns->nb_out_samples, asns->pad);
 +
 +    return 0;
 +}
 +
 +static av_cold void uninit(AVFilterContext *ctx)
 +{
 +    ASNSContext *asns = ctx->priv;
 +    av_audio_fifo_free(asns->fifo);
 +}
 +
 +static int config_props_output(AVFilterLink *outlink)
 +{
 +    ASNSContext *asns = outlink->src->priv;
 +    int nb_channels = av_get_channel_layout_nb_channels(outlink->channel_layout);
 +
 +    asns->fifo = av_audio_fifo_alloc(outlink->format, nb_channels, asns->nb_out_samples);
 +    if (!asns->fifo)
 +        return AVERROR(ENOMEM);
 +
 +    return 0;
 +}
 +
 +static int push_samples(AVFilterLink *outlink)
 +{
 +    ASNSContext *asns = outlink->src->priv;
 +    AVFilterBufferRef *outsamples = NULL;
 +    int nb_out_samples, nb_pad_samples;
 +
 +    if (asns->pad) {
 +        nb_out_samples = av_audio_fifo_size(asns->fifo) ? asns->nb_out_samples : 0;
 +        nb_pad_samples = nb_out_samples - FFMIN(nb_out_samples, av_audio_fifo_size(asns->fifo));
 +    } else {
 +        nb_out_samples = FFMIN(asns->nb_out_samples, av_audio_fifo_size(asns->fifo));
 +        nb_pad_samples = 0;
 +    }
 +
 +    if (!nb_out_samples)
 +        return 0;
 +
 +    outsamples = ff_get_audio_buffer(outlink, AV_PERM_WRITE, nb_out_samples);
 +    av_assert0(outsamples);
 +
 +    av_audio_fifo_read(asns->fifo,
 +                       (void **)outsamples->extended_data, nb_out_samples);
 +
 +    if (nb_pad_samples)
 +        av_samples_set_silence(outsamples->extended_data, nb_out_samples - nb_pad_samples,
 +                               nb_pad_samples, av_get_channel_layout_nb_channels(outlink->channel_layout),
 +                               outlink->format);
 +    outsamples->audio->nb_samples     = nb_out_samples;
 +    outsamples->audio->channel_layout = outlink->channel_layout;
 +    outsamples->audio->sample_rate    = outlink->sample_rate;
 +    outsamples->pts = asns->next_out_pts;
 +
 +    if (asns->next_out_pts != AV_NOPTS_VALUE)
 +        asns->next_out_pts += nb_out_samples;
 +
 +    ff_filter_samples(outlink, outsamples);
 +    asns->req_fullfilled = 1;
 +    return nb_out_samples;
 +}
 +
 +static int filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamples)
 +{
 +    AVFilterContext *ctx = inlink->dst;
 +    ASNSContext *asns = ctx->priv;
 +    AVFilterLink *outlink = ctx->outputs[0];
 +    int ret;
 +    int nb_samples = insamples->audio->nb_samples;
 +
 +    if (av_audio_fifo_space(asns->fifo) < nb_samples) {
 +        av_log(ctx, AV_LOG_DEBUG, "No space for %d samples, stretching audio fifo\n", nb_samples);
 +        ret = av_audio_fifo_realloc(asns->fifo, av_audio_fifo_size(asns->fifo) + nb_samples);
 +        if (ret < 0) {
 +            av_log(ctx, AV_LOG_ERROR,
 +                   "Stretching audio fifo failed, discarded %d samples\n", nb_samples);
 +            return -1;
 +        }
 +    }
 +    av_audio_fifo_write(asns->fifo, (void **)insamples->extended_data, nb_samples);
 +    if (asns->next_out_pts == AV_NOPTS_VALUE)
 +        asns->next_out_pts = insamples->pts;
 +    avfilter_unref_buffer(insamples);
 +
 +    while (av_audio_fifo_size(asns->fifo) >= asns->nb_out_samples)
 +        push_samples(outlink);
 +    return 0;
 +}
 +
 +static int request_frame(AVFilterLink *outlink)
 +{
 +    ASNSContext *asns = outlink->src->priv;
 +    AVFilterLink *inlink = outlink->src->inputs[0];
 +    int ret;
 +
 +    asns->req_fullfilled = 0;
 +    do {
 +        ret = ff_request_frame(inlink);
 +    } while (!asns->req_fullfilled && ret >= 0);
 +
 +    if (ret == AVERROR_EOF)
 +        while (push_samples(outlink))
 +            ;
 +
 +    return ret;
 +}
 +
 +AVFilter avfilter_af_asetnsamples = {
 +    .name           = "asetnsamples",
 +    .description    = NULL_IF_CONFIG_SMALL("Set the number of samples for each output audio frames."),
 +    .priv_size      = sizeof(ASNSContext),
 +    .init           = init,
 +    .uninit         = uninit,
 +
 +    .inputs  = (const AVFilterPad[]) {
 +        {
 +            .name           = "default",
 +            .type           = AVMEDIA_TYPE_AUDIO,
 +            .filter_samples = filter_samples,
 +            .min_perms      = AV_PERM_READ|AV_PERM_WRITE
 +        },
 +        { .name = NULL }
 +    },
 +
 +    .outputs = (const AVFilterPad[]) {
 +        {
 +            .name           = "default",
 +            .type           = AVMEDIA_TYPE_AUDIO,
 +            .request_frame  = request_frame,
 +            .config_props   = config_props_output,
 +        },
 +        { .name = NULL }
 +    },
 +    .priv_class = &asetnsamples_class,
 +};
@@@ -45,13 -45,12 +45,13 @@@ typedef struct ASyncContext 
  
  #define OFFSET(x) offsetof(ASyncContext, x)
  #define A AV_OPT_FLAG_AUDIO_PARAM
 -static const AVOption options[] = {
 -    { "compensate", "Stretch/squeeze the data to make it match the timestamps", OFFSET(resample),      AV_OPT_TYPE_INT,   { .i64 = 0 },   0, 1,       A },
 +#define F AV_OPT_FLAG_FILTERING_PARAM
 +static const AVOption asyncts_options[] = {
-     { "compensate", "Stretch/squeeze the data to make it match the timestamps", OFFSET(resample),      AV_OPT_TYPE_INT,   { 0 },   0, 1,       A|F },
++    { "compensate", "Stretch/squeeze the data to make it match the timestamps", OFFSET(resample),      AV_OPT_TYPE_INT,   { .i64 = 0 },   0, 1,       A|F },
      { "min_delta",  "Minimum difference between timestamps and audio data "
 -                    "(in seconds) to trigger padding/trimmin the data.",        OFFSET(min_delta_sec), AV_OPT_TYPE_FLOAT, { 0.1 }, 0, INT_MAX, A },
 -    { "max_comp",   "Maximum compensation in samples per second.",              OFFSET(max_comp),      AV_OPT_TYPE_INT,   { .i64 = 500 }, 0, INT_MAX, A },
 -    { "first_pts",  "Assume the first pts should be this value.",               OFFSET(pts),           AV_OPT_TYPE_INT64, { .i64 = AV_NOPTS_VALUE }, INT64_MIN, INT64_MAX, A },
 +                    "(in seconds) to trigger padding/trimmin the data.",        OFFSET(min_delta_sec), AV_OPT_TYPE_FLOAT, { 0.1 }, 0, INT_MAX, A|F },
-     { "max_comp",   "Maximum compensation in samples per second.",              OFFSET(max_comp),      AV_OPT_TYPE_INT,   { 500 }, 0, INT_MAX, A|F },
++    { "max_comp",   "Maximum compensation in samples per second.",              OFFSET(max_comp),      AV_OPT_TYPE_INT,   { .i64 = 500 }, 0, INT_MAX, A|F },
 +    { "first_pts",  "Assume the first pts should be this value.",               OFFSET(pts),           AV_OPT_TYPE_INT64, { .i64 = AV_NOPTS_VALUE }, INT64_MIN, INT64_MAX, A|F },
      { NULL },
  };
  
@@@ -76,14 -76,13 +76,14 @@@ typedef struct JoinBufferPriv 
  
  #define OFFSET(x) offsetof(JoinContext, x)
  #define A AV_OPT_FLAG_AUDIO_PARAM
 +#define F AV_OPT_FLAG_FILTERING_PARAM
  static const AVOption join_options[] = {
-     { "inputs",         "Number of input streams.", OFFSET(inputs),             AV_OPT_TYPE_INT,    { 2 }, 1, INT_MAX,       A|F },
 -    { "inputs",         "Number of input streams.", OFFSET(inputs),             AV_OPT_TYPE_INT,    { .i64 = 2 }, 1, INT_MAX,       A },
++    { "inputs",         "Number of input streams.", OFFSET(inputs),             AV_OPT_TYPE_INT,    { .i64 = 2 }, 1, INT_MAX,       A|F },
      { "channel_layout", "Channel layout of the "
 -                        "output stream.",           OFFSET(channel_layout_str), AV_OPT_TYPE_STRING, {.str = "stereo"}, 0, 0, A },
 +                        "output stream.",           OFFSET(channel_layout_str), AV_OPT_TYPE_STRING, {.str = "stereo"}, 0, 0, A|F },
      { "map",            "A comma-separated list of channels maps in the format "
                          "'input_stream.input_channel-output_channel.",
 -                                                    OFFSET(map),                AV_OPT_TYPE_STRING,                 .flags = A },
 +                                                    OFFSET(map),                AV_OPT_TYPE_STRING,                 .flags = A|F },
      { NULL },
  };
  
index d6bcd63,0000000..aea94b2
mode 100644,000000..100644
--- /dev/null
@@@ -1,170 -1,0 +1,170 @@@
-     { "d",         "set minimum duration in seconds",  OFFSET(duration),  AV_OPT_TYPE_INT,    {.dbl=2},    0, INT_MAX, FLAGS },
-     { "duration",  "set minimum duration in seconds",  OFFSET(duration),  AV_OPT_TYPE_INT,    {.dbl=2},    0, INT_MAX, FLAGS },
 +/*
 + * Copyright (c) 2012 Clément Bœsch <ubitux@gmail.com>
 + *
 + * This file is part of FFmpeg.
 + *
 + * FFmpeg is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU Lesser General Public
 + * License as published by the Free Software Foundation; either
 + * version 2.1 of the License, or (at your option) any later version.
 + *
 + * FFmpeg is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 + * Lesser General Public License for more details.
 + *
 + * You should have received a copy of the GNU Lesser General Public
 + * License along with FFmpeg; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 + */
 +
 +/**
 + * @file
 + * Audio silence detector
 + */
 +
 +#include "libavutil/audioconvert.h"
 +#include "libavutil/opt.h"
 +#include "libavutil/timestamp.h"
 +#include "audio.h"
 +#include "formats.h"
 +#include "avfilter.h"
 +#include "internal.h"
 +
 +typedef struct {
 +    const AVClass *class;
 +    char *noise_str;            ///< noise option string
 +    double noise;               ///< noise amplitude ratio
 +    int duration;               ///< minimum duration of silence until notification
 +    int64_t nb_null_samples;    ///< current number of continuous zero samples
 +    int64_t start;              ///< if silence is detected, this value contains the time of the first zero sample
 +    int last_sample_rate;       ///< last sample rate to check for sample rate changes
 +} SilenceDetectContext;
 +
 +#define OFFSET(x) offsetof(SilenceDetectContext, x)
 +#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_AUDIO_PARAM
 +static const AVOption silencedetect_options[] = {
 +    { "n",         "set noise tolerance",              OFFSET(noise_str), AV_OPT_TYPE_STRING, {.str="-60dB"}, CHAR_MIN, CHAR_MAX, FLAGS },
 +    { "noise",     "set noise tolerance",              OFFSET(noise_str), AV_OPT_TYPE_STRING, {.str="-60dB"}, CHAR_MIN, CHAR_MAX, FLAGS },
++    { "d",         "set minimum duration in seconds",  OFFSET(duration),  AV_OPT_TYPE_INT,    {.i64=2},    0, INT_MAX, FLAGS },
++    { "duration",  "set minimum duration in seconds",  OFFSET(duration),  AV_OPT_TYPE_INT,    {.i64=2},    0, INT_MAX, FLAGS },
 +    { NULL },
 +};
 +
 +AVFILTER_DEFINE_CLASS(silencedetect);
 +
 +static av_cold int init(AVFilterContext *ctx, const char *args)
 +{
 +    int ret;
 +    char *tail;
 +    SilenceDetectContext *silence = ctx->priv;
 +
 +    silence->class = &silencedetect_class;
 +    av_opt_set_defaults(silence);
 +
 +    if ((ret = av_set_options_string(silence, args, "=", ":")) < 0)
 +        return ret;
 +
 +    silence->noise = strtod(silence->noise_str, &tail);
 +    if (!strcmp(tail, "dB")) {
 +        silence->noise = pow(10, silence->noise/20);
 +    } else if (*tail) {
 +        av_log(ctx, AV_LOG_ERROR, "Invalid value '%s' for noise parameter.\n",
 +               silence->noise_str);
 +        return AVERROR(EINVAL);
 +    }
 +
 +    return 0;
 +}
 +
 +static int filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamples)
 +{
 +    int i;
 +    SilenceDetectContext *silence = inlink->dst->priv;
 +    const int nb_channels           = av_get_channel_layout_nb_channels(inlink->channel_layout);
 +    const int srate                 = inlink->sample_rate;
 +    const int nb_samples            = insamples->audio->nb_samples * nb_channels;
 +    const int64_t nb_samples_notify = srate * silence->duration    * nb_channels;
 +
 +    // scale number of null samples to the new sample rate
 +    if (silence->last_sample_rate && silence->last_sample_rate != srate)
 +        silence->nb_null_samples =
 +            srate * silence->nb_null_samples / silence->last_sample_rate;
 +    silence->last_sample_rate = srate;
 +
 +    // TODO: support more sample formats
 +    if (insamples->format == AV_SAMPLE_FMT_DBL) {
 +        double *p = (double *)insamples->data[0];
 +
 +        for (i = 0; i < nb_samples; i++, p++) {
 +            if (*p < silence->noise && *p > -silence->noise) {
 +                if (!silence->start) {
 +                    silence->nb_null_samples++;
 +                    if (silence->nb_null_samples >= nb_samples_notify) {
 +                        silence->start = insamples->pts - silence->duration / av_q2d(inlink->time_base);
 +                        av_log(silence, AV_LOG_INFO,
 +                               "silence_start: %s\n", av_ts2timestr(silence->start, &inlink->time_base));
 +                    }
 +                }
 +            } else {
 +                if (silence->start)
 +                    av_log(silence, AV_LOG_INFO,
 +                           "silence_end: %s | silence_duration: %s\n",
 +                           av_ts2timestr(insamples->pts,                  &inlink->time_base),
 +                           av_ts2timestr(insamples->pts - silence->start, &inlink->time_base));
 +                silence->nb_null_samples = silence->start = 0;
 +            }
 +        }
 +    }
 +
 +    return ff_filter_samples(inlink->dst->outputs[0], insamples);
 +}
 +
 +static int query_formats(AVFilterContext *ctx)
 +{
 +    AVFilterFormats *formats = NULL;
 +    AVFilterChannelLayouts *layouts = NULL;
 +    enum AVSampleFormat sample_fmts[] = {
 +        AV_SAMPLE_FMT_DBL,
 +        AV_SAMPLE_FMT_NONE
 +    };
 +
 +    layouts = ff_all_channel_layouts();
 +    if (!layouts)
 +        return AVERROR(ENOMEM);
 +    ff_set_common_channel_layouts(ctx, layouts);
 +
 +    formats = ff_make_format_list(sample_fmts);
 +    if (!formats)
 +        return AVERROR(ENOMEM);
 +    ff_set_common_formats(ctx, formats);
 +
 +    formats = ff_all_samplerates();
 +    if (!formats)
 +        return AVERROR(ENOMEM);
 +    ff_set_common_samplerates(ctx, formats);
 +
 +    return 0;
 +}
 +
 +AVFilter avfilter_af_silencedetect = {
 +    .name          = "silencedetect",
 +    .description   = NULL_IF_CONFIG_SMALL("Detect silence."),
 +    .priv_size     = sizeof(SilenceDetectContext),
 +    .init          = init,
 +    .query_formats = query_formats,
 +
 +    .inputs = (const AVFilterPad[]) {
 +        { .name             = "default",
 +          .type             = AVMEDIA_TYPE_AUDIO,
 +          .get_audio_buffer = ff_null_get_audio_buffer,
 +          .filter_samples   = filter_samples, },
 +        { .name = NULL }
 +    },
 +    .outputs = (const AVFilterPad[]) {
 +        { .name = "default",
 +          .type = AVMEDIA_TYPE_AUDIO, },
 +        { .name = NULL }
 +    },
 +    .priv_class = &silencedetect_class,
 +};
index dbeeba2,0000000..71eadfc
mode 100644,000000..100644
--- /dev/null
@@@ -1,256 -1,0 +1,256 @@@
-     { "nb_samples",  "set the number of samples per requested frame", OFFSET(nb_samples),      AV_OPT_TYPE_INT,    {.dbl = 1024},    0,        INT_MAX, FLAGS },
-     { "n",           "set the number of samples per requested frame", OFFSET(nb_samples),      AV_OPT_TYPE_INT,    {.dbl = 1024},    0,        INT_MAX, FLAGS },
 +/*
 + * Copyright (c) 2011 Stefano Sabatini
 + *
 + * This file is part of FFmpeg.
 + *
 + * FFmpeg is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU Lesser General Public
 + * License as published by the Free Software Foundation; either
 + * version 2.1 of the License, or (at your option) any later version.
 + *
 + * FFmpeg is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 + * Lesser General Public License for more details.
 + *
 + * You should have received a copy of the GNU Lesser General Public
 + * License along with FFmpeg; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 + */
 +
 +/**
 + * @file
 + * eval audio source
 + */
 +
 +#include "libavutil/audioconvert.h"
 +#include "libavutil/avassert.h"
 +#include "libavutil/avstring.h"
 +#include "libavutil/eval.h"
 +#include "libavutil/opt.h"
 +#include "libavutil/parseutils.h"
 +#include "avfilter.h"
 +#include "audio.h"
 +#include "internal.h"
 +
 +static const char * const var_names[] = {
 +    "n",            ///< number of frame
 +    "t",            ///< timestamp expressed in seconds
 +    "s",            ///< sample rate
 +    NULL
 +};
 +
 +enum var_name {
 +    VAR_N,
 +    VAR_T,
 +    VAR_S,
 +    VAR_VARS_NB
 +};
 +
 +typedef struct {
 +    const AVClass *class;
 +    char *sample_rate_str;
 +    int sample_rate;
 +    int64_t chlayout;
 +    char *chlayout_str;
 +    int nb_channels;
 +    int64_t pts;
 +    AVExpr *expr[8];
 +    char *expr_str[8];
 +    int nb_samples;             ///< number of samples per requested frame
 +    char *duration_str;         ///< total duration of the generated audio
 +    double duration;
 +    uint64_t n;
 +    double var_values[VAR_VARS_NB];
 +} EvalContext;
 +
 +#define OFFSET(x) offsetof(EvalContext, x)
 +#define FLAGS AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
 +
 +static const AVOption aevalsrc_options[]= {
++    { "nb_samples",  "set the number of samples per requested frame", OFFSET(nb_samples),      AV_OPT_TYPE_INT,    {.i64 = 1024},    0,        INT_MAX, FLAGS },
++    { "n",           "set the number of samples per requested frame", OFFSET(nb_samples),      AV_OPT_TYPE_INT,    {.i64 = 1024},    0,        INT_MAX, FLAGS },
 +    { "sample_rate", "set the sample rate",                           OFFSET(sample_rate_str), AV_OPT_TYPE_STRING, {.str = "44100"}, CHAR_MIN, CHAR_MAX, FLAGS },
 +    { "s",           "set the sample rate",                           OFFSET(sample_rate_str), AV_OPT_TYPE_STRING, {.str = "44100"}, CHAR_MIN, CHAR_MAX, FLAGS },
 +    { "duration",    "set audio duration", OFFSET(duration_str), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, FLAGS },
 +    { "d",           "set audio duration", OFFSET(duration_str), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, FLAGS },
 +    { "channel_layout", "set channel layout", OFFSET(chlayout_str), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, FLAGS },
 +    { "c",              "set channel layout", OFFSET(chlayout_str), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, FLAGS },
 +{NULL},
 +};
 +
 +AVFILTER_DEFINE_CLASS(aevalsrc);
 +
 +static int init(AVFilterContext *ctx, const char *args)
 +{
 +    EvalContext *eval = ctx->priv;
 +    char *args1 = av_strdup(args);
 +    char *expr, *buf, *bufptr;
 +    int ret, i;
 +
 +    eval->class = &aevalsrc_class;
 +    av_opt_set_defaults(eval);
 +
 +    /* parse expressions */
 +    buf = args1;
 +    i = 0;
 +    while (expr = av_strtok(buf, ":", &bufptr)) {
 +        ret = av_expr_parse(&eval->expr[i], expr, var_names,
 +                            NULL, NULL, NULL, NULL, 0, ctx);
 +        if (ret < 0)
 +            goto end;
 +        i++;
 +        if (bufptr && *bufptr == ':') { /* found last expression */
 +            bufptr++;
 +            break;
 +        }
 +        buf = NULL;
 +    }
 +    eval->nb_channels = i;
 +
 +    if (bufptr && (ret = av_set_options_string(eval, bufptr, "=", ":")) < 0)
 +        goto end;
 +
 +    if (eval->chlayout_str) {
 +        int n;
 +        ret = ff_parse_channel_layout(&eval->chlayout, eval->chlayout_str, ctx);
 +        if (ret < 0)
 +            goto end;
 +
 +        n = av_get_channel_layout_nb_channels(eval->chlayout);
 +        if (n != eval->nb_channels) {
 +            av_log(ctx, AV_LOG_ERROR,
 +                   "Mismatch between the specified number of channels '%d' "
 +                   "and the number of channels '%d' in the specified channel layout '%s'\n",
 +                   eval->nb_channels, n, eval->chlayout_str);
 +            ret = AVERROR(EINVAL);
 +            goto end;
 +        }
 +    } else {
 +        /* guess channel layout from nb expressions/channels */
 +        eval->chlayout = av_get_default_channel_layout(eval->nb_channels);
 +        if (!eval->chlayout) {
 +            av_log(ctx, AV_LOG_ERROR, "Invalid number of channels '%d' provided\n",
 +                   eval->nb_channels);
 +            ret = AVERROR(EINVAL);
 +            goto end;
 +        }
 +    }
 +
 +    if ((ret = ff_parse_sample_rate(&eval->sample_rate, eval->sample_rate_str, ctx)))
 +        goto end;
 +
 +    eval->duration = -1;
 +    if (eval->duration_str) {
 +        int64_t us = -1;
 +        if ((ret = av_parse_time(&us, eval->duration_str, 1)) < 0) {
 +            av_log(ctx, AV_LOG_ERROR, "Invalid duration: '%s'\n", eval->duration_str);
 +            goto end;
 +        }
 +        eval->duration = (double)us / 1000000;
 +    }
 +    eval->n = 0;
 +
 +end:
 +    av_free(args1);
 +    return ret;
 +}
 +
 +static void uninit(AVFilterContext *ctx)
 +{
 +    EvalContext *eval = ctx->priv;
 +    int i;
 +
 +    for (i = 0; i < 8; i++) {
 +        av_expr_free(eval->expr[i]);
 +        eval->expr[i] = NULL;
 +    }
 +    av_freep(&eval->chlayout_str);
 +    av_freep(&eval->duration_str);
 +    av_freep(&eval->sample_rate_str);
 +}
 +
 +static int config_props(AVFilterLink *outlink)
 +{
 +    EvalContext *eval = outlink->src->priv;
 +    char buf[128];
 +
 +    outlink->time_base = (AVRational){1, eval->sample_rate};
 +    outlink->sample_rate = eval->sample_rate;
 +
 +    eval->var_values[VAR_S] = eval->sample_rate;
 +
 +    av_get_channel_layout_string(buf, sizeof(buf), 0, eval->chlayout);
 +
 +    av_log(outlink->src, AV_LOG_VERBOSE,
 +           "sample_rate:%d chlayout:%s duration:%f\n",
 +           eval->sample_rate, buf, eval->duration);
 +
 +    return 0;
 +}
 +
 +static int query_formats(AVFilterContext *ctx)
 +{
 +    EvalContext *eval = ctx->priv;
 +    enum AVSampleFormat sample_fmts[] = { AV_SAMPLE_FMT_DBLP, AV_SAMPLE_FMT_NONE };
 +    int64_t chlayouts[] = { eval->chlayout, -1 };
 +    int sample_rates[] = { eval->sample_rate, -1 };
 +
 +    ff_set_common_formats (ctx, ff_make_format_list(sample_fmts));
 +    ff_set_common_channel_layouts(ctx, avfilter_make_format64_list(chlayouts));
 +    ff_set_common_samplerates(ctx, ff_make_format_list(sample_rates));
 +
 +    return 0;
 +}
 +
 +static int request_frame(AVFilterLink *outlink)
 +{
 +    EvalContext *eval = outlink->src->priv;
 +    AVFilterBufferRef *samplesref;
 +    int i, j;
 +    double t = eval->var_values[VAR_N] * (double)1/eval->sample_rate;
 +
 +    if (eval->duration >= 0 && t > eval->duration)
 +        return AVERROR_EOF;
 +
 +    samplesref = ff_get_audio_buffer(outlink, AV_PERM_WRITE, eval->nb_samples);
 +
 +    /* evaluate expression for each single sample and for each channel */
 +    for (i = 0; i < eval->nb_samples; i++, eval->n++) {
 +        eval->var_values[VAR_N] = eval->n;
 +        eval->var_values[VAR_T] = eval->var_values[VAR_N] * (double)1/eval->sample_rate;
 +
 +        for (j = 0; j < eval->nb_channels; j++) {
 +            *((double *) samplesref->extended_data[j] + i) =
 +                av_expr_eval(eval->expr[j], eval->var_values, NULL);
 +        }
 +    }
 +
 +    samplesref->pts = eval->pts;
 +    samplesref->pos = -1;
 +    samplesref->audio->sample_rate = eval->sample_rate;
 +    eval->pts += eval->nb_samples;
 +
 +    ff_filter_samples(outlink, samplesref);
 +
 +    return 0;
 +}
 +
 +AVFilter avfilter_asrc_aevalsrc = {
 +    .name        = "aevalsrc",
 +    .description = NULL_IF_CONFIG_SMALL("Generate an audio signal generated by an expression."),
 +
 +    .query_formats = query_formats,
 +    .init        = init,
 +    .uninit      = uninit,
 +    .priv_size   = sizeof(EvalContext),
 +
 +    .inputs      = (const AVFilterPad[]) {{ .name = NULL}},
 +
 +    .outputs     = (const AVFilterPad[]) {{ .name = "default",
 +                                      .type = AVMEDIA_TYPE_AUDIO,
 +                                      .config_props = config_props,
 +                                      .request_frame = request_frame, },
 +                                    { .name = NULL}},
 +    .priv_class = &aevalsrc_class,
 +};
  #include <inttypes.h>
  #include <stdio.h>
  
 +#include "audio.h"
  #include "avfilter.h"
  #include "internal.h"
 +
  #include "libavutil/audioconvert.h"
  #include "libavutil/internal.h"
 +#include "libavutil/opt.h"
  
  typedef struct {
 +    const AVClass *class;
 +    char   *channel_layout_str;
      uint64_t channel_layout;
 -    int64_t sample_rate;
 +    char   *sample_rate_str;
 +    int     sample_rate;
 +    int nb_samples;             ///< number of samples per requested frame
 +    int64_t pts;
  } ANullContext;
  
-     { "nb_samples",     "set the number of samples per requested frame", OFFSET(nb_samples), AV_OPT_TYPE_INT, {.dbl = 1024}, 0, INT_MAX, FLAGS },
-     { "n",              "set the number of samples per requested frame", OFFSET(nb_samples), AV_OPT_TYPE_INT, {.dbl = 1024}, 0, INT_MAX, FLAGS },
 +#define OFFSET(x) offsetof(ANullContext, x)
 +#define FLAGS AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
 +
 +static const AVOption anullsrc_options[]= {
 +    { "channel_layout", "set channel_layout", OFFSET(channel_layout_str), AV_OPT_TYPE_STRING, {.str = "stereo"}, 0, 0, FLAGS },
 +    { "cl",             "set channel_layout", OFFSET(channel_layout_str), AV_OPT_TYPE_STRING, {.str = "stereo"}, 0, 0, FLAGS },
 +    { "sample_rate",    "set sample rate",    OFFSET(sample_rate_str)   , AV_OPT_TYPE_STRING, {.str = "44100"}, 0, 0, FLAGS },
 +    { "r",              "set sample rate",    OFFSET(sample_rate_str)   , AV_OPT_TYPE_STRING, {.str = "44100"}, 0, 0, FLAGS },
++    { "nb_samples",     "set the number of samples per requested frame", OFFSET(nb_samples), AV_OPT_TYPE_INT, {.i64 = 1024}, 0, INT_MAX, FLAGS },
++    { "n",              "set the number of samples per requested frame", OFFSET(nb_samples), AV_OPT_TYPE_INT, {.i64 = 1024}, 0, INT_MAX, FLAGS },
 +    { NULL },
 +};
 +
 +AVFILTER_DEFINE_CLASS(anullsrc);
 +
  static int init(AVFilterContext *ctx, const char *args)
  {
 -    ANullContext *priv = ctx->priv;
 -    char channel_layout_str[128] = "";
 +    ANullContext *null = ctx->priv;
 +    int ret;
  
 -    priv->sample_rate = 44100;
 -    priv->channel_layout = AV_CH_LAYOUT_STEREO;
 +    null->class = &anullsrc_class;
 +    av_opt_set_defaults(null);
  
 -    if (args)
 -        sscanf(args, "%"PRId64":%s", &priv->sample_rate, channel_layout_str);
 +    if ((ret = (av_set_options_string(null, args, "=", ":"))) < 0)
 +        return ret;
  
 -    if (priv->sample_rate < 0) {
 -        av_log(ctx, AV_LOG_ERROR, "Invalid negative sample rate: %"PRId64"\n", priv->sample_rate);
 -        return AVERROR(EINVAL);
 -    }
 +    if ((ret = ff_parse_sample_rate(&null->sample_rate,
 +                                     null->sample_rate_str, ctx)) < 0)
 +        return ret;
  
 -    if (*channel_layout_str)
 -        if (!(priv->channel_layout = av_get_channel_layout(channel_layout_str))
 -            && sscanf(channel_layout_str, "%"PRId64, &priv->channel_layout) != 1) {
 -            av_log(ctx, AV_LOG_ERROR, "Invalid value '%s' for channel layout\n",
 -                   channel_layout_str);
 -            return AVERROR(EINVAL);
 -        }
 +    if ((ret = ff_parse_channel_layout(&null->channel_layout,
 +                                        null->channel_layout_str, ctx)) < 0)
 +        return ret;
  
      return 0;
  }
index d4a8b10,0000000..6f8cc95
mode 100644,000000..100644
--- /dev/null
@@@ -1,292 -1,0 +1,292 @@@
-     { "list_voices", "list voices and exit",              OFFSET(list_voices), AV_OPT_TYPE_INT, {.dbl=0}, 0, 1, FLAGS },
-     { "nb_samples",  "set number of samples per frame",   OFFSET(frame_nb_samples), AV_OPT_TYPE_INT, {.dbl=512}, 0, INT_MAX, FLAGS },
-     { "n",           "set number of samples per frame",   OFFSET(frame_nb_samples), AV_OPT_TYPE_INT, {.dbl=512}, 0, INT_MAX, FLAGS },
 +/*
 + * Copyright (c) 2012 Stefano Sabatini
 + *
 + * This file is part of FFmpeg.
 + *
 + * FFmpeg is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU Lesser General Public
 + * License as published by the Free Software Foundation; either
 + * version 2.1 of the License, or (at your option) any later version.
 + *
 + * FFmpeg is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 + * Lesser General Public License for more details.
 + *
 + * You should have received a copy of the GNU Lesser General Public
 + * License along with FFmpeg; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 + */
 +
 +/**
 + * @file
 + * flite voice synth source
 + */
 +
 +#include <flite/flite.h>
 +#include "libavutil/audioconvert.h"
 +#include "libavutil/file.h"
 +#include "libavutil/opt.h"
 +#include "avfilter.h"
 +#include "audio.h"
 +#include "formats.h"
 +#include "internal.h"
 +
 +typedef struct {
 +    const AVClass *class;
 +    char *voice_str;
 +    char *textfile;
 +    char *text;
 +    cst_wave *wave;
 +    int16_t *wave_samples;
 +    int      wave_nb_samples;
 +    int list_voices;
 +    cst_voice *voice;
 +    struct voice_entry *voice_entry;
 +    int64_t pts;
 +    int frame_nb_samples; ///< number of samples per frame
 +} FliteContext;
 +
 +#define OFFSET(x) offsetof(FliteContext, x)
 +#define FLAGS AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
 +
 +static const AVOption flite_options[] = {
++    { "list_voices", "list voices and exit",              OFFSET(list_voices), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, FLAGS },
++    { "nb_samples",  "set number of samples per frame",   OFFSET(frame_nb_samples), AV_OPT_TYPE_INT, {.i64=512}, 0, INT_MAX, FLAGS },
++    { "n",           "set number of samples per frame",   OFFSET(frame_nb_samples), AV_OPT_TYPE_INT, {.i64=512}, 0, INT_MAX, FLAGS },
 +    { "text",        "set text to speak",                 OFFSET(text),      AV_OPT_TYPE_STRING, {.str=NULL}, CHAR_MIN, CHAR_MAX, FLAGS },
 +    { "textfile",    "set filename of the text to speak", OFFSET(textfile),  AV_OPT_TYPE_STRING, {.str=NULL}, CHAR_MIN, CHAR_MAX, FLAGS },
 +    { "v",           "set voice",                         OFFSET(voice_str), AV_OPT_TYPE_STRING, {.str="kal"}, CHAR_MIN, CHAR_MAX, FLAGS },
 +    { "voice",       "set voice",                         OFFSET(voice_str), AV_OPT_TYPE_STRING, {.str="kal"}, CHAR_MIN, CHAR_MAX, FLAGS },
 +    { NULL }
 +};
 +
 +AVFILTER_DEFINE_CLASS(flite);
 +
 +static volatile int flite_inited = 0;
 +
 +/* declare functions for all the supported voices */
 +#define DECLARE_REGISTER_VOICE_FN(name) \
 +    cst_voice *register_cmu_us_## name(const char *); \
 +    void     unregister_cmu_us_## name(cst_voice *);
 +DECLARE_REGISTER_VOICE_FN(awb);
 +DECLARE_REGISTER_VOICE_FN(kal);
 +DECLARE_REGISTER_VOICE_FN(kal16);
 +DECLARE_REGISTER_VOICE_FN(rms);
 +DECLARE_REGISTER_VOICE_FN(slt);
 +
 +struct voice_entry {
 +    const char *name;
 +    cst_voice * (*register_fn)(const char *);
 +    void (*unregister_fn)(cst_voice *);
 +    cst_voice *voice;
 +    unsigned usage_count;
 +} voice_entry;
 +
 +#define MAKE_VOICE_STRUCTURE(voice_name) {             \
 +    .name          =                      #voice_name, \
 +    .register_fn   =   register_cmu_us_ ## voice_name, \
 +    .unregister_fn = unregister_cmu_us_ ## voice_name, \
 +}
 +static struct voice_entry voice_entries[] = {
 +    MAKE_VOICE_STRUCTURE(awb),
 +    MAKE_VOICE_STRUCTURE(kal),
 +    MAKE_VOICE_STRUCTURE(kal16),
 +    MAKE_VOICE_STRUCTURE(rms),
 +    MAKE_VOICE_STRUCTURE(slt),
 +};
 +
 +static void list_voices(void *log_ctx, const char *sep)
 +{
 +    int i, n = FF_ARRAY_ELEMS(voice_entries);
 +    for (i = 0; i < n; i++)
 +        av_log(log_ctx, AV_LOG_INFO, "%s%s",
 +               voice_entries[i].name, i < (n-1) ? sep : "\n");
 +}
 +
 +static int select_voice(struct voice_entry **entry_ret, const char *voice_name, void *log_ctx)
 +{
 +    int i;
 +
 +    for (i = 0; i < FF_ARRAY_ELEMS(voice_entries); i++) {
 +        struct voice_entry *entry = &voice_entries[i];
 +        if (!strcmp(entry->name, voice_name)) {
 +            if (!entry->voice)
 +                entry->voice = entry->register_fn(NULL);
 +            if (!entry->voice) {
 +                av_log(log_ctx, AV_LOG_ERROR,
 +                       "Could not register voice '%s'\n", voice_name);
 +                return AVERROR_UNKNOWN;
 +            }
 +            entry->usage_count++;
 +            *entry_ret = entry;
 +            return 0;
 +        }
 +    }
 +
 +    av_log(log_ctx, AV_LOG_ERROR, "Could not find voice '%s'\n", voice_name);
 +    av_log(log_ctx, AV_LOG_INFO, "Choose between the voices: ");
 +    list_voices(log_ctx, ", ");
 +
 +    return AVERROR(EINVAL);
 +}
 +
 +static av_cold int init(AVFilterContext *ctx, const char *args)
 +{
 +    FliteContext *flite = ctx->priv;
 +    int ret = 0;
 +
 +    flite->class = &flite_class;
 +    av_opt_set_defaults(flite);
 +
 +    if ((ret = av_set_options_string(flite, args, "=", ":")) < 0)
 +        return ret;
 +
 +    if (flite->list_voices) {
 +        list_voices(ctx, "\n");
 +        return AVERROR_EXIT;
 +    }
 +
 +    if (!flite_inited) {
 +        if (flite_init() < 0) {
 +            av_log(ctx, AV_LOG_ERROR, "flite initialization failed\n");
 +            return AVERROR_UNKNOWN;
 +        }
 +        flite_inited++;
 +    }
 +
 +    if ((ret = select_voice(&flite->voice_entry, flite->voice_str, ctx)) < 0)
 +        return ret;
 +    flite->voice = flite->voice_entry->voice;
 +
 +    if (flite->textfile && flite->text) {
 +        av_log(ctx, AV_LOG_ERROR,
 +               "Both text and textfile options set: only one must be specified\n");
 +        return AVERROR(EINVAL);
 +    }
 +
 +    if (flite->textfile) {
 +        uint8_t *textbuf;
 +        size_t textbuf_size;
 +
 +        if ((ret = av_file_map(flite->textfile, &textbuf, &textbuf_size, 0, ctx)) < 0) {
 +            av_log(ctx, AV_LOG_ERROR,
 +                   "The text file '%s' could not be read: %s\n",
 +                   flite->textfile, av_err2str(ret));
 +            return ret;
 +        }
 +
 +        if (!(flite->text = av_malloc(textbuf_size+1)))
 +            return AVERROR(ENOMEM);
 +        memcpy(flite->text, textbuf, textbuf_size);
 +        flite->text[textbuf_size] = 0;
 +        av_file_unmap(textbuf, textbuf_size);
 +    }
 +
 +    if (!flite->text) {
 +        av_log(ctx, AV_LOG_ERROR,
 +               "No speech text specified, specify the 'text' or 'textfile' option\n");
 +        return AVERROR(EINVAL);
 +    }
 +
 +    /* synth all the file data in block */
 +    flite->wave = flite_text_to_wave(flite->text, flite->voice);
 +    flite->wave_samples    = flite->wave->samples;
 +    flite->wave_nb_samples = flite->wave->num_samples;
 +    return 0;
 +}
 +
 +static av_cold void uninit(AVFilterContext *ctx)
 +{
 +    FliteContext *flite = ctx->priv;
 +
 +    av_opt_free(flite);
 +
 +    if (!--flite->voice_entry->usage_count)
 +        flite->voice_entry->unregister_fn(flite->voice);
 +    flite->voice = NULL;
 +    flite->voice_entry = NULL;
 +    delete_wave(flite->wave);
 +    flite->wave = NULL;
 +}
 +
 +static int query_formats(AVFilterContext *ctx)
 +{
 +    FliteContext *flite = ctx->priv;
 +
 +    AVFilterChannelLayouts *chlayouts = NULL;
 +    int64_t chlayout = av_get_default_channel_layout(flite->wave->num_channels);
 +    AVFilterFormats *sample_formats = NULL;
 +    AVFilterFormats *sample_rates = NULL;
 +
 +    ff_add_channel_layout(&chlayouts, chlayout);
 +    ff_set_common_channel_layouts(ctx, chlayouts);
 +    ff_add_format(&sample_formats, AV_SAMPLE_FMT_S16);
 +    ff_set_common_formats(ctx, sample_formats);
 +    ff_add_format(&sample_rates, flite->wave->sample_rate);
 +    ff_set_common_samplerates (ctx, sample_rates);
 +
 +    return 0;
 +}
 +
 +static int config_props(AVFilterLink *outlink)
 +{
 +    AVFilterContext *ctx = outlink->src;
 +    FliteContext *flite = ctx->priv;
 +
 +    outlink->sample_rate = flite->wave->sample_rate;
 +    outlink->time_base = (AVRational){1, flite->wave->sample_rate};
 +
 +    av_log(ctx, AV_LOG_VERBOSE, "voice:%s fmt:%s sample_rate:%d\n",
 +           flite->voice_str,
 +           av_get_sample_fmt_name(outlink->format), outlink->sample_rate);
 +    return 0;
 +}
 +
 +static int request_frame(AVFilterLink *outlink)
 +{
 +    AVFilterBufferRef *samplesref;
 +    FliteContext *flite = outlink->src->priv;
 +    int nb_samples = FFMIN(flite->wave_nb_samples, flite->frame_nb_samples);
 +
 +    if (!nb_samples)
 +        return AVERROR_EOF;
 +
 +    samplesref = ff_get_audio_buffer(outlink, AV_PERM_WRITE, nb_samples);
 +    if (!samplesref)
 +        return AVERROR(ENOMEM);
 +
 +    memcpy(samplesref->data[0], flite->wave_samples,
 +           nb_samples * flite->wave->num_channels * 2);
 +    samplesref->pts = flite->pts;
 +    samplesref->pos = -1;
 +    samplesref->audio->sample_rate = flite->wave->sample_rate;
 +    flite->pts += nb_samples;
 +    flite->wave_samples += nb_samples * flite->wave->num_channels;
 +    flite->wave_nb_samples -= nb_samples;
 +
 +    return ff_filter_samples(outlink, samplesref);
 +}
 +
 +AVFilter avfilter_asrc_flite = {
 +    .name        = "flite",
 +    .description = NULL_IF_CONFIG_SMALL("Synthesize voice from text using libflite."),
 +    .query_formats = query_formats,
 +    .init        = init,
 +    .uninit      = uninit,
 +    .priv_size   = sizeof(FliteContext),
 +
 +    .inputs = (const AVFilterPad[]) {{ .name = NULL}},
 +
 +    .outputs = (const AVFilterPad[]) {
 +        {
 +            .name = "default",
 +            .type = AVMEDIA_TYPE_AUDIO,
 +            .config_props = config_props,
 +            .request_frame = request_frame,
 +        },
 +        { .name = NULL }
 +    },
 +
 +    .priv_class = &flite_class,
 +};
index 208dc3f,0000000..c0bd621
mode 100644,000000..100644
--- /dev/null
@@@ -1,446 -1,0 +1,446 @@@
-       AV_OPT_TYPE_INT, { .dbl = 2 }, 2, INT_MAX, V|A|F},
 +/*
 + * Copyright (c) 2012 Nicolas George
 + *
 + * This file is part of FFmpeg.
 + *
 + * FFmpeg is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU Lesser General Public
 + * License as published by the Free Software Foundation; either
 + * version 2.1 of the License, or (at your option) any later version.
 + *
 + * FFmpeg is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 + * See the GNU Lesser General Public License for more details.
 + *
 + * You should have received a copy of the GNU Lesser General Public License
 + * along with FFmpeg; if not, write to the Free Software Foundation, Inc.,
 + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 + */
 +
 +/**
 + * @file
 + * concat audio-video filter
 + */
 +
 +#include "libavutil/audioconvert.h"
 +#include "libavutil/avassert.h"
 +#include "libavutil/opt.h"
 +#include "avfilter.h"
 +#define FF_BUFQUEUE_SIZE 256
 +#include "bufferqueue.h"
 +#include "internal.h"
 +#include "video.h"
 +#include "audio.h"
 +
 +#define TYPE_ALL 2
 +
 +typedef struct {
 +    const AVClass *class;
 +    unsigned nb_streams[TYPE_ALL]; /**< number of out streams of each type */
 +    unsigned nb_segments;
 +    unsigned cur_idx; /**< index of the first input of current segment */
 +    int64_t delta_ts; /**< timestamp to add to produce output timestamps */
 +    unsigned nb_in_active; /**< number of active inputs in current segment */
 +    struct concat_in {
 +        int64_t pts;
 +        int64_t nb_frames;
 +        unsigned eof;
 +        struct FFBufQueue queue;
 +    } *in;
 +} ConcatContext;
 +
 +#define OFFSET(x) offsetof(ConcatContext, x)
 +#define A AV_OPT_FLAG_AUDIO_PARAM
 +#define F AV_OPT_FLAG_FILTERING_PARAM
 +#define V AV_OPT_FLAG_VIDEO_PARAM
 +
 +static const AVOption concat_options[] = {
 +    { "n", "specify the number of segments", OFFSET(nb_segments),
-       AV_OPT_TYPE_INT, { .dbl = 1 }, 0, INT_MAX, V|F },
++      AV_OPT_TYPE_INT, { .i64 = 2 }, 2, INT_MAX, V|A|F},
 +    { "v", "specify the number of video streams",
 +      OFFSET(nb_streams[AVMEDIA_TYPE_VIDEO]),
-       AV_OPT_TYPE_INT, { .dbl = 0 }, 0, INT_MAX, A|F},
++      AV_OPT_TYPE_INT, { .i64 = 1 }, 0, INT_MAX, V|F },
 +    { "a", "specify the number of audio streams",
 +      OFFSET(nb_streams[AVMEDIA_TYPE_AUDIO]),
++      AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, A|F},
 +    { 0 }
 +};
 +
 +AVFILTER_DEFINE_CLASS(concat);
 +
 +static int query_formats(AVFilterContext *ctx)
 +{
 +    ConcatContext *cat = ctx->priv;
 +    unsigned type, nb_str, idx0 = 0, idx, str, seg;
 +    AVFilterFormats *formats, *rates;
 +    AVFilterChannelLayouts *layouts;
 +
 +    for (type = 0; type < TYPE_ALL; type++) {
 +        nb_str = cat->nb_streams[type];
 +        for (str = 0; str < nb_str; str++) {
 +            idx = idx0;
 +
 +            /* Set the output formats */
 +            formats = ff_all_formats(type);
 +            if (!formats)
 +                return AVERROR(ENOMEM);
 +            ff_formats_ref(formats, &ctx->outputs[idx]->in_formats);
 +            if (type == AVMEDIA_TYPE_AUDIO) {
 +                rates = ff_all_samplerates();
 +                if (!rates)
 +                    return AVERROR(ENOMEM);
 +                ff_formats_ref(rates, &ctx->outputs[idx]->in_samplerates);
 +                layouts = ff_all_channel_layouts();
 +                if (!layouts)
 +                    return AVERROR(ENOMEM);
 +                ff_channel_layouts_ref(layouts, &ctx->outputs[idx]->in_channel_layouts);
 +            }
 +
 +            /* Set the same formats for each corresponding input */
 +            for (seg = 0; seg < cat->nb_segments; seg++) {
 +                ff_formats_ref(formats, &ctx->inputs[idx]->out_formats);
 +                if (type == AVMEDIA_TYPE_AUDIO) {
 +                    ff_formats_ref(rates, &ctx->inputs[idx]->out_samplerates);
 +                    ff_channel_layouts_ref(layouts, &ctx->inputs[idx]->out_channel_layouts);
 +                }
 +                idx += ctx->nb_outputs;
 +            }
 +
 +            idx0++;
 +        }
 +    }
 +    return 0;
 +}
 +
 +static int config_output(AVFilterLink *outlink)
 +{
 +    AVFilterContext *ctx = outlink->src;
 +    ConcatContext *cat   = ctx->priv;
 +    unsigned out_no = FF_OUTLINK_IDX(outlink);
 +    unsigned in_no  = out_no, seg;
 +    AVFilterLink *inlink = ctx->inputs[in_no];
 +
 +    /* enhancement: find a common one */
 +    outlink->time_base           = AV_TIME_BASE_Q;
 +    outlink->w                   = inlink->w;
 +    outlink->h                   = inlink->h;
 +    outlink->sample_aspect_ratio = inlink->sample_aspect_ratio;
 +    outlink->format              = inlink->format;
 +    for (seg = 1; seg < cat->nb_segments; seg++) {
 +        inlink = ctx->inputs[in_no += ctx->nb_outputs];
 +        /* possible enhancement: unsafe mode, do not check */
 +        if (outlink->w                       != inlink->w                       ||
 +            outlink->h                       != inlink->h                       ||
 +            outlink->sample_aspect_ratio.num != inlink->sample_aspect_ratio.num ||
 +            outlink->sample_aspect_ratio.den != inlink->sample_aspect_ratio.den) {
 +            av_log(ctx, AV_LOG_ERROR, "Input link %s parameters "
 +                   "(size %dx%d, SAR %d:%d) do not match the corresponding "
 +                   "output link %s parameters (%dx%d, SAR %d:%d)\n",
 +                   ctx->input_pads[in_no].name, inlink->w, inlink->h,
 +                   inlink->sample_aspect_ratio.num,
 +                   inlink->sample_aspect_ratio.den,
 +                   ctx->input_pads[out_no].name, outlink->w, outlink->h,
 +                   outlink->sample_aspect_ratio.num,
 +                   outlink->sample_aspect_ratio.den);
 +            return AVERROR(EINVAL);
 +        }
 +    }
 +
 +    return 0;
 +}
 +
 +static void push_frame(AVFilterContext *ctx, unsigned in_no,
 +                       AVFilterBufferRef *buf)
 +{
 +    ConcatContext *cat = ctx->priv;
 +    unsigned out_no = in_no % ctx->nb_outputs;
 +    AVFilterLink * inlink = ctx-> inputs[ in_no];
 +    AVFilterLink *outlink = ctx->outputs[out_no];
 +    struct concat_in *in = &cat->in[in_no];
 +
 +    buf->pts = av_rescale_q(buf->pts, inlink->time_base, outlink->time_base);
 +    in->pts = buf->pts;
 +    in->nb_frames++;
 +    /* add duration to input PTS */
 +    if (inlink->sample_rate)
 +        /* use number of audio samples */
 +        in->pts += av_rescale_q(buf->audio->nb_samples,
 +                                (AVRational){ 1, inlink->sample_rate },
 +                                outlink->time_base);
 +    else if (in->nb_frames >= 2)
 +        /* use mean duration */
 +        in->pts = av_rescale(in->pts, in->nb_frames, in->nb_frames - 1);
 +
 +    buf->pts += cat->delta_ts;
 +    switch (buf->type) {
 +    case AVMEDIA_TYPE_VIDEO:
 +        ff_start_frame(outlink, buf);
 +        ff_draw_slice(outlink, 0, outlink->h, 1);
 +        ff_end_frame(outlink);
 +        break;
 +    case AVMEDIA_TYPE_AUDIO:
 +        ff_filter_samples(outlink, buf);
 +        break;
 +    }
 +}
 +
 +static void process_frame(AVFilterLink *inlink, AVFilterBufferRef *buf)
 +{
 +    AVFilterContext *ctx  = inlink->dst;
 +    ConcatContext *cat    = ctx->priv;
 +    unsigned in_no = FF_INLINK_IDX(inlink);
 +
 +    if (in_no < cat->cur_idx) {
 +        av_log(ctx, AV_LOG_ERROR, "Frame after EOF on input %s\n",
 +               ctx->input_pads[in_no].name);
 +        avfilter_unref_buffer(buf);
 +    } if (in_no >= cat->cur_idx + ctx->nb_outputs) {
 +        ff_bufqueue_add(ctx, &cat->in[in_no].queue, buf);
 +    } else {
 +        push_frame(ctx, in_no, buf);
 +    }
 +}
 +
 +static AVFilterBufferRef *get_video_buffer(AVFilterLink *inlink, int perms,
 +                                           int w, int h)
 +{
 +    AVFilterContext *ctx = inlink->dst;
 +    unsigned in_no = FF_INLINK_IDX(inlink);
 +    AVFilterLink *outlink = ctx->outputs[in_no % ctx->nb_outputs];
 +
 +    return ff_get_video_buffer(outlink, perms, w, h);
 +}
 +
 +static AVFilterBufferRef *get_audio_buffer(AVFilterLink *inlink, int perms,
 +                                           int nb_samples)
 +{
 +    AVFilterContext *ctx = inlink->dst;
 +    unsigned in_no = FF_INLINK_IDX(inlink);
 +    AVFilterLink *outlink = ctx->outputs[in_no % ctx->nb_outputs];
 +
 +    return ff_get_audio_buffer(outlink, perms, nb_samples);
 +}
 +
 +static int start_frame(AVFilterLink *inlink, AVFilterBufferRef *buf)
 +{
 +    return 0;
 +}
 +
 +static int draw_slice(AVFilterLink *inlink, int y, int h, int dir)
 +{
 +    return 0;
 +}
 +
 +static int end_frame(AVFilterLink *inlink)
 +{
 +    process_frame(inlink, inlink->cur_buf);
 +    inlink->cur_buf = NULL;
 +    return 0;
 +}
 +
 +static int filter_samples(AVFilterLink *inlink, AVFilterBufferRef *buf)
 +{
 +    process_frame(inlink, buf);
 +    return 0; /* enhancement: handle error return */
 +}
 +
 +static void close_input(AVFilterContext *ctx, unsigned in_no)
 +{
 +    ConcatContext *cat = ctx->priv;
 +
 +    cat->in[in_no].eof = 1;
 +    cat->nb_in_active--;
 +    av_log(ctx, AV_LOG_VERBOSE, "EOF on %s, %d streams left in segment.\n",
 +           ctx->input_pads[in_no].name, cat->nb_in_active);
 +}
 +
 +static void find_next_delta_ts(AVFilterContext *ctx)
 +{
 +    ConcatContext *cat = ctx->priv;
 +    unsigned i = cat->cur_idx;
 +    unsigned imax = i + ctx->nb_outputs;
 +    int64_t pts;
 +
 +    pts = cat->in[i++].pts;
 +    for (; i < imax; i++)
 +        pts = FFMAX(pts, cat->in[i].pts);
 +    cat->delta_ts += pts;
 +}
 +
 +static void send_silence(AVFilterContext *ctx, unsigned in_no, unsigned out_no)
 +{
 +    ConcatContext *cat = ctx->priv;
 +    AVFilterLink *outlink = ctx->outputs[out_no];
 +    int64_t base_pts = cat->in[in_no].pts + cat->delta_ts;
 +    int64_t nb_samples, sent = 0;
 +    int frame_nb_samples;
 +    AVRational rate_tb = { 1, ctx->inputs[in_no]->sample_rate };
 +    AVFilterBufferRef *buf;
 +    int nb_channels = av_get_channel_layout_nb_channels(outlink->channel_layout);
 +
 +    if (!rate_tb.den)
 +        return;
 +    nb_samples = av_rescale_q(cat->delta_ts - base_pts,
 +                              outlink->time_base, rate_tb);
 +    frame_nb_samples = FFMAX(9600, rate_tb.den / 5); /* arbitrary */
 +    while (nb_samples) {
 +        frame_nb_samples = FFMIN(frame_nb_samples, nb_samples);
 +        buf = ff_get_audio_buffer(outlink, AV_PERM_WRITE, frame_nb_samples);
 +        if (!buf)
 +            return;
 +        av_samples_set_silence(buf->extended_data, 0, frame_nb_samples,
 +                               nb_channels, outlink->format);
 +        buf->pts = base_pts + av_rescale_q(sent, rate_tb, outlink->time_base);
 +        ff_filter_samples(outlink, buf);
 +        sent       += frame_nb_samples;
 +        nb_samples -= frame_nb_samples;
 +    }
 +}
 +
 +static void flush_segment(AVFilterContext *ctx)
 +{
 +    ConcatContext *cat = ctx->priv;
 +    unsigned str, str_max;
 +
 +    find_next_delta_ts(ctx);
 +    cat->cur_idx += ctx->nb_outputs;
 +    cat->nb_in_active = ctx->nb_outputs;
 +    av_log(ctx, AV_LOG_VERBOSE, "Segment finished at pts=%"PRId64"\n",
 +           cat->delta_ts);
 +
 +    if (cat->cur_idx < ctx->nb_inputs) {
 +        /* pad audio streams with silence */
 +        str = cat->nb_streams[AVMEDIA_TYPE_VIDEO];
 +        str_max = str + cat->nb_streams[AVMEDIA_TYPE_AUDIO];
 +        for (; str < str_max; str++)
 +            send_silence(ctx, cat->cur_idx - ctx->nb_outputs + str, str);
 +        /* flush queued buffers */
 +        /* possible enhancement: flush in PTS order */
 +        str_max = cat->cur_idx + ctx->nb_outputs;
 +        for (str = cat->cur_idx; str < str_max; str++)
 +            while (cat->in[str].queue.available)
 +                push_frame(ctx, str, ff_bufqueue_get(&cat->in[str].queue));
 +    }
 +}
 +
 +static int request_frame(AVFilterLink *outlink)
 +{
 +    AVFilterContext *ctx = outlink->src;
 +    ConcatContext *cat   = ctx->priv;
 +    unsigned out_no = FF_OUTLINK_IDX(outlink);
 +    unsigned in_no  = out_no + cat->cur_idx;
 +    unsigned str, str_max;
 +    int ret;
 +
 +    while (1) {
 +        if (in_no >= ctx->nb_inputs)
 +            return AVERROR_EOF;
 +        if (!cat->in[in_no].eof) {
 +            ret = ff_request_frame(ctx->inputs[in_no]);
 +            if (ret != AVERROR_EOF)
 +                return ret;
 +            close_input(ctx, in_no);
 +        }
 +        /* cycle on all inputs to finish the segment */
 +        /* possible enhancement: request in PTS order */
 +        str_max = cat->cur_idx + ctx->nb_outputs - 1;
 +        for (str = cat->cur_idx; cat->nb_in_active;
 +             str = str == str_max ? cat->cur_idx : str + 1) {
 +            if (cat->in[str].eof)
 +                continue;
 +            ret = ff_request_frame(ctx->inputs[str]);
 +            if (ret == AVERROR_EOF)
 +                close_input(ctx, str);
 +            else if (ret < 0)
 +                return ret;
 +        }
 +        flush_segment(ctx);
 +        in_no += ctx->nb_outputs;
 +    }
 +}
 +
 +static av_cold int init(AVFilterContext *c