Merge commit 'b519298a1578e0c895d53d4b4ed8867b1c031a56'
authorMichael Niedermayer <michaelni@gmx.at>
Thu, 6 Dec 2012 14:43:34 +0000 (15:43 +0100)
committerMichael Niedermayer <michaelni@gmx.at>
Thu, 6 Dec 2012 14:55:47 +0000 (15:55 +0100)
* commit 'b519298a1578e0c895d53d4b4ed8867b1c031a56':
  pixdesc: fix yuva 10bit bit depth
  avconv: deprecate the -vol option
  x86: af_volume: add SSE2/SSSE3/AVX-optimized s32 volume scaling
  x86: af_volume: add SSE2-optimized s16 volume scaling

Conflicts:
ffmpeg.c
tests/ref/lavfi/pixdesc
tests/ref/lavfi/pixfmts_copy
tests/ref/lavfi/pixfmts_null
tests/ref/lavfi/pixfmts_scale
tests/ref/lavfi/pixfmts_vflip

Merged-by: Michael Niedermayer <michaelni@gmx.at>
1  2 
ffmpeg_filter.c
libavfilter/af_volume.h
libavfilter/af_volume_justin.c
libavfilter/x86/af_volume.asm
libavfilter/x86/af_volume_init.c
libavutil/x86/x86inc.asm

diff --cc ffmpeg_filter.c
index 5e37128,0000000..db95c2f
mode 100644,000000..100644
--- /dev/null
@@@ -1,792 -1,0 +1,795 @@@
 +/*
 + * ffmpeg filter configuration
 + *
 + * 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 "ffmpeg.h"
 +
 +#include "libavfilter/avfilter.h"
 +#include "libavfilter/avfiltergraph.h"
 +#include "libavfilter/buffersink.h"
 +
 +#include "libavutil/avassert.h"
 +#include "libavutil/avstring.h"
 +#include "libavutil/bprint.h"
 +#include "libavutil/channel_layout.h"
 +#include "libavutil/opt.h"
 +#include "libavutil/pixdesc.h"
 +#include "libavutil/pixfmt.h"
 +#include "libavutil/imgutils.h"
 +#include "libavutil/samplefmt.h"
 +
 +enum AVPixelFormat choose_pixel_fmt(AVStream *st, AVCodec *codec, enum AVPixelFormat target)
 +{
 +    if (codec && codec->pix_fmts) {
 +        const enum AVPixelFormat *p = codec->pix_fmts;
 +        const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(target);
 +        int has_alpha = desc ? desc->nb_components % 2 == 0 : 0;
 +        enum AVPixelFormat best= AV_PIX_FMT_NONE;
 +        if (st->codec->strict_std_compliance <= FF_COMPLIANCE_UNOFFICIAL) {
 +            if (st->codec->codec_id == AV_CODEC_ID_MJPEG) {
 +                p = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUVJ420P, AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_NONE };
 +            } else if (st->codec->codec_id == AV_CODEC_ID_LJPEG) {
 +                p = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUVJ420P, AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_YUVJ444P, AV_PIX_FMT_YUV420P,
 +                                                 AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV444P, AV_PIX_FMT_BGRA, AV_PIX_FMT_NONE };
 +            }
 +        }
 +        for (; *p != AV_PIX_FMT_NONE; p++) {
 +            best= avcodec_find_best_pix_fmt_of_2(best, *p, target, has_alpha, NULL);
 +            if (*p == target)
 +                break;
 +        }
 +        if (*p == AV_PIX_FMT_NONE) {
 +            if (target != AV_PIX_FMT_NONE)
 +                av_log(NULL, AV_LOG_WARNING,
 +                       "Incompatible pixel format '%s' for codec '%s', auto-selecting format '%s'\n",
 +                       av_get_pix_fmt_name(target),
 +                       codec->name,
 +                       av_get_pix_fmt_name(best));
 +            return best;
 +        }
 +    }
 +    return target;
 +}
 +
 +void choose_sample_fmt(AVStream *st, AVCodec *codec)
 +{
 +    if (codec && codec->sample_fmts) {
 +        const enum AVSampleFormat *p = codec->sample_fmts;
 +        for (; *p != -1; p++) {
 +            if (*p == st->codec->sample_fmt)
 +                break;
 +        }
 +        if (*p == -1) {
 +            if((codec->capabilities & CODEC_CAP_LOSSLESS) && av_get_sample_fmt_name(st->codec->sample_fmt) > av_get_sample_fmt_name(codec->sample_fmts[0]))
 +                av_log(NULL, AV_LOG_ERROR, "Conversion will not be lossless.\n");
 +            if(av_get_sample_fmt_name(st->codec->sample_fmt))
 +            av_log(NULL, AV_LOG_WARNING,
 +                   "Incompatible sample format '%s' for codec '%s', auto-selecting format '%s'\n",
 +                   av_get_sample_fmt_name(st->codec->sample_fmt),
 +                   codec->name,
 +                   av_get_sample_fmt_name(codec->sample_fmts[0]));
 +            st->codec->sample_fmt = codec->sample_fmts[0];
 +        }
 +    }
 +}
 +
 +static char *choose_pix_fmts(OutputStream *ost)
 +{
 +     if (ost->keep_pix_fmt) {
 +        if (ost->filter)
 +            avfilter_graph_set_auto_convert(ost->filter->graph->graph,
 +                                            AVFILTER_AUTO_CONVERT_NONE);
 +        if (ost->st->codec->pix_fmt == AV_PIX_FMT_NONE)
 +            return NULL;
 +        return av_strdup(av_get_pix_fmt_name(ost->st->codec->pix_fmt));
 +    }
 +    if (ost->st->codec->pix_fmt != AV_PIX_FMT_NONE) {
 +        return av_strdup(av_get_pix_fmt_name(choose_pixel_fmt(ost->st, ost->enc, ost->st->codec->pix_fmt)));
 +    } else if (ost->enc && ost->enc->pix_fmts) {
 +        const enum AVPixelFormat *p;
 +        AVIOContext *s = NULL;
 +        uint8_t *ret;
 +        int len;
 +
 +        if (avio_open_dyn_buf(&s) < 0)
 +            exit(1);
 +
 +        p = ost->enc->pix_fmts;
 +        if (ost->st->codec->strict_std_compliance <= FF_COMPLIANCE_UNOFFICIAL) {
 +            if (ost->st->codec->codec_id == AV_CODEC_ID_MJPEG) {
 +                p = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUVJ420P, AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV422P, AV_PIX_FMT_NONE };
 +            } else if (ost->st->codec->codec_id == AV_CODEC_ID_LJPEG) {
 +                p = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUVJ420P, AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_YUVJ444P, AV_PIX_FMT_YUV420P,
 +                                                    AV_PIX_FMT_YUV422P, AV_PIX_FMT_YUV444P, AV_PIX_FMT_BGRA, AV_PIX_FMT_NONE };
 +            }
 +        }
 +
 +        for (; *p != AV_PIX_FMT_NONE; p++) {
 +            const char *name = av_get_pix_fmt_name(*p);
 +            avio_printf(s, "%s:", name);
 +        }
 +        len = avio_close_dyn_buf(s, &ret);
 +        ret[len - 1] = 0;
 +        return ret;
 +    } else
 +        return NULL;
 +}
 +
 +/* Define a function for building a string containing a list of
 + * allowed formats. */
 +#define DEF_CHOOSE_FORMAT(type, var, supported_list, none, get_name, separator)\
 +static char *choose_ ## var ## s(OutputStream *ost)                            \
 +{                                                                              \
 +    if (ost->st->codec->var != none) {                                         \
 +        get_name(ost->st->codec->var);                                         \
 +        return av_strdup(name);                                                \
 +    } else if (ost->enc->supported_list) {                                     \
 +        const type *p;                                                         \
 +        AVIOContext *s = NULL;                                                 \
 +        uint8_t *ret;                                                          \
 +        int len;                                                               \
 +                                                                               \
 +        if (avio_open_dyn_buf(&s) < 0)                                         \
 +            exit(1);                                                           \
 +                                                                               \
 +        for (p = ost->enc->supported_list; *p != none; p++) {                  \
 +            get_name(*p);                                                      \
 +            avio_printf(s, "%s" separator, name);                              \
 +        }                                                                      \
 +        len = avio_close_dyn_buf(s, &ret);                                     \
 +        ret[len - 1] = 0;                                                      \
 +        return ret;                                                            \
 +    } else                                                                     \
 +        return NULL;                                                           \
 +}
 +
 +// DEF_CHOOSE_FORMAT(enum AVPixelFormat, pix_fmt, pix_fmts, AV_PIX_FMT_NONE,
 +//                   GET_PIX_FMT_NAME, ":")
 +
 +DEF_CHOOSE_FORMAT(enum AVSampleFormat, sample_fmt, sample_fmts,
 +                  AV_SAMPLE_FMT_NONE, GET_SAMPLE_FMT_NAME, ",")
 +
 +DEF_CHOOSE_FORMAT(int, sample_rate, supported_samplerates, 0,
 +                  GET_SAMPLE_RATE_NAME, ",")
 +
 +DEF_CHOOSE_FORMAT(uint64_t, channel_layout, channel_layouts, 0,
 +                  GET_CH_LAYOUT_NAME, ",")
 +
 +FilterGraph *init_simple_filtergraph(InputStream *ist, OutputStream *ost)
 +{
 +    FilterGraph *fg = av_mallocz(sizeof(*fg));
 +
 +    if (!fg)
 +        exit(1);
 +    fg->index = nb_filtergraphs;
 +
 +    fg->outputs = grow_array(fg->outputs, sizeof(*fg->outputs), &fg->nb_outputs,
 +                             fg->nb_outputs + 1);
 +    if (!(fg->outputs[0] = av_mallocz(sizeof(*fg->outputs[0]))))
 +        exit(1);
 +    fg->outputs[0]->ost   = ost;
 +    fg->outputs[0]->graph = fg;
 +
 +    ost->filter = fg->outputs[0];
 +
 +    fg->inputs = grow_array(fg->inputs, sizeof(*fg->inputs), &fg->nb_inputs,
 +                            fg->nb_inputs + 1);
 +    if (!(fg->inputs[0] = av_mallocz(sizeof(*fg->inputs[0]))))
 +        exit(1);
 +    fg->inputs[0]->ist   = ist;
 +    fg->inputs[0]->graph = fg;
 +
 +    ist->filters = grow_array(ist->filters, sizeof(*ist->filters),
 +                              &ist->nb_filters, ist->nb_filters + 1);
 +    ist->filters[ist->nb_filters - 1] = fg->inputs[0];
 +
 +    filtergraphs = grow_array(filtergraphs, sizeof(*filtergraphs),
 +                              &nb_filtergraphs, nb_filtergraphs + 1);
 +    filtergraphs[nb_filtergraphs - 1] = fg;
 +
 +    return fg;
 +}
 +
 +static void init_input_filter(FilterGraph *fg, AVFilterInOut *in)
 +{
 +    InputStream *ist = NULL;
 +    enum AVMediaType type = avfilter_pad_get_type(in->filter_ctx->input_pads, in->pad_idx);
 +    int i;
 +
 +    // TODO: support other filter types
 +    if (type != AVMEDIA_TYPE_VIDEO && type != AVMEDIA_TYPE_AUDIO) {
 +        av_log(NULL, AV_LOG_FATAL, "Only video and audio filters supported "
 +               "currently.\n");
 +        exit(1);
 +    }
 +
 +    if (in->name) {
 +        AVFormatContext *s;
 +        AVStream       *st = NULL;
 +        char *p;
 +        int file_idx = strtol(in->name, &p, 0);
 +
 +        if (file_idx < 0 || file_idx >= nb_input_files) {
 +            av_log(NULL, AV_LOG_FATAL, "Invalid file index %d in filtergraph description %s.\n",
 +                   file_idx, fg->graph_desc);
 +            exit(1);
 +        }
 +        s = input_files[file_idx]->ctx;
 +
 +        for (i = 0; i < s->nb_streams; i++) {
 +            enum AVMediaType stream_type = s->streams[i]->codec->codec_type;
 +            if (stream_type != type &&
 +                !(stream_type == AVMEDIA_TYPE_SUBTITLE &&
 +                  type == AVMEDIA_TYPE_VIDEO /* sub2video hack */))
 +                continue;
 +            if (check_stream_specifier(s, s->streams[i], *p == ':' ? p + 1 : p) == 1) {
 +                st = s->streams[i];
 +                break;
 +            }
 +        }
 +        if (!st) {
 +            av_log(NULL, AV_LOG_FATAL, "Stream specifier '%s' in filtergraph description %s "
 +                   "matches no streams.\n", p, fg->graph_desc);
 +            exit(1);
 +        }
 +        ist = input_streams[input_files[file_idx]->ist_index + st->index];
 +    } else {
 +        /* find the first unused stream of corresponding type */
 +        for (i = 0; i < nb_input_streams; i++) {
 +            ist = input_streams[i];
 +            if (ist->st->codec->codec_type == type && ist->discard)
 +                break;
 +        }
 +        if (i == nb_input_streams) {
 +            av_log(NULL, AV_LOG_FATAL, "Cannot find a matching stream for "
 +                   "unlabeled input pad %d on filter %s\n", in->pad_idx,
 +                   in->filter_ctx->name);
 +            exit(1);
 +        }
 +    }
 +    av_assert0(ist);
 +
 +    ist->discard         = 0;
 +    ist->decoding_needed++;
 +    ist->st->discard = AVDISCARD_NONE;
 +
 +    fg->inputs = grow_array(fg->inputs, sizeof(*fg->inputs),
 +                            &fg->nb_inputs, fg->nb_inputs + 1);
 +    if (!(fg->inputs[fg->nb_inputs - 1] = av_mallocz(sizeof(*fg->inputs[0]))))
 +        exit(1);
 +    fg->inputs[fg->nb_inputs - 1]->ist   = ist;
 +    fg->inputs[fg->nb_inputs - 1]->graph = fg;
 +
 +    ist->filters = grow_array(ist->filters, sizeof(*ist->filters),
 +                              &ist->nb_filters, ist->nb_filters + 1);
 +    ist->filters[ist->nb_filters - 1] = fg->inputs[fg->nb_inputs - 1];
 +}
 +
 +static int configure_output_video_filter(FilterGraph *fg, OutputFilter *ofilter, AVFilterInOut *out)
 +{
 +    char *pix_fmts;
 +    OutputStream *ost = ofilter->ost;
 +    AVCodecContext *codec = ost->st->codec;
 +    AVFilterContext *last_filter = out->filter_ctx;
 +    int pad_idx = out->pad_idx;
 +    int ret;
 +    char name[255];
 +    AVBufferSinkParams *buffersink_params = av_buffersink_params_alloc();
 +
 +    snprintf(name, sizeof(name), "output stream %d:%d", ost->file_index, ost->index);
 +    ret = avfilter_graph_create_filter(&ofilter->filter,
 +                                       avfilter_get_by_name("ffbuffersink"),
 +                                       name, NULL, NULL, fg->graph);
 +    av_freep(&buffersink_params);
 +
 +    if (ret < 0)
 +        return ret;
 +
 +    if (codec->width || codec->height) {
 +        char args[255];
 +        AVFilterContext *filter;
 +
 +        snprintf(args, sizeof(args), "%d:%d:flags=0x%X",
 +                 codec->width,
 +                 codec->height,
 +                 (unsigned)ost->sws_flags);
 +        snprintf(name, sizeof(name), "scaler for output stream %d:%d",
 +                 ost->file_index, ost->index);
 +        if ((ret = avfilter_graph_create_filter(&filter, avfilter_get_by_name("scale"),
 +                                                name, args, NULL, fg->graph)) < 0)
 +            return ret;
 +        if ((ret = avfilter_link(last_filter, pad_idx, filter, 0)) < 0)
 +            return ret;
 +
 +        last_filter = filter;
 +        pad_idx = 0;
 +    }
 +
 +    if ((pix_fmts = choose_pix_fmts(ost))) {
 +        AVFilterContext *filter;
 +        snprintf(name, sizeof(name), "pixel format for output stream %d:%d",
 +                 ost->file_index, ost->index);
 +        if ((ret = avfilter_graph_create_filter(&filter,
 +                                                avfilter_get_by_name("format"),
 +                                                "format", pix_fmts, NULL,
 +                                                fg->graph)) < 0)
 +            return ret;
 +        if ((ret = avfilter_link(last_filter, pad_idx, filter, 0)) < 0)
 +            return ret;
 +
 +        last_filter = filter;
 +        pad_idx     = 0;
 +        av_freep(&pix_fmts);
 +    }
 +
 +    if (ost->frame_rate.num && 0) {
 +        AVFilterContext *fps;
 +        char args[255];
 +
 +        snprintf(args, sizeof(args), "fps=%d/%d", ost->frame_rate.num,
 +                 ost->frame_rate.den);
 +        snprintf(name, sizeof(name), "fps for output stream %d:%d",
 +                 ost->file_index, ost->index);
 +        ret = avfilter_graph_create_filter(&fps, avfilter_get_by_name("fps"),
 +                                           name, args, NULL, fg->graph);
 +        if (ret < 0)
 +            return ret;
 +
 +        ret = avfilter_link(last_filter, pad_idx, fps, 0);
 +        if (ret < 0)
 +            return ret;
 +        last_filter = fps;
 +        pad_idx = 0;
 +    }
 +
 +    if ((ret = avfilter_link(last_filter, pad_idx, ofilter->filter, 0)) < 0)
 +        return ret;
 +
 +    return 0;
 +}
 +
 +static int configure_output_audio_filter(FilterGraph *fg, OutputFilter *ofilter, AVFilterInOut *out)
 +{
 +    OutputStream *ost = ofilter->ost;
 +    AVCodecContext *codec  = ost->st->codec;
 +    AVFilterContext *last_filter = out->filter_ctx;
 +    int pad_idx = out->pad_idx;
 +    char *sample_fmts, *sample_rates, *channel_layouts;
 +    char name[255];
 +    int ret;
 +
 +
 +    snprintf(name, sizeof(name), "output stream %d:%d", ost->file_index, ost->index);
 +    ret = avfilter_graph_create_filter(&ofilter->filter,
 +                                       avfilter_get_by_name("ffabuffersink"),
 +                                       name, NULL, NULL, fg->graph);
 +    if (ret < 0)
 +        return ret;
 +
 +#define AUTO_INSERT_FILTER(opt_name, filter_name, arg) do {                 \
 +    AVFilterContext *filt_ctx;                                              \
 +                                                                            \
 +    av_log(NULL, AV_LOG_INFO, opt_name " is forwarded to lavfi "            \
 +           "similarly to -af " filter_name "=%s.\n", arg);                  \
 +                                                                            \
 +    ret = avfilter_graph_create_filter(&filt_ctx,                           \
 +                                       avfilter_get_by_name(filter_name),   \
 +                                       filter_name, arg, NULL, fg->graph);  \
 +    if (ret < 0)                                                            \
 +        return ret;                                                         \
 +                                                                            \
 +    ret = avfilter_link(last_filter, pad_idx, filt_ctx, 0);                 \
 +    if (ret < 0)                                                            \
 +        return ret;                                                         \
 +                                                                            \
 +    last_filter = filt_ctx;                                                 \
 +    pad_idx = 0;                                                            \
 +} while (0)
 +    if (ost->audio_channels_mapped) {
 +        int i;
 +        AVBPrint pan_buf;
 +        av_bprint_init(&pan_buf, 256, 8192);
 +        av_bprintf(&pan_buf, "0x%"PRIx64,
 +                   av_get_default_channel_layout(ost->audio_channels_mapped));
 +        for (i = 0; i < ost->audio_channels_mapped; i++)
 +            if (ost->audio_channels_map[i] != -1)
 +                av_bprintf(&pan_buf, ":c%d=c%d", i, ost->audio_channels_map[i]);
 +
 +        AUTO_INSERT_FILTER("-map_channel", "pan", pan_buf.str);
 +        av_bprint_finalize(&pan_buf, NULL);
 +    }
 +
 +    if (codec->channels && !codec->channel_layout)
 +        codec->channel_layout = av_get_default_channel_layout(codec->channels);
 +
 +    sample_fmts     = choose_sample_fmts(ost);
 +    sample_rates    = choose_sample_rates(ost);
 +    channel_layouts = choose_channel_layouts(ost);
 +    if (sample_fmts || sample_rates || channel_layouts) {
 +        AVFilterContext *format;
 +        char args[256];
 +        args[0] = 0;
 +
 +        if (sample_fmts)
 +            av_strlcatf(args, sizeof(args), "sample_fmts=%s:",
 +                            sample_fmts);
 +        if (sample_rates)
 +            av_strlcatf(args, sizeof(args), "sample_rates=%s:",
 +                            sample_rates);
 +        if (channel_layouts)
 +            av_strlcatf(args, sizeof(args), "channel_layouts=%s:",
 +                            channel_layouts);
 +
 +        av_freep(&sample_fmts);
 +        av_freep(&sample_rates);
 +        av_freep(&channel_layouts);
 +
 +        snprintf(name, sizeof(name), "audio format for output stream %d:%d",
 +                 ost->file_index, ost->index);
 +        ret = avfilter_graph_create_filter(&format,
 +                                           avfilter_get_by_name("aformat"),
 +                                           name, args, NULL, fg->graph);
 +        if (ret < 0)
 +            return ret;
 +
 +        ret = avfilter_link(last_filter, pad_idx, format, 0);
 +        if (ret < 0)
 +            return ret;
 +
 +        last_filter = format;
 +        pad_idx = 0;
 +    }
 +
 +    if (audio_volume != 256 && 0) {
 +        char args[256];
 +
 +        snprintf(args, sizeof(args), "%f", audio_volume / 256.);
 +        AUTO_INSERT_FILTER("-vol", "volume", args);
 +    }
 +
 +    if ((ret = avfilter_link(last_filter, pad_idx, ofilter->filter, 0)) < 0)
 +        return ret;
 +
 +    return 0;
 +}
 +
 +#define DESCRIBE_FILTER_LINK(f, inout, in)                         \
 +{                                                                  \
 +    AVFilterContext *ctx = inout->filter_ctx;                      \
 +    AVFilterPad *pads = in ? ctx->input_pads  : ctx->output_pads;  \
 +    int       nb_pads = in ? ctx->input_count : ctx->output_count; \
 +    AVIOContext *pb;                                               \
 +                                                                   \
 +    if (avio_open_dyn_buf(&pb) < 0)                                \
 +        exit(1);                                                   \
 +                                                                   \
 +    avio_printf(pb, "%s", ctx->filter->name);                      \
 +    if (nb_pads > 1)                                               \
 +        avio_printf(pb, ":%s", avfilter_pad_get_name(pads, inout->pad_idx));\
 +    avio_w8(pb, 0);                                                \
 +    avio_close_dyn_buf(pb, &f->name);                              \
 +}
 +
 +int configure_output_filter(FilterGraph *fg, OutputFilter *ofilter, AVFilterInOut *out)
 +{
 +    av_freep(&ofilter->name);
 +    DESCRIBE_FILTER_LINK(ofilter, out, 0);
 +
 +    switch (avfilter_pad_get_type(out->filter_ctx->output_pads, out->pad_idx)) {
 +    case AVMEDIA_TYPE_VIDEO: return configure_output_video_filter(fg, ofilter, out);
 +    case AVMEDIA_TYPE_AUDIO: return configure_output_audio_filter(fg, ofilter, out);
 +    default: av_assert0(0);
 +    }
 +}
 +
 +static int sub2video_prepare(InputStream *ist)
 +{
 +    AVFormatContext *avf = input_files[ist->file_index]->ctx;
 +    int i, ret, w, h;
 +    uint8_t *image[4];
 +    int linesize[4];
 +
 +    /* Compute the size of the canvas for the subtitles stream.
 +       If the subtitles codec has set a size, use it. Otherwise use the
 +       maximum dimensions of the video streams in the same file. */
 +    w = ist->st->codec->width;
 +    h = ist->st->codec->height;
 +    if (!(w && h)) {
 +        for (i = 0; i < avf->nb_streams; i++) {
 +            if (avf->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
 +                w = FFMAX(w, avf->streams[i]->codec->width);
 +                h = FFMAX(h, avf->streams[i]->codec->height);
 +            }
 +        }
 +        if (!(w && h)) {
 +            w = FFMAX(w, 720);
 +            h = FFMAX(h, 576);
 +        }
 +        av_log(avf, AV_LOG_INFO, "sub2video: using %dx%d canvas\n", w, h);
 +    }
 +    ist->sub2video.w = ist->st->codec->width  = w;
 +    ist->sub2video.h = ist->st->codec->height = h;
 +
 +    /* rectangles are AV_PIX_FMT_PAL8, but we have no guarantee that the
 +       palettes for all rectangles are identical or compatible */
 +    ist->st->codec->pix_fmt = AV_PIX_FMT_RGB32;
 +
 +    ret = av_image_alloc(image, linesize, w, h, AV_PIX_FMT_RGB32, 32);
 +    if (ret < 0)
 +        return ret;
 +    memset(image[0], 0, h * linesize[0]);
 +    ist->sub2video.ref = avfilter_get_video_buffer_ref_from_arrays(
 +            image, linesize, AV_PERM_READ | AV_PERM_PRESERVE,
 +            w, h, AV_PIX_FMT_RGB32);
 +    if (!ist->sub2video.ref) {
 +        av_free(image[0]);
 +        return AVERROR(ENOMEM);
 +    }
 +    return 0;
 +}
 +
 +static int configure_input_video_filter(FilterGraph *fg, InputFilter *ifilter,
 +                                        AVFilterInOut *in)
 +{
 +    AVFilterContext *first_filter = in->filter_ctx;
 +    AVFilter *filter = avfilter_get_by_name("buffer");
 +    InputStream *ist = ifilter->ist;
 +    AVRational tb = ist->framerate.num ? av_inv_q(ist->framerate) :
 +                                         ist->st->time_base;
 +    AVRational fr = ist->framerate.num ? ist->framerate :
 +                                         ist->st->r_frame_rate;
 +    AVRational sar;
 +    AVBPrint args;
 +    char name[255];
 +    int pad_idx = in->pad_idx;
 +    int ret;
 +
 +    if (!ist->framerate.num && ist->st->codec->ticks_per_frame>1) {
 +        AVRational codec_fr = av_inv_q(ist->st->codec->time_base);
 +        codec_fr.den *= ist->st->codec->ticks_per_frame;
 +        if(codec_fr.num>0 && codec_fr.den>0 && av_q2d(codec_fr) < av_q2d(fr)*0.7)
 +            fr = codec_fr;
 +    }
 +
 +    if (ist->st->codec->codec_type == AVMEDIA_TYPE_SUBTITLE) {
 +        ret = sub2video_prepare(ist);
 +        if (ret < 0)
 +            return ret;
 +    }
 +
 +    sar = ist->st->sample_aspect_ratio.num ?
 +          ist->st->sample_aspect_ratio :
 +          ist->st->codec->sample_aspect_ratio;
 +    if(!sar.den)
 +        sar = (AVRational){0,1};
 +    av_bprint_init(&args, 0, 1);
 +    av_bprintf(&args,
 +             "video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:"
 +             "pixel_aspect=%d/%d:sws_param=flags=%d", ist->st->codec->width,
 +             ist->st->codec->height, ist->st->codec->pix_fmt,
 +             tb.num, tb.den, sar.num, sar.den,
 +             SWS_BILINEAR + ((ist->st->codec->flags&CODEC_FLAG_BITEXACT) ? SWS_BITEXACT:0));
 +    if (fr.num && fr.den)
 +        av_bprintf(&args, ":frame_rate=%d/%d", fr.num, fr.den);
 +    snprintf(name, sizeof(name), "graph %d input from stream %d:%d", fg->index,
 +             ist->file_index, ist->st->index);
 +
 +    if ((ret = avfilter_graph_create_filter(&ifilter->filter, filter, name,
 +                                            args.str, NULL, fg->graph)) < 0)
 +        return ret;
 +
 +    if (ist->framerate.num) {
 +        AVFilterContext *setpts;
 +
 +        snprintf(name, sizeof(name), "force CFR for input from stream %d:%d",
 +                 ist->file_index, ist->st->index);
 +        if ((ret = avfilter_graph_create_filter(&setpts,
 +                                                avfilter_get_by_name("setpts"),
 +                                                name, "N", NULL,
 +                                                fg->graph)) < 0)
 +            return ret;
 +
 +        if ((ret = avfilter_link(setpts, 0, first_filter, pad_idx)) < 0)
 +            return ret;
 +
 +        first_filter = setpts;
 +        pad_idx = 0;
 +    }
 +
 +    if ((ret = avfilter_link(ifilter->filter, 0, first_filter, pad_idx)) < 0)
 +        return ret;
 +    return 0;
 +}
 +
 +static int configure_input_audio_filter(FilterGraph *fg, InputFilter *ifilter,
 +                                        AVFilterInOut *in)
 +{
 +    AVFilterContext *first_filter = in->filter_ctx;
 +    AVFilter *filter = avfilter_get_by_name("abuffer");
 +    InputStream *ist = ifilter->ist;
 +    int pad_idx = in->pad_idx;
 +    char args[255], name[255];
 +    int ret;
 +
 +    snprintf(args, sizeof(args), "time_base=%d/%d:sample_rate=%d:sample_fmt=%s"
 +             ":channel_layout=0x%"PRIx64,
 +             1, ist->st->codec->sample_rate,
 +             ist->st->codec->sample_rate,
 +             av_get_sample_fmt_name(ist->st->codec->sample_fmt),
 +             ist->st->codec->channel_layout);
 +    snprintf(name, sizeof(name), "graph %d input from stream %d:%d", fg->index,
 +             ist->file_index, ist->st->index);
 +
 +    if ((ret = avfilter_graph_create_filter(&ifilter->filter, filter,
 +                                            name, args, NULL,
 +                                            fg->graph)) < 0)
 +        return ret;
 +
 +#define AUTO_INSERT_FILTER_INPUT(opt_name, filter_name, arg) do {                 \
 +    AVFilterContext *filt_ctx;                                              \
 +                                                                            \
 +    av_log(NULL, AV_LOG_INFO, opt_name " is forwarded to lavfi "            \
 +           "similarly to -af " filter_name "=%s.\n", arg);                  \
 +                                                                            \
 +    snprintf(name, sizeof(name), "graph %d %s for input stream %d:%d",      \
 +                fg->index, filter_name, ist->file_index, ist->st->index);   \
 +    ret = avfilter_graph_create_filter(&filt_ctx,                           \
 +                                       avfilter_get_by_name(filter_name),   \
 +                                       name, arg, NULL, fg->graph);         \
 +    if (ret < 0)                                                            \
 +        return ret;                                                         \
 +                                                                            \
 +    ret = avfilter_link(filt_ctx, 0, first_filter, pad_idx);                \
 +    if (ret < 0)                                                            \
 +        return ret;                                                         \
 +                                                                            \
 +    first_filter = filt_ctx;                                                  \
 +} while (0)
 +
 +    if (audio_sync_method > 0) {
 +        char args[256] = {0};
 +
 +        av_strlcatf(args, sizeof(args), "min_comp=0.001:min_hard_comp=%f", audio_drift_threshold);
 +        if (audio_sync_method > 1)
 +            av_strlcatf(args, sizeof(args), ":max_soft_comp=%f", audio_sync_method/(double)ist->st->codec->sample_rate);
 +        AUTO_INSERT_FILTER_INPUT("-async", "aresample", args);
 +    }
 +
 +//     if (ost->audio_channels_mapped) {
 +//         int i;
 +//         AVBPrint pan_buf;
 +//         av_bprint_init(&pan_buf, 256, 8192);
 +//         av_bprintf(&pan_buf, "0x%"PRIx64,
 +//                    av_get_default_channel_layout(ost->audio_channels_mapped));
 +//         for (i = 0; i < ost->audio_channels_mapped; i++)
 +//             if (ost->audio_channels_map[i] != -1)
 +//                 av_bprintf(&pan_buf, ":c%d=c%d", i, ost->audio_channels_map[i]);
 +//         AUTO_INSERT_FILTER_INPUT("-map_channel", "pan", pan_buf.str);
 +//         av_bprint_finalize(&pan_buf, NULL);
 +//     }
 +
 +    if (audio_volume != 256) {
 +        char args[256];
 +
++        av_log(NULL, AV_LOG_WARNING, "-vol has been deprecated. Use the volume "
++               "audio filter instead.\n");
++
 +        snprintf(args, sizeof(args), "%f", audio_volume / 256.);
 +        AUTO_INSERT_FILTER_INPUT("-vol", "volume", args);
 +    }
 +    if ((ret = avfilter_link(ifilter->filter, 0, first_filter, pad_idx)) < 0)
 +        return ret;
 +
 +    return 0;
 +}
 +
 +static int configure_input_filter(FilterGraph *fg, InputFilter *ifilter,
 +                                  AVFilterInOut *in)
 +{
 +    av_freep(&ifilter->name);
 +    DESCRIBE_FILTER_LINK(ifilter, in, 1);
 +
 +    switch (avfilter_pad_get_type(in->filter_ctx->input_pads, in->pad_idx)) {
 +    case AVMEDIA_TYPE_VIDEO: return configure_input_video_filter(fg, ifilter, in);
 +    case AVMEDIA_TYPE_AUDIO: return configure_input_audio_filter(fg, ifilter, in);
 +    default: av_assert0(0);
 +    }
 +}
 +
 +int configure_filtergraph(FilterGraph *fg)
 +{
 +    AVFilterInOut *inputs, *outputs, *cur;
 +    int ret, i, init = !fg->graph, simple = !fg->graph_desc;
 +    const char *graph_desc = simple ? fg->outputs[0]->ost->avfilter :
 +                                      fg->graph_desc;
 +
 +    avfilter_graph_free(&fg->graph);
 +    if (!(fg->graph = avfilter_graph_alloc()))
 +        return AVERROR(ENOMEM);
 +
 +    if (simple) {
 +        OutputStream *ost = fg->outputs[0]->ost;
 +        char args[255];
 +        snprintf(args, sizeof(args), "flags=0x%X", (unsigned)ost->sws_flags);
 +        fg->graph->scale_sws_opts = av_strdup(args);
 +
 +        args[0] = 0;
 +        if (ost->swr_filter_type != SWR_FILTER_TYPE_KAISER)
 +            av_strlcatf(args, sizeof(args), "filter_type=%d:", (int)ost->swr_filter_type);
 +        if (ost->swr_dither_method)
 +            av_strlcatf(args, sizeof(args), "dither_method=%d:", (int)ost->swr_dither_method);
 +        if (ost->swr_dither_scale != 1.0)
 +            av_strlcatf(args, sizeof(args), "dither_scale=%f:", ost->swr_dither_scale);
 +        if (strlen(args))
 +            args[strlen(args)-1] = 0;
 +        av_opt_set(fg->graph, "aresample_swr_opts", args, 0);
 +    }
 +
 +    if ((ret = avfilter_graph_parse2(fg->graph, graph_desc, &inputs, &outputs)) < 0)
 +        return ret;
 +
 +    if (simple && (!inputs || inputs->next || !outputs || outputs->next)) {
 +        av_log(NULL, AV_LOG_ERROR, "Simple filtergraph '%s' does not have "
 +               "exactly one input and output.\n", graph_desc);
 +        return AVERROR(EINVAL);
 +    }
 +
 +    for (cur = inputs; !simple && init && cur; cur = cur->next)
 +        init_input_filter(fg, cur);
 +
 +    for (cur = inputs, i = 0; cur; cur = cur->next, i++)
 +        if ((ret = configure_input_filter(fg, fg->inputs[i], cur)) < 0)
 +            return ret;
 +    avfilter_inout_free(&inputs);
 +
 +    if (!init || simple) {
 +        /* we already know the mappings between lavfi outputs and output streams,
 +         * so we can finish the setup */
 +        for (cur = outputs, i = 0; cur; cur = cur->next, i++)
 +            configure_output_filter(fg, fg->outputs[i], cur);
 +        avfilter_inout_free(&outputs);
 +
 +        if ((ret = avfilter_graph_config(fg->graph, NULL)) < 0)
 +            return ret;
 +    } else {
 +        /* wait until output mappings are processed */
 +        for (cur = outputs; cur;) {
 +            fg->outputs = grow_array(fg->outputs, sizeof(*fg->outputs),
 +                                     &fg->nb_outputs, fg->nb_outputs + 1);
 +            if (!(fg->outputs[fg->nb_outputs - 1] = av_mallocz(sizeof(*fg->outputs[0]))))
 +                exit(1);
 +            fg->outputs[fg->nb_outputs - 1]->graph   = fg;
 +            fg->outputs[fg->nb_outputs - 1]->out_tmp = cur;
 +            cur = cur->next;
 +            fg->outputs[fg->nb_outputs - 1]->out_tmp->next = NULL;
 +        }
 +    }
 +
 +    return 0;
 +}
 +
 +int ist_in_filtergraph(FilterGraph *fg, InputStream *ist)
 +{
 +    int i;
 +    for (i = 0; i < fg->nb_inputs; i++)
 +        if (fg->inputs[i]->ist == ist)
 +            return 1;
 +    return 0;
 +}
 +
Simple merge
index 1d7c219,0000000..4162cb9
mode 100644,000000..100644
--- /dev/null
@@@ -1,314 -1,0 +1,317 @@@
 +/*
 + * Copyright (c) 2011 Stefano Sabatini
 + * Copyright (c) 2012 Justin Ruggles <justin.ruggles@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 volume filter
 + */
 +
 +#include "libavutil/audioconvert.h"
 +#include "libavutil/common.h"
 +#include "libavutil/eval.h"
 +#include "libavutil/float_dsp.h"
 +#include "libavutil/opt.h"
 +#include "audio.h"
 +#include "avfilter.h"
 +#include "formats.h"
 +#include "internal.h"
 +#include "af_volume.h"
 +
 +static const char *precision_str[] = {
 +    "fixed", "float", "double"
 +};
 +
 +#define OFFSET(x) offsetof(VolumeContext, x)
 +#define A AV_OPT_FLAG_AUDIO_PARAM
 +
 +static const AVOption options[] = {
 +    { "volume", "Volume adjustment.",
 +            OFFSET(volume), AV_OPT_TYPE_DOUBLE, { .dbl = 1.0 }, 0, 0x7fffff, A },
 +    { "precision", "Mathematical precision.",
 +            OFFSET(precision), AV_OPT_TYPE_INT, { .i64 = PRECISION_FLOAT }, PRECISION_FIXED, PRECISION_DOUBLE, A, "precision" },
 +        { "fixed",  "8-bit fixed-point.",     0, AV_OPT_TYPE_CONST, { .i64 = PRECISION_FIXED  }, INT_MIN, INT_MAX, A, "precision" },
 +        { "float",  "32-bit floating-point.", 0, AV_OPT_TYPE_CONST, { .i64 = PRECISION_FLOAT  }, INT_MIN, INT_MAX, A, "precision" },
 +        { "double", "64-bit floating-point.", 0, AV_OPT_TYPE_CONST, { .i64 = PRECISION_DOUBLE }, INT_MIN, INT_MAX, A, "precision" },
 +    { NULL },
 +};
 +
 +static const AVClass volume_class = {
 +    .class_name = "volume filter",
 +    .item_name  = av_default_item_name,
 +    .option     = options,
 +    .version    = LIBAVUTIL_VERSION_INT,
 +};
 +
 +static av_cold int init(AVFilterContext *ctx, const char *args)
 +{
 +    VolumeContext *vol = ctx->priv;
 +    int ret;
 +
 +    vol->class = &volume_class;
 +    av_opt_set_defaults(vol);
 +
 +    if ((ret = av_set_options_string(vol, args, "=", ":")) < 0) {
 +        av_log(ctx, AV_LOG_ERROR, "Error parsing options string '%s'.\n", args);
 +        return ret;
 +    }
 +
 +    if (vol->precision == PRECISION_FIXED) {
 +        vol->volume_i = (int)(vol->volume * 256 + 0.5);
 +        vol->volume   = vol->volume_i / 256.0;
 +        av_log(ctx, AV_LOG_VERBOSE, "volume:(%d/256)(%f)(%1.2fdB) precision:fixed\n",
 +               vol->volume_i, vol->volume, 20.0*log(vol->volume)/M_LN10);
 +    } else {
 +        av_log(ctx, AV_LOG_VERBOSE, "volume:(%f)(%1.2fdB) precision:%s\n",
 +               vol->volume, 20.0*log(vol->volume)/M_LN10,
 +               precision_str[vol->precision]);
 +    }
 +
 +    av_opt_free(vol);
 +    return ret;
 +}
 +
 +static int query_formats(AVFilterContext *ctx)
 +{
 +    VolumeContext *vol = ctx->priv;
 +    AVFilterFormats *formats = NULL;
 +    AVFilterChannelLayouts *layouts;
 +    static const enum AVSampleFormat sample_fmts[][7] = {
 +        /* PRECISION_FIXED */
 +        {
 +            AV_SAMPLE_FMT_U8,
 +            AV_SAMPLE_FMT_U8P,
 +            AV_SAMPLE_FMT_S16,
 +            AV_SAMPLE_FMT_S16P,
 +            AV_SAMPLE_FMT_S32,
 +            AV_SAMPLE_FMT_S32P,
 +            AV_SAMPLE_FMT_NONE
 +        },
 +        /* PRECISION_FLOAT */
 +        {
 +            AV_SAMPLE_FMT_FLT,
 +            AV_SAMPLE_FMT_FLTP,
 +            AV_SAMPLE_FMT_NONE
 +        },
 +        /* PRECISION_DOUBLE */
 +        {
 +            AV_SAMPLE_FMT_DBL,
 +            AV_SAMPLE_FMT_DBLP,
 +            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[vol->precision]);
 +    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;
 +}
 +
 +static inline void scale_samples_u8(uint8_t *dst, const uint8_t *src,
 +                                    int nb_samples, int volume)
 +{
 +    int i;
 +    for (i = 0; i < nb_samples; i++)
 +        dst[i] = av_clip_uint8(((((int64_t)src[i] - 128) * volume + 128) >> 8) + 128);
 +}
 +
 +static inline void scale_samples_u8_small(uint8_t *dst, const uint8_t *src,
 +                                          int nb_samples, int volume)
 +{
 +    int i;
 +    for (i = 0; i < nb_samples; i++)
 +        dst[i] = av_clip_uint8((((src[i] - 128) * volume + 128) >> 8) + 128);
 +}
 +
 +static inline void scale_samples_s16(uint8_t *dst, const uint8_t *src,
 +                                     int nb_samples, int volume)
 +{
 +    int i;
 +    int16_t *smp_dst       = (int16_t *)dst;
 +    const int16_t *smp_src = (const int16_t *)src;
 +    for (i = 0; i < nb_samples; i++)
 +        smp_dst[i] = av_clip_int16(((int64_t)smp_src[i] * volume + 128) >> 8);
 +}
 +
 +static inline void scale_samples_s16_small(uint8_t *dst, const uint8_t *src,
 +                                           int nb_samples, int volume)
 +{
 +    int i;
 +    int16_t *smp_dst       = (int16_t *)dst;
 +    const int16_t *smp_src = (const int16_t *)src;
 +    for (i = 0; i < nb_samples; i++)
 +        smp_dst[i] = av_clip_int16((smp_src[i] * volume + 128) >> 8);
 +}
 +
 +static inline void scale_samples_s32(uint8_t *dst, const uint8_t *src,
 +                                     int nb_samples, int volume)
 +{
 +    int i;
 +    int32_t *smp_dst       = (int32_t *)dst;
 +    const int32_t *smp_src = (const int32_t *)src;
 +    for (i = 0; i < nb_samples; i++)
 +        smp_dst[i] = av_clipl_int32((((int64_t)smp_src[i] * volume + 128) >> 8));
 +}
 +
 +
 +
 +static void volume_init(VolumeContext *vol)
 +{
 +    vol->samples_align = 1;
 +
 +    switch (av_get_packed_sample_fmt(vol->sample_fmt)) {
 +    case AV_SAMPLE_FMT_U8:
 +        if (vol->volume_i < 0x1000000)
 +            vol->scale_samples = scale_samples_u8_small;
 +        else
 +            vol->scale_samples = scale_samples_u8;
 +        break;
 +    case AV_SAMPLE_FMT_S16:
 +        if (vol->volume_i < 0x10000)
 +            vol->scale_samples = scale_samples_s16_small;
 +        else
 +            vol->scale_samples = scale_samples_s16;
 +        break;
 +    case AV_SAMPLE_FMT_S32:
 +        vol->scale_samples = scale_samples_s32;
 +        break;
 +    case AV_SAMPLE_FMT_FLT:
 +        avpriv_float_dsp_init(&vol->fdsp, 0);
 +        vol->samples_align = 4;
 +        break;
 +    case AV_SAMPLE_FMT_DBL:
 +        avpriv_float_dsp_init(&vol->fdsp, 0);
 +        vol->samples_align = 8;
 +        break;
 +    }
++
++    if (ARCH_X86)
++        ff_volume_init_x86(vol);
 +}
 +
 +static int config_output(AVFilterLink *outlink)
 +{
 +    AVFilterContext *ctx = outlink->src;
 +    VolumeContext *vol   = ctx->priv;
 +    AVFilterLink *inlink = ctx->inputs[0];
 +
 +    vol->sample_fmt = inlink->format;
 +    vol->channels   = av_get_channel_layout_nb_channels(inlink->channel_layout);
 +    vol->planes     = av_sample_fmt_is_planar(inlink->format) ? vol->channels : 1;
 +
 +    volume_init(vol);
 +
 +    return 0;
 +}
 +
 +static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *buf)
 +{
 +    VolumeContext *vol    = inlink->dst->priv;
 +    AVFilterLink *outlink = inlink->dst->outputs[0];
 +    int nb_samples        = buf->audio->nb_samples;
 +    AVFilterBufferRef *out_buf;
 +
 +    if (vol->volume == 1.0 || vol->volume_i == 256)
 +        return ff_filter_frame(outlink, buf);
 +
 +    /* do volume scaling in-place if input buffer is writable */
 +    if (buf->perms & AV_PERM_WRITE) {
 +        out_buf = buf;
 +    } else {
 +        out_buf = ff_get_audio_buffer(inlink, AV_PERM_WRITE, nb_samples);
 +        if (!out_buf)
 +            return AVERROR(ENOMEM);
 +        out_buf->pts = buf->pts;
 +    }
 +
 +    if (vol->precision != PRECISION_FIXED || vol->volume_i > 0) {
 +        int p, plane_samples;
 +
 +        if (av_sample_fmt_is_planar(buf->format))
 +            plane_samples = FFALIGN(nb_samples, vol->samples_align);
 +        else
 +            plane_samples = FFALIGN(nb_samples * vol->channels, vol->samples_align);
 +
 +        if (vol->precision == PRECISION_FIXED) {
 +            for (p = 0; p < vol->planes; p++) {
 +                vol->scale_samples(out_buf->extended_data[p],
 +                                   buf->extended_data[p], plane_samples,
 +                                   vol->volume_i);
 +            }
 +        } else if (av_get_packed_sample_fmt(vol->sample_fmt) == AV_SAMPLE_FMT_FLT) {
 +            for (p = 0; p < vol->planes; p++) {
 +                vol->fdsp.vector_fmul_scalar((float *)out_buf->extended_data[p],
 +                                             (const float *)buf->extended_data[p],
 +                                             vol->volume, plane_samples);
 +            }
 +        } else {
 +            for (p = 0; p < vol->planes; p++) {
 +                vol->fdsp.vector_dmul_scalar((double *)out_buf->extended_data[p],
 +                                             (const double *)buf->extended_data[p],
 +                                             vol->volume, plane_samples);
 +            }
 +        }
 +    }
 +
 +    if (buf != out_buf)
 +        avfilter_unref_buffer(buf);
 +
 +    return ff_filter_frame(outlink, out_buf);
 +}
 +
 +static const AVFilterPad avfilter_af_volume_inputs[] = {
 +    {
 +        .name           = "default",
 +        .type           = AVMEDIA_TYPE_AUDIO,
 +        .filter_frame   = filter_frame,
 +    },
 +    { NULL }
 +};
 +
 +static const AVFilterPad avfilter_af_volume_outputs[] = {
 +    {
 +        .name         = "default",
 +        .type         = AVMEDIA_TYPE_AUDIO,
 +        .config_props = config_output,
 +    },
 +    { NULL }
 +};
 +
 +AVFilter avfilter_af_volume_justin = {
 +    .name           = "volume_justin",
 +    .description    = NULL_IF_CONFIG_SMALL("Change input volume."),
 +    .query_formats  = query_formats,
 +    .priv_size      = sizeof(VolumeContext),
 +    .init           = init,
 +    .inputs         = avfilter_af_volume_inputs,
 +    .outputs        = avfilter_af_volume_outputs,
 +};
index 0000000,4e5ad22..dc54f6e
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,138 +1,138 @@@
 -;* This file is part of Libav.
+ ;*****************************************************************************
+ ;* x86-optimized functions for volume filter
+ ;* Copyright (c) 2012 Justin Ruggles <justin.ruggles@gmail.com>
+ ;*
 -;* Libav is free software; you can redistribute it and/or
++;* This file is part of FFmpeg.
+ ;*
 -;* Libav is distributed in the hope that it will be useful,
++;* FFmpeg is free software; you can redistribute it and/or
+ ;* modify it under the terms of the GNU Lesser General Public
+ ;* License as published by the Free Software Foundation; either
+ ;* version 2.1 of the License, or (at your option) any later version.
+ ;*
 -;* License along with Libav; if not, write to the Free Software
++;* FFmpeg is distributed in the hope that it will be useful,
+ ;* but WITHOUT ANY WARRANTY; without even the implied warranty of
+ ;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ ;* Lesser General Public License for more details.
+ ;*
+ ;* You should have received a copy of the GNU Lesser General Public
++;* 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/x86/x86util.asm"
+ SECTION_RODATA 32
+ pd_1_256:     times 4 dq 0x3F70000000000000
+ pd_int32_max: times 4 dq 0x41DFFFFFFFC00000
+ pw_1:         times 8 dw 1
+ pw_128:       times 8 dw 128
+ pq_128:       times 2 dq 128
+ SECTION_TEXT
+ ;------------------------------------------------------------------------------
+ ; void ff_scale_samples_s16(uint8_t *dst, const uint8_t *src, int len,
+ ;                           int volume)
+ ;------------------------------------------------------------------------------
+ INIT_XMM sse2
+ cglobal scale_samples_s16, 4,4,4, dst, src, len, volume
+     movd        m0, volumem
+     pshuflw     m0, m0, 0
+     punpcklwd   m0, [pw_1]
+     mova        m1, [pw_128]
+     lea       lenq, [lend*2-mmsize]
+ .loop:
+     ; dst[i] = av_clip_int16((src[i] * volume + 128) >> 8);
+     mova        m2, [srcq+lenq]
+     punpcklwd   m3, m2, m1
+     punpckhwd   m2, m1
+     pmaddwd     m3, m0
+     pmaddwd     m2, m0
+     psrad       m3, 8
+     psrad       m2, 8
+     packssdw    m3, m2
+     mova  [dstq+lenq], m3
+     sub       lenq, mmsize
+     jge .loop
+     REP_RET
+ ;------------------------------------------------------------------------------
+ ; void ff_scale_samples_s32(uint8_t *dst, const uint8_t *src, int len,
+ ;                           int volume)
+ ;------------------------------------------------------------------------------
+ %macro SCALE_SAMPLES_S32 0
+ cglobal scale_samples_s32, 4,4,4, dst, src, len, volume
+ %if ARCH_X86_32 && cpuflag(avx)
+     vbroadcastss   xmm2, volumem
+ %else
+     movd           xmm2, volumed
+     pshufd         xmm2, xmm2, 0
+ %endif
+     CVTDQ2PD         m2, xmm2
+     mulpd            m2, m2, [pd_1_256]
+     mova             m3, [pd_int32_max]
+     lea            lenq, [lend*4-mmsize]
+ .loop:
+     CVTDQ2PD         m0, [srcq+lenq         ]
+     CVTDQ2PD         m1, [srcq+lenq+mmsize/2]
+     mulpd            m0, m0, m2
+     mulpd            m1, m1, m2
+     minpd            m0, m0, m3
+     minpd            m1, m1, m3
+     cvtpd2dq       xmm0, m0
+     cvtpd2dq       xmm1, m1
+ %if cpuflag(avx)
+     vmovdqa [dstq+lenq         ], xmm0
+     vmovdqa [dstq+lenq+mmsize/2], xmm1
+ %else
+     movq    [dstq+lenq         ], xmm0
+     movq    [dstq+lenq+mmsize/2], xmm1
+ %endif
+     sub            lenq, mmsize
+     jge .loop
+     REP_RET
+ %endmacro
+ INIT_XMM sse2
+ %define CVTDQ2PD cvtdq2pd
+ SCALE_SAMPLES_S32
+ %define CVTDQ2PD vcvtdq2pd
+ INIT_YMM avx
+ SCALE_SAMPLES_S32
+ %undef CVTDQ2PD
+ ; NOTE: This is not bit-identical with the C version because it clips to
+ ;       [-INT_MAX, INT_MAX] instead of [INT_MIN, INT_MAX]
+ INIT_XMM ssse3, atom
+ cglobal scale_samples_s32, 4,4,8, dst, src, len, volume
+     movd        m4, volumem
+     pshufd      m4, m4, 0
+     mova        m5, [pq_128]
+     pxor        m6, m6
+     lea       lenq, [lend*4-mmsize]
+ .loop:
+     ; src[i] = av_clipl_int32((src[i] * volume + 128) >> 8);
+     mova        m7, [srcq+lenq]
+     pabsd       m3, m7
+     pshufd      m0, m3, q0100
+     pshufd      m1, m3, q0302
+     pmuludq     m0, m4
+     pmuludq     m1, m4
+     paddq       m0, m5
+     paddq       m1, m5
+     psrlq       m0, 7
+     psrlq       m1, 7
+     shufps      m2, m0, m1, q3131
+     shufps      m0, m0, m1, q2020
+     pcmpgtd     m2, m6
+     por         m0, m2
+     psrld       m0, 1
+     psignd      m0, m7
+     mova  [dstq+lenq], m0
+     sub       lenq, mmsize
+     jge .loop
+     REP_RET
index 0000000,02bedd2..beee8ca
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,59 +1,59 @@@
 - * This file is part of Libav.
+ /*
 - * Libav is free software; you can redistribute it and/or
++ * This file is part of FFmpeg.
+  *
 - * Libav is distributed in the hope that it will be useful,
++ * FFmpeg is free software; you can redistribute it and/or
+  * modify it under the terms of the GNU Lesser General Public
+  * License as published by the Free Software Foundation; either
+  * version 2.1 of the License, or (at your option) any later version.
+  *
 - * License along with Libav; if not, write to the Free Software
++ * FFmpeg is distributed in the hope that it will be useful,
+  * but WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  * Lesser General Public License for more details.
+  *
+  * You should have received a copy of the GNU Lesser General Public
++ * License along with FFmpeg; if not, write to the Free Software
+  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+  */
+ #include "config.h"
+ #include "libavutil/cpu.h"
+ #include "libavutil/samplefmt.h"
+ #include "libavutil/x86/cpu.h"
+ #include "libavfilter/af_volume.h"
+ void ff_scale_samples_s16_sse2(uint8_t *dst, const uint8_t *src, int len,
+                                int volume);
+ void ff_scale_samples_s32_sse2(uint8_t *dst, const uint8_t *src, int len,
+                                int volume);
+ void ff_scale_samples_s32_ssse3_atom(uint8_t *dst, const uint8_t *src, int len,
+                                      int volume);
+ void ff_scale_samples_s32_avx(uint8_t *dst, const uint8_t *src, int len,
+                               int volume);
+ void ff_volume_init_x86(VolumeContext *vol)
+ {
+     int mm_flags = av_get_cpu_flags();
+     enum AVSampleFormat sample_fmt = av_get_packed_sample_fmt(vol->sample_fmt);
+     if (sample_fmt == AV_SAMPLE_FMT_S16) {
+         if (EXTERNAL_SSE2(mm_flags) && vol->volume_i < 32768) {
+             vol->scale_samples = ff_scale_samples_s16_sse2;
+             vol->samples_align = 8;
+         }
+     } else if (sample_fmt == AV_SAMPLE_FMT_S32) {
+         if (EXTERNAL_SSE2(mm_flags)) {
+             vol->scale_samples = ff_scale_samples_s32_sse2;
+             vol->samples_align = 4;
+         }
+         if (EXTERNAL_SSSE3(mm_flags) && mm_flags & AV_CPU_FLAG_ATOM) {
+             vol->scale_samples = ff_scale_samples_s32_ssse3_atom;
+             vol->samples_align = 4;
+         }
+         if (EXTERNAL_AVX(mm_flags)) {
+             vol->scale_samples = ff_scale_samples_s32_avx;
+             vol->samples_align = 8;
+         }
+     }
+ }
Simple merge