summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Niedermayer <michaelni@gmx.at>2012-05-16 02:27:31 +0200
committerMichael Niedermayer <michaelni@gmx.at>2012-05-16 02:27:31 +0200
commit1cbf7fb4345a3e5b7791d483241bf4759bde4ece (patch)
treed7acd8317309e051fb240e3505f77aabe2ea0437
parenta48abf5e263ad7f2e68821766e7cf4d29befb58e (diff)
parent0ff0af731ce4544f84b2f748dcc699717a2df8d6 (diff)
Merge remote-tracking branch 'qatar/master'
* qatar/master: (26 commits) fate: use diff -b in oneline comparison Add missing version bumps and APIchanges/Changelog entries. lavfi: move buffer management function to a separate file. lavfi: move formats-related functions from default.c to formats.c lavfi: move video-related functions to a separate file. fate: make smjpeg a demux test fate: separate sierra-vmd audio and video tests fate: separate smacker audio and video tests libmp3lame: set supported channel layouts. avconv: automatically insert asyncts when -async is used. avconv: add support for audio filters. lavfi: add asyncts filter. lavfi: add aformat filter lavfi: add an audio buffer sink. lavfi: add an audio buffer source. buffersrc: add av_buffersrc_write_frame(). buffersrc: fix invalid read in uninit if the fifo hasn't been allocated lavfi: rename vsrc_buffer.c to buffersrc.c avfiltergraph: reindent lavfi: add channel layout/sample rate negotiation. ... Conflicts: Changelog doc/APIchanges doc/filters.texi ffmpeg.c ffprobe.c libavcodec/libmp3lame.c libavfilter/Makefile libavfilter/af_aformat.c libavfilter/allfilters.c libavfilter/avfilter.c libavfilter/avfilter.h libavfilter/avfiltergraph.c libavfilter/buffersrc.c libavfilter/defaults.c libavfilter/formats.c libavfilter/src_buffer.c libavfilter/version.h libavfilter/vf_yadif.c libavfilter/vsrc_buffer.c libavfilter/vsrc_buffer.h libavutil/avutil.h tests/fate/audio.mak tests/fate/demux.mak tests/fate/video.mak Merged-by: Michael Niedermayer <michaelni@gmx.at>
-rw-r--r--Changelog1
-rw-r--r--doc/APIchanges21
-rw-r--r--doc/ffmpeg.texi6
-rw-r--r--doc/filters.texi79
-rw-r--r--ffprobe.c22
-rw-r--r--libavcodec/libmp3lame.c11
-rw-r--r--libavfilter/Makefile5
-rw-r--r--libavfilter/af_aconvert.c15
-rw-r--r--libavfilter/af_aformat.c140
-rw-r--r--libavfilter/af_amerge.c21
-rw-r--r--libavfilter/af_aresample.c37
-rw-r--r--libavfilter/af_astreamsync.c7
-rw-r--r--libavfilter/af_asyncts.c237
-rw-r--r--libavfilter/af_earwax.c11
-rw-r--r--libavfilter/af_pan.c13
-rw-r--r--libavfilter/af_resample.c11
-rw-r--r--libavfilter/af_silencedetect.c13
-rw-r--r--libavfilter/af_volume.c13
-rw-r--r--libavfilter/allfilters.c10
-rw-r--r--libavfilter/asrc_aevalsrc.c2
-rw-r--r--libavfilter/avcodec.c71
-rw-r--r--libavfilter/avfilter.c374
-rw-r--r--libavfilter/avfilter.h32
-rw-r--r--libavfilter/avfiltergraph.c336
-rw-r--r--libavfilter/buffer.c244
-rw-r--r--libavfilter/buffersink.c102
-rw-r--r--libavfilter/buffersink.h21
-rw-r--r--libavfilter/buffersrc.c403
-rw-r--r--libavfilter/buffersrc.h11
-rw-r--r--libavfilter/defaults.c140
-rw-r--r--libavfilter/formats.c369
-rw-r--r--libavfilter/formats.h81
-rw-r--r--libavfilter/internal.h5
-rw-r--r--libavfilter/sink_buffer.c7
-rw-r--r--libavfilter/src_buffer.c10
-rw-r--r--libavfilter/src_movie.c5
-rw-r--r--libavfilter/version.h5
-rw-r--r--libavfilter/vf_yadif.c54
-rw-r--r--libavfilter/video.c345
-rw-r--r--libavutil/avutil.h2
-rwxr-xr-xtests/fate-run.sh4
-rw-r--r--tests/fate/audio.mak6
-rw-r--r--tests/fate/demux.mak7
-rw-r--r--tests/fate/video.mak7
-rw-r--r--tests/ref/fate/sierra-vmd334
-rw-r--r--tests/ref/fate/sierra-vmd-audio216
-rw-r--r--tests/ref/fate/sierra-vmd-video118
-rw-r--r--tests/ref/fate/smacker-audio87
-rw-r--r--tests/ref/fate/smacker-video (renamed from tests/ref/fate/smacker)87
-rw-r--r--tests/ref/fate/smjpeg425
-rw-r--r--tests/ref/fate/smjpeg-demux425
-rw-r--r--tools/lavfi-showfiltfmts.c2
52 files changed, 3304 insertions, 1706 deletions
diff --git a/Changelog b/Changelog
index 92383a723a..99b7f0e80d 100644
--- a/Changelog
+++ b/Changelog
@@ -30,6 +30,7 @@ version next:
- MicroDVD decoder
- Avid Meridien (AVUI) decoder
- accept + prefix to -pix_fmt option to disable automatic conversions.
+- audio filters support in libavfilter and avconv
version 0.10:
diff --git a/doc/APIchanges b/doc/APIchanges
index 2d25d49114..d00416c9c6 100644
--- a/doc/APIchanges
+++ b/doc/APIchanges
@@ -27,13 +27,30 @@ API changes, most recent first:
2012-03-26 - a67d9cf - lavfi 2.66.100
Add avfilter_fill_frame_from_{audio_,}buffer_ref() functions.
-2012-xx-xx - xxxxxxx - lavc 54.13.1
+2012-05-15 - lavfi 2.17.0
+ Add support for audio filters
+ ac71230/a2cd9be - add video/audio buffer sink in a new installed
+ header buffersink.h
+ 720c6b7 - add av_buffersrc_write_frame(), deprecate
+ av_vsrc_buffer_add_frame()
+ ab16504 - add avfilter_copy_buf_props()
+ 9453c9e - add extended_data to AVFilterBuffer
+ 1b8c927 - add avfilter_get_audio_buffer_ref_from_arrays()
+
+2012-05-09 - lavu 51.30.0 - samplefmt.h
+ 142e740 - add av_samples_copy()
+ 6d7f617 - add av_samples_set_silence()
+
+2012-05-09 - a5117a2 - lavc 54.13.1
For audio formats with fixed frame size, the last frame
no longer needs to be padded with silence, libavcodec
will handle this internally (effectively all encoders
behave as if they had CODEC_CAP_SMALL_LAST_FRAME set).
-2012-xx-xx - xxxxxxx - lavr 0.0.1
+2012-05-07 - 828bd08 - lavc 54.13.0 - avcodec.h
+ Add sample_rate and channel_layout fields to AVFrame.
+
+2012-05-01 - 4010d72 - lavr 0.0.1
Change AV_MIX_COEFF_TYPE_Q6 to AV_MIX_COEFF_TYPE_Q8.
2012-04-25 - 3527a73 - lavu 51.29.0 - cpu.h
diff --git a/doc/ffmpeg.texi b/doc/ffmpeg.texi
index 6765121680..5e2f33a4bb 100644
--- a/doc/ffmpeg.texi
+++ b/doc/ffmpeg.texi
@@ -499,6 +499,11 @@ Set the audio codec. This is an alias for @code{-codec:a}.
@item -sample_fmt[:@var{stream_specifier}] @var{sample_fmt} (@emph{output,per-stream})
Set the audio sample format. Use @code{-sample_fmts} to get a list
of supported sample formats.
+@item -af @var{filter_graph} (@emph{output})
+@var{filter_graph} is a description of the filter graph to apply to
+the input audio.
+Use the option "-filters" to show all the available filters (including
+also sources and sinks). This is an alias for @code{-filter:a}.
@end table
@section Advanced Audio options:
@@ -781,6 +786,7 @@ Audio sync method. "Stretches/squeezes" the audio stream to match the timestamps
the parameter is the maximum samples per second by which the audio is changed.
-async 1 is a special case where only the start of the audio stream is corrected
without any later correction.
+This option has been deprecated. Use the @code{asyncts} audio filter instead.
@item -copyts
Copy timestamps from input to output.
@item -copytb @var{mode}
diff --git a/doc/filters.texi b/doc/filters.texi
index 2af7b37d07..ba8c9f46fb 100644
--- a/doc/filters.texi
+++ b/doc/filters.texi
@@ -211,6 +211,32 @@ amovie=input.mkv:si=5 [a5];
[x3][a5] amerge" -c:a pcm_s16le output.mkv
@end example
+@section aformat
+
+Convert the input audio to one of the specified formats. The framework will
+negotiate the most appropriate format to minimize conversions.
+
+The filter accepts the following named parameters:
+@table @option
+
+@item sample_fmts
+A comma-separated list of requested sample formats.
+
+@item sample_rates
+A comma-separated list of requested sample rates.
+
+@item channel_layouts
+A comma-separated list of requested channel layouts.
+
+@end table
+
+If a parameter is omitted, all values are allowed.
+
+For example to force the output to either unsigned 8-bit or signed 16-bit stereo:
+@example
+aformat=sample_fmts\=u8\,s16:channel_layouts\=stereo
+@end example
+
@section anull
Pass the audio source unchanged to the output.
@@ -502,6 +528,25 @@ volume=-12dB
@end example
@end itemize
+@section asyncts
+Synchronize audio data with timestamps by squeezing/stretching it and/or
+dropping samples/adding silence when needed.
+
+The filter accepts the following named parameters:
+@table @option
+
+@item compensate
+Enable stretching/squeezing the data to make it match the timestamps.
+
+@item min_delta
+Minimum difference between timestamps and audio data (in seconds) to trigger
+adding/dropping samples.
+
+@item max_comp
+Maximum compensation in samples per second.
+
+@end table
+
@section resample
Convert the audio sample format, sample rate and channel layout. This filter is
not meant to be used directly.
@@ -721,6 +766,33 @@ anullsrc=r=48000:cl=4
anullsrc=r=48000:cl=mono
@end example
+@section abuffer
+Buffer audio frames, and make them available to the filter chain.
+
+This source is not intended to be part of user-supplied graph descriptions but
+for insertion by calling programs through the interface defined in
+@file{libavfilter/buffersrc.h}.
+
+It accepts the following named parameters:
+@table @option
+
+@item time_base
+Timebase which will be used for timestamps of submitted frames. It must be
+either a floating-point number or in @var{numerator}/@var{denominator} form.
+
+@item sample_rate
+Audio sample rate.
+
+@item sample_fmt
+Name of the sample format, as returned by @code{av_get_sample_fmt_name()}.
+
+@item channel_layout
+Channel layout of the audio data, in the form that can be accepted by
+@code{av_get_channel_layout()}.
+@end table
+
+All the parameters need to be explicitly defined.
+
@c man end AUDIO SOURCES
@chapter Audio Sinks
@@ -745,6 +817,13 @@ Null audio sink, do absolutely nothing with the input audio. It is
mainly useful as a template and to be employed in analysis / debugging
tools.
+@section abuffersink
+This sink is intended for programmatic use. Frames that arrive on this sink can
+be retrieved by the calling program using the interface defined in
+@file{libavfilter/buffersink.h}.
+
+This filter accepts no parameters.
+
@c man end AUDIO SINKS
@chapter Video Filters
diff --git a/ffprobe.c b/ffprobe.c
index b1b909dc57..5009d58f14 100644
--- a/ffprobe.c
+++ b/ffprobe.c
@@ -1549,6 +1549,19 @@ static int open_input_file(AVFormatContext **fmt_ctx_ptr, const char *filename)
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 != 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); \
@@ -1586,10 +1599,7 @@ static int probe_file(WriterContext *wctx, const char *filename)
}
PRINT_CHAPTER(streams);
PRINT_CHAPTER(format);
- for (i = 0; i < fmt_ctx->nb_streams; i++)
- if (fmt_ctx->streams[i]->codec->codec_id != CODEC_ID_NONE)
- avcodec_close(fmt_ctx->streams[i]->codec);
- avformat_close_input(&fmt_ctx);
+ close_input_file(&fmt_ctx);
av_freep(&nb_streams_frames);
av_freep(&nb_streams_packets);
}
@@ -1803,6 +1813,10 @@ int main(int argc, char **argv)
end:
av_freep(&print_format);
+
+ uninit_opts();
+ av_dict_free(&fmt_entries_to_show);
+
avformat_network_deinit();
return ret;
diff --git a/libavcodec/libmp3lame.c b/libavcodec/libmp3lame.c
index 43f76c85b6..1e50e0a48b 100644
--- a/libavcodec/libmp3lame.c
+++ b/libavcodec/libmp3lame.c
@@ -26,6 +26,7 @@
#include <lame/lame.h>
+#include "libavutil/audioconvert.h"
#include "libavutil/intreadwrite.h"
#include "libavutil/log.h"
#include "libavutil/opt.h"
@@ -76,13 +77,7 @@ static av_cold int mp3lame_encode_init(AVCodecContext *avctx)
if ((s->gfp = lame_init()) == NULL)
return AVERROR(ENOMEM);
- /* channels */
- if (avctx->channels > 2) {
- av_log(avctx, AV_LOG_ERROR,
- "Invalid number of channels %d, must be <= 2\n", avctx->channels);
- ret = AVERROR(EINVAL);
- goto error;
- }
+
lame_set_num_channels(s->gfp, avctx->channels);
lame_set_mode(s->gfp, avctx->channels > 1 ? JOINT_STEREO : MONO);
@@ -308,6 +303,8 @@ AVCodec ff_libmp3lame_encoder = {
AV_SAMPLE_FMT_S16,
AV_SAMPLE_FMT_NONE },
.supported_samplerates = libmp3lame_sample_rates,
+ .channel_layouts = (const uint64_t[]) { AV_CH_LAYOUT_MONO,
+ AV_CH_LAYOUT_STEREO },
.long_name = NULL_IF_CONFIG_SMALL("libmp3lame MP3 (MPEG audio layer 3)"),
.priv_class = &libmp3lame_class,
.defaults = libmp3lame_defaults,
diff --git a/libavfilter/Makefile b/libavfilter/Makefile
index 70f2c9e5ca..1f9d4117d1 100644
--- a/libavfilter/Makefile
+++ b/libavfilter/Makefile
@@ -2,6 +2,7 @@ include $(SUBDIR)../config.mak
NAME = avfilter
FFLIBS = avutil swscale
+FFLIBS-$(CONFIG_ASYNCTS_FILTER) += avresample
FFLIBS-$(CONFIG_RESAMPLE_FILTER) += avresample
FFLIBS-$(CONFIG_ACONVERT_FILTER) += swresample
@@ -25,6 +26,7 @@ OBJS = allfilters.o \
audio.o \
avfilter.o \
avfiltergraph.o \
+ buffer.o \
buffersink.o \
defaults.o \
drawutils.o \
@@ -34,6 +36,8 @@ OBJS = allfilters.o \
src_buffer.o \
transform.o \
vf_scale.o \
+ video.o \
+
OBJS-$(CONFIG_AVCODEC) += avcodec.o
OBJS-$(CONFIG_AVFORMAT) += lavfutils.o
@@ -47,6 +51,7 @@ OBJS-$(CONFIG_ARESAMPLE_FILTER) += af_aresample.o
OBJS-$(CONFIG_ASHOWINFO_FILTER) += af_ashowinfo.o
OBJS-$(CONFIG_ASPLIT_FILTER) += af_asplit.o
OBJS-$(CONFIG_ASTREAMSYNC_FILTER) += af_astreamsync.o
+OBJS-$(CONFIG_ASYNCTS_FILTER) += af_asyncts.o
OBJS-$(CONFIG_EARWAX_FILTER) += af_earwax.o
OBJS-$(CONFIG_PAN_FILTER) += af_pan.o
OBJS-$(CONFIG_RESAMPLE_FILTER) += af_resample.o
diff --git a/libavfilter/af_aconvert.c b/libavfilter/af_aconvert.c
index 9d420f84e4..2b3a330e3b 100644
--- a/libavfilter/af_aconvert.c
+++ b/libavfilter/af_aconvert.c
@@ -74,6 +74,7 @@ static int query_formats(AVFilterContext *ctx)
AVFilterLink *inlink = ctx->inputs[0];
AVFilterLink *outlink = ctx->outputs[0];
int out_packing = av_sample_fmt_is_planar(aconvert->out_sample_fmt);
+ AVFilterChannelLayouts *layouts;
avfilter_formats_ref(avfilter_make_all_formats(AVMEDIA_TYPE_AUDIO),
&inlink->out_formats);
@@ -85,15 +86,15 @@ static int query_formats(AVFilterContext *ctx)
avfilter_formats_ref(avfilter_make_all_formats(AVMEDIA_TYPE_AUDIO),
&outlink->in_formats);
- avfilter_formats_ref(avfilter_make_all_channel_layouts(),
- &inlink->out_chlayouts);
+ ff_channel_layouts_ref(ff_all_channel_layouts(),
+ &inlink->out_channel_layouts);
if (aconvert->out_chlayout != 0) {
- formats = NULL;
- avfilter_add_format(&formats, aconvert->out_chlayout);
- avfilter_formats_ref(formats, &outlink->in_chlayouts);
+ layouts = NULL;
+ ff_add_channel_layout(&layouts, aconvert->out_chlayout);
+ ff_channel_layouts_ref(layouts, &outlink->in_channel_layouts);
} else
- avfilter_formats_ref(avfilter_make_all_channel_layouts(),
- &outlink->in_chlayouts);
+ ff_channel_layouts_ref(ff_all_channel_layouts(),
+ &outlink->in_channel_layouts);
avfilter_formats_ref(avfilter_make_all_packing_formats(),
&inlink->out_packing);
diff --git a/libavfilter/af_aformat.c b/libavfilter/af_aformat.c
index 0a5857ec41..c602f5ddce 100644
--- a/libavfilter/af_aformat.c
+++ b/libavfilter/af_aformat.c
@@ -25,72 +25,110 @@
#include "libavutil/audioconvert.h"
#include "libavutil/avstring.h"
-#include "avfilter.h"
+#include "libavutil/opt.h"
+
#include "audio.h"
+#include "avfilter.h"
+#include "formats.h"
#include "internal.h"
-typedef struct {
- AVFilterFormats *formats, *chlayouts, *packing;
+typedef struct AFormatContext {
+ const AVClass *class;
+
+ AVFilterFormats *formats;
+ AVFilterFormats *sample_rates;
+ AVFilterChannelLayouts *channel_layouts;
+
+ char *formats_str;
+ char *sample_rates_str;
+ char *channel_layouts_str;
} AFormatContext;
+#define OFFSET(x) offsetof(AFormatContext, x)
+#define A AV_OPT_FLAG_AUDIO_PARAM
+static const AVOption options[] = {
+ { "sample_fmts", "A comma-separated list of sample formats.", OFFSET(formats_str), AV_OPT_TYPE_STRING, .flags = A },
+ { "sample_rates", "A comma-separated list of sample rates.", OFFSET(sample_rates_str), AV_OPT_TYPE_STRING, .flags = A },
+ { "channel_layouts", "A comma-separated list of channel layouts.", OFFSET(channel_layouts_str), AV_OPT_TYPE_STRING, .flags = A },
+ { NULL },
+};
+
+static const AVClass aformat_class = {
+ .class_name = "aformat filter",
+ .item_name = av_default_item_name,
+ .option = options,
+ .version = LIBAVUTIL_VERSION_INT,
+};
+
+#define PARSE_FORMATS(str, type, list, add_to_list, get_fmt, none, desc) \
+do { \
+ char *next, *cur = str; \
+ while (cur) { \
+ type fmt; \
+ next = strchr(cur, ','); \
+ if (next) \
+ *next++ = 0; \
+ \
+ if ((fmt = get_fmt(cur)) == none) { \
+ av_log(ctx, AV_LOG_ERROR, "Error parsing " desc ": %s.\n", cur);\
+ ret = AVERROR(EINVAL); \
+ goto fail; \
+ } \
+ add_to_list(&list, fmt); \
+ \
+ cur = next; \
+ } \
+} while (0)
+
+static int get_sample_rate(const char *samplerate)
+{
+ int ret = strtol(samplerate, NULL, 0);
+ return FFMAX(ret, 0);
+}
+
static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque)
{
- AFormatContext * const aformat = ctx->priv;
- char *fmts_str = NULL, *fmt_str, *ptr = NULL;
- int64_t fmt;
+ AFormatContext *s = ctx->priv;
int ret;
- if (!args)
- goto arg_fail;
-
-#define ADD_FORMATS(all_formats, fmt_name, fmt_type, fmts_list) do { \
- fmts_str = av_get_token(&args, ":"); \
- if (!fmts_str || !*fmts_str) \
- goto arg_fail; \
- if (!strcmp(fmts_str, "all")) { \
- aformat->fmts_list = all_formats; \
- } else { \
- for (fmt_str = fmts_str; \
- fmt_str = av_strtok(fmt_str, ",", &ptr); fmt_str = NULL) { \
- if ((ret = ff_parse_##fmt_name((fmt_type *)&fmt, \
- fmt_str, ctx)) < 0) { \
- av_freep(&fmts_str); \
- return ret; \
- } \
- avfilter_add_format(&aformat->fmts_list, fmt); \
- } \
- } \
- av_freep(&fmts_str); \
- if (*args) \
- args++; \
-} while (0)
+ if (!args) {
+ av_log(ctx, AV_LOG_ERROR, "No parameters supplied.\n");
+ return AVERROR(EINVAL);
+ }
- ADD_FORMATS(avfilter_make_all_formats(AVMEDIA_TYPE_AUDIO), sample_format, int, formats);
- ADD_FORMATS(avfilter_make_all_channel_layouts(), channel_layout, int64_t, chlayouts);
- ADD_FORMATS(avfilter_make_all_packing_formats(), packing_format, int, packing);
+ s->class = &aformat_class;
+ av_opt_set_defaults(s);
- return 0;
+ if ((ret = av_set_options_string(s, args, "=", ":")) < 0) {
+ av_log(ctx, AV_LOG_ERROR, "Error parsing options string '%s'.\n", args);
+ return ret;
+ }
-arg_fail:
- av_log(ctx, AV_LOG_ERROR, "Invalid arguments, they must be of the form "
- "sample_fmts:channel_layouts:packing_fmts\n");
- av_freep(&fmts_str);
- return AVERROR(EINVAL);
+ PARSE_FORMATS(s->formats_str, enum AVSampleFormat, s->formats,
+ avfilter_add_format, av_get_sample_fmt, AV_SAMPLE_FMT_NONE, "sample format");
+ PARSE_FORMATS(s->sample_rates_str, int, s->sample_rates, avfilter_add_format,
+ get_sample_rate, 0, "sample rate");
+ PARSE_FORMATS(s->channel_layouts_str, uint64_t, s->channel_layouts,
+ ff_add_channel_layout, av_get_channel_layout, 0,
+ "channel layout");
+
+fail:
+ av_opt_free(s);
+ return ret;
}
static int query_formats(AVFilterContext *ctx)
{
- AFormatContext * const aformat = ctx->priv;
+ AFormatContext *s = ctx->priv;
- avfilter_set_common_sample_formats (ctx, aformat->formats);
- avfilter_set_common_channel_layouts(ctx, aformat->chlayouts);
- avfilter_set_common_packing_formats(ctx, aformat->packing);
- return 0;
-}
+ avfilter_set_common_formats(ctx, s->formats ? s->formats :
+ avfilter_all_formats(AVMEDIA_TYPE_AUDIO));
+ ff_set_common_samplerates(ctx, s->sample_rates ? s->sample_rates :
+ ff_all_samplerates());
+ ff_set_common_channel_layouts(ctx, s->channel_layouts ? s->channel_layouts :
+ ff_all_channel_layouts());
-static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamplesref)
-{
- ff_filter_samples(inlink->dst->outputs[0], insamplesref);
+ return 0;
}
AVFilter avfilter_af_aformat = {
@@ -100,11 +138,11 @@ AVFilter avfilter_af_aformat = {
.query_formats = query_formats,
.priv_size = sizeof(AFormatContext),
- .inputs = (const AVFilterPad[]) {{ .name = "default",
+ .inputs = (AVFilterPad[]) {{ .name = "default",
.type = AVMEDIA_TYPE_AUDIO,
- .filter_samples = filter_samples},
+ .filter_samples = ff_null_filter_samples },
{ .name = NULL}},
- .outputs = (const AVFilterPad[]) {{ .name = "default",
+ .outputs = (AVFilterPad[]) {{ .name = "default",
.type = AVMEDIA_TYPE_AUDIO},
{ .name = NULL}},
};
diff --git a/libavfilter/af_amerge.c b/libavfilter/af_amerge.c
index faa64e1977..fcc1089d6f 100644
--- a/libavfilter/af_amerge.c
+++ b/libavfilter/af_amerge.c
@@ -56,17 +56,18 @@ static int query_formats(AVFilterContext *ctx)
int64_t inlayout[2], outlayout;
const int packing_fmts[] = { AVFILTER_PACKED, -1 };
AVFilterFormats *formats;
+ AVFilterChannelLayouts *layouts;
int i;
for (i = 0; i < 2; i++) {
- if (!ctx->inputs[i]->in_chlayouts ||
- !ctx->inputs[i]->in_chlayouts->format_count) {
+ 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_chlayouts->formats[0];
- if (ctx->inputs[i]->in_chlayouts->format_count > 1) {
+ 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);
@@ -101,13 +102,13 @@ static int query_formats(AVFilterContext *ctx)
formats = avfilter_make_format_list(packing_fmts);
avfilter_set_common_packing_formats(ctx, formats);
for (i = 0; i < 2; i++) {
- formats = NULL;
- avfilter_add_format(&formats, inlayout[i]);
- avfilter_formats_ref(formats, &ctx->inputs[i]->out_chlayouts);
+ layouts = NULL;
+ ff_add_channel_layout(&layouts, inlayout[i]);
+ ff_channel_layouts_ref(layouts, &ctx->inputs[i]->out_channel_layouts);
}
- formats = NULL;
- avfilter_add_format(&formats, outlayout);
- avfilter_formats_ref(formats, &ctx->outputs[0]->in_chlayouts);
+ layouts = NULL;
+ ff_add_channel_layout(&layouts, outlayout);
+ ff_channel_layouts_ref(layouts, &ctx->outputs[0]->in_channel_layouts);
return 0;
}
diff --git a/libavfilter/af_aresample.c b/libavfilter/af_aresample.c
index a2980d90cd..521ccf7f8d 100644
--- a/libavfilter/af_aresample.c
+++ b/libavfilter/af_aresample.c
@@ -56,6 +56,42 @@ static av_cold void uninit(AVFilterContext *ctx)
swr_free(&aresample->swr);
}
+static int query_formats(AVFilterContext *ctx)
+{
+ AResampleContext *aresample = ctx->priv;
+
+ AVFilterLink *inlink = ctx->inputs[0];
+ AVFilterLink *outlink = ctx->outputs[0];
+
+ AVFilterFormats *in_formats = avfilter_all_formats(AVMEDIA_TYPE_AUDIO);
+ AVFilterFormats *out_formats = avfilter_all_formats(AVMEDIA_TYPE_AUDIO);
+ AVFilterFormats *in_samplerates = ff_all_samplerates();
+ AVFilterFormats *out_samplerates;
+
+
+ AVFilterChannelLayouts *in_layouts = ff_all_channel_layouts();
+ AVFilterChannelLayouts *out_layouts = ff_all_channel_layouts();
+
+ avfilter_formats_ref(in_formats, &inlink->out_formats);
+ avfilter_formats_ref(out_formats, &outlink->in_formats);
+
+ avfilter_formats_ref(in_samplerates, &inlink->out_samplerates);
+
+ ff_channel_layouts_ref(in_layouts, &inlink->out_channel_layouts);
+ ff_channel_layouts_ref(out_layouts, &outlink->in_channel_layouts);
+
+ if(aresample->out_rate > 0) {
+ int sample_rates[] = { aresample->out_rate, -1 };
+ ff_set_common_samplerates(ctx, avfilter_make_format_list(sample_rates));
+ } else {
+ out_samplerates = ff_all_samplerates();
+ avfilter_formats_ref(out_samplerates, &outlink->in_samplerates);
+ }
+
+ return 0;
+}
+
+
static int config_output(AVFilterLink *outlink)
{
int ret;
@@ -113,6 +149,7 @@ AVFilter avfilter_af_aresample = {
.description = NULL_IF_CONFIG_SMALL("Resample audio data."),
.init = init,
.uninit = uninit,
+ .query_formats = query_formats,
.priv_size = sizeof(AResampleContext),
.inputs = (const AVFilterPad[]) {{ .name = "default",
diff --git a/libavfilter/af_astreamsync.c b/libavfilter/af_astreamsync.c
index faa3b7ce8a..9f040238d9 100644
--- a/libavfilter/af_astreamsync.c
+++ b/libavfilter/af_astreamsync.c
@@ -81,6 +81,7 @@ static int query_formats(AVFilterContext *ctx)
{
int i;
AVFilterFormats *formats;
+ AVFilterChannelLayouts *layouts;
for (i = 0; i < 2; i++) {
formats = ctx->inputs[i]->in_formats;
@@ -89,9 +90,9 @@ static int query_formats(AVFilterContext *ctx)
formats = ctx->inputs[i]->in_packing;
avfilter_formats_ref(formats, &ctx->inputs[i]->out_packing);
avfilter_formats_ref(formats, &ctx->outputs[i]->in_packing);
- formats = ctx->inputs[i]->in_chlayouts;
- avfilter_formats_ref(formats, &ctx->inputs[i]->out_chlayouts);
- avfilter_formats_ref(formats, &ctx->outputs[i]->in_chlayouts);
+ layouts = ctx->inputs[i]->in_channel_layouts;
+ ff_channel_layouts_ref(layouts, &ctx->inputs[i]->out_channel_layouts);
+ ff_channel_layouts_ref(layouts, &ctx->outputs[i]->in_channel_layouts);
}
return 0;
}
diff --git a/libavfilter/af_asyncts.c b/libavfilter/af_asyncts.c
new file mode 100644
index 0000000000..5cde0bf00a
--- /dev/null
+++ b/libavfilter/af_asyncts.c
@@ -0,0 +1,237 @@
+/*
+ * This file is part of Libav.
+ *
+ * Libav is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * Libav is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Libav; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "libavresample/avresample.h"
+#include "libavutil/audio_fifo.h"
+#include "libavutil/mathematics.h"
+#include "libavutil/opt.h"
+#include "libavutil/samplefmt.h"
+
+#include "audio.h"
+#include "avfilter.h"
+
+typedef struct ASyncContext {
+ const AVClass *class;
+
+ AVAudioResampleContext *avr;
+ int64_t pts; ///< timestamp in samples of the first sample in fifo
+ int min_delta; ///< pad/trim min threshold in samples
+
+ /* options */
+ int resample;
+ float min_delta_sec;
+ int max_comp;
+} 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, { 0 }, 0, 1, A },
+ { "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, { 500 }, 0, INT_MAX, A },
+ { NULL },
+};
+
+static const AVClass async_class = {
+ .class_name = "asyncts filter",
+ .item_name = av_default_item_name,
+ .option = options,
+ .version = LIBAVUTIL_VERSION_INT,
+};
+
+static int init(AVFilterContext *ctx, const char *args, void *opaque)
+{
+ ASyncContext *s = ctx->priv;
+ int ret;
+
+ s->class = &async_class;
+ av_opt_set_defaults(s);
+
+ if ((ret = av_set_options_string(s, args, "=", ":")) < 0) {
+ av_log(ctx, AV_LOG_ERROR, "Error parsing options string '%s'.\n", args);
+ return ret;
+ }
+ av_opt_free(s);
+
+ s->pts = AV_NOPTS_VALUE;
+
+ return 0;
+}
+
+static void uninit(AVFilterContext *ctx)
+{
+ ASyncContext *s = ctx->priv;
+
+ if (s->avr) {
+ avresample_close(s->avr);
+ avresample_free(&s->avr);
+ }
+}
+
+static int config_props(AVFilterLink *link)
+{
+ ASyncContext *s = link->src->priv;
+ int ret;
+
+ s->min_delta = s->min_delta_sec * link->sample_rate;
+ link->time_base = (AVRational){1, link->sample_rate};
+
+ s->avr = avresample_alloc_context();
+ if (!s->avr)
+ return AVERROR(ENOMEM);
+
+ av_opt_set_int(s->avr, "in_channel_layout", link->channel_layout, 0);
+ av_opt_set_int(s->avr, "out_channel_layout", link->channel_layout, 0);
+ av_opt_set_int(s->avr, "in_sample_fmt", link->format, 0);
+ av_opt_set_int(s->avr, "out_sample_fmt", link->format, 0);
+ av_opt_set_int(s->avr, "in_sample_rate", link->sample_rate, 0);
+ av_opt_set_int(s->avr, "out_sample_rate", link->sample_rate, 0);
+
+ if (s->resample)
+ av_opt_set_int(s->avr, "force_resampling", 1, 0);
+
+ if ((ret = avresample_open(s->avr)) < 0)
+ return ret;
+
+ return 0;
+}
+
+static int request_frame(AVFilterLink *link)
+{
+ AVFilterContext *ctx = link->src;
+ ASyncContext *s = ctx->priv;
+ int ret = avfilter_request_frame(ctx->inputs[0]);
+ int nb_samples;
+
+ /* flush the fifo */
+ if (ret == AVERROR_EOF && (nb_samples = avresample_get_delay(s->avr))) {
+ AVFilterBufferRef *buf = ff_get_audio_buffer(link, AV_PERM_WRITE,
+ nb_samples);
+ if (!buf)
+ return AVERROR(ENOMEM);
+ avresample_convert(s->avr, (void**)buf->extended_data, buf->linesize[0],
+ nb_samples, NULL, 0, 0);
+ buf->pts = s->pts;
+ ff_filter_samples(link, buf);
+ return 0;
+ }
+
+ return ret;
+}
+
+static void write_to_fifo(ASyncContext *s, AVFilterBufferRef *buf)
+{
+ avresample_convert(s->avr, NULL, 0, 0, (void**)buf->extended_data,
+ buf->linesize[0], buf->audio->nb_samples);
+ avfilter_unref_buffer(buf);
+}
+
+/* get amount of data currently buffered, in samples */
+static int64_t get_delay(ASyncContext *s)
+{
+ return avresample_available(s->avr) + avresample_get_delay(s->avr);
+}
+
+static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *buf)
+{
+ AVFilterContext *ctx = inlink->dst;
+ ASyncContext *s = ctx->priv;
+ AVFilterLink *outlink = ctx->outputs[0];
+ int nb_channels = av_get_channel_layout_nb_channels(buf->audio->channel_layout);
+ int64_t pts = (buf->pts == AV_NOPTS_VALUE) ? buf->pts :
+ av_rescale_q(buf->pts, inlink->time_base, outlink->time_base);
+ int out_size;
+ int64_t delta;
+
+ /* buffer data until we get the first timestamp */
+ if (s->pts == AV_NOPTS_VALUE) {
+ if (pts != AV_NOPTS_VALUE) {
+ s->pts = pts - get_delay(s);
+ }
+ write_to_fifo(s, buf);
+ return;
+ }
+
+ /* now wait for the next timestamp */
+ if (pts == AV_NOPTS_VALUE) {
+ write_to_fifo(s, buf);
+ return;
+ }
+
+ /* when we have two timestamps, compute how many samples would we have
+ * to add/remove to get proper sync between data and timestamps */
+ delta = pts - s->pts - get_delay(s);
+ out_size = avresample_available(s->avr);
+
+ if (labs(delta) > s->min_delta) {
+ av_log(ctx, AV_LOG_VERBOSE, "Discontinuity - %"PRId64" samples.\n", delta);
+ out_size += delta;
+ } else if (s->resample) {
+ int comp = av_clip(delta, -s->max_comp, s->max_comp);
+ av_log(ctx, AV_LOG_VERBOSE, "Compensating %d samples per second.\n", comp);
+ avresample_set_compensation(s->avr, delta, inlink->sample_rate);
+ }
+
+ if (out_size > 0) {
+ AVFilterBufferRef *buf_out = ff_get_audio_buffer(outlink, AV_PERM_WRITE,
+ out_size);
+ if (!buf_out)
+ return;
+
+ avresample_read(s->avr, (void**)buf_out->extended_data, out_size);
+ buf_out->pts = s->pts;
+
+ if (delta > 0) {
+ av_samples_set_silence(buf_out->extended_data, out_size - delta,
+ delta, nb_channels, buf->format);
+ }
+ ff_filter_samples(outlink, buf_out);
+ } else {
+ av_log(ctx, AV_LOG_WARNING, "Non-monotonous timestamps, dropping "
+ "whole buffer.\n");
+ }
+
+ /* drain any remaining buffered data */
+ avresample_read(s->avr, NULL, avresample_available(s->avr));
+
+ s->pts = pts - avresample_get_delay(s->avr);
+ avresample_convert(s->avr, NULL, 0, 0, (void**)buf->extended_data,
+ buf->linesize[0], buf->audio->nb_samples);
+ avfilter_unref_buffer(buf);
+}
+
+AVFilter avfilter_af_asyncts = {
+ .name = "asyncts",
+ .description = NULL_IF_CONFIG_SMALL("Sync audio data to timestamps"),
+
+ .init = init,
+ .uninit = uninit,
+
+ .priv_size = sizeof(ASyncContext),
+
+ .inputs = (const AVFilterPad[]) {{ .name = "default",
+ .type = AVMEDIA_TYPE_AUDIO,
+ .filter_samples = filter_samples },
+ { NULL }},
+ .outputs = (const AVFilterPad[]) {{ .name = "default",
+ .type = AVMEDIA_TYPE_AUDIO,
+ .config_props = config_props,
+ .request_frame = request_frame },
+ { NULL }},
+};
diff --git a/libavfilter/af_earwax.c b/libavfilter/af_earwax.c
index 6afed72182..2ab248f390 100644
--- a/libavfilter/af_earwax.c
+++ b/libavfilter/af_earwax.c
@@ -32,6 +32,7 @@
#include "libavutil/audioconvert.h"
#include "avfilter.h"
#include "audio.h"
+#include "formats.h"
#define NUMTAPS 64
@@ -76,15 +77,19 @@ typedef struct {
static int query_formats(AVFilterContext *ctx)
{
+ int sample_rates[] = { 44100, -1 };
+
AVFilterFormats *formats = NULL;
+ AVFilterChannelLayouts *layout = NULL;
+
avfilter_add_format(&formats, AV_SAMPLE_FMT_S16);
avfilter_set_common_sample_formats(ctx, formats);
- formats = NULL;
- avfilter_add_format(&formats, AV_CH_LAYOUT_STEREO);
- avfilter_set_common_channel_layouts(ctx, formats);
+ ff_add_channel_layout(&layout, AV_CH_LAYOUT_STEREO);
+ ff_set_common_channel_layouts(ctx, layout);
formats = NULL;
avfilter_add_format(&formats, AVFILTER_PACKED);
avfilter_set_common_packing_formats(ctx, formats);
+ ff_set_common_samplerates(ctx, avfilter_make_format_list(sample_rates));
return 0;
}
diff --git a/libavfilter/af_pan.c b/libavfilter/af_pan.c
index fd65aac58c..3100a14881 100644
--- a/libavfilter/af_pan.c
+++ b/libavfilter/af_pan.c
@@ -33,6 +33,7 @@
#include "libswresample/swresample.h"
#include "audio.h"
#include "avfilter.h"
+#include "formats.h"
#define MAX_CHANNELS 63
@@ -212,7 +213,7 @@ static int query_formats(AVFilterContext *ctx)
PanContext *pan = ctx->priv;
AVFilterLink *inlink = ctx->inputs[0];
AVFilterLink *outlink = ctx->outputs[0];
- AVFilterFormats *formats;
+ AVFilterChannelLayouts *layouts;
pan->pure_gains = are_gains_pure(pan);
/* libswr supports any sample and packing formats */
@@ -220,13 +221,13 @@ static int query_formats(AVFilterContext *ctx)
avfilter_set_common_packing_formats(ctx, avfilter_make_all_packing_formats());
// inlink supports any channel layout
- formats = avfilter_make_all_channel_layouts();
- avfilter_formats_ref(formats, &inlink->out_chlayouts);
+ layouts = ff_all_channel_layouts();
+ ff_channel_layouts_ref(layouts, &inlink->out_channel_layouts);
// outlink supports only requested output channel layout
- formats = NULL;
- avfilter_add_format(&formats, pan->out_channel_layout);
- avfilter_formats_ref(formats, &outlink->in_chlayouts);
+ layouts = NULL;
+ ff_add_channel_layout(&layouts, pan->out_channel_layout);
+ ff_channel_layouts_ref(layouts, &outlink->in_channel_layouts);
return 0;
}
diff --git a/libavfilter/af_resample.c b/libavfilter/af_resample.c
index f46e24b1b6..4ad5a8c38e 100644
--- a/libavfilter/af_resample.c
+++ b/libavfilter/af_resample.c
@@ -31,6 +31,7 @@
#include "audio.h"
#include "avfilter.h"
+#include "formats.h"
#include "internal.h"
typedef struct ResampleContext {
@@ -56,10 +57,20 @@ static int query_formats(AVFilterContext *ctx)
AVFilterFormats *in_formats = avfilter_all_formats(AVMEDIA_TYPE_AUDIO);
AVFilterFormats *out_formats = avfilter_all_formats(AVMEDIA_TYPE_AUDIO);
+ AVFilterFormats *in_samplerates = ff_all_samplerates();
+ AVFilterFormats *out_samplerates = ff_all_samplerates();
+ AVFilterChannelLayouts *in_layouts = ff_all_channel_layouts();
+ AVFilterChannelLayouts *out_layouts = ff_all_channel_layouts();
avfilter_formats_ref(in_formats, &inlink->out_formats);
avfilter_formats_ref(out_formats, &outlink->in_formats);
+ avfilter_formats_ref(in_samplerates, &inlink->out_samplerates);
+ avfilter_formats_ref(out_samplerates, &outlink->in_samplerates);
+
+ ff_channel_layouts_ref(in_layouts, &inlink->out_channel_layouts);
+ ff_channel_layouts_ref(out_layouts, &outlink->in_channel_layouts);
+
return 0;
}
diff --git a/libavfilter/af_silencedetect.c b/libavfilter/af_silencedetect.c
index 093ca2b21f..4f5d8e0dd4 100644
--- a/libavfilter/af_silencedetect.c
+++ b/libavfilter/af_silencedetect.c
@@ -26,6 +26,7 @@
#include "libavutil/opt.h"
#include "libavutil/timestamp.h"
#include "audio.h"
+#include "formats.h"
#include "avfilter.h"
typedef struct {
@@ -130,16 +131,17 @@ static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *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
};
int packing_fmts[] = { AVFILTER_PACKED, -1 };
- formats = avfilter_make_all_channel_layouts();
- if (!formats)
+ layouts = ff_all_channel_layouts();
+ if (!layouts)
return AVERROR(ENOMEM);
- avfilter_set_common_channel_layouts(ctx, formats);
+ ff_set_common_channel_layouts(ctx, layouts);
formats = avfilter_make_format_list(sample_fmts);
if (!formats)
@@ -151,6 +153,11 @@ static int query_formats(AVFilterContext *ctx)
return AVERROR(ENOMEM);
avfilter_set_common_packing_formats(ctx, formats);
+ formats = ff_all_samplerates();
+ if (!formats)
+ return AVERROR(ENOMEM);
+ ff_set_common_samplerates(ctx, formats);
+
return 0;
}
diff --git a/libavfilter/af_volume.c b/libavfilter/af_volume.c
index 8e2e37e730..50f3cbd002 100644
--- a/libavfilter/af_volume.c
+++ b/libavfilter/af_volume.c
@@ -28,6 +28,7 @@
#include "libavutil/eval.h"
#include "audio.h"
#include "avfilter.h"
+#include "formats.h"
typedef struct {
double volume;
@@ -81,6 +82,7 @@ static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque)
static int query_formats(AVFilterContext *ctx)
{
AVFilterFormats *formats = NULL;
+ AVFilterChannelLayouts *layouts;
enum AVSampleFormat sample_fmts[] = {
AV_SAMPLE_FMT_U8,
AV_SAMPLE_FMT_S16,
@@ -91,10 +93,10 @@ static int query_formats(AVFilterContext *ctx)
};
int packing_fmts[] = { AVFILTER_PACKED, -1 };
- formats = avfilter_make_all_channel_layouts();
- if (!formats)
+ layouts = ff_all_channel_layouts();
+ if (!layouts)
return AVERROR(ENOMEM);
- avfilter_set_common_channel_layouts(ctx, formats);
+ ff_set_common_channel_layouts(ctx, layouts);
formats = avfilter_make_format_list(sample_fmts);
if (!formats)
@@ -106,6 +108,11 @@ static int query_formats(AVFilterContext *ctx)
return AVERROR(ENOMEM);
avfilter_set_common_packing_formats(ctx, formats);
+ formats = ff_all_samplerates();
+ if (!formats)
+ return AVERROR(ENOMEM);
+ ff_set_common_samplerates(ctx, formats);
+
return 0;
}
diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c
index 4e4c5d37f4..29cd3e3402 100644
--- a/libavfilter/allfilters.c
+++ b/libavfilter/allfilters.c
@@ -42,13 +42,13 @@ void avfilter_register_all(void)
REGISTER_FILTER (ASHOWINFO, ashowinfo, af);
REGISTER_FILTER (ASPLIT, asplit, af);
REGISTER_FILTER (ASTREAMSYNC, astreamsync, af);
+ REGISTER_FILTER (ASYNCTS, asyncts, af);
REGISTER_FILTER (EARWAX, earwax, af);
REGISTER_FILTER (PAN, pan, af);
REGISTER_FILTER (SILENCEDETECT, silencedetect, af);
REGISTER_FILTER (VOLUME, volume, af);
REGISTER_FILTER (RESAMPLE, resample, af);
- REGISTER_FILTER (ABUFFER, abuffer, asrc);
REGISTER_FILTER (AEVALSRC, aevalsrc, asrc);
REGISTER_FILTER (AMOVIE, amovie, asrc);
REGISTER_FILTER (ANULLSRC, anullsrc, asrc);
@@ -130,10 +130,18 @@ void avfilter_register_all(void)
avfilter_register(&avfilter_vsrc_buffer);
}
{
+ extern AVFilter avfilter_asrc_abuffer;
+ avfilter_register(&avfilter_asrc_abuffer);
+ }
+ {
extern AVFilter avfilter_vsink_buffer;
avfilter_register(&avfilter_vsink_buffer);
}
{
+ extern AVFilter avfilter_asink_abuffer;
+ avfilter_register(&avfilter_asink_abuffer);
+ }
+ {
extern AVFilter avfilter_vf_scale;
avfilter_register(&avfilter_vf_scale);
}
diff --git a/libavfilter/asrc_aevalsrc.c b/libavfilter/asrc_aevalsrc.c
index 4abcbc46aa..94197b2fd8 100644
--- a/libavfilter/asrc_aevalsrc.c
+++ b/libavfilter/asrc_aevalsrc.c
@@ -190,7 +190,7 @@ static int query_formats(AVFilterContext *ctx)
int packing_fmts[] = { AVFILTER_PLANAR, -1 };
avfilter_set_common_sample_formats (ctx, avfilter_make_format_list(sample_fmts));
- avfilter_set_common_channel_layouts(ctx, avfilter_make_format64_list(chlayouts));
+ ff_set_common_channel_layouts(ctx, avfilter_make_format64_list(chlayouts));
avfilter_set_common_packing_formats(ctx, avfilter_make_format_list(packing_fmts));
return 0;
diff --git a/libavfilter/avcodec.c b/libavfilter/avcodec.c
index d4c92f98cc..ce003abaa0 100644
--- a/libavfilter/avcodec.c
+++ b/libavfilter/avcodec.c
@@ -24,77 +24,6 @@
#include "avcodec.h"
#include "libavutil/opt.h"
-int avfilter_copy_frame_props(AVFilterBufferRef *dst, const AVFrame *src)
-{
- dst->pts = src->pts;
- dst->pos = src->pkt_pos;
- dst->format = src->format;
-
- switch (dst->type) {
- case AVMEDIA_TYPE_VIDEO:
- dst->video->w = src->width;
- dst->video->h = src->height;
- dst->video->sample_aspect_ratio = src->sample_aspect_ratio;
- dst->video->interlaced = src->interlaced_frame;
- dst->video->top_field_first = src->top_field_first;
- dst->video->key_frame = src->key_frame;
- dst->video->pict_type = src->pict_type;
- break;
- case AVMEDIA_TYPE_AUDIO:
- dst->audio->sample_rate = src->sample_rate;
- dst->audio->channel_layout = src->channel_layout;
- break;
- default:
- return AVERROR(EINVAL);
- }
-
- return 0;
-}
-
-int avfilter_copy_buf_props(AVFrame *dst, const AVFilterBufferRef *src)
-{
- int planes, nb_channels;
-
- memcpy(dst->data, src->data, sizeof(dst->data));
- memcpy(dst->linesize, src->linesize, sizeof(dst->linesize));
-
- dst->pts = src->pts;
- dst->format = src->format;
-
- switch (src->type) {
- case AVMEDIA_TYPE_VIDEO:
- dst->width = src->video->w;
- dst->height = src->video->h;
- dst->sample_aspect_ratio = src->video->sample_aspect_ratio;
- dst->interlaced_frame = src->video->interlaced;
- dst->top_field_first = src->video->top_field_first;
- dst->key_frame = src->video->key_frame;
- dst->pict_type = src->video->pict_type;
- break;
- case AVMEDIA_TYPE_AUDIO:
- nb_channels = av_get_channel_layout_nb_channels(src->audio->channel_layout);
- planes = av_sample_fmt_is_planar(src->format) ? nb_channels : 1;
-
- if (planes > FF_ARRAY_ELEMS(dst->data)) {
- dst->extended_data = av_mallocz(planes * sizeof(*dst->extended_data));
- if (!dst->extended_data)
- return AVERROR(ENOMEM);
- memcpy(dst->extended_data, src->extended_data,
- planes * sizeof(dst->extended_data));
- } else
- dst->extended_data = dst->data;
-
- dst->sample_rate = src->audio->sample_rate;
- dst->channel_layout = src->audio->channel_layout;
- dst->nb_samples = src->audio->nb_samples;
- break;
- default:
- return AVERROR(EINVAL);
- }
-
- return 0;
-}
-
AVFilterBufferRef *avfilter_get_video_buffer_ref_from_frame(const AVFrame *frame,
int perms)
{
diff --git a/libavfilter/avfilter.c b/libavfilter/avfilter.c
index 4354f8ca03..9704dc0a96 100644
--- a/libavfilter/avfilter.c
+++ b/libavfilter/avfilter.c
@@ -24,11 +24,11 @@
#include "libavutil/pixdesc.h"
#include "libavutil/rational.h"
#include "libavutil/audioconvert.h"
-#include "libavutil/imgutils.h"
#include "libavutil/avassert.h"
#include "libavutil/avstring.h"
#include "avfilter.h"
+#include "formats.h"
#include "internal.h"
unsigned avfilter_version(void) {
@@ -47,7 +47,7 @@ const char *avfilter_license(void)
return LICENSE_PREFIX FFMPEG_LICENSE + sizeof(LICENSE_PREFIX) - 1;
}
-static void command_queue_pop(AVFilterContext *filter)
+void ff_command_queue_pop(AVFilterContext *filter)
{
AVFilterCommand *c= filter->command_queue;
av_freep(&c->arg);
@@ -56,133 +56,6 @@ static void command_queue_pop(AVFilterContext *filter)
av_free(c);
}
-AVFilterBufferRef *avfilter_ref_buffer(AVFilterBufferRef *ref, int pmask)
-{
- AVFilterBufferRef *ret = av_malloc(sizeof(AVFilterBufferRef));
- if (!ret)
- return NULL;
- *ret = *ref;
- if (ref->type == AVMEDIA_TYPE_VIDEO) {
- ret->video = av_malloc(sizeof(AVFilterBufferRefVideoProps));
- if (!ret->video) {
- av_free(ret);
- return NULL;
- }
- *ret->video = *ref->video;
- ret->extended_data = ret->data;
- } else if (ref->type == AVMEDIA_TYPE_AUDIO) {
- ret->audio = av_malloc(sizeof(AVFilterBufferRefAudioProps));
- if (!ret->audio) {
- av_free(ret);
- return NULL;
- }
- *ret->audio = *ref->audio;
-
- if (ref->extended_data && ref->extended_data != ref->data) {
- int nb_channels = av_get_channel_layout_nb_channels(ref->audio->channel_layout);
- if (!(ret->extended_data = av_malloc(sizeof(*ret->extended_data) *
- nb_channels))) {
- av_freep(&ret->audio);
- av_freep(&ret);
- return NULL;
- }
- memcpy(ret->extended_data, ref->extended_data,
- sizeof(*ret->extended_data) * nb_channels);
- } else
- ret->extended_data = ret->data;
- }
- ret->perms &= pmask;
- ret->buf->refcount ++;
- return ret;
-}
-
-static void free_pool(AVFilterPool *pool)
-{
- int i;
-
- av_assert0(pool->refcount > 0);
-
- for (i = 0; i < POOL_SIZE; i++) {
- if (pool->pic[i]) {
- AVFilterBufferRef *picref = pool->pic[i];
- /* free buffer: picrefs stored in the pool are not
- * supposed to contain a free callback */
- av_assert0(!picref->buf->refcount);
- av_freep(&picref->buf->data[0]);
- av_freep(&picref->buf);
-
- av_freep(&picref->audio);
- av_freep(&picref->video);
- av_freep(&pool->pic[i]);
- pool->count--;
- }
- }
- pool->draining = 1;
-
- if (!--pool->refcount) {
- av_assert0(!pool->count);
- av_free(pool);
- }
-}
-
-static void store_in_pool(AVFilterBufferRef *ref)
-{
- int i;
- AVFilterPool *pool= ref->buf->priv;
-
- av_assert0(ref->buf->data[0]);
- av_assert0(pool->refcount>0);
-
- if (pool->count == POOL_SIZE) {
- AVFilterBufferRef *ref1 = pool->pic[0];
- av_freep(&ref1->video);
- av_freep(&ref1->audio);
- av_freep(&ref1->buf->data[0]);
- av_freep(&ref1->buf);
- av_free(ref1);
- memmove(&pool->pic[0], &pool->pic[1], sizeof(void*)*(POOL_SIZE-1));
- pool->count--;
- pool->pic[POOL_SIZE-1] = NULL;
- }
-
- for (i = 0; i < POOL_SIZE; i++) {
- if (!pool->pic[i]) {
- pool->pic[i] = ref;
- pool->count++;
- break;
- }
- }
- if (pool->draining) {
- free_pool(pool);
- } else
- --pool->refcount;
-}
-
-void avfilter_unref_buffer(AVFilterBufferRef *ref)
-{
- if (!ref)
- return;
- av_assert0(ref->buf->refcount > 0);
- if (!(--ref->buf->refcount)) {
- if (!ref->buf->free) {
- store_in_pool(ref);
- return;
- }
- ref->buf->free(ref->buf);
- }
- if (ref->extended_data != ref->data)
- av_freep(&ref->extended_data);
- av_freep(&ref->video);
- av_freep(&ref->audio);
- av_free(ref);
-}
-
-void avfilter_unref_bufferp(AVFilterBufferRef **ref)
-{
- avfilter_unref_buffer(*ref);
- *ref = NULL;
-}
-
void avfilter_insert_pad(unsigned idx, unsigned *count, size_t padidx_off,
AVFilterPad **pads, AVFilterLink ***links,
AVFilterPad *newpad)
@@ -240,7 +113,7 @@ void avfilter_link_free(AVFilterLink **link)
return;
if ((*link)->pool)
- free_pool((*link)->pool);
+ ff_free_pool((*link)->pool);
av_freep(link);
}
@@ -272,12 +145,15 @@ int avfilter_insert_filter(AVFilterLink *link, AVFilterContext *filt,
if (link->out_formats)
avfilter_formats_changeref(&link->out_formats,
&filt->outputs[filt_dstpad_idx]->out_formats);
- if (link->out_chlayouts)
- avfilter_formats_changeref(&link->out_chlayouts,
- &filt->outputs[filt_dstpad_idx]->out_chlayouts);
+ if (link->out_channel_layouts)
+ ff_channel_layouts_changeref(&link->out_channel_layouts,
+ &filt->outputs[filt_dstpad_idx]->out_channel_layouts);
if (link->out_packing)
avfilter_formats_changeref(&link->out_packing,
&filt->outputs[filt_dstpad_idx]->out_packing);
+ if (link->out_samplerates)
+ avfilter_formats_changeref(&link->out_samplerates,
+ &filt->outputs[filt_dstpad_idx]->out_samplerates);
return 0;
}
@@ -329,6 +205,7 @@ int avfilter_config_links(AVFilterContext *filter)
link->sample_aspect_ratio = inlink ?
inlink->sample_aspect_ratio : (AVRational){1,1};
+#if 1
if (inlink) {
if (!link->w)
link->w = inlink->w;
@@ -359,6 +236,7 @@ int avfilter_config_links(AVFilterContext *filter)
link->time_base = (AVRational) {1, link->sample_rate};
}
+#endif
if ((config_link = link->dstpad->config_props))
if ((ret = config_link(link)) < 0)
return ret;
@@ -370,47 +248,6 @@ int avfilter_config_links(AVFilterContext *filter)
return 0;
}
-static char *ff_get_ref_perms_string(char *buf, size_t buf_size, int perms)
-{
- snprintf(buf, buf_size, "%s%s%s%s%s%s",
- perms & AV_PERM_READ ? "r" : "",
- perms & AV_PERM_WRITE ? "w" : "",
- perms & AV_PERM_PRESERVE ? "p" : "",
- perms & AV_PERM_REUSE ? "u" : "",
- perms & AV_PERM_REUSE2 ? "U" : "",
- perms & AV_PERM_NEG_LINESIZES ? "n" : "");
- return buf;
-}
-
-static void ff_dlog_ref(void *ctx, AVFilterBufferRef *ref, int end)
-{
- av_unused char buf[16];
- av_dlog(ctx,
- "ref[%p buf:%p refcount:%d perms:%s data:%p linesize[%d, %d, %d, %d] pts:%"PRId64" pos:%"PRId64,
- ref, ref->buf, ref->buf->refcount, ff_get_ref_perms_string(buf, sizeof(buf), ref->perms), ref->data[0],
- ref->linesize[0], ref->linesize[1], ref->linesize[2], ref->linesize[3],
- ref->pts, ref->pos);
-
- if (ref->video) {
- av_dlog(ctx, " a:%d/%d s:%dx%d i:%c iskey:%d type:%c",
- ref->video->sample_aspect_ratio.num, ref->video->sample_aspect_ratio.den,
- ref->video->w, ref->video->h,
- !ref->video->interlaced ? 'P' : /* Progressive */
- ref->video->top_field_first ? 'T' : 'B', /* Top / Bottom */
- ref->video->key_frame,
- av_get_picture_type_char(ref->video->pict_type));
- }
- if (ref->audio) {
- av_dlog(ctx, " cl:%"PRId64"d n:%d r:%d p:%d",
- ref->audio->channel_layout,
- ref->audio->nb_samples,
- ref->audio->sample_rate,
- ref->audio->planar);
- }
-
- av_dlog(ctx, "]%s", end ? "\n" : "");
-}
-
void ff_dlog_link(void *ctx, AVFilterLink *link, int end)
{
if (link->type == AVMEDIA_TYPE_VIDEO) {
@@ -435,71 +272,6 @@ void ff_dlog_link(void *ctx, AVFilterLink *link, int end)
}
}
-AVFilterBufferRef *avfilter_get_video_buffer(AVFilterLink *link, int perms, int w, int h)
-{
- AVFilterBufferRef *ret = NULL;
-
- av_unused char buf[16];
- FF_DPRINTF_START(NULL, get_video_buffer); ff_dlog_link(NULL, link, 0);
- av_dlog(NULL, " perms:%s w:%d h:%d\n", ff_get_ref_perms_string(buf, sizeof(buf), perms), w, h);
-
- if (link->dstpad->get_video_buffer)
- ret = link->dstpad->get_video_buffer(link, perms, w, h);
-
- if (!ret)
- ret = avfilter_default_get_video_buffer(link, perms, w, h);
-
- if (ret)
- ret->type = AVMEDIA_TYPE_VIDEO;
-
- FF_DPRINTF_START(NULL, get_video_buffer); ff_dlog_link(NULL, link, 0); av_dlog(NULL, " returning "); ff_dlog_ref(NULL, ret, 1);
-
- return ret;
-}
-
-AVFilterBufferRef *
-avfilter_get_video_buffer_ref_from_arrays(uint8_t * const data[4], const int linesize[4], int perms,
- int w, int h, enum PixelFormat format)
-{
- AVFilterBuffer *pic = av_mallocz(sizeof(AVFilterBuffer));
- AVFilterBufferRef *picref = av_mallocz(sizeof(AVFilterBufferRef));
-
- if (!pic || !picref)
- goto fail;
-
- picref->buf = pic;
- picref->buf->free = ff_avfilter_default_free_buffer;
- if (!(picref->video = av_mallocz(sizeof(AVFilterBufferRefVideoProps))))
- goto fail;
-
- pic->w = picref->video->w = w;
- pic->h = picref->video->h = h;
-
- /* make sure the buffer gets read permission or it's useless for output */
- picref->perms = perms | AV_PERM_READ;
-
- pic->refcount = 1;
- picref->type = AVMEDIA_TYPE_VIDEO;
- pic->format = picref->format = format;
-
- memcpy(pic->data, data, 4*sizeof(data[0]));
- memcpy(pic->linesize, linesize, 4*sizeof(linesize[0]));
- memcpy(picref->data, pic->data, sizeof(picref->data));
- memcpy(picref->linesize, pic->linesize, sizeof(picref->linesize));
-
- pic-> extended_data = pic->data;
- picref->extended_data = picref->data;
-
- return picref;
-
-fail:
- if (picref && picref->video)
- av_free(picref->video);
- av_free(picref);
- av_free(pic);
- return NULL;
-}
-
int avfilter_request_frame(AVFilterLink *link)
{
FF_DPRINTF_START(NULL, request_frame); ff_dlog_link(NULL, link, 1);
@@ -538,107 +310,6 @@ void ff_update_link_current_pts(AVFilterLink *link, int64_t pts)
ff_avfilter_graph_update_heap(link->graph, link);
}
-/* XXX: should we do the duplicating of the picture ref here, instead of
- * forcing the source filter to do it? */
-void avfilter_start_frame(AVFilterLink *link, AVFilterBufferRef *picref)
-{
- void (*start_frame)(AVFilterLink *, AVFilterBufferRef *);
- AVFilterPad *dst = link->dstpad;
- int perms = picref->perms;
- AVFilterCommand *cmd= link->dst->command_queue;
-
- FF_DPRINTF_START(NULL, start_frame); ff_dlog_link(NULL, link, 0); av_dlog(NULL, " "); ff_dlog_ref(NULL, picref, 1);
-
- if (!(start_frame = dst->start_frame))
- start_frame = avfilter_default_start_frame;
-
- if (picref->linesize[0] < 0)
- perms |= AV_PERM_NEG_LINESIZES;
- /* prepare to copy the picture if it has insufficient permissions */
- if ((dst->min_perms & perms) != dst->min_perms || dst->rej_perms & perms) {
- av_log(link->dst, AV_LOG_DEBUG,
- "frame copy needed (have perms %x, need %x, reject %x)\n",
- picref->perms,
- link->dstpad->min_perms, link->dstpad->rej_perms);
-
- link->cur_buf = avfilter_get_video_buffer(link, dst->min_perms, link->w, link->h);
- link->src_buf = picref;
- avfilter_copy_buffer_ref_props(link->cur_buf, link->src_buf);
- }
- else
- link->cur_buf = picref;
-
- while(cmd && cmd->time <= picref->pts * av_q2d(link->time_base)){
- av_log(link->dst, AV_LOG_DEBUG,
- "Processing command time:%f command:%s arg:%s\n",
- cmd->time, cmd->command, cmd->arg);
- avfilter_process_command(link->dst, cmd->command, cmd->arg, 0, 0, cmd->flags);
- command_queue_pop(link->dst);
- cmd= link->dst->command_queue;
- }
-
- start_frame(link, link->cur_buf);
- ff_update_link_current_pts(link, link->cur_buf->pts);
-}
-
-void avfilter_end_frame(AVFilterLink *link)
-{
- void (*end_frame)(AVFilterLink *);
-
- if (!(end_frame = link->dstpad->end_frame))
- end_frame = avfilter_default_end_frame;
-
- end_frame(link);
-
- /* unreference the source picture if we're feeding the destination filter
- * a copied version dues to permission issues */
- if (link->src_buf) {
- avfilter_unref_buffer(link->src_buf);
- link->src_buf = NULL;
- }
-}
-
-void avfilter_draw_slice(AVFilterLink *link, int y, int h, int slice_dir)
-{
- uint8_t *src[4], *dst[4];
- int i, j, vsub;
- void (*draw_slice)(AVFilterLink *, int, int, int);
-
- FF_DPRINTF_START(NULL, draw_slice); ff_dlog_link(NULL, link, 0); av_dlog(NULL, " y:%d h:%d dir:%d\n", y, h, slice_dir);
-
- /* copy the slice if needed for permission reasons */
- if (link->src_buf) {
- vsub = av_pix_fmt_descriptors[link->format].log2_chroma_h;
-
- for (i = 0; i < 4; i++) {
- if (link->src_buf->data[i]) {
- src[i] = link->src_buf-> data[i] +
- (y >> (i==1 || i==2 ? vsub : 0)) * link->src_buf-> linesize[i];
- dst[i] = link->cur_buf->data[i] +
- (y >> (i==1 || i==2 ? vsub : 0)) * link->cur_buf->linesize[i];
- } else
- src[i] = dst[i] = NULL;
- }
-
- for (i = 0; i < 4; i++) {
- int planew =
- av_image_get_linesize(link->format, link->cur_buf->video->w, i);
-
- if (!src[i]) continue;
-
- for (j = 0; j < h >> (i==1 || i==2 ? vsub : 0); j++) {
- memcpy(dst[i], src[i], planew);
- src[i] += link->src_buf->linesize[i];
- dst[i] += link->cur_buf->linesize[i];
- }
- }
- }
-
- if (!(draw_slice = link->dstpad->draw_slice))
- draw_slice = avfilter_default_draw_slice;
- draw_slice(link, y, h, slice_dir);
-}
-
int avfilter_process_command(AVFilterContext *filter, const char *cmd, const char *arg, char *res, int res_len, int flags)
{
if(!strcmp(cmd, "ping")){
@@ -788,6 +459,10 @@ void avfilter_free(AVFilterContext *filter)
link->src->outputs[link->srcpad - link->src->output_pads] = NULL;
avfilter_formats_unref(&link->in_formats);
avfilter_formats_unref(&link->out_formats);
+ avfilter_formats_unref(&link->in_samplerates);
+ avfilter_formats_unref(&link->out_samplerates);
+ ff_channel_layouts_unref(&link->in_channel_layouts);
+ ff_channel_layouts_unref(&link->out_channel_layouts);
}
avfilter_link_free(&link);
}
@@ -797,6 +472,10 @@ void avfilter_free(AVFilterContext *filter)
link->dst->inputs[link->dstpad - link->dst->input_pads] = NULL;
avfilter_formats_unref(&link->in_formats);
avfilter_formats_unref(&link->out_formats);
+ avfilter_formats_unref(&link->in_samplerates);
+ avfilter_formats_unref(&link->out_samplerates);
+ ff_channel_layouts_unref(&link->in_channel_layouts);
+ ff_channel_layouts_unref(&link->out_channel_layouts);
}
avfilter_link_free(&link);
}
@@ -808,7 +487,7 @@ void avfilter_free(AVFilterContext *filter)
av_freep(&filter->outputs);
av_freep(&filter->priv);
while(filter->command_queue){
- command_queue_pop(filter);
+ ff_command_queue_pop(filter);
}
av_free(filter);
}
@@ -821,16 +500,3 @@ int avfilter_init_filter(AVFilterContext *filter, const char *args, void *opaque
ret = filter->filter->init(filter, args, opaque);
return ret;
}
-
-void avfilter_copy_buffer_ref_props(AVFilterBufferRef *dst, AVFilterBufferRef *src)
-{
- // copy common properties
- dst->pts = src->pts;
- dst->pos = src->pos;
-
- switch (src->type) {
- case AVMEDIA_TYPE_VIDEO: *dst->video = *src->video; break;
- case AVMEDIA_TYPE_AUDIO: *dst->audio = *src->audio; break;
- default: break;
- }
-}
diff --git a/libavfilter/avfilter.h b/libavfilter/avfilter.h
index 06146cfc2d..c76c637e8d 100644
--- a/libavfilter/avfilter.h
+++ b/libavfilter/avfilter.h
@@ -258,8 +258,8 @@ void avfilter_unref_bufferp(AVFilterBufferRef **ref);
* pointer to each of the pointers to itself.
*/
typedef struct AVFilterFormats {
- unsigned format_count; ///< number of formats
int64_t *formats; ///< list of media formats
+ unsigned format_count; ///< number of formats
unsigned refcount; ///< number of references to this list
struct AVFilterFormats ***refs; ///< references to this list
@@ -274,7 +274,6 @@ typedef struct AVFilterFormats {
* @return the format list, with no existing references
*/
AVFilterFormats *avfilter_make_format_list(const int *fmts);
-AVFilterFormats *avfilter_make_format64_list(const int64_t *fmts);
/**
* Add fmt to the list of media formats contained in *avff.
@@ -305,11 +304,6 @@ AVFilterFormats *avfilter_make_all_formats(enum AVMediaType type);
extern const int64_t avfilter_all_channel_layouts[];
/**
- * Return a list of all channel layouts supported by FFmpeg.
- */
-AVFilterFormats *avfilter_make_all_channel_layouts(void);
-
-/**
* Return a list of all audio packing formats.
*/
AVFilterFormats *avfilter_make_all_packing_formats(void);
@@ -521,6 +515,7 @@ AVFilterBufferRef *avfilter_default_get_video_buffer(AVFilterLink *link,
* formats/layouts. If there are no links hooked to this filter, the list
* of formats is freed.
*/
+void avfilter_set_common_formats(AVFilterContext *ctx, AVFilterFormats *formats);
void avfilter_set_common_pixel_formats(AVFilterContext *ctx, AVFilterFormats *formats);
void avfilter_set_common_sample_formats(AVFilterContext *ctx, AVFilterFormats *formats);
void avfilter_set_common_channel_layouts(AVFilterContext *ctx, AVFilterFormats *formats);
@@ -674,8 +669,6 @@ struct AVFilterLink {
AVFilterFormats *in_formats;
AVFilterFormats *out_formats;
- AVFilterFormats *in_chlayouts;
- AVFilterFormats *out_chlayouts;
AVFilterFormats *in_packing;
AVFilterFormats *out_packing;
@@ -713,17 +706,26 @@ struct AVFilterLink {
*/
int64_t current_pts;
- /**
- * Private fields
- *
- * The following fields are for internal use only.
- * Their type, offset, number and semantic can change without notice.
+ /*****************************************************************
+ * All fields below this line are not part of the public API. They
+ * may not be used outside of libavfilter and can be changed and
+ * removed at will.
+ * New public fields should be added right above.
+ *****************************************************************
*/
-
/**
* Index in the age array.
*/
int age_index;
+
+ /**
+ * Lists of channel layouts and sample rates used for automatic
+ * negotiation.
+ */
+ AVFilterFormats *in_samplerates;
+ AVFilterFormats *out_samplerates;
+ struct AVFilterChannelLayouts *in_channel_layouts;
+ struct AVFilterChannelLayouts *out_channel_layouts;
};
/**
diff --git a/libavfilter/avfiltergraph.c b/libavfilter/avfiltergraph.c
index 3bc10f9586..90d7560d6e 100644
--- a/libavfilter/avfiltergraph.c
+++ b/libavfilter/avfiltergraph.c
@@ -28,8 +28,10 @@
#include "libavutil/pixdesc.h"
#include "avfilter.h"
#include "avfiltergraph.h"
+#include "formats.h"
#include "internal.h"
+#include "libavutil/audioconvert.h"
#include "libavutil/log.h"
static const AVClass filtergraph_class = {
@@ -198,10 +200,10 @@ static int insert_conv_filter(AVFilterGraph *graph, AVFilterLink *link,
if (link->type == AVMEDIA_TYPE_AUDIO &&
(((link = filt_ctx-> inputs[0]) &&
- (!avfilter_merge_formats(link->in_chlayouts, link->out_chlayouts) ||
+ (!ff_merge_channel_layouts(link->in_channel_layouts, link->out_channel_layouts) ||
!avfilter_merge_formats(link->in_packing, link->out_packing))) ||
((link = filt_ctx->outputs[0]) &&
- (!avfilter_merge_formats(link->in_chlayouts, link->out_chlayouts) ||
+ (!ff_merge_channel_layouts(link->in_channel_layouts, link->out_channel_layouts) ||
!avfilter_merge_formats(link->in_packing, link->out_packing))))
) {
av_log(NULL, AV_LOG_ERROR,
@@ -217,7 +219,10 @@ static int query_formats(AVFilterGraph *graph, AVClass *log_ctx)
{
int i, j, ret;
char filt_args[128];
- AVFilterFormats *formats, *chlayouts, *packing;
+ AVFilterFormats *formats, *packing;
+ AVFilterChannelLayouts *chlayouts;
+ AVFilterFormats *samplerates;
+ int scaler_count = 0, resampler_count = 0;
/* ask all the sub-filters for their supported media formats */
for (i = 0; i < graph->filter_count; i++) {
@@ -233,6 +238,7 @@ static int query_formats(AVFilterGraph *graph, AVClass *log_ctx)
for (j = 0; j < filter->input_count; j++) {
AVFilterLink *link = filter->inputs[j];
+#if 0
if (!link) continue;
if (!link->in_formats || !link->out_formats)
@@ -248,7 +254,7 @@ static int query_formats(AVFilterGraph *graph, AVClass *log_ctx)
return ret;
}
else if (link->type == AVMEDIA_TYPE_AUDIO) {
- if (!link->in_chlayouts || !link->out_chlayouts ||
+ if (!link->in_channel_layouts || !link->out_channel_layouts ||
!link->in_packing || !link->out_packing)
return AVERROR(EINVAL);
@@ -256,11 +262,100 @@ static int query_formats(AVFilterGraph *graph, AVClass *log_ctx)
* three categories, aconvert will use a common format
* whenever possible. */
formats = avfilter_merge_formats(link->in_formats, link->out_formats);
- chlayouts = avfilter_merge_formats(link->in_chlayouts, link->out_chlayouts);
+ chlayouts = ff_merge_channel_layouts(link->in_channel_layouts , link->out_channel_layouts);
+ samplerates = ff_merge_samplerates (link->in_samplerates, link->out_samplerates);
packing = avfilter_merge_formats(link->in_packing, link->out_packing);
- if (!formats || !chlayouts || !packing)
+
+ if (!formats || !chlayouts || !packing || !samplerates)
if (ret = insert_conv_filter(graph, link, "aconvert", NULL))
return ret;
+#else
+ int convert_needed = 0;
+
+ if (!link)
+ continue;
+
+ if (link->in_formats != link->out_formats &&
+ !avfilter_merge_formats(link->in_formats,
+ link->out_formats))
+ convert_needed = 1;
+ if (link->type == AVMEDIA_TYPE_AUDIO) {
+ if (link->in_channel_layouts != link->out_channel_layouts &&
+ !ff_merge_channel_layouts(link->in_channel_layouts,
+ link->out_channel_layouts))
+ convert_needed = 1;
+ if (link->in_samplerates != link->out_samplerates &&
+ !ff_merge_samplerates(link->in_samplerates,
+ link->out_samplerates))
+ convert_needed = 1;
+ }
+
+ if (convert_needed) {
+ AVFilterContext *convert;
+ AVFilter *filter;
+ AVFilterLink *inlink, *outlink;
+ char scale_args[256];
+ char inst_name[30];
+
+ /* couldn't merge format lists. auto-insert conversion filter */
+ switch (link->type) {
+ case AVMEDIA_TYPE_VIDEO:
+ snprintf(inst_name, sizeof(inst_name), "auto-inserted scaler %d",
+ scaler_count++);
+ snprintf(scale_args, sizeof(scale_args), "0:0:%s", graph->scale_sws_opts);
+ if ((ret = avfilter_graph_create_filter(&convert,
+ avfilter_get_by_name("scale"),
+ inst_name, scale_args, NULL,
+ graph)) < 0)
+ return ret;
+ break;
+ case AVMEDIA_TYPE_AUDIO:
+ if (!(filter = avfilter_get_by_name("resample"))) {
+ av_log(log_ctx, AV_LOG_ERROR, "'resample' filter "
+ "not present, cannot convert audio formats.\n");
+ return AVERROR(EINVAL);
+ }
+
+ snprintf(inst_name, sizeof(inst_name), "auto-inserted resampler %d",
+ resampler_count++);
+ if ((ret = avfilter_graph_create_filter(&convert,
+ avfilter_get_by_name("resample"),
+ inst_name, NULL, NULL, graph)) < 0)
+ return ret;
+ break;
+ default:
+ return AVERROR(EINVAL);
+ }
+
+ if ((ret = avfilter_insert_filter(link, convert, 0, 0)) < 0)
+ return ret;
+
+ convert->filter->query_formats(convert);
+ inlink = convert->inputs[0];
+ outlink = convert->outputs[0];
+ if (!avfilter_merge_formats( inlink->in_formats, inlink->out_formats) ||
+ !avfilter_merge_formats(outlink->in_formats, outlink->out_formats))
+ ret |= AVERROR(ENOSYS);
+ if (inlink->type == AVMEDIA_TYPE_AUDIO &&
+ (!ff_merge_samplerates(inlink->in_samplerates,
+ inlink->out_samplerates) ||
+ !ff_merge_channel_layouts(inlink->in_channel_layouts,
+ inlink->out_channel_layouts)))
+ ret |= AVERROR(ENOSYS);
+ if (outlink->type == AVMEDIA_TYPE_AUDIO &&
+ (!ff_merge_samplerates(outlink->in_samplerates,
+ outlink->out_samplerates) ||
+ !ff_merge_channel_layouts(outlink->in_channel_layouts,
+ outlink->out_channel_layouts)))
+ ret |= AVERROR(ENOSYS);
+
+ if (ret < 0) {
+ av_log(log_ctx, AV_LOG_ERROR,
+ "Impossible to convert between the formats supported by the filter "
+ "'%s' and the filter '%s'\n", link->src->name, link->dst->name);
+ return ret;
+ }
+#endif
}
}
}
@@ -268,10 +363,10 @@ static int query_formats(AVFilterGraph *graph, AVClass *log_ctx)
return 0;
}
-static void pick_format(AVFilterLink *link, AVFilterLink *ref)
+static int pick_format(AVFilterLink *link, AVFilterLink *ref)
{
if (!link || !link->in_formats)
- return;
+ return 0;
if (link->type == AVMEDIA_TYPE_VIDEO) {
if(ref && ref->type == AVMEDIA_TYPE_VIDEO){
@@ -288,50 +383,83 @@ static void pick_format(AVFilterLink *link, AVFilterLink *ref)
link->in_formats->format_count = 1;
link->format = link->in_formats->formats[0];
- avfilter_formats_unref(&link->in_formats);
- avfilter_formats_unref(&link->out_formats);
if (link->type == AVMEDIA_TYPE_AUDIO) {
- link->in_chlayouts->format_count = 1;
- link->channel_layout = link->in_chlayouts->formats[0];
- avfilter_formats_unref(&link->in_chlayouts);
- avfilter_formats_unref(&link->out_chlayouts);
-
- link->in_packing->format_count = 1;
- link->planar = link->in_packing->formats[0] == AVFILTER_PLANAR;
- avfilter_formats_unref(&link->in_packing);
- avfilter_formats_unref(&link->out_packing);
+ if (!link->in_samplerates->format_count) {
+ av_log(link->src, AV_LOG_ERROR, "Cannot select sample rate for"
+ " the link between filters %s and %s.\n", link->src->name,
+ link->dst->name);
+ return AVERROR(EINVAL);
+ }
+ link->in_samplerates->format_count = 1;
+ link->sample_rate = link->in_samplerates->formats[0];
+
+ if (!link->in_channel_layouts->nb_channel_layouts) {
+ av_log(link->src, AV_LOG_ERROR, "Cannot select channel layout for"
+ "the link between filters %s and %s.\n", link->src->name,
+ link->dst->name);
+ return AVERROR(EINVAL);
+ }
+ link->in_channel_layouts->nb_channel_layouts = 1;
+ link->channel_layout = link->in_channel_layouts->channel_layouts[0];
}
+
+ avfilter_formats_unref(&link->in_formats);
+ avfilter_formats_unref(&link->out_formats);
+ avfilter_formats_unref(&link->in_samplerates);
+ avfilter_formats_unref(&link->out_samplerates);
+ ff_channel_layouts_unref(&link->in_channel_layouts);
+ ff_channel_layouts_unref(&link->out_channel_layouts);
+
+ return 0;
}
+#define REDUCE_FORMATS(fmt_type, list_type, list, var, nb, add_format) \
+do { \
+ for (i = 0; i < filter->input_count; i++) { \
+ AVFilterLink *link = filter->inputs[i]; \
+ fmt_type fmt; \
+ \
+ if (!link->out_ ## list || link->out_ ## list->nb != 1) \
+ continue; \
+ fmt = link->out_ ## list->var[0]; \
+ \
+ for (j = 0; j < filter->output_count; j++) { \
+ AVFilterLink *out_link = filter->outputs[j]; \
+ list_type *fmts; \
+ \
+ if (link->type != out_link->type || \
+ out_link->in_ ## list->nb == 1) \
+ continue; \
+ fmts = out_link->in_ ## list; \
+ \
+ if (!out_link->in_ ## list->nb) { \
+ add_format(&out_link->in_ ##list, fmt); \
+ break; \
+ } \
+ \
+ for (k = 0; k < out_link->in_ ## list->nb; k++) \
+ if (fmts->var[k] == fmt) { \
+ fmts->var[0] = fmt; \
+ fmts->nb = 1; \
+ ret = 1; \
+ break; \
+ } \
+ } \
+ } \
+} while (0)
+
static int reduce_formats_on_filter(AVFilterContext *filter)
{
int i, j, k, ret = 0;
- for (i = 0; i < filter->input_count; i++) {
- AVFilterLink *link = filter->inputs[i];
- int format = link->out_formats->formats[0];
-
- if (link->out_formats->format_count != 1)
- continue;
-
- for (j = 0; j < filter->output_count; j++) {
- AVFilterLink *out_link = filter->outputs[j];
- AVFilterFormats *fmts = out_link->in_formats;
-
- if (link->type != out_link->type ||
- out_link->in_formats->format_count == 1)
- continue;
+ REDUCE_FORMATS(int, AVFilterFormats, formats, formats,
+ format_count, avfilter_add_format);
+ REDUCE_FORMATS(int, AVFilterFormats, samplerates, formats,
+ format_count, avfilter_add_format);
+ REDUCE_FORMATS(uint64_t, AVFilterChannelLayouts, channel_layouts,
+ channel_layouts, nb_channel_layouts, ff_add_channel_layout);
- for (k = 0; k < out_link->in_formats->format_count; k++)
- if (fmts->formats[k] == format) {
- fmts->formats[0] = format;
- fmts->format_count = 1;
- ret = 1;
- break;
- }
- }
- }
return ret;
}
@@ -347,9 +475,109 @@ static void reduce_formats(AVFilterGraph *graph)
} while (reduced);
}
-static void pick_formats(AVFilterGraph *graph)
+static void swap_samplerates_on_filter(AVFilterContext *filter)
+{
+ AVFilterLink *link = NULL;
+ int sample_rate;
+ int i, j;
+
+ for (i = 0; i < filter->input_count; i++) {
+ link = filter->inputs[i];
+
+ if (link->type == AVMEDIA_TYPE_AUDIO &&
+ link->out_samplerates->format_count == 1)
+ break;
+ }
+ if (i == filter->input_count)
+ return;
+
+ sample_rate = link->out_samplerates->formats[0];
+
+ for (i = 0; i < filter->output_count; i++) {
+ AVFilterLink *outlink = filter->outputs[i];
+ int best_idx, best_diff = INT_MAX;
+
+ if (outlink->type != AVMEDIA_TYPE_AUDIO ||
+ outlink->in_samplerates->format_count < 2)
+ continue;
+
+ for (j = 0; j < outlink->in_samplerates->format_count; j++) {
+ int diff = abs(sample_rate - outlink->in_samplerates->formats[j]);
+
+ if (diff < best_diff) {
+ best_diff = diff;
+ best_idx = j;
+ }
+ }
+ FFSWAP(int, outlink->in_samplerates->formats[0],
+ outlink->in_samplerates->formats[best_idx]);
+ }
+}
+
+static void swap_samplerates(AVFilterGraph *graph)
{
+ int i;
+
+ for (i = 0; i < graph->filter_count; i++)
+ swap_samplerates_on_filter(graph->filters[i]);
+}
+
+static void swap_channel_layouts_on_filter(AVFilterContext *filter)
+{
+ AVFilterLink *link = NULL;
+ uint64_t chlayout;
int i, j;
+
+ for (i = 0; i < filter->input_count; i++) {
+ link = filter->inputs[i];
+
+ if (link->type == AVMEDIA_TYPE_AUDIO &&
+ link->out_channel_layouts->nb_channel_layouts == 1)
+ break;
+ }
+ if (i == filter->input_count)
+ return;
+
+ chlayout = link->out_channel_layouts->channel_layouts[0];
+
+ for (i = 0; i < filter->output_count; i++) {
+ AVFilterLink *outlink = filter->outputs[i];
+ int best_idx, best_score = INT_MIN;
+
+ if (outlink->type != AVMEDIA_TYPE_AUDIO ||
+ outlink->in_channel_layouts->nb_channel_layouts < 2)
+ continue;
+
+ for (j = 0; j < outlink->in_channel_layouts->nb_channel_layouts; j++) {
+ uint64_t out_chlayout = outlink->in_channel_layouts->channel_layouts[j];
+ int matched_channels = av_get_channel_layout_nb_channels(chlayout &
+ out_chlayout);
+ int extra_channels = av_get_channel_layout_nb_channels(out_chlayout &
+ (~chlayout));
+ int score = matched_channels - extra_channels;
+
+ if (score > best_score) {
+ best_score = score;
+ best_idx = j;
+ }
+ }
+ FFSWAP(uint64_t, outlink->in_channel_layouts->channel_layouts[0],
+ outlink->in_channel_layouts->channel_layouts[best_idx]);
+ }
+
+}
+
+static void swap_channel_layouts(AVFilterGraph *graph)
+{
+ int i;
+
+ for (i = 0; i < graph->filter_count; i++)
+ swap_channel_layouts_on_filter(graph->filters[i]);
+}
+
+static int pick_formats(AVFilterGraph *graph)
+{
+ int i, j, ret;
int change;
do{
@@ -385,13 +613,15 @@ static void pick_formats(AVFilterGraph *graph)
for (i = 0; i < graph->filter_count; i++) {
AVFilterContext *filter = graph->filters[i];
- if (1) {
- for (j = 0; j < filter->input_count; j++)
- pick_format(filter->inputs[j], NULL);
- for (j = 0; j < filter->output_count; j++)
- pick_format(filter->outputs[j], NULL);
- }
+
+ for (j = 0; j < filter->input_count; j++)
+ if ((ret = pick_format(filter->inputs[j], NULL)) < 0)
+ return ret;
+ for (j = 0; j < filter->output_count; j++)
+ if ((ret = pick_format(filter->outputs[j], NULL)) < 0)
+ return ret;
}
+ return 0;
}
int ff_avfilter_graph_config_formats(AVFilterGraph *graph, AVClass *log_ctx)
@@ -407,7 +637,13 @@ int ff_avfilter_graph_config_formats(AVFilterGraph *graph, AVClass *log_ctx)
* of format conversion inside filters */
reduce_formats(graph);
- pick_formats(graph);
+ /* for audio filters, ensure the best sample rate and channel layout
+ * is selected */
+ swap_samplerates(graph);
+ swap_channel_layouts(graph);
+
+ if ((ret = pick_formats(graph)) < 0)
+ return ret;
return 0;
}
diff --git a/libavfilter/buffer.c b/libavfilter/buffer.c
new file mode 100644
index 0000000000..32431c6d95
--- /dev/null
+++ b/libavfilter/buffer.c
@@ -0,0 +1,244 @@
+/*
+ * 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/audioconvert.h"
+#include "libavutil/avassert.h"
+#include "libavcodec/avcodec.h"
+
+#include "avfilter.h"
+#include "internal.h"
+#include "avcodec.h"
+
+void ff_avfilter_default_free_buffer(AVFilterBuffer *ptr)
+{
+ if (ptr->extended_data != ptr->data)
+ av_freep(&ptr->extended_data);
+ av_free(ptr->data[0]);
+ av_free(ptr);
+}
+
+AVFilterBufferRef *avfilter_ref_buffer(AVFilterBufferRef *ref, int pmask)
+{
+ AVFilterBufferRef *ret = av_malloc(sizeof(AVFilterBufferRef));
+ if (!ret)
+ return NULL;
+ *ret = *ref;
+ if (ref->type == AVMEDIA_TYPE_VIDEO) {
+ ret->video = av_malloc(sizeof(AVFilterBufferRefVideoProps));
+ if (!ret->video) {
+ av_free(ret);
+ return NULL;
+ }
+ *ret->video = *ref->video;
+ ret->extended_data = ret->data;
+ } else if (ref->type == AVMEDIA_TYPE_AUDIO) {
+ ret->audio = av_malloc(sizeof(AVFilterBufferRefAudioProps));
+ if (!ret->audio) {
+ av_free(ret);
+ return NULL;
+ }
+ *ret->audio = *ref->audio;
+
+ if (ref->extended_data && ref->extended_data != ref->data) {
+ int nb_channels = av_get_channel_layout_nb_channels(ref->audio->channel_layout);
+ if (!(ret->extended_data = av_malloc(sizeof(*ret->extended_data) *
+ nb_channels))) {
+ av_freep(&ret->audio);
+ av_freep(&ret);
+ return NULL;
+ }
+ memcpy(ret->extended_data, ref->extended_data,
+ sizeof(*ret->extended_data) * nb_channels);
+ } else
+ ret->extended_data = ret->data;
+ }
+ ret->perms &= pmask;
+ ret->buf->refcount ++;
+ return ret;
+}
+
+void ff_free_pool(AVFilterPool *pool)
+{
+ int i;
+
+ av_assert0(pool->refcount > 0);
+
+ for (i = 0; i < POOL_SIZE; i++) {
+ if (pool->pic[i]) {
+ AVFilterBufferRef *picref = pool->pic[i];
+ /* free buffer: picrefs stored in the pool are not
+ * supposed to contain a free callback */
+ av_assert0(!picref->buf->refcount);
+ av_freep(&picref->buf->data[0]);
+ av_freep(&picref->buf);
+
+ av_freep(&picref->audio);
+ av_freep(&picref->video);
+ av_freep(&pool->pic[i]);
+ pool->count--;
+ }
+ }
+ pool->draining = 1;
+
+ if (!--pool->refcount) {
+ av_assert0(!pool->count);
+ av_free(pool);
+ }
+}
+
+static void store_in_pool(AVFilterBufferRef *ref)
+{
+ int i;
+ AVFilterPool *pool= ref->buf->priv;
+
+ av_assert0(ref->buf->data[0]);
+ av_assert0(pool->refcount>0);
+
+ if (pool->count == POOL_SIZE) {
+ AVFilterBufferRef *ref1 = pool->pic[0];
+ av_freep(&ref1->video);
+ av_freep(&ref1->audio);
+ av_freep(&ref1->buf->data[0]);
+ av_freep(&ref1->buf);
+ av_free(ref1);
+ memmove(&pool->pic[0], &pool->pic[1], sizeof(void*)*(POOL_SIZE-1));
+ pool->count--;
+ pool->pic[POOL_SIZE-1] = NULL;
+ }
+
+ for (i = 0; i < POOL_SIZE; i++) {
+ if (!pool->pic[i]) {
+ pool->pic[i] = ref;
+ pool->count++;
+ break;
+ }
+ }
+ if (pool->draining) {
+ ff_free_pool(pool);
+ } else
+ --pool->refcount;
+}
+
+void avfilter_unref_buffer(AVFilterBufferRef *ref)
+{
+ if (!ref)
+ return;
+ av_assert0(ref->buf->refcount > 0);
+ if (!(--ref->buf->refcount)) {
+ if (!ref->buf->free) {
+ store_in_pool(ref);
+ return;
+ }
+ ref->buf->free(ref->buf);
+ }
+ if (ref->extended_data != ref->data)
+ av_freep(&ref->extended_data);
+ av_freep(&ref->video);
+ av_freep(&ref->audio);
+ av_free(ref);
+}
+
+void avfilter_unref_bufferp(AVFilterBufferRef **ref)
+{
+ avfilter_unref_buffer(*ref);
+ *ref = NULL;
+}
+
+int avfilter_copy_frame_props(AVFilterBufferRef *dst, const AVFrame *src)
+{
+ dst->pts = src->pts;
+ dst->pos = src->pkt_pos;
+ dst->format = src->format;
+
+ switch (dst->type) {
+ case AVMEDIA_TYPE_VIDEO:
+ dst->video->w = src->width;
+ dst->video->h = src->height;
+ dst->video->sample_aspect_ratio = src->sample_aspect_ratio;
+ dst->video->interlaced = src->interlaced_frame;
+ dst->video->top_field_first = src->top_field_first;
+ dst->video->key_frame = src->key_frame;
+ dst->video->pict_type = src->pict_type;
+ break;
+ case AVMEDIA_TYPE_AUDIO:
+ dst->audio->sample_rate = src->sample_rate;
+ dst->audio->channel_layout = src->channel_layout;
+ break;
+ default:
+ return AVERROR(EINVAL);
+ }
+
+ return 0;
+}
+
+int avfilter_copy_buf_props(AVFrame *dst, const AVFilterBufferRef *src)
+{
+ int planes, nb_channels;
+
+ memcpy(dst->data, src->data, sizeof(dst->data));
+ memcpy(dst->linesize, src->linesize, sizeof(dst->linesize));
+
+ dst->pts = src->pts;
+ dst->format = src->format;
+
+ switch (src->type) {
+ case AVMEDIA_TYPE_VIDEO:
+ dst->width = src->video->w;
+ dst->height = src->video->h;
+ dst->sample_aspect_ratio = src->video->sample_aspect_ratio;
+ dst->interlaced_frame = src->video->interlaced;
+ dst->top_field_first = src->video->top_field_first;
+ dst->key_frame = src->video->key_frame;
+ dst->pict_type = src->video->pict_type;
+ break;
+ case AVMEDIA_TYPE_AUDIO:
+ nb_channels = av_get_channel_layout_nb_channels(src->audio->channel_layout);
+ planes = av_sample_fmt_is_planar(src->format) ? nb_channels : 1;
+
+ if (planes > FF_ARRAY_ELEMS(dst->data)) {
+ dst->extended_data = av_mallocz(planes * sizeof(*dst->extended_data));
+ if (!dst->extended_data)
+ return AVERROR(ENOMEM);
+ memcpy(dst->extended_data, src->extended_data,
+ planes * sizeof(dst->extended_data));
+ } else
+ dst->extended_data = dst->data;
+
+ dst->sample_rate = src->audio->sample_rate;
+ dst->channel_layout = src->audio->channel_layout;
+ dst->nb_samples = src->audio->nb_samples;
+ break;
+ default:
+ return AVERROR(EINVAL);
+ }
+
+ return 0;
+}
+
+void avfilter_copy_buffer_ref_props(AVFilterBufferRef *dst, AVFilterBufferRef *src)
+{
+ // copy common properties
+ dst->pts = src->pts;
+ dst->pos = src->pos;
+
+ switch (src->type) {
+ case AVMEDIA_TYPE_VIDEO: *dst->video = *src->video; break;
+ case AVMEDIA_TYPE_AUDIO: *dst->audio = *src->audio; break;
+ default: break;
+ }
+}
diff --git a/libavfilter/buffersink.c b/libavfilter/buffersink.c
index f0fcab553e..90ebd93908 100644
--- a/libavfilter/buffersink.c
+++ b/libavfilter/buffersink.c
@@ -23,13 +23,20 @@
* buffer sink
*/
+#include "libavutil/audio_fifo.h"
+#include "libavutil/audioconvert.h"
#include "libavutil/fifo.h"
+#include "libavutil/mathematics.h"
+#include "audio.h"
#include "avfilter.h"
#include "buffersink.h"
typedef struct {
- AVFifoBuffer *fifo; ///< FIFO buffer of video frame references
+ AVFifoBuffer *fifo; ///< FIFO buffer of frame references
+
+ AVAudioFifo *audio_fifo; ///< FIFO for audio samples
+ int64_t next_pts; ///< interpolating audio pts
} BufferSinkContext;
#define FIFO_INIT_SIZE 8
@@ -44,6 +51,9 @@ static av_cold void uninit(AVFilterContext *ctx)
avfilter_unref_buffer(buf);
}
av_fifo_free(sink->fifo);
+
+ if (sink->audio_fifo)
+ av_audio_fifo_free(sink->audio_fifo);
}
static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque)
@@ -58,9 +68,8 @@ static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque)
return 0;
}
-static void end_frame(AVFilterLink *link)
+static void write_buf(AVFilterContext *ctx, AVFilterBufferRef *buf)
{
- AVFilterContext *ctx = link->dst;
BufferSinkContext *sink = ctx->priv;
if (av_fifo_space(sink->fifo) < sizeof(AVFilterBufferRef *) &&
@@ -69,10 +78,20 @@ static void end_frame(AVFilterLink *link)
return;
}
- av_fifo_generic_write(sink->fifo, &link->cur_buf, sizeof(link->cur_buf), NULL);
+ av_fifo_generic_write(sink->fifo, &buf, sizeof(buf), NULL);
+}
+
+static void end_frame(AVFilterLink *link)
+{
+ write_buf(link->dst, link->cur_buf);
link->cur_buf = NULL;
}
+static void filter_samples(AVFilterLink *link, AVFilterBufferRef *buf)
+{
+ write_buf(link->dst, buf);
+}
+
int av_buffersink_read(AVFilterContext *ctx, AVFilterBufferRef **buf)
{
BufferSinkContext *sink = ctx->priv;
@@ -98,6 +117,66 @@ int av_buffersink_read(AVFilterContext *ctx, AVFilterBufferRef **buf)
return 0;
}
+static int read_from_fifo(AVFilterContext *ctx, AVFilterBufferRef **pbuf,
+ int nb_samples)
+{
+ BufferSinkContext *s = ctx->priv;
+ AVFilterLink *link = ctx->inputs[0];
+ AVFilterBufferRef *buf;
+
+ if (!(buf = ff_get_audio_buffer(link, AV_PERM_WRITE, nb_samples)))
+ return AVERROR(ENOMEM);
+ av_audio_fifo_read(s->audio_fifo, (void**)buf->extended_data, nb_samples);
+
+ buf->pts = s->next_pts;
+ s->next_pts += av_rescale_q(nb_samples, (AVRational){1, link->sample_rate},
+ link->time_base);
+
+ *pbuf = buf;
+ return 0;
+
+}
+
+int av_buffersink_read_samples(AVFilterContext *ctx, AVFilterBufferRef **pbuf,
+ int nb_samples)
+{
+ BufferSinkContext *s = ctx->priv;
+ AVFilterLink *link = ctx->inputs[0];
+ int ret = 0;
+
+ if (!s->audio_fifo) {
+ int nb_channels = av_get_channel_layout_nb_channels(link->channel_layout);
+ if (!(s->audio_fifo = av_audio_fifo_alloc(link->format, nb_channels, nb_samples)))
+ return AVERROR(ENOMEM);
+ }
+
+ while (ret >= 0) {
+ AVFilterBufferRef *buf;
+
+ if (av_audio_fifo_size(s->audio_fifo) >= nb_samples)
+ return read_from_fifo(ctx, pbuf, nb_samples);
+
+ ret = av_buffersink_read(ctx, &buf);
+ if (ret == AVERROR_EOF && av_audio_fifo_size(s->audio_fifo))
+ return read_from_fifo(ctx, pbuf, av_audio_fifo_size(s->audio_fifo));
+ else if (ret < 0)
+ return ret;
+
+ if (buf->pts != AV_NOPTS_VALUE) {
+ s->next_pts = buf->pts -
+ av_rescale_q(av_audio_fifo_size(s->audio_fifo),
+ (AVRational){ 1, link->sample_rate },
+ link->time_base);
+ }
+
+ ret = av_audio_fifo_write(s->audio_fifo, (void**)buf->extended_data,
+ buf->audio->nb_samples);
+ avfilter_unref_buffer(buf);
+ }
+
+ return ret;
+}
+
AVFilter avfilter_vsink_buffer = {
.name = "buffersink_old",
.description = NULL_IF_CONFIG_SMALL("Buffer video frames, and make them available to the end of the filter graph."),
@@ -112,3 +191,18 @@ AVFilter avfilter_vsink_buffer = {
{ .name = NULL }},
.outputs = (AVFilterPad[]) {{ .name = NULL }},
};
+
+AVFilter avfilter_asink_abuffer = {
+ .name = "abuffersink_old",
+ .description = NULL_IF_CONFIG_SMALL("Buffer audio frames, and make them available to the end of the filter graph."),
+ .priv_size = sizeof(BufferSinkContext),
+ .init = init,
+ .uninit = uninit,
+
+ .inputs = (AVFilterPad[]) {{ .name = "default",
+ .type = AVMEDIA_TYPE_AUDIO,
+ .filter_samples = filter_samples,
+ .min_perms = AV_PERM_READ, },
+ { .name = NULL }},
+ .outputs = (AVFilterPad[]) {{ .name = NULL }},
+};
diff --git a/libavfilter/buffersink.h b/libavfilter/buffersink.h
index 86a4b2462b..2ee5294b26 100644
--- a/libavfilter/buffersink.h
+++ b/libavfilter/buffersink.h
@@ -101,7 +101,7 @@ int av_vsink_buffer_get_video_buffer_ref(AVFilterContext *buffer_sink,
/**
* Get a buffer with filtered data from sink and put it in buf.
*
- * @param sink pointer to a context of a buffersink AVFilter.
+ * @param sink pointer to a context of a buffersink or abuffersink AVFilter.
* @param buf pointer to the buffer will be written here if buf is non-NULL. buf
* must be freed by the caller using avfilter_unref_buffer().
* Buf may also be NULL to query whether a buffer is ready to be
@@ -112,4 +112,23 @@ int av_vsink_buffer_get_video_buffer_ref(AVFilterContext *buffer_sink,
*/
int av_buffersink_read(AVFilterContext *sink, AVFilterBufferRef **buf);
+/**
+ * Same as av_buffersink_read, but with the ability to specify the number of
+ * samples read. This function is less efficient than av_buffersink_read(),
+ * because it copies the data around.
+ *
+ * @param sink pointer to a context of the abuffersink AVFilter.
+ * @param buf pointer to the buffer will be written here if buf is non-NULL. buf
+ * must be freed by the caller using avfilter_unref_buffer(). buf
+ * will contain exactly nb_samples audio samples, except at the end
+ * of stream, when it can contain less than nb_samples.
+ * Buf may also be NULL to query whether a buffer is ready to be
+ * output.
+ *
+ * @warning do not mix this function with av_buffersink_read(). Use only one or
+ * the other with a single sink, not both.
+ */
+int av_buffersink_read_samples(AVFilterContext *ctx, AVFilterBufferRef **buf,
+ int nb_samples);
+
#endif /* AVFILTER_BUFFERSINK_H */
diff --git a/libavfilter/buffersrc.c b/libavfilter/buffersrc.c
new file mode 100644
index 0000000000..305d1c49d6
--- /dev/null
+++ b/libavfilter/buffersrc.c
@@ -0,0 +1,403 @@
+/*
+ * Copyright (c) 2008 Vitor Sessak
+ *
+ * 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
+ * memory buffer source filter
+ */
+
+#include "audio.h"
+#include "avfilter.h"
+#include "buffersrc.h"
+#include "formats.h"
+#include "vsrc_buffer.h"
+#include "avcodec.h"
+
+#include "libavutil/audioconvert.h"
+#include "libavutil/fifo.h"
+#include "libavutil/imgutils.h"
+#include "libavutil/opt.h"
+#include "libavutil/samplefmt.h"
+
+typedef struct {
+ const AVClass *class;
+ AVFifoBuffer *fifo;
+ AVRational time_base; ///< time_base to set in the output link
+
+ /* video only */
+ int h, w;
+ enum PixelFormat pix_fmt;
+ AVRational pixel_aspect;
+
+ /* audio only */
+ int sample_rate;
+ enum AVSampleFormat sample_fmt;
+ char *sample_fmt_str;
+ uint64_t channel_layout;
+ char *channel_layout_str;
+
+ int eof;
+} BufferSourceContext;
+
+#define CHECK_VIDEO_PARAM_CHANGE(s, c, width, height, format)\
+ if (c->w != width || c->h != height || c->pix_fmt != format) {\
+ av_log(s, AV_LOG_ERROR, "Changing frame properties on the fly is not supported.\n");\
+ return AVERROR(EINVAL);\
+ }
+
+#define CHECK_AUDIO_PARAM_CHANGE(s, c, srate, ch_layout, format)\
+ if (c->sample_fmt != format || c->sample_rate != srate ||\
+ c->channel_layout != ch_layout) {\
+ av_log(s, AV_LOG_ERROR, "Changing frame properties on the fly is not supported.\n");\
+ return AVERROR(EINVAL);\
+ }
+
+#if FF_API_VSRC_BUFFER_ADD_FRAME
+static int av_vsrc_buffer_add_frame_alt(AVFilterContext *buffer_filter, AVFrame *frame,
+ int64_t pts, AVRational pixel_aspect)
+{
+ int64_t orig_pts = frame->pts;
+ AVRational orig_sar = frame->sample_aspect_ratio;
+ int ret;
+
+ frame->pts = pts;
+ frame->sample_aspect_ratio = pixel_aspect;
+ if ((ret = av_buffersrc_write_frame(buffer_filter, frame)) < 0)
+ return ret;
+ frame->pts = orig_pts;
+ frame->sample_aspect_ratio = orig_sar;
+
+ return 0;
+}
+#endif
+
+int av_buffersrc_write_frame(AVFilterContext *buffer_filter, AVFrame *frame)
+{
+ BufferSourceContext *c = buffer_filter->priv;
+ AVFilterBufferRef *buf;
+ int ret;
+
+ if (!frame) {
+ c->eof = 1;
+ return 0;
+ } else if (c->eof)
+ return AVERROR(EINVAL);
+
+ if (!av_fifo_space(c->fifo) &&
+ (ret = av_fifo_realloc2(c->fifo, av_fifo_size(c->fifo) +
+ sizeof(buf))) < 0)
+ return ret;
+
+ switch (buffer_filter->outputs[0]->type) {
+ case AVMEDIA_TYPE_VIDEO:
+ CHECK_VIDEO_PARAM_CHANGE(buffer_filter, c, frame->width, frame->height,
+ frame->format);
+ buf = avfilter_get_video_buffer(buffer_filter->outputs[0], AV_PERM_WRITE,
+ c->w, c->h);
+ av_image_copy(buf->data, buf->linesize, frame->data, frame->linesize,
+ c->pix_fmt, c->w, c->h);
+ break;
+ case AVMEDIA_TYPE_AUDIO:
+ CHECK_AUDIO_PARAM_CHANGE(buffer_filter, c, frame->sample_rate, frame->channel_layout,
+ frame->format);
+ buf = ff_get_audio_buffer(buffer_filter->outputs[0], AV_PERM_WRITE,
+ frame->nb_samples);
+ av_samples_copy(buf->extended_data, frame->extended_data,
+ 0, 0, frame->nb_samples,
+ av_get_channel_layout_nb_channels(frame->channel_layout),
+ frame->format);
+ break;
+ default:
+ return AVERROR(EINVAL);
+ }
+
+ avfilter_copy_frame_props(buf, frame);
+
+ if ((ret = av_fifo_generic_write(c->fifo, &buf, sizeof(buf), NULL)) < 0) {
+ avfilter_unref_buffer(buf);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int av_buffersrc_buffer(AVFilterContext *s, AVFilterBufferRef *buf)
+{
+ BufferSourceContext *c = s->priv;
+ int ret;
+
+ if (!buf) {
+ c->eof = 1;
+ return 0;
+ } else if (c->eof)
+ return AVERROR(EINVAL);
+
+ if (!av_fifo_space(c->fifo) &&
+ (ret = av_fifo_realloc2(c->fifo, av_fifo_size(c->fifo) +
+ sizeof(buf))) < 0)
+ return ret;
+
+ switch (s->outputs[0]->type) {
+ case AVMEDIA_TYPE_VIDEO:
+ CHECK_VIDEO_PARAM_CHANGE(s, c, buf->video->w, buf->video->h, buf->format);
+ break;
+ case AVMEDIA_TYPE_AUDIO:
+ CHECK_AUDIO_PARAM_CHANGE(s, c, buf->audio->sample_rate, buf->audio->channel_layout,
+ buf->format);
+ break;
+ default:
+ return AVERROR(EINVAL);
+ }
+
+ if ((ret = av_fifo_generic_write(c->fifo, &buf, sizeof(buf), NULL)) < 0)
+ return ret;
+
+ return 0;
+}
+
+static av_cold int init_video(AVFilterContext *ctx, const char *args, void *opaque)
+{
+ BufferSourceContext *c = ctx->priv;
+ char pix_fmt_str[128];
+ int n = 0;
+
+ if (!args ||
+ (n = sscanf(args, "%d:%d:%127[^:]:%d:%d:%d:%d", &c->w, &c->h, pix_fmt_str,
+ &c->time_base.num, &c->time_base.den,
+ &c->pixel_aspect.num, &c->pixel_aspect.den)) != 7) {
+ av_log(ctx, AV_LOG_ERROR, "Expected 7 arguments, but %d found in '%s'\n", n, args);
+ return AVERROR(EINVAL);
+ }
+ if ((c->pix_fmt = av_get_pix_fmt(pix_fmt_str)) == PIX_FMT_NONE) {
+ char *tail;
+ c->pix_fmt = strtol(pix_fmt_str, &tail, 10);
+ if (*tail || c->pix_fmt < 0 || c->pix_fmt >= PIX_FMT_NB) {
+ av_log(ctx, AV_LOG_ERROR, "Invalid pixel format string '%s'\n", pix_fmt_str);
+ return AVERROR(EINVAL);
+ }
+ }
+
+ if (!(c->fifo = av_fifo_alloc(sizeof(AVFilterBufferRef*))))
+ return AVERROR(ENOMEM);
+
+ av_log(ctx, AV_LOG_INFO, "w:%d h:%d pixfmt:%s\n", c->w, c->h, av_pix_fmt_descriptors[c->pix_fmt].name);
+ return 0;
+}
+
+#define OFFSET(x) offsetof(BufferSourceContext, x)
+#define A AV_OPT_FLAG_AUDIO_PARAM
+static const AVOption audio_options[] = {
+ { "time_base", NULL, OFFSET(time_base), AV_OPT_TYPE_RATIONAL, { 0 }, 0, INT_MAX, A },
+ { "sample_rate", NULL, OFFSET(sample_rate), AV_OPT_TYPE_INT, { 0 }, 0, INT_MAX, A },
+ { "sample_fmt", NULL, OFFSET(sample_fmt_str), AV_OPT_TYPE_STRING, .flags = A },
+ { "channel_layout", NULL, OFFSET(channel_layout_str), AV_OPT_TYPE_STRING, .flags = A },
+ { NULL },
+};
+
+static const AVClass abuffer_class = {
+ .class_name = "abuffer source",
+ .item_name = av_default_item_name,
+ .option = audio_options,
+ .version = LIBAVUTIL_VERSION_INT,
+};
+
+static av_cold int init_audio(AVFilterContext *ctx, const char *args, void *opaque)
+{
+ BufferSourceContext *s = ctx->priv;
+ int ret = 0;
+
+ s->class = &abuffer_class;
+ av_opt_set_defaults(s);
+
+ if ((ret = av_set_options_string(s, args, "=", ":")) < 0) {
+ av_log(ctx, AV_LOG_ERROR, "Error parsing options string: %s.\n", args);
+ goto fail;
+ }
+
+ s->sample_fmt = av_get_sample_fmt(s->sample_fmt_str);
+ if (s->sample_fmt == AV_SAMPLE_FMT_NONE) {
+ av_log(ctx, AV_LOG_ERROR, "Invalid sample format %s.\n",
+ s->sample_fmt_str);
+ ret = AVERROR(EINVAL);
+ goto fail;
+ }
+
+ s->channel_layout = av_get_channel_layout(s->channel_layout_str);
+ if (!s->channel_layout) {
+ av_log(ctx, AV_LOG_ERROR, "Invalid channel layout %s.\n",
+ s->channel_layout_str);
+ ret = AVERROR(EINVAL);
+ goto fail;
+ }
+
+ if (!(s->fifo = av_fifo_alloc(sizeof(AVFilterBufferRef*)))) {
+ ret = AVERROR(ENOMEM);
+ goto fail;
+ }
+
+ if (!s->time_base.num)
+ s->time_base = (AVRational){1, s->sample_rate};
+
+ av_log(ctx, AV_LOG_VERBOSE, "tb:%d/%d samplefmt:%s samplerate: %d "
+ "ch layout:%s\n", s->time_base.num, s->time_base.den, s->sample_fmt_str,
+ s->sample_rate, s->channel_layout_str);
+
+fail:
+ av_opt_free(s);
+ return ret;
+}
+
+static av_cold void uninit(AVFilterContext *ctx)
+{
+ BufferSourceContext *s = ctx->priv;
+ while (s->fifo && av_fifo_size(s->fifo)) {
+ AVFilterBufferRef *buf;
+ av_fifo_generic_read(s->fifo, &buf, sizeof(buf), NULL);
+ avfilter_unref_buffer(buf);
+ }
+ av_fifo_free(s->fifo);
+ s->fifo = NULL;
+}
+
+static int query_formats(AVFilterContext *ctx)
+{
+ BufferSourceContext *c = ctx->priv;
+ AVFilterChannelLayouts *channel_layouts = NULL;
+ AVFilterFormats *formats = NULL;
+ AVFilterFormats *samplerates = NULL;
+
+ switch (ctx->outputs[0]->type) {
+ case AVMEDIA_TYPE_VIDEO:
+ avfilter_add_format(&formats, c->pix_fmt);
+ avfilter_set_common_formats(ctx, formats);
+ break;
+ case AVMEDIA_TYPE_AUDIO:
+ avfilter_add_format(&formats, c->sample_fmt);
+ avfilter_set_common_formats(ctx, formats);
+
+ avfilter_add_format(&samplerates, c->sample_rate);
+ ff_set_common_samplerates(ctx, samplerates);
+
+ ff_add_channel_layout(&channel_layouts, c->channel_layout);
+ ff_set_common_channel_layouts(ctx, channel_layouts);
+ break;
+ default:
+ return AVERROR(EINVAL);
+ }
+
+ return 0;
+}
+
+static int config_props(AVFilterLink *link)
+{
+ BufferSourceContext *c = link->src->priv;
+
+ switch (link->type) {
+ case AVMEDIA_TYPE_VIDEO:
+ link->w = c->w;
+ link->h = c->h;
+ link->sample_aspect_ratio = c->pixel_aspect;
+ break;
+ case AVMEDIA_TYPE_AUDIO:
+ link->channel_layout = c->channel_layout;
+ link->sample_rate = c->sample_rate;
+ break;
+ default:
+ return AVERROR(EINVAL);
+ }
+
+ link->time_base = c->time_base;
+ return 0;
+}
+
+static int request_frame(AVFilterLink *link)
+{
+ BufferSourceContext *c = link->src->priv;
+ AVFilterBufferRef *buf;
+
+ if (!av_fifo_size(c->fifo)) {
+ if (c->eof)
+ return AVERROR_EOF;
+ return AVERROR(EAGAIN);
+ }
+ av_fifo_generic_read(c->fifo, &buf, sizeof(buf), NULL);
+
+ switch (link->type) {
+ case AVMEDIA_TYPE_VIDEO:
+ avfilter_start_frame(link, avfilter_ref_buffer(buf, ~0));
+ avfilter_draw_slice(link, 0, link->h, 1);
+ avfilter_end_frame(link);
+ break;
+ case AVMEDIA_TYPE_AUDIO:
+ ff_filter_samples(link, avfilter_ref_buffer(buf, ~0));
+ break;
+ default:
+ return AVERROR(EINVAL);
+ }
+
+ avfilter_unref_buffer(buf);
+
+ return 0;
+}
+
+static int poll_frame(AVFilterLink *link)
+{
+ BufferSourceContext *c = link->src->priv;
+ int size = av_fifo_size(c->fifo);
+ if (!size && c->eof)
+ return AVERROR_EOF;
+ return size/sizeof(AVFilterBufferRef*);
+}
+
+AVFilter avfilter_vsrc_buffer = {
+ .name = "buffer",
+ .description = NULL_IF_CONFIG_SMALL("Buffer video frames, and make them accessible to the filterchain."),
+ .priv_size = sizeof(BufferSourceContext),
+ .query_formats = query_formats,
+
+ .init = init_video,
+ .uninit = uninit,
+
+ .inputs = (AVFilterPad[]) {{ .name = NULL }},
+ .outputs = (AVFilterPad[]) {{ .name = "default",
+ .type = AVMEDIA_TYPE_VIDEO,
+ .request_frame = request_frame,
+ .poll_frame = poll_frame,
+ .config_props = config_props, },
+ { .name = NULL}},
+};
+
+AVFilter avfilter_asrc_abuffer = {
+ .name = "abuffer",
+ .description = NULL_IF_CONFIG_SMALL("Buffer audio frames, and make them accessible to the filterchain."),
+ .priv_size = sizeof(BufferSourceContext),
+ .query_formats = query_formats,
+
+ .init = init_audio,
+ .uninit = uninit,
+
+ .inputs = (AVFilterPad[]) {{ .name = NULL }},
+ .outputs = (AVFilterPad[]) {{ .name = "default",
+ .type = AVMEDIA_TYPE_AUDIO,
+ .request_frame = request_frame,
+ .poll_frame = poll_frame,
+ .config_props = config_props, },
+ { .name = NULL}},
+};
diff --git a/libavfilter/buffersrc.h b/libavfilter/buffersrc.h
index f1f566b46e..25e2fbf6dc 100644
--- a/libavfilter/buffersrc.h
+++ b/libavfilter/buffersrc.h
@@ -62,4 +62,15 @@ int av_buffersrc_add_ref(AVFilterContext *buffer_src,
*/
unsigned av_buffersrc_get_nb_failed_requests(AVFilterContext *buffer_src);
+/**
+ * Add a frame to the buffer source.
+ *
+ * @param s an instance of the buffersrc filter.
+ * @param frame frame to be added.
+ *
+ * @warning frame data will be memcpy()ed, which may be a big performance
+ * hit. Use av_buffersrc_buffer() to avoid copying the data.
+ */
+int av_buffersrc_write_frame(AVFilterContext *s, AVFrame *frame);
+
#endif /* AVFILTER_BUFFERSRC_H */
diff --git a/libavfilter/defaults.c b/libavfilter/defaults.c
index d2e01499be..31dc18d9f7 100644
--- a/libavfilter/defaults.c
+++ b/libavfilter/defaults.c
@@ -26,111 +26,7 @@
#include "avfilter.h"
#include "internal.h"
-
-void ff_avfilter_default_free_buffer(AVFilterBuffer *ptr)
-{
- if (ptr->extended_data != ptr->data)
- av_freep(&ptr->extended_data);
- av_free(ptr->data[0]);
- av_free(ptr);
-}
-
-/* TODO: set the buffer's priv member to a context structure for the whole
- * filter chain. This will allow for a buffer pool instead of the constant
- * alloc & free cycle currently implemented. */
-AVFilterBufferRef *avfilter_default_get_video_buffer(AVFilterLink *link, int perms, int w, int h)
-{
- int linesize[4];
- uint8_t *data[4];
- int i;
- AVFilterBufferRef *picref = NULL;
- AVFilterPool *pool = link->pool;
-
- if (pool) {
- for (i = 0; i < POOL_SIZE; i++) {
- picref = pool->pic[i];
- if (picref && picref->buf->format == link->format && picref->buf->w == w && picref->buf->h == h) {
- AVFilterBuffer *pic = picref->buf;
- pool->pic[i] = NULL;
- pool->count--;
- picref->video->w = w;
- picref->video->h = h;
- picref->perms = perms | AV_PERM_READ;
- picref->format = link->format;
- pic->refcount = 1;
- memcpy(picref->data, pic->data, sizeof(picref->data));
- memcpy(picref->linesize, pic->linesize, sizeof(picref->linesize));
- pool->refcount++;
- return picref;
- }
- }
- } else {
- pool = link->pool = av_mallocz(sizeof(AVFilterPool));
- pool->refcount = 1;
- }
-
- // align: +2 is needed for swscaler, +16 to be SIMD-friendly
- if ((i = av_image_alloc(data, linesize, w, h, link->format, 32)) < 0)
- return NULL;
-
- picref = avfilter_get_video_buffer_ref_from_arrays(data, linesize,
- perms, w, h, link->format);
- if (!picref) {
- av_free(data[0]);
- return NULL;
- }
- memset(data[0], 128, i);
-
- picref->buf->priv = pool;
- picref->buf->free = NULL;
- pool->refcount++;
-
- return picref;
-}
-
-void avfilter_default_start_frame(AVFilterLink *inlink, AVFilterBufferRef *picref)
-{
- AVFilterLink *outlink = NULL;
-
- if (inlink->dst->output_count)
- outlink = inlink->dst->outputs[0];
-
- if (outlink) {
- outlink->out_buf = avfilter_get_video_buffer(outlink, AV_PERM_WRITE, outlink->w, outlink->h);
- avfilter_copy_buffer_ref_props(outlink->out_buf, picref);
- avfilter_start_frame(outlink, avfilter_ref_buffer(outlink->out_buf, ~0));
- }
-}
-
-void avfilter_default_draw_slice(AVFilterLink *inlink, int y, int h, int slice_dir)
-{
- AVFilterLink *outlink = NULL;
-
- if (inlink->dst->output_count)
- outlink = inlink->dst->outputs[0];
-
- if (outlink)
- avfilter_draw_slice(outlink, y, h, slice_dir);
-}
-
-void avfilter_default_end_frame(AVFilterLink *inlink)
-{
- AVFilterLink *outlink = NULL;
-
- if (inlink->dst->output_count)
- outlink = inlink->dst->outputs[0];
-
- avfilter_unref_buffer(inlink->cur_buf);
- inlink->cur_buf = NULL;
-
- if (outlink) {
- if (outlink->out_buf) {
- avfilter_unref_buffer(outlink->out_buf);
- outlink->out_buf = NULL;
- }
- avfilter_end_frame(outlink);
- }
-}
+#include "formats.h"
static void set_common_formats(AVFilterContext *ctx, AVFilterFormats *fmts,
enum AVMediaType type, int offin, int offout)
@@ -170,8 +66,8 @@ void avfilter_set_common_sample_formats(AVFilterContext *ctx, AVFilterFormats *f
void avfilter_set_common_channel_layouts(AVFilterContext *ctx, AVFilterFormats *formats)
{
set_common_formats(ctx, formats, AVMEDIA_TYPE_AUDIO,
- offsetof(AVFilterLink, in_chlayouts),
- offsetof(AVFilterLink, out_chlayouts));
+ offsetof(AVFilterLink, in_channel_layouts),
+ offsetof(AVFilterLink, out_channel_layouts));
}
void avfilter_set_common_packing_formats(AVFilterContext *ctx, AVFilterFormats *formats)
@@ -180,33 +76,3 @@ void avfilter_set_common_packing_formats(AVFilterContext *ctx, AVFilterFormats *
offsetof(AVFilterLink, in_packing),
offsetof(AVFilterLink, out_packing));
}
-
-int avfilter_default_query_formats(AVFilterContext *ctx)
-{
- avfilter_set_common_pixel_formats(ctx, avfilter_make_all_formats(AVMEDIA_TYPE_VIDEO));
- avfilter_set_common_sample_formats(ctx, avfilter_make_all_formats(AVMEDIA_TYPE_AUDIO));
- avfilter_set_common_channel_layouts(ctx, avfilter_make_all_channel_layouts());
- avfilter_set_common_packing_formats(ctx, avfilter_make_all_packing_formats());
-
- return 0;
-}
-
-void avfilter_null_start_frame(AVFilterLink *link, AVFilterBufferRef *picref)
-{
- avfilter_start_frame(link->dst->outputs[0], picref);
-}
-
-void avfilter_null_draw_slice(AVFilterLink *link, int y, int h, int slice_dir)
-{
- avfilter_draw_slice(link->dst->outputs[0], y, h, slice_dir);
-}
-
-void avfilter_null_end_frame(AVFilterLink *link)
-{
- avfilter_end_frame(link->dst->outputs[0]);
-}
-
-AVFilterBufferRef *avfilter_null_get_video_buffer(AVFilterLink *link, int perms, int w, int h)
-{
- return avfilter_get_video_buffer(link->dst->outputs[0], perms, w, h);
-}
diff --git a/libavfilter/formats.c b/libavfilter/formats.c
index 569178fca8..41c6da92b7 100644
--- a/libavfilter/formats.c
+++ b/libavfilter/formats.c
@@ -24,63 +24,138 @@
#include "libavutil/audioconvert.h"
#include "avfilter.h"
#include "internal.h"
+#include "formats.h"
/**
* Add all refs from a to ret and destroy a.
*/
-static void merge_ref(AVFilterFormats *ret, AVFilterFormats *a)
-{
- int i;
-
- for (i = 0; i < a->refcount; i++) {
- ret->refs[ret->refcount] = a->refs[i];
- *ret->refs[ret->refcount++] = ret;
- }
+#define MERGE_REF(ret, a, fmts, type, fail) \
+do { \
+ type ***tmp; \
+ int i; \
+ \
+ if (!(tmp = av_realloc(ret->refs, \
+ sizeof(*tmp) * (ret->refcount + a->refcount)))) \
+ goto fail; \
+ ret->refs = tmp; \
+ \
+ for (i = 0; i < a->refcount; i ++) { \
+ ret->refs[ret->refcount] = a->refs[i]; \
+ *ret->refs[ret->refcount++] = ret; \
+ } \
+ \
+ av_freep(&a->refs); \
+ av_freep(&a->fmts); \
+ av_freep(&a); \
+} while (0)
- av_free(a->refs);
- av_free(a->formats);
- av_free(a);
-}
+/**
+ * Add all formats common for a and b to ret, copy the refs and destroy
+ * a and b.
+ */
+#define MERGE_FORMATS(ret, a, b, fmts, nb, type, fail) \
+do { \
+ int i, j, k = 0, count = FFMIN(a->nb, b->nb); \
+ \
+ if (!(ret = av_mallocz(sizeof(*ret)))) \
+ goto fail; \
+ \
+ if (count) { \
+ if (!(ret->fmts = av_malloc(sizeof(*ret->fmts) * count))) \
+ goto fail; \
+ for (i = 0; i < a->nb; i++) \
+ for (j = 0; j < b->nb; j++) \
+ if (a->fmts[i] == b->fmts[j]) { \
+ if(k >= FFMIN(a->nb, b->nb)){ \
+ av_log(0, AV_LOG_ERROR, "Duplicate formats in avfilter_merge_formats() detected\n"); \
+ av_free(ret->fmts); \
+ av_free(ret); \
+ return NULL; \
+ } \
+ ret->fmts[k++] = a->fmts[i]; \
+ } \
+ } \
+ ret->nb = k; \
+ /* check that there was at least one common format */ \
+ if (!ret->nb) \
+ goto fail; \
+ \
+ MERGE_REF(ret, a, fmts, type, fail); \
+ MERGE_REF(ret, b, fmts, type, fail); \
+} while (0)
AVFilterFormats *avfilter_merge_formats(AVFilterFormats *a, AVFilterFormats *b)
{
- AVFilterFormats *ret;
- unsigned i, j, k = 0;
+ AVFilterFormats *ret = NULL;
if (a == b)
return a;
- ret = av_mallocz(sizeof(*ret));
-
- /* merge list of formats */
- ret->formats = av_malloc(sizeof(*ret->formats) * FFMIN(a->format_count,
- b->format_count));
- for (i = 0; i < a->format_count; i++)
- for (j = 0; j < b->format_count; j++)
- if (a->formats[i] == b->formats[j]){
- if(k >= FFMIN(a->format_count, b->format_count)){
- av_log(0, AV_LOG_ERROR, "Duplicate formats in avfilter_merge_formats() detected\n");
- av_free(ret->formats);
- av_free(ret);
- return NULL;
- }
- ret->formats[k++] = a->formats[i];
- }
-
- ret->format_count = k;
- /* check that there was at least one common format */
- if (!ret->format_count) {
- av_free(ret->formats);
- av_free(ret);
- return NULL;
+ MERGE_FORMATS(ret, a, b, formats, format_count, AVFilterFormats, fail);
+
+ return ret;
+fail:
+ if (ret) {
+ av_freep(&ret->refs);
+ av_freep(&ret->formats);
}
+ av_freep(&ret);
+ return NULL;
+}
+
+AVFilterFormats *ff_merge_samplerates(AVFilterFormats *a,
+ AVFilterFormats *b)
+{
+ AVFilterFormats *ret = NULL;
- ret->refs = av_malloc(sizeof(*ret->refs) * (a->refcount + b->refcount));
+ if (a == b) return a;
- merge_ref(ret, a);
- merge_ref(ret, b);
+ if (a->format_count && b->format_count) {
+ MERGE_FORMATS(ret, a, b, formats, format_count, AVFilterFormats, fail);
+ } else if (a->format_count) {
+ MERGE_REF(a, b, formats, AVFilterFormats, fail);
+ ret = a;
+ } else {
+ MERGE_REF(b, a, formats, AVFilterFormats, fail);
+ ret = b;
+ }
return ret;
+fail:
+ if (ret) {
+ av_freep(&ret->refs);
+ av_freep(&ret->formats);
+ }
+ av_freep(&ret);
+ return NULL;
+}
+
+AVFilterChannelLayouts *ff_merge_channel_layouts(AVFilterChannelLayouts *a,
+ AVFilterChannelLayouts *b)
+{
+ AVFilterChannelLayouts *ret = NULL;
+
+ if (a == b) return a;
+
+ if (a->nb_channel_layouts && b->nb_channel_layouts) {
+ MERGE_FORMATS(ret, a, b, channel_layouts, nb_channel_layouts,
+ AVFilterChannelLayouts, fail);
+ } else if (a->nb_channel_layouts) {
+ MERGE_REF(a, b, channel_layouts, AVFilterChannelLayouts, fail);
+ ret = a;
+ } else {
+ MERGE_REF(b, a, channel_layouts, AVFilterChannelLayouts, fail);
+ ret = b;
+ }
+
+ return ret;
+fail:
+ if (ret) {
+ av_freep(&ret->refs);
+ av_freep(&ret->channel_layouts);
+ }
+ av_freep(&ret);
+ return NULL;
}
int ff_fmt_is_in(int fmt, const int *fmts)
@@ -146,30 +221,40 @@ AVFilterFormats *avfilter_make_format_list(const int *fmts)
return formats;
}
-AVFilterFormats *avfilter_make_format64_list(const int64_t *fmts)
+AVFilterChannelLayouts *avfilter_make_format64_list(const int64_t *fmts)
{
MAKE_FORMAT_LIST();
if (count)
memcpy(formats->formats, fmts, sizeof(*formats->formats) * count);
- return formats;
+ return (AVFilterChannelLayouts*)formats;
}
+#define ADD_FORMAT(f, fmt, type, list, nb) \
+do { \
+ type *fmts; \
+ \
+ if (!(*f) && !(*f = av_mallocz(sizeof(**f)))) \
+ return AVERROR(ENOMEM); \
+ \
+ fmts = av_realloc((*f)->list, \
+ sizeof(*(*f)->list) * ((*f)->nb + 1));\
+ if (!fmts) \
+ return AVERROR(ENOMEM); \
+ \
+ (*f)->list = fmts; \
+ (*f)->list[(*f)->nb++] = fmt; \
+ return 0; \
+} while (0)
+
int avfilter_add_format(AVFilterFormats **avff, int64_t fmt)
{
- int64_t *fmts;
-
- if (!(*avff) && !(*avff = av_mallocz(sizeof(**avff))))
- return AVERROR(ENOMEM);
-
- fmts = av_realloc((*avff)->formats,
- sizeof(*(*avff)->formats) * ((*avff)->format_count+1));
- if (!fmts)
- return AVERROR(ENOMEM);
+ ADD_FORMAT(avff, fmt, int64_t, formats, format_count);
+}
- (*avff)->formats = fmts;
- (*avff)->formats[(*avff)->format_count++] = fmt;
- return 0;
+int ff_add_channel_layout(AVFilterChannelLayouts **l, uint64_t channel_layout)
+{
+ ADD_FORMAT(l, channel_layout, uint64_t, channel_layouts, nb_channel_layouts);
}
#if FF_API_OLD_ALL_FORMATS_API
@@ -199,10 +284,10 @@ const int64_t avfilter_all_channel_layouts[] = {
-1
};
-AVFilterFormats *avfilter_make_all_channel_layouts(void)
-{
- return avfilter_make_format64_list(avfilter_all_channel_layouts);
-}
+// AVFilterFormats *avfilter_make_all_channel_layouts(void)
+// {
+// return avfilter_make_format64_list(avfilter_all_channel_layouts);
+// }
AVFilterFormats *avfilter_make_all_packing_formats(void)
{
@@ -215,53 +300,163 @@ AVFilterFormats *avfilter_make_all_packing_formats(void)
return avfilter_make_format_list(packing);
}
-void avfilter_formats_ref(AVFilterFormats *f, AVFilterFormats **ref)
+AVFilterFormats *ff_all_samplerates(void)
{
- *ref = f;
- f->refs = av_realloc(f->refs, sizeof(*f->refs) * ++f->refcount);
- f->refs[f->refcount-1] = ref;
+ AVFilterFormats *ret = av_mallocz(sizeof(*ret));
+ return ret;
}
-static int find_ref_index(AVFilterFormats **ref)
+AVFilterChannelLayouts *ff_all_channel_layouts(void)
{
- int i;
- for (i = 0; i < (*ref)->refcount; i++)
- if ((*ref)->refs[i] == ref)
- return i;
- return -1;
+ AVFilterChannelLayouts *ret = av_mallocz(sizeof(*ret));
+ return ret;
}
-void avfilter_formats_unref(AVFilterFormats **ref)
+#define FORMATS_REF(f, ref) \
+do { \
+ *ref = f; \
+ f->refs = av_realloc(f->refs, sizeof(*f->refs) * ++f->refcount); \
+ f->refs[f->refcount-1] = ref; \
+} while (0)
+
+void ff_channel_layouts_ref(AVFilterChannelLayouts *f, AVFilterChannelLayouts **ref)
+{
+ FORMATS_REF(f, ref);
+}
+
+void avfilter_formats_ref(AVFilterFormats *f, AVFilterFormats **ref)
{
- int idx;
+ FORMATS_REF(f, ref);
+}
- if (!*ref)
- return;
+#define FIND_REF_INDEX(ref, idx) \
+do { \
+ int i; \
+ for (i = 0; i < (*ref)->refcount; i ++) \
+ if((*ref)->refs[i] == ref) { \
+ idx = i; \
+ break; \
+ } \
+} while (0)
+
+#define FORMATS_UNREF(ref, list) \
+do { \
+ int idx = -1; \
+ \
+ if (!*ref) \
+ return; \
+ \
+ FIND_REF_INDEX(ref, idx); \
+ \
+ if (idx >= 0) \
+ memmove((*ref)->refs + idx, (*ref)->refs + idx + 1, \
+ sizeof(*(*ref)->refs) * ((*ref)->refcount - idx - 1)); \
+ \
+ if(!--(*ref)->refcount) { \
+ av_free((*ref)->list); \
+ av_free((*ref)->refs); \
+ av_free(*ref); \
+ } \
+ *ref = NULL; \
+} while (0)
- idx = find_ref_index(ref);
+void avfilter_formats_unref(AVFilterFormats **ref)
+{
+ FORMATS_UNREF(ref, formats);
+}
- if(idx >= 0)
- memmove((*ref)->refs + idx, (*ref)->refs + idx + 1,
- sizeof(*(*ref)->refs) * ((*ref)->refcount - idx - 1));
+void ff_channel_layouts_unref(AVFilterChannelLayouts **ref)
+{
+ FORMATS_UNREF(ref, channel_layouts);
+}
- if (!--(*ref)->refcount) {
- av_free((*ref)->formats);
- av_free((*ref)->refs);
- av_free(*ref);
- }
- *ref = NULL;
+#define FORMATS_CHANGEREF(oldref, newref) \
+do { \
+ int idx = -1; \
+ \
+ FIND_REF_INDEX(oldref, idx); \
+ \
+ if (idx >= 0) { \
+ (*oldref)->refs[idx] = newref; \
+ *newref = *oldref; \
+ *oldref = NULL; \
+ } \
+} while (0)
+
+void ff_channel_layouts_changeref(AVFilterChannelLayouts **oldref,
+ AVFilterChannelLayouts **newref)
+{
+ FORMATS_CHANGEREF(oldref, newref);
}
void avfilter_formats_changeref(AVFilterFormats **oldref,
AVFilterFormats **newref)
{
- int idx = find_ref_index(oldref);
+ FORMATS_CHANGEREF(oldref, newref);
+}
+
+#define SET_COMMON_FORMATS(ctx, fmts, in_fmts, out_fmts, ref, list) \
+{ \
+ int count = 0, i; \
+ \
+ for (i = 0; i < ctx->input_count; i++) { \
+ if (ctx->inputs[i]) { \
+ ref(fmts, &ctx->inputs[i]->out_fmts); \
+ count++; \
+ } \
+ } \
+ for (i = 0; i < ctx->output_count; i++) { \
+ if (ctx->outputs[i]) { \
+ ref(fmts, &ctx->outputs[i]->in_fmts); \
+ count++; \
+ } \
+ } \
+ \
+ if (!count) { \
+ av_freep(&fmts->list); \
+ av_freep(&fmts->refs); \
+ av_freep(&fmts); \
+ } \
+}
+
+void ff_set_common_channel_layouts(AVFilterContext *ctx,
+ AVFilterChannelLayouts *layouts)
+{
+ SET_COMMON_FORMATS(ctx, layouts, in_channel_layouts, out_channel_layouts,
+ ff_channel_layouts_ref, channel_layouts);
+}
+
+void ff_set_common_samplerates(AVFilterContext *ctx,
+ AVFilterFormats *samplerates)
+{
+ SET_COMMON_FORMATS(ctx, samplerates, in_samplerates, out_samplerates,
+ avfilter_formats_ref, formats);
+}
+
+/**
+ * A helper for query_formats() which sets all links to the same list of
+ * formats. If there are no links hooked to this filter, the list of formats is
+ * freed.
+ */
+void avfilter_set_common_formats(AVFilterContext *ctx, AVFilterFormats *formats)
+{
+ SET_COMMON_FORMATS(ctx, formats, in_formats, out_formats,
+ avfilter_formats_ref, formats);
+}
- if (idx >= 0) {
- (*oldref)->refs[idx] = newref;
- *newref = *oldref;
- *oldref = NULL;
+int avfilter_default_query_formats(AVFilterContext *ctx)
+{
+ enum AVMediaType type = ctx->inputs && ctx->inputs [0] ? ctx->inputs [0]->type :
+ ctx->outputs && ctx->outputs[0] ? ctx->outputs[0]->type :
+ AVMEDIA_TYPE_VIDEO;
+
+ avfilter_set_common_formats(ctx, avfilter_all_formats(type));
+ if (type == AVMEDIA_TYPE_AUDIO) {
+ ff_set_common_channel_layouts(ctx, ff_all_channel_layouts());
+ ff_set_common_samplerates(ctx, ff_all_samplerates());
}
+
+ return 0;
}
/* internal functions for parsing audio format arguments */
diff --git a/libavfilter/formats.h b/libavfilter/formats.h
new file mode 100644
index 0000000000..7b0eab5dea
--- /dev/null
+++ b/libavfilter/formats.h
@@ -0,0 +1,81 @@
+/*
+ * 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
+ */
+
+#ifndef AVFILTER_FORMATS_H
+#define AVFILTER_FORMATS_H
+
+#include "avfilter.h"
+
+typedef struct AVFilterChannelLayouts {
+ uint64_t *channel_layouts; ///< list of channel layouts
+ int nb_channel_layouts; ///< number of channel layouts
+
+ unsigned refcount; ///< number of references to this list
+ struct AVFilterChannelLayouts ***refs; ///< references to this list
+} AVFilterChannelLayouts;
+
+/**
+ * Return a channel layouts/samplerates list which contains the intersection of
+ * the layouts/samplerates of a and b. Also, all the references of a, all the
+ * references of b, and a and b themselves will be deallocated.
+ *
+ * If a and b do not share any common elements, neither is modified, and NULL
+ * is returned.
+ */
+AVFilterChannelLayouts *ff_merge_channel_layouts(AVFilterChannelLayouts *a,
+ AVFilterChannelLayouts *b);
+AVFilterFormats *ff_merge_samplerates(AVFilterFormats *a,
+ AVFilterFormats *b);
+
+/**
+ * Construct an empty AVFilterChannelLayouts/AVFilterFormats struct --
+ * representing any channel layout/sample rate.
+ */
+AVFilterChannelLayouts *ff_all_channel_layouts(void);
+AVFilterFormats *ff_all_samplerates(void);
+
+AVFilterChannelLayouts *avfilter_make_format64_list(const int64_t *fmts);
+
+
+/**
+ * A helper for query_formats() which sets all links to the same list of channel
+ * layouts/sample rates. If there are no links hooked to this filter, the list
+ * is freed.
+ */
+void ff_set_common_channel_layouts(AVFilterContext *ctx,
+ AVFilterChannelLayouts *layouts);
+void ff_set_common_samplerates(AVFilterContext *ctx,
+ AVFilterFormats *samplerates);
+
+int ff_add_channel_layout(AVFilterChannelLayouts **l, uint64_t channel_layout);
+
+/**
+ * Add *ref as a new reference to f.
+ */
+void ff_channel_layouts_ref(AVFilterChannelLayouts *f,
+ AVFilterChannelLayouts **ref);
+
+/**
+ * Remove a reference to a channel layouts list.
+ */
+void ff_channel_layouts_unref(AVFilterChannelLayouts **ref);
+
+void ff_channel_layouts_changeref(AVFilterChannelLayouts **oldref,
+ AVFilterChannelLayouts **newref);
+
+#endif // AVFILTER_FORMATS_H
diff --git a/libavfilter/internal.h b/libavfilter/internal.h
index 09d605541f..034a6c9cab 100644
--- a/libavfilter/internal.h
+++ b/libavfilter/internal.h
@@ -26,6 +26,7 @@
#include "avfilter.h"
#include "avfiltergraph.h"
+#include "formats.h"
#define POOL_SIZE 32
typedef struct AVFilterPool {
@@ -151,6 +152,10 @@ static inline void ff_null_start_frame_keep_ref(AVFilterLink *inlink,
void ff_update_link_current_pts(AVFilterLink *link, int64_t pts);
+void ff_free_pool(AVFilterPool *pool);
+
+void ff_command_queue_pop(AVFilterContext *filter);
+
#define FF_DPRINTF_START(ctx, func) av_dlog(NULL, "%-16s: ", #func)
void ff_dlog_link(void *ctx, AVFilterLink *link, int end);
diff --git a/libavfilter/sink_buffer.c b/libavfilter/sink_buffer.c
index b0cc519217..ab7aa4f5a8 100644
--- a/libavfilter/sink_buffer.c
+++ b/libavfilter/sink_buffer.c
@@ -269,19 +269,22 @@ static int asink_query_formats(AVFilterContext *ctx)
{
BufferSinkContext *buf = ctx->priv;
AVFilterFormats *formats = NULL;
+ AVFilterChannelLayouts *layouts = NULL;
if (!(formats = avfilter_make_format_list(buf->sample_fmts)))
return AVERROR(ENOMEM);
avfilter_set_common_sample_formats(ctx, formats);
- if (!(formats = avfilter_make_format64_list(buf->channel_layouts)))
+ if (!(layouts = avfilter_make_format64_list(buf->channel_layouts)))
return AVERROR(ENOMEM);
- avfilter_set_common_channel_layouts(ctx, formats);
+ ff_set_common_channel_layouts(ctx, layouts);
if (!(formats = avfilter_make_format_list(buf->packing_fmts)))
return AVERROR(ENOMEM);
avfilter_set_common_packing_formats(ctx, formats);
+ ff_set_common_samplerates (ctx, ff_all_samplerates());
+
return 0;
}
diff --git a/libavfilter/src_buffer.c b/libavfilter/src_buffer.c
index f8d572d085..cadc4ee2a4 100644
--- a/libavfilter/src_buffer.c
+++ b/libavfilter/src_buffer.c
@@ -507,14 +507,15 @@ static int query_formats_audio(AVFilterContext *ctx)
{
BufferSourceContext *abuffer = ctx->priv;
AVFilterFormats *formats;
+ AVFilterChannelLayouts *layouts;
formats = NULL;
avfilter_add_format(&formats, abuffer->sample_format);
avfilter_set_common_sample_formats(ctx, formats);
- formats = NULL;
- avfilter_add_format(&formats, abuffer->channel_layout);
- avfilter_set_common_channel_layouts(ctx, formats);
+ layouts = NULL;
+ ff_add_channel_layout(&layouts, abuffer->channel_layout);
+ ff_set_common_channel_layouts(ctx, layouts);
formats = NULL;
avfilter_add_format(&formats, abuffer->packing_format);
@@ -653,8 +654,6 @@ AVFilter avfilter_vsrc_buffer = {
{ .name = NULL}},
};
-#if CONFIG_ABUFFER_FILTER
-
AVFilter avfilter_asrc_abuffer = {
.name = "abuffer",
.description = NULL_IF_CONFIG_SMALL("Buffer audio frames, and make them accessible to the filterchain."),
@@ -673,4 +672,3 @@ AVFilter avfilter_asrc_abuffer = {
{ .name = NULL}},
};
-#endif
diff --git a/libavfilter/src_movie.c b/libavfilter/src_movie.c
index a00d30d9cf..30624559fc 100644
--- a/libavfilter/src_movie.c
+++ b/libavfilter/src_movie.c
@@ -38,6 +38,7 @@
#include "audio.h"
#include "avcodec.h"
#include "avfilter.h"
+#include "formats.h"
typedef struct {
/* common A/V fields */
@@ -370,12 +371,14 @@ static int amovie_query_formats(AVFilterContext *ctx)
enum AVSampleFormat sample_fmts[] = { c->sample_fmt, -1 };
int packing_fmts[] = { AVFILTER_PACKED, -1 };
+ int sample_rates[] = { c->sample_rate, -1 };
int64_t chlayouts[] = { c->channel_layout ? c->channel_layout :
av_get_default_channel_layout(c->channels), -1 };
avfilter_set_common_sample_formats (ctx, avfilter_make_format_list(sample_fmts));
avfilter_set_common_packing_formats(ctx, avfilter_make_format_list(packing_fmts));
- avfilter_set_common_channel_layouts(ctx, avfilter_make_format64_list(chlayouts));
+ ff_set_common_samplerates (ctx, avfilter_make_format_list(sample_rates));
+ ff_set_common_channel_layouts(ctx, avfilter_make_format64_list(chlayouts));
return 0;
}
diff --git a/libavfilter/version.h b/libavfilter/version.h
index 05318047f4..a8e4f893d4 100644
--- a/libavfilter/version.h
+++ b/libavfilter/version.h
@@ -29,7 +29,7 @@
#include "libavutil/avutil.h"
#define LIBAVFILTER_VERSION_MAJOR 2
-#define LIBAVFILTER_VERSION_MINOR 73
+#define LIBAVFILTER_VERSION_MINOR 74
#define LIBAVFILTER_VERSION_MICRO 100
#define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \
@@ -50,5 +50,8 @@
#ifndef FF_API_SAMPLERATE64
#define FF_API_SAMPLERATE64 (LIBAVFILTER_VERSION_MAJOR < 3)
#endif
+#ifndef FF_API_VSRC_BUFFER_ADD_FRAME
+#define FF_API_VSRC_BUFFER_ADD_FRAME (LIBAVFILTER_VERSION_MAJOR < 3)
+#endif
#endif // AVFILTER_VERSION_H
diff --git a/libavfilter/vf_yadif.c b/libavfilter/vf_yadif.c
index 684f9099fa..fb4862d0be 100644
--- a/libavfilter/vf_yadif.c
+++ b/libavfilter/vf_yadif.c
@@ -59,6 +59,7 @@ typedef struct {
int w, int prefs, int mrefs, int parity, int mode);
const AVPixFmtDescriptor *csp;
+ int eof;
} YADIFContext;
#define CHECK(j)\
@@ -216,22 +217,11 @@ static void return_frame(AVFilterContext *ctx, int is_second)
filter(ctx, yadif->out, tff ^ !is_second, tff);
if (is_second) {
- if (yadif->next->pts != AV_NOPTS_VALUE &&
- yadif->cur->pts != AV_NOPTS_VALUE) {
- uint64_t next_pts = yadif->next->pts;
- uint64_t cur_pts = yadif->cur->pts;
- uint64_t prev_pts = yadif->prev->pts;
-
- uint64_t ft = FFMIN3( cur_pts-prev_pts,
- next_pts-cur_pts,
- (next_pts-prev_pts)/2);
-
- if(next_pts - cur_pts < 2*ft)
- yadif->out->pts =
- (next_pts&cur_pts) +
- ((next_pts^cur_pts)>>1);
- else
- yadif->out->pts = cur_pts + ft/2;
+ int64_t cur_pts = yadif->cur->pts;
+ int64_t next_pts = yadif->next->pts;
+
+ if (next_pts != AV_NOPTS_VALUE && cur_pts != AV_NOPTS_VALUE) {
+ yadif->out->pts = cur_pts + next_pts;
} else {
yadif->out->pts = AV_NOPTS_VALUE;
}
@@ -264,6 +254,8 @@ static void start_frame(AVFilterLink *link, AVFilterBufferRef *picref)
yadif->out = avfilter_ref_buffer(yadif->cur, AV_PERM_READ);
avfilter_unref_buffer(yadif->prev);
yadif->prev = NULL;
+ if (yadif->out->pts != AV_NOPTS_VALUE)
+ yadif->out->pts *= 2;
avfilter_start_frame(ctx->outputs[0], yadif->out);
return;
}
@@ -276,6 +268,8 @@ static void start_frame(AVFilterLink *link, AVFilterBufferRef *picref)
avfilter_copy_buffer_ref_props(yadif->out, yadif->cur);
yadif->out->video->interlaced = 0;
+ if (yadif->out->pts != AV_NOPTS_VALUE)
+ yadif->out->pts *= 2;
avfilter_start_frame(ctx->outputs[0], yadif->out);
}
@@ -309,8 +303,21 @@ static int request_frame(AVFilterLink *link)
do {
int ret;
- if ((ret = avfilter_request_frame(link->src->inputs[0])))
+ if (yadif->eof)
+ return AVERROR_EOF;
+
+ ret = avfilter_request_frame(link->src->inputs[0]);
+
+ if (ret == AVERROR_EOF && yadif->next) {
+ AVFilterBufferRef *next = avfilter_ref_buffer(yadif->next, AV_PERM_READ);
+ next->pts = yadif->next->pts * 2 - yadif->cur->pts;
+
+ start_frame(link->src->inputs[0], next);
+ end_frame(link->src->inputs[0]);
+ yadif->eof = 1;
+ } else if (ret < 0) {
return ret;
+ }
} while (!yadif->cur);
return 0;
@@ -411,6 +418,16 @@ static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque)
static void null_draw_slice(AVFilterLink *link, int y, int h, int slice_dir) { }
+static int config_props(AVFilterLink *link)
+{
+ link->time_base.num = link->src->inputs[0]->time_base.num;
+ link->time_base.den = link->src->inputs[0]->time_base.den * 2;
+ link->w = link->src->inputs[0]->w;
+ link->h = link->src->inputs[0]->h;
+
+ return 0;
+}
+
AVFilter avfilter_vf_yadif = {
.name = "yadif",
.description = NULL_IF_CONFIG_SMALL("Deinterlace the input image."),
@@ -432,6 +449,7 @@ AVFilter avfilter_vf_yadif = {
.outputs = (const AVFilterPad[]) {{ .name = "default",
.type = AVMEDIA_TYPE_VIDEO,
.poll_frame = poll_frame,
- .request_frame = request_frame, },
+ .request_frame = request_frame,
+ .config_props = config_props, },
{ .name = NULL}},
};
diff --git a/libavfilter/video.c b/libavfilter/video.c
new file mode 100644
index 0000000000..86dfd901f8
--- /dev/null
+++ b/libavfilter/video.c
@@ -0,0 +1,345 @@
+/*
+ * 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/imgutils.h"
+
+#include "avfilter.h"
+#include "internal.h"
+
+static char *ff_get_ref_perms_string(char *buf, size_t buf_size, int perms)
+{
+ snprintf(buf, buf_size, "%s%s%s%s%s%s",
+ perms & AV_PERM_READ ? "r" : "",
+ perms & AV_PERM_WRITE ? "w" : "",
+ perms & AV_PERM_PRESERVE ? "p" : "",
+ perms & AV_PERM_REUSE ? "u" : "",
+ perms & AV_PERM_REUSE2 ? "U" : "",
+ perms & AV_PERM_NEG_LINESIZES ? "n" : "");
+ return buf;
+}
+
+static void ff_dlog_ref(void *ctx, AVFilterBufferRef *ref, int end)
+{
+ av_unused char buf[16];
+ av_dlog(ctx,
+ "ref[%p buf:%p refcount:%d perms:%s data:%p linesize[%d, %d, %d, %d] pts:%"PRId64" pos:%"PRId64,
+ ref, ref->buf, ref->buf->refcount, ff_get_ref_perms_string(buf, sizeof(buf), ref->perms), ref->data[0],
+ ref->linesize[0], ref->linesize[1], ref->linesize[2], ref->linesize[3],
+ ref->pts, ref->pos);
+
+ if (ref->video) {
+ av_dlog(ctx, " a:%d/%d s:%dx%d i:%c iskey:%d type:%c",
+ ref->video->sample_aspect_ratio.num, ref->video->sample_aspect_ratio.den,
+ ref->video->w, ref->video->h,
+ !ref->video->interlaced ? 'P' : /* Progressive */
+ ref->video->top_field_first ? 'T' : 'B', /* Top / Bottom */
+ ref->video->key_frame,
+ av_get_picture_type_char(ref->video->pict_type));
+ }
+ if (ref->audio) {
+ av_dlog(ctx, " cl:%"PRId64"d n:%d r:%d p:%d",
+ ref->audio->channel_layout,
+ ref->audio->nb_samples,
+ ref->audio->sample_rate,
+ ref->audio->planar);
+ }
+
+ av_dlog(ctx, "]%s", end ? "\n" : "");
+}
+
+AVFilterBufferRef *avfilter_null_get_video_buffer(AVFilterLink *link, int perms, int w, int h)
+{
+ return avfilter_get_video_buffer(link->dst->outputs[0], perms, w, h);
+}
+
+AVFilterBufferRef *avfilter_default_get_video_buffer(AVFilterLink *link, int perms, int w, int h)
+{
+ int linesize[4];
+ uint8_t *data[4];
+ int i;
+ AVFilterBufferRef *picref = NULL;
+ AVFilterPool *pool = link->pool;
+
+ if (pool) {
+ for (i = 0; i < POOL_SIZE; i++) {
+ picref = pool->pic[i];
+ if (picref && picref->buf->format == link->format && picref->buf->w == w && picref->buf->h == h) {
+ AVFilterBuffer *pic = picref->buf;
+ pool->pic[i] = NULL;
+ pool->count--;
+ picref->video->w = w;
+ picref->video->h = h;
+ picref->perms = perms | AV_PERM_READ;
+ picref->format = link->format;
+ pic->refcount = 1;
+ memcpy(picref->data, pic->data, sizeof(picref->data));
+ memcpy(picref->linesize, pic->linesize, sizeof(picref->linesize));
+ pool->refcount++;
+ return picref;
+ }
+ }
+ } else {
+ pool = link->pool = av_mallocz(sizeof(AVFilterPool));
+ pool->refcount = 1;
+ }
+
+ // align: +2 is needed for swscaler, +16 to be SIMD-friendly
+ if ((i = av_image_alloc(data, linesize, w, h, link->format, 32)) < 0)
+ return NULL;
+
+ picref = avfilter_get_video_buffer_ref_from_arrays(data, linesize,
+ perms, w, h, link->format);
+ if (!picref) {
+ av_free(data[0]);
+ return NULL;
+ }
+
+ memset(data[0], 128, i);
+
+ picref->buf->priv = pool;
+ picref->buf->free = NULL;
+ pool->refcount++;
+
+ return picref;
+}
+
+AVFilterBufferRef *
+avfilter_get_video_buffer_ref_from_arrays(uint8_t * const data[4], const int linesize[4], int perms,
+ int w, int h, enum PixelFormat format)
+{
+ AVFilterBuffer *pic = av_mallocz(sizeof(AVFilterBuffer));
+ AVFilterBufferRef *picref = av_mallocz(sizeof(AVFilterBufferRef));
+
+ if (!pic || !picref)
+ goto fail;
+
+ picref->buf = pic;
+ picref->buf->free = ff_avfilter_default_free_buffer;
+ if (!(picref->video = av_mallocz(sizeof(AVFilterBufferRefVideoProps))))
+ goto fail;
+
+ pic->w = picref->video->w = w;
+ pic->h = picref->video->h = h;
+
+ /* make sure the buffer gets read permission or it's useless for output */
+ picref->perms = perms | AV_PERM_READ;
+
+ pic->refcount = 1;
+ picref->type = AVMEDIA_TYPE_VIDEO;
+ pic->format = picref->format = format;
+
+ memcpy(pic->data, data, 4*sizeof(data[0]));
+ memcpy(pic->linesize, linesize, 4*sizeof(linesize[0]));
+ memcpy(picref->data, pic->data, sizeof(picref->data));
+ memcpy(picref->linesize, pic->linesize, sizeof(picref->linesize));
+
+ pic-> extended_data = pic->data;
+ picref->extended_data = picref->data;
+
+ return picref;
+
+fail:
+ if (picref && picref->video)
+ av_free(picref->video);
+ av_free(picref);
+ av_free(pic);
+ return NULL;
+}
+
+AVFilterBufferRef *avfilter_get_video_buffer(AVFilterLink *link, int perms, int w, int h)
+{
+ AVFilterBufferRef *ret = NULL;
+
+ av_unused char buf[16];
+ FF_DPRINTF_START(NULL, get_video_buffer); ff_dlog_link(NULL, link, 0);
+ av_dlog(NULL, " perms:%s w:%d h:%d\n", ff_get_ref_perms_string(buf, sizeof(buf), perms), w, h);
+
+ if (link->dstpad->get_video_buffer)
+ ret = link->dstpad->get_video_buffer(link, perms, w, h);
+
+ if (!ret)
+ ret = avfilter_default_get_video_buffer(link, perms, w, h);
+
+ if (ret)
+ ret->type = AVMEDIA_TYPE_VIDEO;
+
+ FF_DPRINTF_START(NULL, get_video_buffer); ff_dlog_link(NULL, link, 0); av_dlog(NULL, " returning "); ff_dlog_ref(NULL, ret, 1);
+
+ return ret;
+}
+
+void avfilter_null_start_frame(AVFilterLink *link, AVFilterBufferRef *picref)
+{
+ avfilter_start_frame(link->dst->outputs[0], picref);
+}
+
+void avfilter_default_start_frame(AVFilterLink *inlink, AVFilterBufferRef *picref)
+{
+ AVFilterLink *outlink = NULL;
+
+ if (inlink->dst->output_count)
+ outlink = inlink->dst->outputs[0];
+
+ if (outlink) {
+ outlink->out_buf = avfilter_get_video_buffer(outlink, AV_PERM_WRITE, outlink->w, outlink->h);
+ avfilter_copy_buffer_ref_props(outlink->out_buf, picref);
+ avfilter_start_frame(outlink, avfilter_ref_buffer(outlink->out_buf, ~0));
+ }
+}
+
+/* XXX: should we do the duplicating of the picture ref here, instead of
+ * forcing the source filter to do it? */
+void avfilter_start_frame(AVFilterLink *link, AVFilterBufferRef *picref)
+{
+ void (*start_frame)(AVFilterLink *, AVFilterBufferRef *);
+ AVFilterPad *dst = link->dstpad;
+ int perms = picref->perms;
+ AVFilterCommand *cmd= link->dst->command_queue;
+
+ FF_DPRINTF_START(NULL, start_frame); ff_dlog_link(NULL, link, 0); av_dlog(NULL, " "); ff_dlog_ref(NULL, picref, 1);
+
+ if (!(start_frame = dst->start_frame))
+ start_frame = avfilter_default_start_frame;
+
+ if (picref->linesize[0] < 0)
+ perms |= AV_PERM_NEG_LINESIZES;
+ /* prepare to copy the picture if it has insufficient permissions */
+ if ((dst->min_perms & perms) != dst->min_perms || dst->rej_perms & perms) {
+ av_log(link->dst, AV_LOG_DEBUG,
+ "frame copy needed (have perms %x, need %x, reject %x)\n",
+ picref->perms,
+ link->dstpad->min_perms, link->dstpad->rej_perms);
+
+ link->cur_buf = avfilter_get_video_buffer(link, dst->min_perms, link->w, link->h);
+ link->src_buf = picref;
+ avfilter_copy_buffer_ref_props(link->cur_buf, link->src_buf);
+ }
+ else
+ link->cur_buf = picref;
+
+ while(cmd && cmd->time <= picref->pts * av_q2d(link->time_base)){
+ av_log(link->dst, AV_LOG_DEBUG,
+ "Processing command time:%f command:%s arg:%s\n",
+ cmd->time, cmd->command, cmd->arg);
+ avfilter_process_command(link->dst, cmd->command, cmd->arg, 0, 0, cmd->flags);
+ ff_command_queue_pop(link->dst);
+ cmd= link->dst->command_queue;
+ }
+
+ start_frame(link, link->cur_buf);
+ ff_update_link_current_pts(link, link->cur_buf->pts);
+}
+
+void avfilter_null_end_frame(AVFilterLink *link)
+{
+ avfilter_end_frame(link->dst->outputs[0]);
+}
+
+void avfilter_default_end_frame(AVFilterLink *inlink)
+{
+ AVFilterLink *outlink = NULL;
+
+ if (inlink->dst->output_count)
+ outlink = inlink->dst->outputs[0];
+
+ avfilter_unref_buffer(inlink->cur_buf);
+ inlink->cur_buf = NULL;
+
+ if (outlink) {
+ if (outlink->out_buf) {
+ avfilter_unref_buffer(outlink->out_buf);
+ outlink->out_buf = NULL;
+ }
+ avfilter_end_frame(outlink);
+ }
+}
+
+void avfilter_end_frame(AVFilterLink *link)
+{
+ void (*end_frame)(AVFilterLink *);
+
+ if (!(end_frame = link->dstpad->end_frame))
+ end_frame = avfilter_default_end_frame;
+
+ end_frame(link);
+
+ /* unreference the source picture if we're feeding the destination filter
+ * a copied version dues to permission issues */
+ if (link->src_buf) {
+ avfilter_unref_buffer(link->src_buf);
+ link->src_buf = NULL;
+ }
+}
+
+void avfilter_null_draw_slice(AVFilterLink *link, int y, int h, int slice_dir)
+{
+ avfilter_draw_slice(link->dst->outputs[0], y, h, slice_dir);
+}
+
+void avfilter_default_draw_slice(AVFilterLink *inlink, int y, int h, int slice_dir)
+{
+ AVFilterLink *outlink = NULL;
+
+ if (inlink->dst->output_count)
+ outlink = inlink->dst->outputs[0];
+
+ if (outlink)
+ avfilter_draw_slice(outlink, y, h, slice_dir);
+}
+
+void avfilter_draw_slice(AVFilterLink *link, int y, int h, int slice_dir)
+{
+ uint8_t *src[4], *dst[4];
+ int i, j, vsub;
+ void (*draw_slice)(AVFilterLink *, int, int, int);
+
+ FF_DPRINTF_START(NULL, draw_slice); ff_dlog_link(NULL, link, 0); av_dlog(NULL, " y:%d h:%d dir:%d\n", y, h, slice_dir);
+
+ /* copy the slice if needed for permission reasons */
+ if (link->src_buf) {
+ vsub = av_pix_fmt_descriptors[link->format].log2_chroma_h;
+
+ for (i = 0; i < 4; i++) {
+ if (link->src_buf->data[i]) {
+ src[i] = link->src_buf-> data[i] +
+ (y >> (i==1 || i==2 ? vsub : 0)) * link->src_buf-> linesize[i];
+ dst[i] = link->cur_buf->data[i] +
+ (y >> (i==1 || i==2 ? vsub : 0)) * link->cur_buf->linesize[i];
+ } else
+ src[i] = dst[i] = NULL;
+ }
+
+ for (i = 0; i < 4; i++) {
+ int planew =
+ av_image_get_linesize(link->format, link->cur_buf->video->w, i);
+
+ if (!src[i]) continue;
+
+ for (j = 0; j < h >> (i==1 || i==2 ? vsub : 0); j++) {
+ memcpy(dst[i], src[i], planew);
+ src[i] += link->src_buf->linesize[i];
+ dst[i] += link->cur_buf->linesize[i];
+ }
+ }
+ }
+
+ if (!(draw_slice = link->dstpad->draw_slice))
+ draw_slice = avfilter_default_draw_slice;
+ draw_slice(link, y, h, slice_dir);
+}
+
diff --git a/libavutil/avutil.h b/libavutil/avutil.h
index d80393bece..130a4dac7f 100644
--- a/libavutil/avutil.h
+++ b/libavutil/avutil.h
@@ -153,7 +153,7 @@
*/
#define LIBAVUTIL_VERSION_MAJOR 51
-#define LIBAVUTIL_VERSION_MINOR 52
+#define LIBAVUTIL_VERSION_MINOR 53
#define LIBAVUTIL_VERSION_MICRO 100
#define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \
diff --git a/tests/fate-run.sh b/tests/fate-run.sh
index c205169899..9a1eb7d201 100755
--- a/tests/fate-run.sh
+++ b/tests/fate-run.sh
@@ -61,9 +61,7 @@ stddev(){
}
oneline(){
- val=$(cat "$2")
- test x"$val" = x"$1" || { r=$?; printf -- '-%s\n+%s\n' "$ref" "$val"; }
- return ${r:-0}
+ printf '%s\n' "$1" | diff -u -b - "$2"
}
run(){
diff --git a/tests/fate/audio.mak b/tests/fate/audio.mak
index 0831406d64..6ba46d9635 100644
--- a/tests/fate/audio.mak
+++ b/tests/fate/audio.mak
@@ -43,6 +43,12 @@ fate-nellymoser-aref-encode: CMP_SHIFT = -1172
fate-nellymoser-aref-encode: CMP_TARGET = 9617
fate-nellymoser-aref-encode: SIZE_TOLERANCE = 268
+FATE_AUDIO += fate-sierra-vmd-audio
+fate-sierra-vmd-audio: CMD = framecrc -i $(SAMPLES)/vmd/12.vmd -vn
+
+FATE_AUDIO += fate-smacker-audio
+fate-smacker-audio: CMD = framecrc -i $(SAMPLES)/smacker/wetlogo.smk -vn
+
FATE_AUDIO += fate-ws_snd
fate-ws_snd: CMD = md5 -i $(SAMPLES)/vqa/ws_snd.vqa -f s16le
diff --git a/tests/fate/demux.mak b/tests/fate/demux.mak
index 67ea698430..8c291f3864 100644
--- a/tests/fate/demux.mak
+++ b/tests/fate/demux.mak
@@ -58,14 +58,11 @@ fate-qcp-demux: CMD = crc -i $(SAMPLES)/qcp/0036580847.QCP -acodec copy
FATE_DEMUX += fate-redcode-demux
fate-redcode-demux: CMD = framecrc -i $(SAMPLES)/r3d/4MB-sample.r3d -vcodec copy -acodec copy
-FATE_DEMUX += fate-sierra-vmd
-fate-sierra-vmd: CMD = framecrc -i $(SAMPLES)/vmd/12.vmd -pix_fmt rgb24
-
FATE_DEMUX += fate-siff
fate-siff: CMD = framecrc -i $(SAMPLES)/SIFF/INTRO_B.VB -t 3 -pix_fmt rgb24
-FATE_DEMUX += fate-smjpeg
-fate-smjpeg: CMD = framecrc -i $(SAMPLES)/smjpeg/scenwin.mjpg -vcodec copy
+FATE_DEMUX += fate-smjpeg-demux
+fate-smjpeg-demux: CMD = framecrc -i $(SAMPLES)/smjpeg/scenwin.mjpg -c copy
FATE_DEMUX += fate-westwood-aud
fate-westwood-aud: CMD = framecrc -i $(SAMPLES)/westwood-aud/excellent.aud -c copy
diff --git a/tests/fate/video.mak b/tests/fate/video.mak
index ae5edb3211..6fa4997187 100644
--- a/tests/fate/video.mak
+++ b/tests/fate/video.mak
@@ -176,8 +176,11 @@ fate-rl2: CMD = framecrc -i $(SAMPLES)/rl2/Z4915300.RL2 -pix_fmt rgb24 -an
FATE_VIDEO += fate-roqvideo
fate-roqvideo: CMD = framecrc -i $(SAMPLES)/idroq/idlogo.roq -an
-FATE_VIDEO += fate-smacker
-fate-smacker: CMD = framecrc -i $(SAMPLES)/smacker/wetlogo.smk -pix_fmt rgb24
+FATA_VIDEO += fate-sierra-vmd-video
+fate-sierra-vmd-video: CMD = framecrc -i $(SAMPLES)/vmd/12.vmd -pix_fmt rgb24 -an
+
+FATA_VIDEO += fate-smacker-video
+fate-smacker-video: CMD = framecrc -i $(SAMPLES)/smacker/wetlogo.smk -pix_fmt rgb24 -an
FATE_VIDEO += fate-smc
fate-smc: CMD = framecrc -i $(SAMPLES)/smc/cass_schi.qt -pix_fmt rgb24
diff --git a/tests/ref/fate/sierra-vmd b/tests/ref/fate/sierra-vmd
deleted file mode 100644
index c72813e5b8..0000000000
--- a/tests/ref/fate/sierra-vmd
+++ /dev/null
@@ -1,334 +0,0 @@
-#tb 0: 1/10
-#tb 1: 1/22050
-0, 0, 0, 1, 230400, 0x0224ab01
-1, 0, 0, 61740, 123480, 0x3a794c13
-0, 1, 1, 1, 230400, 0x449e4d81
-0, 2, 2, 1, 230400, 0x3e15e07a
-0, 3, 3, 1, 230400, 0xdabe4172
-0, 4, 4, 1, 230400, 0x0947b7db
-0, 5, 5, 1, 230400, 0x934e243b
-0, 6, 6, 1, 230400, 0x6b5c5b6c
-0, 7, 7, 1, 230400, 0x4bf7bbb5
-0, 8, 8, 1, 230400, 0x423eec8e
-0, 9, 9, 1, 230400, 0x63663b5e
-0, 10, 10, 1, 230400, 0x9c258a67
-0, 11, 11, 1, 230400, 0x1c92b6e0
-0, 12, 12, 1, 230400, 0xdd0a0e28
-0, 13, 13, 1, 230400, 0x51d64af1
-0, 14, 14, 1, 230400, 0x5776ac12
-0, 15, 15, 1, 230400, 0x49070132
-0, 16, 16, 1, 230400, 0xa59635ab
-0, 17, 17, 1, 230400, 0xb1f99504
-0, 18, 18, 1, 230400, 0x61fac725
-0, 19, 19, 1, 230400, 0xc32c28d5
-0, 20, 20, 1, 230400, 0x2b7a91d6
-0, 21, 21, 1, 230400, 0x917be717
-0, 22, 22, 1, 230400, 0xd3c5a2ff
-0, 23, 23, 1, 230400, 0x0678a707
-0, 24, 24, 1, 230400, 0x122504e6
-0, 25, 25, 1, 230400, 0x76aebdae
-0, 26, 26, 1, 230400, 0x81357545
-0, 27, 27, 1, 230400, 0x38baeebd
-0, 28, 28, 1, 230400, 0x1c5c44d4
-1, 61740, 61740, 2205, 4410, 0x109d04e0
-0, 29, 29, 1, 230400, 0x60e189cc
-1, 63945, 63945, 2205, 4410, 0x224d244f
-0, 30, 30, 1, 230400, 0xb1f4381c
-1, 66150, 66150, 2205, 4410, 0xbb72413d
-0, 31, 31, 1, 230400, 0xb5048fed
-1, 68355, 68355, 2205, 4410, 0xaa5f5b86
-0, 32, 32, 1, 230400, 0xc947c30e
-1, 70560, 70560, 2205, 4410, 0x94e7aea7
-0, 33, 33, 1, 230400, 0xe8e31c07
-1, 72765, 72765, 2205, 4410, 0xad497ca0
-0, 34, 34, 1, 230400, 0x6d49dd02
-1, 74970, 74970, 2205, 4410, 0x1de10c9e
-0, 35, 35, 1, 230400, 0x293e15d3
-1, 77175, 77175, 2205, 4410, 0x9f55efa8
-0, 36, 36, 1, 230400, 0x354d792e
-1, 79380, 79380, 2205, 4410, 0x220a072a
-0, 37, 37, 1, 230400, 0x35468780
-1, 81585, 81585, 2205, 4410, 0xa7dafb29
-0, 38, 38, 1, 230400, 0x365d3991
-1, 83790, 83790, 2205, 4410, 0xd5e29c7a
-0, 39, 39, 1, 230400, 0xc9debef2
-1, 85995, 85995, 2205, 4410, 0xb8465006
-0, 40, 40, 1, 230400, 0x4c4634c2
-1, 88200, 88200, 2205, 4410, 0x518669c7
-0, 41, 41, 1, 230400, 0x347c2dca
-1, 90405, 90405, 2205, 4410, 0xb5b5efca
-0, 42, 42, 1, 230400, 0x1efa0aaa
-1, 92610, 92610, 2205, 4410, 0x8600015d
-0, 43, 43, 1, 230400, 0xa79a0b5a
-1, 94815, 94815, 2205, 4410, 0xe2f68fe9
-0, 44, 44, 1, 230400, 0xfdb2dcdb
-1, 97020, 97020, 2205, 4410, 0x8d3458d9
-0, 45, 45, 1, 230400, 0x42dbea33
-1, 99225, 99225, 2205, 4410, 0xf1ff4775
-0, 46, 46, 1, 230400, 0x2a207e43
-1, 101430, 101430, 2205, 4410, 0x830f67c9
-0, 47, 47, 1, 230400, 0x86573783
-1, 103635, 103635, 2205, 4410, 0x110e0bc1
-0, 48, 48, 1, 230400, 0xc3968473
-1, 105840, 105840, 2205, 4410, 0x71682f47
-0, 49, 49, 1, 230400, 0x8f62a7b4
-1, 108045, 108045, 2205, 4410, 0x38119095
-0, 50, 50, 1, 230400, 0x5a2e3073
-1, 110250, 110250, 2205, 4410, 0xd2494db6
-0, 51, 51, 1, 230400, 0xd24f5e2c
-1, 112455, 112455, 2205, 4410, 0x8b552509
-0, 52, 52, 1, 230400, 0x1df3c67d
-1, 114660, 114660, 2205, 4410, 0x71e52909
-0, 53, 53, 1, 230400, 0xe4fd884d
-1, 116865, 116865, 2205, 4410, 0x9f0a6f4d
-1, 119070, 119070, 2205, 4410, 0x901302f2
-1, 121275, 121275, 2205, 4410, 0x855d5222
-1, 123480, 123480, 2205, 4410, 0x324bb2fe
-0, 57, 57, 1, 230400, 0x9a228555
-1, 125685, 125685, 2205, 4410, 0xe85f583f
-0, 58, 58, 1, 230400, 0x9eba8ed5
-1, 127890, 127890, 2205, 4410, 0x2cbc67c4
-0, 59, 59, 1, 230400, 0x3d808a3d
-1, 130095, 130095, 2205, 4410, 0xc82e6aa1
-0, 60, 60, 1, 230400, 0xf57e866d
-1, 132300, 132300, 2205, 4410, 0xb9fc423c
-0, 61, 61, 1, 230400, 0x85f594f5
-1, 134505, 134505, 2205, 4410, 0x6b9b4ef9
-0, 62, 62, 1, 230400, 0xb09f99dd
-1, 136710, 136710, 2205, 4410, 0x39290f10
-0, 63, 63, 1, 230400, 0x2b368475
-1, 138915, 138915, 2205, 4410, 0xad718eb4
-0, 64, 64, 1, 230400, 0xa2417afd
-1, 141120, 141120, 2205, 4410, 0x82f463ac
-0, 65, 65, 1, 230400, 0x590b709d
-1, 143325, 143325, 2205, 4410, 0xfac87cac
-0, 66, 66, 1, 230400, 0x5d617705
-1, 145530, 145530, 2205, 4410, 0x9e8bcca7
-0, 67, 67, 1, 230400, 0xabf981ad
-1, 147735, 147735, 2205, 4410, 0x52f79c99
-0, 68, 68, 1, 230400, 0x5a8590cd
-1, 149940, 149940, 2205, 4410, 0xf2d14de2
-0, 69, 69, 1, 230400, 0x1bff853d
-1, 152145, 152145, 2205, 4410, 0x367f95e1
-0, 70, 70, 1, 230400, 0x71d08055
-1, 154350, 154350, 2205, 4410, 0x8bfac293
-0, 71, 71, 1, 230400, 0x2ebd817d
-1, 156555, 156555, 2205, 4410, 0x01ea5040
-0, 72, 72, 1, 230400, 0x6e838255
-1, 158760, 158760, 2205, 4410, 0x8ff5e212
-0, 73, 73, 1, 230400, 0x043984cd
-1, 160965, 160965, 2205, 4410, 0x93f32824
-0, 74, 74, 1, 230400, 0x7ff18495
-1, 163170, 163170, 2205, 4410, 0x998f90dc
-0, 75, 75, 1, 230400, 0xa43b8385
-1, 165375, 165375, 2205, 4410, 0x65231170
-0, 76, 76, 1, 230400, 0x72b5825d
-1, 167580, 167580, 2205, 4410, 0xc79039a1
-0, 77, 77, 1, 230400, 0x3a178085
-1, 169785, 169785, 2205, 4410, 0x0b0e58bd
-0, 78, 78, 1, 230400, 0x67748245
-1, 171990, 171990, 2205, 4410, 0xc24ab4fa
-0, 79, 79, 1, 230400, 0xeddf81d5
-1, 174195, 174195, 2205, 4410, 0xd3796a8e
-0, 80, 80, 1, 230400, 0x8b088665
-1, 176400, 176400, 2205, 4410, 0xa37f8295
-0, 81, 81, 1, 230400, 0x6c408e15
-1, 178605, 178605, 2205, 4410, 0xb760fed7
-0, 82, 82, 1, 230400, 0x81f196dd
-1, 180810, 180810, 2205, 4410, 0x05495a34
-0, 83, 83, 1, 230400, 0xab9f953d
-1, 183015, 183015, 2205, 4410, 0x6f203437
-0, 84, 84, 1, 230400, 0xa5f69795
-1, 185220, 185220, 2205, 4410, 0x71299402
-0, 85, 85, 1, 230400, 0xa772950d
-1, 187425, 187425, 2205, 4410, 0x72e7b346
-0, 86, 86, 1, 230400, 0x6a5596d5
-1, 189630, 189630, 2205, 4410, 0x879b0dae
-0, 87, 87, 1, 230400, 0x1355958d
-1, 191835, 191835, 2205, 4410, 0x041aa1bd
-0, 88, 88, 1, 230400, 0x4134981d
-1, 194040, 194040, 2205, 4410, 0x18a962e6
-0, 89, 89, 1, 230400, 0x8b929515
-1, 196245, 196245, 2205, 4410, 0x21d20539
-0, 90, 90, 1, 230400, 0x482f95c5
-1, 198450, 198450, 2205, 4410, 0x8f449267
-0, 91, 91, 1, 230400, 0x7a9795d5
-1, 200655, 200655, 2205, 4410, 0xecdc01d6
-0, 92, 92, 1, 230400, 0x21c29abd
-1, 202860, 202860, 2205, 4410, 0x458abd5a
-0, 93, 93, 1, 230400, 0x9ae6a475
-1, 205065, 205065, 2205, 4410, 0xa070ea63
-0, 94, 94, 1, 230400, 0x3734aee5
-1, 207270, 207270, 2205, 4410, 0xc25b26ce
-0, 95, 95, 1, 230400, 0xa0a1b365
-1, 209475, 209475, 2205, 4410, 0x4d9237ca
-0, 96, 96, 1, 230400, 0x2dcab1c5
-1, 211680, 211680, 2205, 4410, 0x748e1801
-0, 97, 97, 1, 230400, 0x9c8b6c44
-1, 213885, 213885, 2205, 4410, 0xc96b69e6
-0, 98, 98, 1, 230400, 0x5da75feb
-1, 216090, 216090, 2205, 4410, 0x6663186c
-0, 99, 99, 1, 230400, 0x4d02f8e3
-1, 218295, 218295, 2205, 4410, 0x7f6d3081
-0, 100, 100, 1, 230400, 0x66824f3a
-1, 220500, 220500, 2205, 4410, 0x1a0343b5
-0, 101, 101, 1, 230400, 0x0c9257e2
-1, 222705, 222705, 2205, 4410, 0xc48e338c
-0, 102, 102, 1, 230400, 0xb2927092
-1, 224910, 224910, 2205, 4410, 0x26fc03c8
-0, 103, 103, 1, 230400, 0xb5dc6e9a
-1, 227115, 227115, 2205, 4410, 0x69be7e2d
-0, 104, 104, 1, 230400, 0x6e567bc6
-1, 229320, 229320, 2205, 4410, 0x69a74da1
-0, 105, 105, 1, 230400, 0xbf9e0f7a
-1, 231525, 231525, 2205, 4410, 0x85bd2ab3
-0, 106, 106, 1, 230400, 0xb16f684a
-1, 233730, 233730, 2205, 4410, 0xeff05426
-0, 107, 107, 1, 230400, 0xf9e55e81
-1, 235935, 235935, 2205, 4410, 0x292829e0
-0, 108, 108, 1, 230400, 0xd8d0bcba
-1, 238140, 238140, 2205, 4410, 0x8f741798
-0, 109, 109, 1, 230400, 0x44720ac0
-1, 240345, 240345, 2205, 4410, 0x6b9337e9
-0, 110, 110, 1, 230400, 0x7d4c2058
-1, 242550, 242550, 2205, 4410, 0xe4e1703f
-1, 244755, 244755, 2205, 4410, 0x043d6c35
-1, 246960, 246960, 2205, 4410, 0x3a8988e7
-0, 113, 113, 1, 230400, 0xb0973eb9
-1, 249165, 249165, 2205, 4410, 0x1fa7d2a9
-0, 114, 114, 1, 230400, 0x405a13ce
-1, 251370, 251370, 2205, 4410, 0xe28799e3
-0, 115, 115, 1, 230400, 0x6422f00a
-1, 253575, 253575, 2205, 4410, 0xc2df4470
-0, 116, 116, 1, 230400, 0x924b6c1e
-1, 255780, 255780, 2205, 4410, 0x694d0cf5
-1, 257985, 257985, 2205, 4410, 0x5aac2dcf
-1, 260190, 260190, 2205, 4410, 0x259fa2db
-1, 262395, 262395, 2205, 4410, 0xd16d6803
-1, 264600, 264600, 2205, 4410, 0xa4b3478a
-1, 266805, 266805, 2205, 4410, 0xdbe0443d
-1, 269010, 269010, 2205, 4410, 0x26c16119
-1, 271215, 271215, 2205, 4410, 0x0c06475c
-1, 273420, 273420, 2205, 4410, 0x6ffaba2d
-1, 275625, 275625, 2205, 4410, 0x5b287192
-1, 277830, 277830, 2205, 4410, 0xf2cf2651
-1, 280035, 280035, 2205, 4410, 0x3857673a
-1, 282240, 282240, 2205, 4410, 0x5b555feb
-1, 284445, 284445, 2205, 4410, 0x93f997af
-1, 286650, 286650, 2205, 4410, 0xb3ba8d35
-1, 288855, 288855, 2205, 4410, 0x66433944
-1, 291060, 291060, 2205, 4410, 0xf0005a5f
-1, 293265, 293265, 2205, 4410, 0xb948541f
-1, 295470, 295470, 2205, 4410, 0xc8f1b16f
-1, 297675, 297675, 2205, 4410, 0x7d4b7506
-1, 299880, 299880, 2205, 4410, 0xac723c55
-1, 302085, 302085, 2205, 4410, 0x2926fab5
-1, 304290, 304290, 2205, 4410, 0x31684995
-1, 306495, 306495, 2205, 4410, 0x35ebfca4
-1, 308700, 308700, 2205, 4410, 0x9cd42c18
-1, 310905, 310905, 2205, 4410, 0xd7ecd7b1
-1, 313110, 313110, 2205, 4410, 0x5e13c602
-1, 315315, 315315, 2205, 4410, 0xe955b5e3
-1, 317520, 317520, 2205, 4410, 0xefad19a1
-0, 145, 145, 1, 230400, 0xcf7809c0
-1, 319725, 319725, 2205, 4410, 0x435950de
-0, 146, 146, 1, 230400, 0x883a3863
-1, 321930, 321930, 2205, 4410, 0x9d624ebe
-0, 147, 147, 1, 230400, 0x6adc9e03
-1, 324135, 324135, 2205, 4410, 0x774a9158
-0, 148, 148, 1, 230400, 0x4f5ab7a8
-1, 326340, 326340, 2205, 4410, 0x8c41e66a
-1, 328545, 328545, 2205, 4410, 0x70112740
-1, 330750, 330750, 2205, 4410, 0x55abc7a2
-1, 332955, 332955, 2205, 4410, 0x0ec3183c
-1, 335160, 335160, 2205, 4410, 0x54609c56
-1, 337365, 337365, 2205, 4410, 0x60d49f92
-1, 339570, 339570, 2205, 4410, 0x5fb061c8
-1, 341775, 341775, 2205, 4410, 0x6e119c98
-1, 343980, 343980, 2205, 4410, 0x3f39fc69
-1, 346185, 346185, 2205, 4410, 0xef466d0e
-1, 348390, 348390, 2205, 4410, 0xf4cb6fe1
-1, 350595, 350595, 2205, 4410, 0xc4434439
-1, 352800, 352800, 2205, 4410, 0xd02329d2
-1, 355005, 355005, 2205, 4410, 0x216cffaf
-1, 357210, 357210, 2205, 4410, 0x7e59e8c1
-1, 359415, 359415, 2205, 4410, 0xc7c3346d
-1, 361620, 361620, 2205, 4410, 0x5b3723af
-1, 363825, 363825, 2205, 4410, 0x76097270
-1, 366030, 366030, 2205, 4410, 0xae39a233
-1, 368235, 368235, 2205, 4410, 0x686a471c
-1, 370440, 370440, 2205, 4410, 0x3af3c5e0
-1, 372645, 372645, 2205, 4410, 0x11ac711e
-1, 374850, 374850, 2205, 4410, 0xcd8da8ce
-1, 377055, 377055, 2205, 4410, 0x21296e3a
-1, 379260, 379260, 2205, 4410, 0x77168188
-1, 381465, 381465, 2205, 4410, 0x5fcf59cd
-1, 383670, 383670, 2205, 4410, 0x390c8717
-1, 385875, 385875, 2205, 4410, 0x3d5d5b3c
-1, 388080, 388080, 2205, 4410, 0x3b8f13d3
-1, 390285, 390285, 2205, 4410, 0x5b002c2f
-1, 392490, 392490, 2205, 4410, 0x9e1d2b08
-1, 394695, 394695, 2205, 4410, 0x69454ebd
-1, 396900, 396900, 2205, 4410, 0x62a54bec
-1, 399105, 399105, 2205, 4410, 0x4d231fdb
-1, 401310, 401310, 2205, 4410, 0x65624ff7
-1, 403515, 403515, 2205, 4410, 0x6fc66932
-1, 405720, 405720, 2205, 4410, 0x23200cf6
-1, 407925, 407925, 2205, 4410, 0xf8033122
-1, 410130, 410130, 2205, 4410, 0x0fce0744
-1, 412335, 412335, 2205, 4410, 0x9302683e
-1, 414540, 414540, 2205, 4410, 0xd2380245
-1, 416745, 416745, 2205, 4410, 0x482e0872
-1, 418950, 418950, 2205, 4410, 0xe98e6461
-1, 421155, 421155, 2205, 4410, 0x1db404e3
-1, 423360, 423360, 2205, 4410, 0x47a26d45
-1, 425565, 425565, 2205, 4410, 0x449a348a
-1, 427770, 427770, 2205, 4410, 0xee874f84
-1, 429975, 429975, 2205, 4410, 0xc4ecf965
-1, 432180, 432180, 2205, 4410, 0xcc450bc8
-1, 434385, 434385, 2205, 4410, 0xb18d044b
-1, 436590, 436590, 2205, 4410, 0x895435e8
-1, 438795, 438795, 2205, 4410, 0x57e7574e
-1, 441000, 441000, 2205, 4410, 0x8041ad3d
-1, 443205, 443205, 2205, 4410, 0x853d1616
-1, 445410, 445410, 2205, 4410, 0xa11bb32b
-1, 447615, 447615, 2205, 4410, 0xe10ea0de
-1, 449820, 449820, 2205, 4410, 0xdf2ee328
-1, 452025, 452025, 2205, 4410, 0xd5a6dcae
-1, 454230, 454230, 2205, 4410, 0xd176c00b
-1, 456435, 456435, 2205, 4410, 0x9cd6bcf3
-1, 458640, 458640, 2205, 4410, 0x2569690a
-1, 460845, 460845, 2205, 4410, 0x6824aa1d
-1, 463050, 463050, 2205, 4410, 0xa9110afa
-1, 465255, 465255, 2205, 4410, 0x115c25be
-1, 467460, 467460, 2205, 4410, 0x1100f085
-1, 469665, 469665, 2205, 4410, 0x00000000
-0, 214, 214, 1, 230400, 0xdc0aab94
-1, 471870, 471870, 2205, 4410, 0x00000000
-1, 474075, 474075, 2205, 4410, 0x00000000
-1, 476280, 476280, 2205, 4410, 0x00000000
-1, 478485, 478485, 2205, 4410, 0x00000000
-1, 480690, 480690, 2205, 4410, 0x00000000
-1, 482895, 482895, 2205, 4410, 0x00000000
-1, 485100, 485100, 2205, 4410, 0x00000000
-1, 487305, 487305, 2205, 4410, 0x00000000
-1, 489510, 489510, 2205, 4410, 0x00000000
-1, 491715, 491715, 2205, 4410, 0x00000000
-1, 493920, 493920, 2205, 4410, 0x00000000
-1, 496125, 496125, 2205, 4410, 0x00000000
-1, 498330, 498330, 2205, 4410, 0x00000000
-1, 500535, 500535, 2205, 4410, 0x00000000
-1, 502740, 502740, 2205, 4410, 0x00000000
-1, 504945, 504945, 2205, 4410, 0x00000000
-1, 507150, 507150, 2205, 4410, 0x00000000
-1, 509355, 509355, 2205, 4410, 0x00000000
-1, 511560, 511560, 2205, 4410, 0x00000000
-1, 513765, 513765, 2205, 4410, 0x00000000
-1, 515970, 515970, 2205, 4410, 0x00000000
-1, 518175, 518175, 2205, 4410, 0x00000000
-1, 520380, 520380, 2205, 4410, 0x00000000
-1, 522585, 522585, 2205, 4410, 0x00000000
-1, 524790, 524790, 2205, 4410, 0x00000000
-1, 526995, 526995, 2205, 4410, 0x00000000
-1, 529200, 529200, 2205, 4410, 0x00000000
-1, 531405, 531405, 2205, 4410, 0x00000000
diff --git a/tests/ref/fate/sierra-vmd-audio b/tests/ref/fate/sierra-vmd-audio
new file mode 100644
index 0000000000..13d3567e11
--- /dev/null
+++ b/tests/ref/fate/sierra-vmd-audio
@@ -0,0 +1,216 @@
+#tb 0: 1/22050
+0, 0, 0, 61740, 123480, 0x3a794c13
+0, 61740, 61740, 2205, 4410, 0x109d04e0
+0, 63945, 63945, 2205, 4410, 0x224d244f
+0, 66150, 66150, 2205, 4410, 0xbb72413d
+0, 68355, 68355, 2205, 4410, 0xaa5f5b86
+0, 70560, 70560, 2205, 4410, 0x94e7aea7
+0, 72765, 72765, 2205, 4410, 0xad497ca0
+0, 74970, 74970, 2205, 4410, 0x1de10c9e
+0, 77175, 77175, 2205, 4410, 0x9f55efa8
+0, 79380, 79380, 2205, 4410, 0x220a072a
+0, 81585, 81585, 2205, 4410, 0xa7dafb29
+0, 83790, 83790, 2205, 4410, 0xd5e29c7a
+0, 85995, 85995, 2205, 4410, 0xb8465006
+0, 88200, 88200, 2205, 4410, 0x518669c7
+0, 90405, 90405, 2205, 4410, 0xb5b5efca
+0, 92610, 92610, 2205, 4410, 0x8600015d
+0, 94815, 94815, 2205, 4410, 0xe2f68fe9
+0, 97020, 97020, 2205, 4410, 0x8d3458d9
+0, 99225, 99225, 2205, 4410, 0xf1ff4775
+0, 101430, 101430, 2205, 4410, 0x830f67c9
+0, 103635, 103635, 2205, 4410, 0x110e0bc1
+0, 105840, 105840, 2205, 4410, 0x71682f47
+0, 108045, 108045, 2205, 4410, 0x38119095
+0, 110250, 110250, 2205, 4410, 0xd2494db6
+0, 112455, 112455, 2205, 4410, 0x8b552509
+0, 114660, 114660, 2205, 4410, 0x71e52909
+0, 116865, 116865, 2205, 4410, 0x9f0a6f4d
+0, 119070, 119070, 2205, 4410, 0x901302f2
+0, 121275, 121275, 2205, 4410, 0x855d5222
+0, 123480, 123480, 2205, 4410, 0x324bb2fe
+0, 125685, 125685, 2205, 4410, 0xe85f583f
+0, 127890, 127890, 2205, 4410, 0x2cbc67c4
+0, 130095, 130095, 2205, 4410, 0xc82e6aa1
+0, 132300, 132300, 2205, 4410, 0xb9fc423c
+0, 134505, 134505, 2205, 4410, 0x6b9b4ef9
+0, 136710, 136710, 2205, 4410, 0x39290f10
+0, 138915, 138915, 2205, 4410, 0xad718eb4
+0, 141120, 141120, 2205, 4410, 0x82f463ac
+0, 143325, 143325, 2205, 4410, 0xfac87cac
+0, 145530, 145530, 2205, 4410, 0x9e8bcca7
+0, 147735, 147735, 2205, 4410, 0x52f79c99
+0, 149940, 149940, 2205, 4410, 0xf2d14de2
+0, 152145, 152145, 2205, 4410, 0x367f95e1
+0, 154350, 154350, 2205, 4410, 0x8bfac293
+0, 156555, 156555, 2205, 4410, 0x01ea5040
+0, 158760, 158760, 2205, 4410, 0x8ff5e212
+0, 160965, 160965, 2205, 4410, 0x93f32824
+0, 163170, 163170, 2205, 4410, 0x998f90dc
+0, 165375, 165375, 2205, 4410, 0x65231170
+0, 167580, 167580, 2205, 4410, 0xc79039a1
+0, 169785, 169785, 2205, 4410, 0x0b0e58bd
+0, 171990, 171990, 2205, 4410, 0xc24ab4fa
+0, 174195, 174195, 2205, 4410, 0xd3796a8e
+0, 176400, 176400, 2205, 4410, 0xa37f8295
+0, 178605, 178605, 2205, 4410, 0xb760fed7
+0, 180810, 180810, 2205, 4410, 0x05495a34
+0, 183015, 183015, 2205, 4410, 0x6f203437
+0, 185220, 185220, 2205, 4410, 0x71299402
+0, 187425, 187425, 2205, 4410, 0x72e7b346
+0, 189630, 189630, 2205, 4410, 0x879b0dae
+0, 191835, 191835, 2205, 4410, 0x041aa1bd
+0, 194040, 194040, 2205, 4410, 0x18a962e6
+0, 196245, 196245, 2205, 4410, 0x21d20539
+0, 198450, 198450, 2205, 4410, 0x8f449267
+0, 200655, 200655, 2205, 4410, 0xecdc01d6
+0, 202860, 202860, 2205, 4410, 0x458abd5a
+0, 205065, 205065, 2205, 4410, 0xa070ea63
+0, 207270, 207270, 2205, 4410, 0xc25b26ce
+0, 209475, 209475, 2205, 4410, 0x4d9237ca
+0, 211680, 211680, 2205, 4410, 0x748e1801
+0, 213885, 213885, 2205, 4410, 0xc96b69e6
+0, 216090, 216090, 2205, 4410, 0x6663186c
+0, 218295, 218295, 2205, 4410, 0x7f6d3081
+0, 220500, 220500, 2205, 4410, 0x1a0343b5
+0, 222705, 222705, 2205, 4410, 0xc48e338c
+0, 224910, 224910, 2205, 4410, 0x26fc03c8
+0, 227115, 227115, 2205, 4410, 0x69be7e2d
+0, 229320, 229320, 2205, 4410, 0x69a74da1
+0, 231525, 231525, 2205, 4410, 0x85bd2ab3
+0, 233730, 233730, 2205, 4410, 0xeff05426
+0, 235935, 235935, 2205, 4410, 0x292829e0
+0, 238140, 238140, 2205, 4410, 0x8f741798
+0, 240345, 240345, 2205, 4410, 0x6b9337e9
+0, 242550, 242550, 2205, 4410, 0xe4e1703f
+0, 244755, 244755, 2205, 4410, 0x043d6c35
+0, 246960, 246960, 2205, 4410, 0x3a8988e7
+0, 249165, 249165, 2205, 4410, 0x1fa7d2a9
+0, 251370, 251370, 2205, 4410, 0xe28799e3
+0, 253575, 253575, 2205, 4410, 0xc2df4470
+0, 255780, 255780, 2205, 4410, 0x694d0cf5
+0, 257985, 257985, 2205, 4410, 0x5aac2dcf
+0, 260190, 260190, 2205, 4410, 0x259fa2db
+0, 262395, 262395, 2205, 4410, 0xd16d6803
+0, 264600, 264600, 2205, 4410, 0xa4b3478a
+0, 266805, 266805, 2205, 4410, 0xdbe0443d
+0, 269010, 269010, 2205, 4410, 0x26c16119
+0, 271215, 271215, 2205, 4410, 0x0c06475c
+0, 273420, 273420, 2205, 4410, 0x6ffaba2d
+0, 275625, 275625, 2205, 4410, 0x5b287192
+0, 277830, 277830, 2205, 4410, 0xf2cf2651
+0, 280035, 280035, 2205, 4410, 0x3857673a
+0, 282240, 282240, 2205, 4410, 0x5b555feb
+0, 284445, 284445, 2205, 4410, 0x93f997af
+0, 286650, 286650, 2205, 4410, 0xb3ba8d35
+0, 288855, 288855, 2205, 4410, 0x66433944
+0, 291060, 291060, 2205, 4410, 0xf0005a5f
+0, 293265, 293265, 2205, 4410, 0xb948541f
+0, 295470, 295470, 2205, 4410, 0xc8f1b16f
+0, 297675, 297675, 2205, 4410, 0x7d4b7506
+0, 299880, 299880, 2205, 4410, 0xac723c55
+0, 302085, 302085, 2205, 4410, 0x2926fab5
+0, 304290, 304290, 2205, 4410, 0x31684995
+0, 306495, 306495, 2205, 4410, 0x35ebfca4
+0, 308700, 308700, 2205, 4410, 0x9cd42c18
+0, 310905, 310905, 2205, 4410, 0xd7ecd7b1
+0, 313110, 313110, 2205, 4410, 0x5e13c602
+0, 315315, 315315, 2205, 4410, 0xe955b5e3
+0, 317520, 317520, 2205, 4410, 0xefad19a1
+0, 319725, 319725, 2205, 4410, 0x435950de
+0, 321930, 321930, 2205, 4410, 0x9d624ebe
+0, 324135, 324135, 2205, 4410, 0x774a9158
+0, 326340, 326340, 2205, 4410, 0x8c41e66a
+0, 328545, 328545, 2205, 4410, 0x70112740
+0, 330750, 330750, 2205, 4410, 0x55abc7a2
+0, 332955, 332955, 2205, 4410, 0x0ec3183c
+0, 335160, 335160, 2205, 4410, 0x54609c56
+0, 337365, 337365, 2205, 4410, 0x60d49f92
+0, 339570, 339570, 2205, 4410, 0x5fb061c8
+0, 341775, 341775, 2205, 4410, 0x6e119c98
+0, 343980, 343980, 2205, 4410, 0x3f39fc69
+0, 346185, 346185, 2205, 4410, 0xef466d0e
+0, 348390, 348390, 2205, 4410, 0xf4cb6fe1
+0, 350595, 350595, 2205, 4410, 0xc4434439
+0, 352800, 352800, 2205, 4410, 0xd02329d2
+0, 355005, 355005, 2205, 4410, 0x216cffaf
+0, 357210, 357210, 2205, 4410, 0x7e59e8c1
+0, 359415, 359415, 2205, 4410, 0xc7c3346d
+0, 361620, 361620, 2205, 4410, 0x5b3723af
+0, 363825, 363825, 2205, 4410, 0x76097270
+0, 366030, 366030, 2205, 4410, 0xae39a233
+0, 368235, 368235, 2205, 4410, 0x686a471c
+0, 370440, 370440, 2205, 4410, 0x3af3c5e0
+0, 372645, 372645, 2205, 4410, 0x11ac711e
+0, 374850, 374850, 2205, 4410, 0xcd8da8ce
+0, 377055, 377055, 2205, 4410, 0x21296e3a
+0, 379260, 379260, 2205, 4410, 0x77168188
+0, 381465, 381465, 2205, 4410, 0x5fcf59cd
+0, 383670, 383670, 2205, 4410, 0x390c8717
+0, 385875, 385875, 2205, 4410, 0x3d5d5b3c
+0, 388080, 388080, 2205, 4410, 0x3b8f13d3
+0, 390285, 390285, 2205, 4410, 0x5b002c2f
+0, 392490, 392490, 2205, 4410, 0x9e1d2b08
+0, 394695, 394695, 2205, 4410, 0x69454ebd
+0, 396900, 396900, 2205, 4410, 0x62a54bec
+0, 399105, 399105, 2205, 4410, 0x4d231fdb
+0, 401310, 401310, 2205, 4410, 0x65624ff7
+0, 403515, 403515, 2205, 4410, 0x6fc66932
+0, 405720, 405720, 2205, 4410, 0x23200cf6
+0, 407925, 407925, 2205, 4410, 0xf8033122
+0, 410130, 410130, 2205, 4410, 0x0fce0744
+0, 412335, 412335, 2205, 4410, 0x9302683e
+0, 414540, 414540, 2205, 4410, 0xd2380245
+0, 416745, 416745, 2205, 4410, 0x482e0872
+0, 418950, 418950, 2205, 4410, 0xe98e6461
+0, 421155, 421155, 2205, 4410, 0x1db404e3
+0, 423360, 423360, 2205, 4410, 0x47a26d45
+0, 425565, 425565, 2205, 4410, 0x449a348a
+0, 427770, 427770, 2205, 4410, 0xee874f84
+0, 429975, 429975, 2205, 4410, 0xc4ecf965
+0, 432180, 432180, 2205, 4410, 0xcc450bc8
+0, 434385, 434385, 2205, 4410, 0xb18d044b
+0, 436590, 436590, 2205, 4410, 0x895435e8
+0, 438795, 438795, 2205, 4410, 0x57e7574e
+0, 441000, 441000, 2205, 4410, 0x8041ad3d
+0, 443205, 443205, 2205, 4410, 0x853d1616
+0, 445410, 445410, 2205, 4410, 0xa11bb32b
+0, 447615, 447615, 2205, 4410, 0xe10ea0de
+0, 449820, 449820, 2205, 4410, 0xdf2ee328
+0, 452025, 452025, 2205, 4410, 0xd5a6dcae
+0, 454230, 454230, 2205, 4410, 0xd176c00b
+0, 456435, 456435, 2205, 4410, 0x9cd6bcf3
+0, 458640, 458640, 2205, 4410, 0x2569690a
+0, 460845, 460845, 2205, 4410, 0x6824aa1d
+0, 463050, 463050, 2205, 4410, 0xa9110afa
+0, 465255, 465255, 2205, 4410, 0x115c25be
+0, 467460, 467460, 2205, 4410, 0x1100f085
+0, 469665, 469665, 2205, 4410, 0x00000000
+0, 471870, 471870, 2205, 4410, 0x00000000
+0, 474075, 474075, 2205, 4410, 0x00000000
+0, 476280, 476280, 2205, 4410, 0x00000000
+0, 478485, 478485, 2205, 4410, 0x00000000
+0, 480690, 480690, 2205, 4410, 0x00000000
+0, 482895, 482895, 2205, 4410, 0x00000000
+0, 485100, 485100, 2205, 4410, 0x00000000
+0, 487305, 487305, 2205, 4410, 0x00000000
+0, 489510, 489510, 2205, 4410, 0x00000000
+0, 491715, 491715, 2205, 4410, 0x00000000
+0, 493920, 493920, 2205, 4410, 0x00000000
+0, 496125, 496125, 2205, 4410, 0x00000000
+0, 498330, 498330, 2205, 4410, 0x00000000
+0, 500535, 500535, 2205, 4410, 0x00000000
+0, 502740, 502740, 2205, 4410, 0x00000000
+0, 504945, 504945, 2205, 4410, 0x00000000
+0, 507150, 507150, 2205, 4410, 0x00000000
+0, 509355, 509355, 2205, 4410, 0x00000000
+0, 511560, 511560, 2205, 4410, 0x00000000
+0, 513765, 513765, 2205, 4410, 0x00000000
+0, 515970, 515970, 2205, 4410, 0x00000000
+0, 518175, 518175, 2205, 4410, 0x00000000
+0, 520380, 520380, 2205, 4410, 0x00000000
+0, 522585, 522585, 2205, 4410, 0x00000000
+0, 524790, 524790, 2205, 4410, 0x00000000
+0, 526995, 526995, 2205, 4410, 0x00000000
+0, 529200, 529200, 2205, 4410, 0x00000000
+0, 531405, 531405, 2205, 4410, 0x00000000
diff --git a/tests/ref/fate/sierra-vmd-video b/tests/ref/fate/sierra-vmd-video
new file mode 100644
index 0000000000..5b9dde1b32
--- /dev/null
+++ b/tests/ref/fate/sierra-vmd-video
@@ -0,0 +1,118 @@
+#tb 0: 1/10
+0, 0, 0, 1, 230400, 0x0224ab01
+0, 1, 1, 1, 230400, 0x449e4d81
+0, 2, 2, 1, 230400, 0x3e15e07a
+0, 3, 3, 1, 230400, 0xdabe4172
+0, 4, 4, 1, 230400, 0x0947b7db
+0, 5, 5, 1, 230400, 0x934e243b
+0, 6, 6, 1, 230400, 0x6b5c5b6c
+0, 7, 7, 1, 230400, 0x4bf7bbb5
+0, 8, 8, 1, 230400, 0x423eec8e
+0, 9, 9, 1, 230400, 0x63663b5e
+0, 10, 10, 1, 230400, 0x9c258a67
+0, 11, 11, 1, 230400, 0x1c92b6e0
+0, 12, 12, 1, 230400, 0xdd0a0e28
+0, 13, 13, 1, 230400, 0x51d64af1
+0, 14, 14, 1, 230400, 0x5776ac12
+0, 15, 15, 1, 230400, 0x49070132
+0, 16, 16, 1, 230400, 0xa59635ab
+0, 17, 17, 1, 230400, 0xb1f99504
+0, 18, 18, 1, 230400, 0x61fac725
+0, 19, 19, 1, 230400, 0xc32c28d5
+0, 20, 20, 1, 230400, 0x2b7a91d6
+0, 21, 21, 1, 230400, 0x917be717
+0, 22, 22, 1, 230400, 0xd3c5a2ff
+0, 23, 23, 1, 230400, 0x0678a707
+0, 24, 24, 1, 230400, 0x122504e6
+0, 25, 25, 1, 230400, 0x76aebdae
+0, 26, 26, 1, 230400, 0x81357545
+0, 27, 27, 1, 230400, 0x38baeebd
+0, 28, 28, 1, 230400, 0x1c5c44d4
+0, 29, 29, 1, 230400, 0x60e189cc
+0, 30, 30, 1, 230400, 0xb1f4381c
+0, 31, 31, 1, 230400, 0xb5048fed
+0, 32, 32, 1, 230400, 0xc947c30e
+0, 33, 33, 1, 230400, 0xe8e31c07
+0, 34, 34, 1, 230400, 0x6d49dd02
+0, 35, 35, 1, 230400, 0x293e15d3
+0, 36, 36, 1, 230400, 0x354d792e
+0, 37, 37, 1, 230400, 0x35468780
+0, 38, 38, 1, 230400, 0x365d3991
+0, 39, 39, 1, 230400, 0xc9debef2
+0, 40, 40, 1, 230400, 0x4c4634c2
+0, 41, 41, 1, 230400, 0x347c2dca
+0, 42, 42, 1, 230400, 0x1efa0aaa
+0, 43, 43, 1, 230400, 0xa79a0b5a
+0, 44, 44, 1, 230400, 0xfdb2dcdb
+0, 45, 45, 1, 230400, 0x42dbea33
+0, 46, 46, 1, 230400, 0x2a207e43
+0, 47, 47, 1, 230400, 0x86573783
+0, 48, 48, 1, 230400, 0xc3968473
+0, 49, 49, 1, 230400, 0x8f62a7b4
+0, 50, 50, 1, 230400, 0x5a2e3073
+0, 51, 51, 1, 230400, 0xd24f5e2c
+0, 52, 52, 1, 230400, 0x1df3c67d
+0, 53, 53, 1, 230400, 0xe4fd884d
+0, 57, 57, 1, 230400, 0x9a228555
+0, 58, 58, 1, 230400, 0x9eba8ed5
+0, 59, 59, 1, 230400, 0x3d808a3d
+0, 60, 60, 1, 230400, 0xf57e866d
+0, 61, 61, 1, 230400, 0x85f594f5
+0, 62, 62, 1, 230400, 0xb09f99dd
+0, 63, 63, 1, 230400, 0x2b368475
+0, 64, 64, 1, 230400, 0xa2417afd
+0, 65, 65, 1, 230400, 0x590b709d
+0, 66, 66, 1, 230400, 0x5d617705
+0, 67, 67, 1, 230400, 0xabf981ad
+0, 68, 68, 1, 230400, 0x5a8590cd
+0, 69, 69, 1, 230400, 0x1bff853d
+0, 70, 70, 1, 230400, 0x71d08055
+0, 71, 71, 1, 230400, 0x2ebd817d
+0, 72, 72, 1, 230400, 0x6e838255
+0, 73, 73, 1, 230400, 0x043984cd
+0, 74, 74, 1, 230400, 0x7ff18495
+0, 75, 75, 1, 230400, 0xa43b8385
+0, 76, 76, 1, 230400, 0x72b5825d
+0, 77, 77, 1, 230400, 0x3a178085
+0, 78, 78, 1, 230400, 0x67748245
+0, 79, 79, 1, 230400, 0xeddf81d5
+0, 80, 80, 1, 230400, 0x8b088665
+0, 81, 81, 1, 230400, 0x6c408e15
+0, 82, 82, 1, 230400, 0x81f196dd
+0, 83, 83, 1, 230400, 0xab9f953d
+0, 84, 84, 1, 230400, 0xa5f69795
+0, 85, 85, 1, 230400, 0xa772950d
+0, 86, 86, 1, 230400, 0x6a5596d5
+0, 87, 87, 1, 230400, 0x1355958d
+0, 88, 88, 1, 230400, 0x4134981d
+0, 89, 89, 1, 230400, 0x8b929515
+0, 90, 90, 1, 230400, 0x482f95c5
+0, 91, 91, 1, 230400, 0x7a9795d5
+0, 92, 92, 1, 230400, 0x21c29abd
+0, 93, 93, 1, 230400, 0x9ae6a475
+0, 94, 94, 1, 230400, 0x3734aee5
+0, 95, 95, 1, 230400, 0xa0a1b365
+0, 96, 96, 1, 230400, 0x2dcab1c5
+0, 97, 97, 1, 230400, 0x9c8b6c44
+0, 98, 98, 1, 230400, 0x5da75feb
+0, 99, 99, 1, 230400, 0x4d02f8e3
+0, 100, 100, 1, 230400, 0x66824f3a
+0, 101, 101, 1, 230400, 0x0c9257e2
+0, 102, 102, 1, 230400, 0xb2927092
+0, 103, 103, 1, 230400, 0xb5dc6e9a
+0, 104, 104, 1, 230400, 0x6e567bc6
+0, 105, 105, 1, 230400, 0xbf9e0f7a
+0, 106, 106, 1, 230400, 0xb16f684a
+0, 107, 107, 1, 230400, 0xf9e55e81
+0, 108, 108, 1, 230400, 0xd8d0bcba
+0, 109, 109, 1, 230400, 0x44720ac0
+0, 110, 110, 1, 230400, 0x7d4c2058
+0, 113, 113, 1, 230400, 0xb0973eb9
+0, 114, 114, 1, 230400, 0x405a13ce
+0, 115, 115, 1, 230400, 0x6422f00a
+0, 116, 116, 1, 230400, 0x924b6c1e
+0, 145, 145, 1, 230400, 0xcf7809c0
+0, 146, 146, 1, 230400, 0x883a3863
+0, 147, 147, 1, 230400, 0x6adc9e03
+0, 148, 148, 1, 230400, 0x4f5ab7a8
+0, 214, 214, 1, 230400, 0xdc0aab94
diff --git a/tests/ref/fate/smacker-audio b/tests/ref/fate/smacker-audio
new file mode 100644
index 0000000000..442f479dd8
--- /dev/null
+++ b/tests/ref/fate/smacker-audio
@@ -0,0 +1,87 @@
+#tb 0: 1/22050
+0, 0, 0, 23620, 47240, 0x9974897c
+0, 23620, 23620, 1564, 3128, 0x7e4064b4
+0, 25184, 25184, 1564, 3128, 0x80883301
+0, 26748, 26748, 1568, 3136, 0x2ad2d341
+0, 28316, 28316, 1564, 3128, 0xda8468e3
+0, 29880, 29880, 1568, 3136, 0x9d6f6cdf
+0, 31448, 31448, 1564, 3128, 0x1aaa64b5
+0, 33012, 33012, 1564, 3128, 0x9182728b
+0, 34576, 34576, 1568, 3136, 0xfa8e17b3
+0, 36144, 36144, 1564, 3128, 0x0dc3c1cf
+0, 37708, 37708, 1568, 3136, 0x0109639d
+0, 39276, 39276, 1564, 3128, 0x6d8a12d9
+0, 40840, 40840, 1564, 3128, 0x4b9a9597
+0, 42404, 42404, 1568, 3136, 0x9112710e
+0, 43972, 43972, 1564, 3128, 0x8cccf522
+0, 45536, 45536, 1564, 3128, 0x6594bbf3
+0, 47100, 47100, 1568, 3136, 0xd878a7d5
+0, 48668, 48668, 1564, 3128, 0xaa6e3905
+0, 50232, 50232, 1568, 3136, 0x2a062e04
+0, 51800, 51800, 1564, 3128, 0x84e4006a
+0, 53364, 53364, 1564, 3128, 0x85183633
+0, 54928, 54928, 1568, 3136, 0xb62d4b02
+0, 56496, 56496, 1564, 3128, 0xe209462a
+0, 58060, 58060, 1568, 3136, 0x57c4824b
+0, 59628, 59628, 1564, 3128, 0x664a9163
+0, 61192, 61192, 1564, 3128, 0xb4287874
+0, 62756, 62756, 1568, 3136, 0xde626885
+0, 64324, 64324, 1564, 3128, 0x919763c2
+0, 65888, 65888, 1564, 3128, 0xa4f664e1
+0, 67452, 67452, 1568, 3136, 0xa0bab0d4
+0, 69020, 69020, 1564, 3128, 0xe938939c
+0, 70584, 70584, 1568, 3136, 0x3679bfc7
+0, 72152, 72152, 1564, 3128, 0xc96c55c3
+0, 73716, 73716, 1564, 3128, 0x119114d6
+0, 75280, 75280, 1568, 3136, 0x42f3800f
+0, 76848, 76848, 1564, 3128, 0x4250c4ad
+0, 78412, 78412, 1568, 3136, 0x5cdd4925
+0, 79980, 79980, 1564, 3128, 0xa4c12360
+0, 81544, 81544, 1564, 3128, 0x849f48de
+0, 83108, 83108, 1568, 3136, 0x6acd8ff9
+0, 84676, 84676, 1564, 3128, 0xb2758556
+0, 86240, 86240, 1564, 3128, 0x10f2fcb1
+0, 87804, 87804, 1568, 3136, 0xf0f02b23
+0, 89372, 89372, 1564, 3128, 0x64f759c6
+0, 90936, 90936, 1568, 3136, 0x7ec075e3
+0, 92504, 92504, 1564, 3128, 0xf981d51e
+0, 94068, 94068, 1564, 3128, 0xc622e8b9
+0, 95632, 95632, 1568, 3136, 0xf632e2f8
+0, 97200, 97200, 1564, 3128, 0xda561864
+0, 98764, 98764, 1568, 3136, 0x14d2e888
+0, 100332, 100332, 1564, 3128, 0x015bb869
+0, 101896, 101896, 1564, 3128, 0xedb1fb62
+0, 103460, 103460, 1568, 3136, 0xe0560c41
+0, 105028, 105028, 1564, 3128, 0x14773c9a
+0, 106592, 106592, 1568, 3136, 0x850f1c82
+0, 108160, 108160, 1564, 3128, 0xb0bd5347
+0, 109724, 109724, 1564, 3128, 0x8f82edbf
+0, 111288, 111288, 1568, 3136, 0x493abee2
+0, 112856, 112856, 1564, 3128, 0xf5daff3f
+0, 114420, 114420, 1564, 3128, 0x78ad2690
+0, 115984, 115984, 1568, 3136, 0x490ebafc
+0, 117552, 117552, 1564, 3128, 0x70333fd2
+0, 119116, 119116, 1568, 3136, 0x8cb1c350
+0, 120684, 120684, 1564, 3128, 0x8bd057cb
+0, 122248, 122248, 1564, 3128, 0x161b3dbc
+0, 123812, 123812, 1568, 3136, 0xb47fb88a
+0, 125380, 125380, 1564, 3128, 0x474b381e
+0, 126944, 126944, 1568, 3136, 0x07c519bb
+0, 128512, 128512, 1564, 3128, 0x15b916c8
+0, 130076, 130076, 1564, 3128, 0x0ed7f6fb
+0, 131640, 131640, 1568, 3136, 0x54d6397b
+0, 133208, 133208, 1564, 3128, 0x437242bb
+0, 134772, 134772, 1564, 3128, 0x38f05c4d
+0, 136336, 136336, 1568, 3136, 0x5d000e59
+0, 137904, 137904, 1564, 3128, 0xdeab2d04
+0, 139468, 139468, 1568, 3136, 0x77de6880
+0, 141036, 141036, 1564, 3128, 0xbc87ef25
+0, 142600, 142600, 1564, 3128, 0xc1638ade
+0, 144164, 144164, 1568, 3136, 0xcfb64a5f
+0, 145732, 145732, 1564, 3128, 0x90b1b826
+0, 147296, 147296, 1568, 3136, 0x00000000
+0, 148864, 148864, 1564, 3128, 0x00000000
+0, 150428, 150428, 1564, 3128, 0x00000000
+0, 151992, 151992, 1568, 3136, 0x00000000
+0, 153560, 153560, 1564, 3128, 0x00000000
+0, 155124, 155124, 1428, 2856, 0x00000000
diff --git a/tests/ref/fate/smacker b/tests/ref/fate/smacker-video
index b8d4d22d01..8bd307159f 100644
--- a/tests/ref/fate/smacker
+++ b/tests/ref/fate/smacker-video
@@ -1,7 +1,5 @@
#tb 0: 71/1000
-#tb 1: 1/22050
0, 0, 0, 1, 192000, 0x8926d7fc
-1, 0, 0, 23620, 47240, 0x9974897c
0, 1, 1, 1, 192000, 0x2506d384
0, 2, 2, 1, 192000, 0x9a8dc93a
0, 3, 3, 1, 192000, 0x4badb7f2
@@ -17,172 +15,87 @@
0, 13, 13, 1, 192000, 0x1a3d7971
0, 14, 14, 1, 192000, 0xa1a65bd5
0, 15, 15, 1, 192000, 0x344957b9
-1, 23620, 23620, 1564, 3128, 0x7e4064b4
0, 16, 16, 1, 192000, 0xe23b5f4e
-1, 25184, 25184, 1564, 3128, 0x80883301
0, 17, 17, 1, 192000, 0xb5c2710b
-1, 26748, 26748, 1568, 3136, 0x2ad2d341
0, 18, 18, 1, 192000, 0x7a25938f
-1, 28316, 28316, 1564, 3128, 0xda8468e3
0, 19, 19, 1, 192000, 0x0a84e4c9
-1, 29880, 29880, 1568, 3136, 0x9d6f6cdf
0, 20, 20, 1, 192000, 0x94209b0d
-1, 31448, 31448, 1564, 3128, 0x1aaa64b5
0, 21, 21, 1, 192000, 0xf940e51f
-1, 33012, 33012, 1564, 3128, 0x9182728b
0, 22, 22, 1, 192000, 0xb9fdec42
-1, 34576, 34576, 1568, 3136, 0xfa8e17b3
0, 23, 23, 1, 192000, 0x7b04a376
-1, 36144, 36144, 1564, 3128, 0x0dc3c1cf
0, 24, 24, 1, 192000, 0x5fe0026b
-1, 37708, 37708, 1568, 3136, 0x0109639d
0, 25, 25, 1, 192000, 0x775aca39
-1, 39276, 39276, 1564, 3128, 0x6d8a12d9
0, 26, 26, 1, 192000, 0xae14fb32
-1, 40840, 40840, 1564, 3128, 0x4b9a9597
0, 27, 27, 1, 192000, 0x661106e5
-1, 42404, 42404, 1568, 3136, 0x9112710e
0, 28, 28, 1, 192000, 0xe8658dbf
-1, 43972, 43972, 1564, 3128, 0x8cccf522
0, 29, 29, 1, 192000, 0x5359f0f9
-1, 45536, 45536, 1564, 3128, 0x6594bbf3
0, 30, 30, 1, 192000, 0xc1ec80f4
-1, 47100, 47100, 1568, 3136, 0xd878a7d5
0, 31, 31, 1, 192000, 0xca53806b
-1, 48668, 48668, 1564, 3128, 0xaa6e3905
0, 32, 32, 1, 192000, 0xf0766b2e
-1, 50232, 50232, 1568, 3136, 0x2a062e04
0, 33, 33, 1, 192000, 0x39962da8
-1, 51800, 51800, 1564, 3128, 0x84e4006a
0, 34, 34, 1, 192000, 0x4171c37f
-1, 53364, 53364, 1564, 3128, 0x85183633
0, 35, 35, 1, 192000, 0x3abf3b46
-1, 54928, 54928, 1568, 3136, 0xb62d4b02
0, 36, 36, 1, 192000, 0xecc68313
-1, 56496, 56496, 1564, 3128, 0xe209462a
0, 37, 37, 1, 192000, 0xea339baf
-1, 58060, 58060, 1568, 3136, 0x57c4824b
0, 38, 38, 1, 192000, 0x616b8f16
-1, 59628, 59628, 1564, 3128, 0x664a9163
0, 39, 39, 1, 192000, 0xf77a8581
-1, 61192, 61192, 1564, 3128, 0xb4287874
0, 40, 40, 1, 192000, 0xb315678b
-1, 62756, 62756, 1568, 3136, 0xde626885
0, 41, 41, 1, 192000, 0x0a4a5218
-1, 64324, 64324, 1564, 3128, 0x919763c2
0, 42, 42, 1, 192000, 0x98802be4
-1, 65888, 65888, 1564, 3128, 0xa4f664e1
0, 43, 43, 1, 192000, 0xa2f0fd94
-1, 67452, 67452, 1568, 3136, 0xa0bab0d4
0, 44, 44, 1, 192000, 0x6671c84f
-1, 69020, 69020, 1564, 3128, 0xe938939c
0, 45, 45, 1, 192000, 0x38327e31
-1, 70584, 70584, 1568, 3136, 0x3679bfc7
0, 46, 46, 1, 192000, 0xb85d3e08
-1, 72152, 72152, 1564, 3128, 0xc96c55c3
0, 47, 47, 1, 192000, 0xdc69eba9
-1, 73716, 73716, 1564, 3128, 0x119114d6
0, 48, 48, 1, 192000, 0x8955a0b3
-1, 75280, 75280, 1568, 3136, 0x42f3800f
0, 49, 49, 1, 192000, 0x714a548b
-1, 76848, 76848, 1564, 3128, 0x4250c4ad
0, 50, 50, 1, 192000, 0xc0471de9
-1, 78412, 78412, 1568, 3136, 0x5cdd4925
0, 51, 51, 1, 192000, 0x2e16e039
-1, 79980, 79980, 1564, 3128, 0xa4c12360
0, 52, 52, 1, 192000, 0x9fa4b033
-1, 81544, 81544, 1564, 3128, 0x849f48de
0, 53, 53, 1, 192000, 0x4a0f9402
-1, 83108, 83108, 1568, 3136, 0x6acd8ff9
0, 54, 54, 1, 192000, 0x1f3e6843
-1, 84676, 84676, 1564, 3128, 0xb2758556
0, 55, 55, 1, 192000, 0x31774850
-1, 86240, 86240, 1564, 3128, 0x10f2fcb1
0, 56, 56, 1, 192000, 0x9d5336a2
-1, 87804, 87804, 1568, 3136, 0xf0f02b23
0, 57, 57, 1, 192000, 0xf7de27a2
-1, 89372, 89372, 1564, 3128, 0x64f759c6
0, 58, 58, 1, 192000, 0x98c717ce
-1, 90936, 90936, 1568, 3136, 0x7ec075e3
0, 59, 59, 1, 192000, 0x615b10b8
-1, 92504, 92504, 1564, 3128, 0xf981d51e
0, 60, 60, 1, 192000, 0xd5bc0e7e
-1, 94068, 94068, 1564, 3128, 0xc622e8b9
0, 61, 61, 1, 192000, 0xd5bc0e7e
-1, 95632, 95632, 1568, 3136, 0xf632e2f8
0, 62, 62, 1, 192000, 0xd5bc0e7e
-1, 97200, 97200, 1564, 3128, 0xda561864
0, 63, 63, 1, 192000, 0xd5bc0e7e
-1, 98764, 98764, 1568, 3136, 0x14d2e888
0, 64, 64, 1, 192000, 0xd5bc0e7e
-1, 100332, 100332, 1564, 3128, 0x015bb869
0, 65, 65, 1, 192000, 0xd5bc0e7e
-1, 101896, 101896, 1564, 3128, 0xedb1fb62
0, 66, 66, 1, 192000, 0xd5bc0e7e
-1, 103460, 103460, 1568, 3136, 0xe0560c41
0, 67, 67, 1, 192000, 0xd5bc0e7e
-1, 105028, 105028, 1564, 3128, 0x14773c9a
0, 68, 68, 1, 192000, 0xd5bc0e7e
-1, 106592, 106592, 1568, 3136, 0x850f1c82
0, 69, 69, 1, 192000, 0xd5bc0e7e
-1, 108160, 108160, 1564, 3128, 0xb0bd5347
0, 70, 70, 1, 192000, 0xd5bc0e7e
-1, 109724, 109724, 1564, 3128, 0x8f82edbf
0, 71, 71, 1, 192000, 0xd5bc0e7e
-1, 111288, 111288, 1568, 3136, 0x493abee2
0, 72, 72, 1, 192000, 0xd5bc0e7e
-1, 112856, 112856, 1564, 3128, 0xf5daff3f
0, 73, 73, 1, 192000, 0xd5bc0e7e
-1, 114420, 114420, 1564, 3128, 0x78ad2690
0, 74, 74, 1, 192000, 0xd5bc0e7e
-1, 115984, 115984, 1568, 3136, 0x490ebafc
0, 75, 75, 1, 192000, 0xd5bc0e7e
-1, 117552, 117552, 1564, 3128, 0x70333fd2
0, 76, 76, 1, 192000, 0xd5bc0e7e
-1, 119116, 119116, 1568, 3136, 0x8cb1c350
0, 77, 77, 1, 192000, 0xd5bc0e7e
-1, 120684, 120684, 1564, 3128, 0x8bd057cb
0, 78, 78, 1, 192000, 0xd5bc0e7e
-1, 122248, 122248, 1564, 3128, 0x161b3dbc
0, 79, 79, 1, 192000, 0xd5bc0e7e
-1, 123812, 123812, 1568, 3136, 0xb47fb88a
0, 80, 80, 1, 192000, 0xd5bc0e7e
-1, 125380, 125380, 1564, 3128, 0x474b381e
0, 81, 81, 1, 192000, 0xd5bc0e7e
-1, 126944, 126944, 1568, 3136, 0x07c519bb
0, 82, 82, 1, 192000, 0xd5bc0e7e
-1, 128512, 128512, 1564, 3128, 0x15b916c8
0, 83, 83, 1, 192000, 0xd5bc0e7e
-1, 130076, 130076, 1564, 3128, 0x0ed7f6fb
0, 84, 84, 1, 192000, 0xd5bc0e7e
-1, 131640, 131640, 1568, 3136, 0x54d6397b
0, 85, 85, 1, 192000, 0xd5bc0e7e
-1, 133208, 133208, 1564, 3128, 0x437242bb
0, 86, 86, 1, 192000, 0xd5bc0e7e
-1, 134772, 134772, 1564, 3128, 0x38f05c4d
0, 87, 87, 1, 192000, 0xd5bc0e7e
-1, 136336, 136336, 1568, 3136, 0x5d000e59
0, 88, 88, 1, 192000, 0xd5bc0e7e
-1, 137904, 137904, 1564, 3128, 0xdeab2d04
0, 89, 89, 1, 192000, 0xd5bc0e7e
-1, 139468, 139468, 1568, 3136, 0x77de6880
0, 90, 90, 1, 192000, 0xd5bc0e7e
-1, 141036, 141036, 1564, 3128, 0xbc87ef25
0, 91, 91, 1, 192000, 0xd5bc0e7e
-1, 142600, 142600, 1564, 3128, 0xc1638ade
0, 92, 92, 1, 192000, 0xd5bc0e7e
-1, 144164, 144164, 1568, 3136, 0xcfb64a5f
0, 93, 93, 1, 192000, 0xd5bc0e7e
-1, 145732, 145732, 1564, 3128, 0x90b1b826
0, 94, 94, 1, 192000, 0xd5bc0e7e
-1, 147296, 147296, 1568, 3136, 0x00000000
0, 95, 95, 1, 192000, 0xd5bc0e7e
-1, 148864, 148864, 1564, 3128, 0x00000000
0, 96, 96, 1, 192000, 0xd5bc0e7e
-1, 150428, 150428, 1564, 3128, 0x00000000
0, 97, 97, 1, 192000, 0xd5bc0e7e
-1, 151992, 151992, 1568, 3136, 0x00000000
0, 98, 98, 1, 192000, 0xd5bc0e7e
-1, 153560, 153560, 1564, 3128, 0x00000000
0, 99, 99, 1, 192000, 0xd5bc0e7e
-1, 155124, 155124, 1428, 2856, 0x00000000
diff --git a/tests/ref/fate/smjpeg b/tests/ref/fate/smjpeg
deleted file mode 100644
index 78b750a5ac..0000000000
--- a/tests/ref/fate/smjpeg
+++ /dev/null
@@ -1,425 +0,0 @@
-#tb 0: 1/1000
-#tb 1: 1/22050
-0, 0, 0, 0, 734, 0x5a042c2c
-1, 0, 0, 512, 1024, 0x00000000
-1, 507, 507, 512, 1024, 0x00000000
-1, 1014, 1014, 512, 1024, 0xd89a448e
-1, 1521, 1521, 512, 1024, 0x695b369c
-1, 2029, 2029, 512, 1024, 0xc8ba5707
-0, 111, 111, 0, 763, 0xb5893f2f
-1, 2558, 2558, 512, 1024, 0xdf241fc6
-1, 3065, 3065, 512, 1024, 0x61cf4166
-1, 3572, 3572, 512, 1024, 0x97cbc386
-1, 4079, 4079, 512, 1024, 0x44899d04
-1, 4586, 4586, 512, 1024, 0xa7cbaa62
-0, 222, 222, 0, 3023, 0x0f3907d3
-1, 5116, 5116, 512, 1024, 0xa7aea60c
-1, 5623, 5623, 512, 1024, 0xd7b18a89
-1, 6130, 6130, 512, 1024, 0x268e81f6
-1, 6637, 6637, 512, 1024, 0x9cf83a2f
-1, 7166, 7166, 512, 1024, 0x5559b508
-0, 333, 333, 0, 4800, 0x22e6e18a
-1, 7673, 7673, 512, 1024, 0xe1b9e71c
-1, 8181, 8181, 512, 1024, 0xdcee733e
-1, 8688, 8688, 512, 1024, 0xe5918f60
-1, 9195, 9195, 512, 1024, 0x29dbd209
-1, 9724, 9724, 512, 1024, 0x9bcbcf16
-0, 444, 444, 0, 6417, 0x427adde5
-1, 10231, 10231, 512, 1024, 0x86f5f458
-1, 10738, 10738, 512, 1024, 0xabcbda86
-1, 11246, 11246, 512, 1024, 0xc51f77b9
-1, 11775, 11775, 512, 1024, 0xf6b3a504
-0, 555, 555, 0, 6776, 0x7a74c6ad
-1, 12282, 12282, 512, 1024, 0x1af3e40e
-1, 12789, 12789, 512, 1024, 0x3866b03b
-1, 13296, 13296, 512, 1024, 0xbc005403
-1, 13803, 13803, 512, 1024, 0xe9dfcc51
-1, 14332, 14332, 512, 1024, 0x83c837cb
-0, 666, 666, 0, 6808, 0x1f6eb7c3
-1, 14840, 14840, 512, 1024, 0xfa649580
-1, 15347, 15347, 512, 1024, 0x519452ea
-1, 15854, 15854, 512, 1024, 0xd4978774
-1, 16383, 16383, 512, 1024, 0xe2a3b1cd
-1, 16890, 16890, 512, 1024, 0x9a9472ad
-0, 777, 777, 0, 6726, 0x452087e6
-1, 17397, 17397, 512, 1024, 0xa12d4060
-1, 17905, 17905, 512, 1024, 0x31fb0646
-1, 18412, 18412, 512, 1024, 0xfc44343f
-1, 18941, 18941, 512, 1024, 0x0847751a
-1, 19448, 19448, 512, 1024, 0x227968a2
-0, 888, 888, 0, 6829, 0xee82b109
-1, 19955, 19955, 512, 1024, 0x7cce9f1c
-1, 20462, 20462, 512, 1024, 0xb8356713
-1, 20992, 20992, 512, 1024, 0xb29f6e6f
-1, 21499, 21499, 512, 1024, 0x9e1430ab
-1, 22006, 22006, 512, 1024, 0x26d85423
-0, 999, 999, 0, 7055, 0xf41f1108
-1, 22513, 22513, 512, 1024, 0x6496547d
-1, 23020, 23020, 512, 1024, 0x316b1a86
-1, 23549, 23549, 512, 1024, 0x3cd83afc
-1, 24057, 24057, 512, 1024, 0x993ff633
-0, 1111, 1111, 0, 6977, 0xf8fe1ede
-1, 24564, 24564, 512, 1024, 0x0708d1a2
-1, 25071, 25071, 512, 1024, 0xd7230db9
-1, 25578, 25578, 512, 1024, 0xbb0779ca
-1, 26107, 26107, 512, 1024, 0xc6094e1b
-1, 26614, 26614, 512, 1024, 0x15a8b039
-0, 1222, 1222, 0, 6942, 0x9ad105c6
-1, 27122, 27122, 512, 1024, 0xd6dbe88c
-1, 27629, 27629, 512, 1024, 0x7e8d1140
-1, 28158, 28158, 512, 1024, 0xef88e525
-1, 28665, 28665, 512, 1024, 0x44e21149
-1, 29172, 29172, 512, 1024, 0x65b0f5f4
-0, 1333, 1333, 0, 6926, 0xe239dad6
-1, 29679, 29679, 512, 1024, 0xb955f687
-1, 30186, 30186, 512, 1024, 0xc85fba9c
-1, 30716, 30716, 512, 1024, 0xf59655ad
-1, 31223, 31223, 512, 1024, 0x6de80bf1
-1, 31730, 31730, 512, 1024, 0x2dcf6e41
-0, 1444, 1444, 0, 6966, 0x81dcfab1
-1, 32237, 32237, 512, 1024, 0xd0ddcf8a
-1, 32766, 32766, 512, 1024, 0x00135c2d
-1, 33273, 33273, 512, 1024, 0x697f8efd
-1, 33781, 33781, 512, 1024, 0x7a9bada5
-0, 1555, 1555, 0, 6896, 0x31e6cc02
-1, 34288, 34288, 512, 1024, 0x0d22783c
-1, 34795, 34795, 512, 1024, 0x7726d07d
-1, 35324, 35324, 512, 1024, 0xa2f14f67
-1, 35831, 35831, 512, 1024, 0x7f51060d
-1, 36338, 36338, 512, 1024, 0xc4ec6aea
-0, 1666, 1666, 0, 6889, 0x1cc1006e
-1, 36846, 36846, 512, 1024, 0x9bb37ca4
-1, 37375, 37375, 512, 1024, 0x9b085577
-1, 37882, 37882, 512, 1024, 0x8812f8af
-1, 38389, 38389, 512, 1024, 0x788f5221
-1, 38896, 38896, 512, 1024, 0x3a2ce642
-0, 1777, 1777, 0, 6933, 0xc303f87f
-1, 39403, 39403, 512, 1024, 0x72415692
-1, 39933, 39933, 512, 1024, 0xe3dcc105
-1, 40440, 40440, 512, 1024, 0xb26c0599
-1, 40947, 40947, 512, 1024, 0x5c9e55eb
-1, 41454, 41454, 512, 1024, 0x8fe88707
-0, 1888, 1888, 0, 7034, 0xb4970a20
-1, 41983, 41983, 512, 1024, 0xc5d7beb6
-1, 42490, 42490, 512, 1024, 0xe1d3a3b4
-1, 42998, 42998, 512, 1024, 0x012da0c6
-1, 43505, 43505, 512, 1024, 0x8d010922
-1, 44012, 44012, 512, 1024, 0x3366eb0d
-0, 1999, 1999, 0, 6961, 0xf064095d
-1, 44541, 44541, 512, 1024, 0xc9381a27
-1, 45048, 45048, 512, 1024, 0x0774f685
-1, 45555, 45555, 512, 1024, 0xc5cae0a5
-1, 46062, 46062, 512, 1024, 0xa6f4737c
-0, 2111, 2111, 0, 7089, 0x5ba350f9
-1, 46592, 46592, 512, 1024, 0x8fb6d0d1
-1, 47099, 47099, 512, 1024, 0x05f579c2
-1, 47606, 47606, 512, 1024, 0x56905d99
-1, 48113, 48113, 512, 1024, 0x002ee18d
-1, 48620, 48620, 512, 1024, 0xeb37ef51
-0, 2222, 2222, 0, 7078, 0xa83f3e88
-1, 49149, 49149, 512, 1024, 0x38025635
-1, 49657, 49657, 512, 1024, 0x4fe643c8
-1, 50164, 50164, 512, 1024, 0x11d66ab1
-1, 50671, 50671, 512, 1024, 0xcc3051e9
-1, 51178, 51178, 512, 1024, 0xcd93e854
-0, 2333, 2333, 0, 7147, 0xcda66cfc
-1, 51707, 51707, 512, 1024, 0x38f1196d
-1, 52214, 52214, 512, 1024, 0x657a15fc
-1, 52722, 52722, 512, 1024, 0x669ce2a9
-1, 53229, 53229, 512, 1024, 0x95862dda
-1, 53758, 53758, 512, 1024, 0x1726a7b2
-0, 2444, 2444, 0, 7173, 0xb7455859
-1, 54265, 54265, 512, 1024, 0xd6ece2a1
-1, 54772, 54772, 512, 1024, 0x33ab9553
-1, 55279, 55279, 512, 1024, 0xd50c73a6
-1, 55786, 55786, 512, 1024, 0xfe25b63a
-1, 56316, 56316, 512, 1024, 0x7e2959e3
-0, 2555, 2555, 0, 7213, 0x97b89994
-1, 56823, 56823, 512, 1024, 0xa4c07b34
-1, 57330, 57330, 512, 1024, 0xd6d8f15c
-1, 57837, 57837, 512, 1024, 0x1eccddd7
-1, 58366, 58366, 512, 1024, 0x2b69f9cb
-0, 2666, 2666, 0, 7170, 0xca8b2948
-1, 58874, 58874, 512, 1024, 0x667b775f
-1, 59381, 59381, 512, 1024, 0xad3b84e9
-1, 59888, 59888, 512, 1024, 0x4f29fc67
-1, 60395, 60395, 512, 1024, 0x8d611ab7
-1, 60924, 60924, 512, 1024, 0x278966ea
-0, 2777, 2777, 0, 7174, 0xc7cc6bbb
-1, 61431, 61431, 512, 1024, 0xaf33812b
-1, 61938, 61938, 512, 1024, 0xa55f4265
-1, 62446, 62446, 512, 1024, 0x023cb51c
-1, 62975, 62975, 512, 1024, 0x1d1f1005
-1, 63482, 63482, 512, 1024, 0x874cccf7
-0, 2888, 2888, 0, 7235, 0xc2e68d2b
-1, 63989, 63989, 512, 1024, 0xda705428
-1, 64496, 64496, 512, 1024, 0x48d9b440
-1, 65003, 65003, 512, 1024, 0xa14e0712
-1, 65533, 65533, 512, 1024, 0x7efbad1f
-1, 66040, 66040, 512, 1024, 0xdb82c17f
-0, 3000, 3000, 0, 7261, 0x8204a423
-1, 66547, 66547, 512, 1024, 0xcbe87613
-1, 67054, 67054, 512, 1024, 0x3a63df1d
-1, 67583, 67583, 512, 1024, 0xd5636bba
-1, 68090, 68090, 512, 1024, 0x9397af23
-0, 3111, 3111, 0, 7353, 0xacc7e7c0
-1, 68598, 68598, 512, 1024, 0x32a07c98
-1, 69105, 69105, 512, 1024, 0x202ca667
-1, 69612, 69612, 512, 1024, 0xdf969011
-1, 70141, 70141, 512, 1024, 0xc434d238
-1, 70648, 70648, 512, 1024, 0xe9ad7562
-0, 3222, 3222, 0, 7065, 0x45035c5c
-1, 71155, 71155, 512, 1024, 0xb51b6b50
-1, 71662, 71662, 512, 1024, 0xe70aecd3
-1, 72192, 72192, 512, 1024, 0x03c816b2
-1, 72699, 72699, 512, 1024, 0x869fdf25
-1, 73206, 73206, 512, 1024, 0xd40a0a62
-0, 3333, 3333, 0, 7269, 0x72edbb76
-1, 73713, 73713, 512, 1024, 0x5af7dd35
-1, 74220, 74220, 512, 1024, 0x891ffc72
-1, 74750, 74750, 512, 1024, 0x1ff68a08
-1, 75257, 75257, 512, 1024, 0x5a7517a9
-1, 75764, 75764, 512, 1024, 0x0f959f74
-0, 3444, 3444, 0, 7220, 0xb926772f
-1, 76271, 76271, 512, 1024, 0xe92a12a2
-1, 76778, 76778, 512, 1024, 0x38000e55
-1, 77307, 77307, 512, 1024, 0x39fbdd70
-1, 77814, 77814, 512, 1024, 0xca3d9184
-1, 78322, 78322, 512, 1024, 0x66c8995b
-0, 3555, 3555, 0, 7326, 0x0a66c632
-1, 78829, 78829, 512, 1024, 0xac25acea
-1, 79358, 79358, 512, 1024, 0x3cd1046c
-1, 79865, 79865, 512, 1024, 0x6a1df31c
-1, 80372, 80372, 512, 1024, 0x21ca10a1
-0, 3666, 3666, 0, 7225, 0xe39076ab
-1, 80879, 80879, 512, 1024, 0x1aeccedc
-1, 81387, 81387, 512, 1024, 0xddea1335
-1, 81916, 81916, 512, 1024, 0x19f5ca9f
-1, 82423, 82423, 512, 1024, 0x88e95e43
-1, 82930, 82930, 512, 1024, 0x726284fe
-0, 3777, 3777, 0, 7265, 0xe0209036
-1, 83437, 83437, 512, 1024, 0x6b85b40e
-1, 83966, 83966, 512, 1024, 0x111fee2a
-1, 84474, 84474, 512, 1024, 0x3656b588
-1, 84981, 84981, 512, 1024, 0xa5a2b552
-1, 85488, 85488, 512, 1024, 0x38fb2467
-0, 3888, 3888, 0, 7337, 0x7a5dc093
-1, 85995, 85995, 512, 1024, 0xaa919ccc
-1, 86524, 86524, 512, 1024, 0x15993dbc
-1, 87031, 87031, 512, 1024, 0xbe01a7b9
-1, 87538, 87538, 512, 1024, 0xefe93c09
-1, 88046, 88046, 512, 1024, 0x1bb566e5
-0, 4000, 4000, 0, 7246, 0x519a7a3c
-1, 88575, 88575, 512, 1024, 0x15ce6237
-1, 89082, 89082, 512, 1024, 0xa8552e66
-1, 89589, 89589, 512, 1024, 0x9d80187e
-1, 90096, 90096, 512, 1024, 0x5df3fc30
-1, 90603, 90603, 512, 1024, 0x1a312aa5
-0, 4111, 4111, 0, 7266, 0x352c8078
-1, 91133, 91133, 512, 1024, 0x6bb8e302
-1, 91640, 91640, 512, 1024, 0xbd9684bb
-1, 92147, 92147, 512, 1024, 0x78b0b166
-1, 92654, 92654, 512, 1024, 0xd9af5eae
-0, 4222, 4222, 0, 7323, 0xcaf69d7c
-1, 93183, 93183, 512, 1024, 0xdb90fe82
-1, 93690, 93690, 512, 1024, 0x327614e9
-1, 94198, 94198, 512, 1024, 0x1f19b7fe
-1, 94705, 94705, 512, 1024, 0x46c53f96
-1, 95212, 95212, 512, 1024, 0x921b2189
-0, 4333, 4333, 0, 7309, 0x98c1e6f7
-1, 95741, 95741, 512, 1024, 0xa8fbc85a
-1, 96248, 96248, 512, 1024, 0xabfdaaae
-1, 96755, 96755, 512, 1024, 0x6acc7387
-1, 97263, 97263, 512, 1024, 0x0d9c27b5
-1, 97792, 97792, 512, 1024, 0xba4dd809
-0, 4444, 4444, 0, 7121, 0x913d5bd6
-1, 98299, 98299, 512, 1024, 0x2a2ad521
-1, 98806, 98806, 512, 1024, 0x892de38a
-1, 99313, 99313, 512, 1024, 0xdc97a2eb
-1, 99820, 99820, 512, 1024, 0x4f614ca4
-1, 100350, 100350, 512, 1024, 0x9c8a77ea
-0, 4555, 4555, 111, 7088, 0x56302362
-1, 100857, 100857, 512, 1024, 0x2d30e646
-1, 101364, 101364, 512, 1024, 0x74e800a7
-1, 101871, 101871, 512, 1024, 0x1e01fb02
-1, 102378, 102378, 512, 1024, 0x4ed2c1d8
-0, 4666, 4666, 111, 7104, 0xc0d14f78
-1, 102907, 102907, 512, 1024, 0xf2fdbe63
-1, 103414, 103414, 512, 1024, 0x8d6f63a1
-1, 103922, 103922, 512, 1024, 0xded468d9
-1, 104429, 104429, 512, 1024, 0xccad839e
-1, 104958, 104958, 512, 1024, 0xdde7c082
-0, 4777, 4777, 111, 7169, 0xd03c825b
-1, 105465, 105465, 512, 1024, 0x548613c5
-1, 105972, 105972, 512, 1024, 0x383909bd
-1, 106479, 106479, 512, 1024, 0xfd37627b
-1, 106987, 106987, 512, 1024, 0x6d95a481
-1, 107516, 107516, 512, 1024, 0x56aa87fa
-0, 4888, 4888, 111, 7038, 0x1ecc201d
-1, 108023, 108023, 512, 1024, 0x7b67258c
-1, 108530, 108530, 512, 1024, 0x7dd99a92
-1, 109037, 109037, 512, 1024, 0x4a66d102
-1, 109566, 109566, 512, 1024, 0x7b3fce51
-1, 110074, 110074, 512, 1024, 0xbbd968aa
-0, 5000, 5000, 111, 7015, 0x83c94454
-1, 110581, 110581, 512, 1024, 0x8283ec36
-1, 111088, 111088, 512, 1024, 0x3c96493d
-1, 111595, 111595, 512, 1024, 0xfa4f8cf8
-1, 112124, 112124, 512, 1024, 0xe2cf872d
-1, 112631, 112631, 512, 1024, 0x0a9e7aa6
-0, 5111, 5111, 111, 6983, 0x9e51f54d
-1, 113139, 113139, 512, 1024, 0x6e7a0550
-1, 113646, 113646, 512, 1024, 0x3acfea2f
-1, 114175, 114175, 512, 1024, 0x7111d0fa
-1, 114682, 114682, 512, 1024, 0xe9a1eca9
-0, 5222, 5222, 111, 7088, 0x70d33de1
-1, 115189, 115189, 512, 1024, 0x24da6c46
-1, 115696, 115696, 512, 1024, 0x117cff37
-1, 116204, 116204, 512, 1024, 0x0f27cab6
-1, 116733, 116733, 512, 1024, 0x69b6b4e6
-1, 117240, 117240, 512, 1024, 0x1e6cc841
-0, 5333, 5333, 111, 7096, 0x4d0f81b5
-1, 117747, 117747, 512, 1024, 0xb01e2365
-1, 118254, 118254, 512, 1024, 0x14e200d3
-1, 118783, 118783, 512, 1024, 0xd1184c98
-1, 119290, 119290, 512, 1024, 0xef9140e9
-1, 119798, 119798, 512, 1024, 0x4cbb645e
-0, 5444, 5444, 111, 7106, 0xd1a83ddc
-1, 120305, 120305, 512, 1024, 0xe7fe2f06
-1, 120812, 120812, 512, 1024, 0xf8c45028
-1, 121341, 121341, 512, 1024, 0x561358f4
-1, 121848, 121848, 512, 1024, 0xd0129b77
-1, 122355, 122355, 512, 1024, 0xcc636e88
-0, 5555, 5555, 111, 7219, 0x20f47fe4
-1, 122863, 122863, 512, 1024, 0xe9406321
-1, 123392, 123392, 512, 1024, 0x9f16a041
-1, 123899, 123899, 512, 1024, 0x468bf409
-1, 124406, 124406, 512, 1024, 0x3df70f7b
-1, 124913, 124913, 512, 1024, 0xa880b11b
-0, 5666, 5666, 111, 7184, 0x45dc6a0e
-1, 125420, 125420, 512, 1024, 0x3286c489
-1, 125950, 125950, 512, 1024, 0x39fe9ebc
-1, 126457, 126457, 512, 1024, 0xc533d83b
-1, 126964, 126964, 512, 1024, 0x153b195d
-0, 5777, 5777, 111, 7222, 0x488c6499
-1, 127471, 127471, 512, 1024, 0xd84786a1
-1, 127978, 127978, 512, 1024, 0xdc295aaa
-1, 128507, 128507, 512, 1024, 0xfb764d8c
-1, 129015, 129015, 512, 1024, 0xeebc9db9
-1, 129522, 129522, 512, 1024, 0x7ba9403e
-0, 5888, 5888, 111, 7254, 0xbd097ba7
-1, 130029, 130029, 512, 1024, 0x4e5571ec
-1, 130558, 130558, 512, 1024, 0xd965fad4
-1, 131065, 131065, 512, 1024, 0x87e259f2
-1, 131572, 131572, 512, 1024, 0xae7e533b
-1, 132080, 132080, 512, 1024, 0x313cf4d6
-0, 6000, 6000, 111, 7189, 0x46e06d43
-1, 132587, 132587, 512, 1024, 0xe1844c90
-1, 133116, 133116, 512, 1024, 0xbb057b44
-1, 133623, 133623, 512, 1024, 0xa5099687
-1, 134130, 134130, 512, 1024, 0xbff10707
-1, 134637, 134637, 512, 1024, 0x37c4ffc0
-0, 6111, 6111, 111, 7283, 0x19dd7319
-1, 135166, 135166, 512, 1024, 0xf9fb6caa
-1, 135674, 135674, 512, 1024, 0x3b6a3a1f
-1, 136181, 136181, 512, 1024, 0x83431edb
-1, 136688, 136688, 512, 1024, 0x1eb713cf
-1, 137195, 137195, 512, 1024, 0xd7b07a6d
-0, 6222, 6222, 111, 7161, 0x23171d02
-1, 137724, 137724, 512, 1024, 0x81ae3391
-1, 138231, 138231, 512, 1024, 0xf150130a
-1, 138739, 138739, 512, 1024, 0x09678eaa
-1, 139246, 139246, 512, 1024, 0xb94e06f1
-0, 6333, 6333, 111, 6976, 0xcc610c26
-1, 139775, 139775, 512, 1024, 0x67b1dbc9
-1, 140282, 140282, 512, 1024, 0xd6edc235
-1, 140789, 140789, 512, 1024, 0x34e4c499
-1, 141296, 141296, 512, 1024, 0xeefd89c0
-1, 141804, 141804, 512, 1024, 0x38afdaf1
-0, 6444, 6444, 111, 7056, 0x6cd917b0
-1, 142333, 142333, 512, 1024, 0x29a60d76
-1, 142840, 142840, 512, 1024, 0xe28a4372
-1, 143347, 143347, 512, 1024, 0x7089454d
-1, 143854, 143854, 512, 1024, 0x0c01bb7b
-1, 144383, 144383, 512, 1024, 0xbd776a72
-0, 6555, 6555, 111, 6736, 0x02b78951
-1, 144891, 144891, 512, 1024, 0x86776fd0
-1, 145398, 145398, 512, 1024, 0xb37c88f7
-1, 145905, 145905, 512, 1024, 0x5f90aaf8
-1, 146412, 146412, 512, 1024, 0x203d4222
-1, 146941, 146941, 512, 1024, 0x382692a6
-0, 6666, 6666, 111, 6540, 0x767e0854
-1, 147448, 147448, 512, 1024, 0xf37c95fd
-1, 147956, 147956, 512, 1024, 0x6c0b8877
-1, 148463, 148463, 512, 1024, 0x2e54a8b6
-1, 148992, 148992, 512, 1024, 0x7f266488
-0, 6777, 6777, 111, 6170, 0xc84962fb
-1, 149499, 149499, 512, 1024, 0xfbf20f9a
-1, 150006, 150006, 512, 1024, 0xf2985cc0
-1, 150513, 150513, 512, 1024, 0xc7075340
-1, 151020, 151020, 512, 1024, 0xe4585695
-1, 151550, 151550, 512, 1024, 0xbdffa380
-0, 6888, 6888, 111, 6169, 0x27e06c03
-1, 152057, 152057, 512, 1024, 0x2422a8a9
-1, 152564, 152564, 512, 1024, 0x59cbd75f
-1, 153071, 153071, 512, 1024, 0x04ad1a8c
-1, 153578, 153578, 512, 1024, 0x33c09191
-1, 154107, 154107, 512, 1024, 0x55efa6fd
-0, 7000, 7000, 111, 5864, 0xd14db83f
-1, 154615, 154615, 512, 1024, 0xf73d0e5d
-1, 155122, 155122, 512, 1024, 0x6141ebae
-1, 155629, 155629, 512, 1024, 0x7db17a68
-1, 156158, 156158, 512, 1024, 0xa6c690b6
-1, 156665, 156665, 512, 1024, 0xa6fd6725
-0, 7111, 7111, 111, 5375, 0x4a21055d
-1, 157172, 157172, 512, 1024, 0x50a90b9b
-1, 157680, 157680, 512, 1024, 0xef990dc8
-1, 158187, 158187, 512, 1024, 0x75adf6b5
-1, 158716, 158716, 512, 1024, 0x61eac43e
-1, 159223, 159223, 512, 1024, 0x67797a19
-0, 7222, 7222, 111, 5206, 0x95ead3cb
-1, 159730, 159730, 512, 1024, 0xf325277a
-1, 160237, 160237, 512, 1024, 0x18bf254a
-1, 160767, 160767, 512, 1024, 0x2ce6bee3
-1, 161274, 161274, 512, 1024, 0x8d320860
-0, 7333, 7333, 111, 5220, 0xcfdcc37e
-1, 161781, 161781, 512, 1024, 0xc979b6e8
-1, 162288, 162288, 512, 1024, 0xdb644b41
-1, 162795, 162795, 512, 1024, 0xe1b368ba
-1, 163324, 163324, 512, 1024, 0xacc53d15
-1, 163832, 163832, 512, 1024, 0x42ea8c18
-0, 7444, 7444, 111, 4946, 0x2d864a77
-1, 164339, 164339, 512, 1024, 0xe52c99a4
-1, 164846, 164846, 512, 1024, 0xd7db54a6
-1, 165375, 165375, 512, 1024, 0x7f27a7e3
-1, 165882, 165882, 512, 1024, 0xf7ffeaa9
-1, 166389, 166389, 512, 1024, 0x792b6088
-0, 7555, 7555, 111, 4390, 0x2ab9f462
-1, 166896, 166896, 512, 1024, 0x61d99724
-1, 167404, 167404, 512, 1024, 0x5213720e
-1, 167933, 167933, 512, 1024, 0xac09dd30
-1, 168440, 168440, 512, 1024, 0x960bf6bb
-1, 168947, 168947, 512, 1024, 0xc90168e1
-0, 7666, 7666, 111, 4051, 0x1d09592e
-1, 169454, 169454, 512, 1024, 0x43b45768
-1, 169983, 169983, 512, 1024, 0x935d60a1
-1, 170491, 170491, 512, 1024, 0x9a342ef2
-1, 170998, 170998, 512, 1024, 0xc894709f
-0, 7777, 7777, 111, 3680, 0x39bd6a12
-1, 171505, 171505, 512, 1024, 0x59b43b07
-1, 172012, 172012, 512, 1024, 0x36a1a98d
-1, 172541, 172541, 512, 1024, 0x9e1a121c
-1, 173048, 173048, 512, 1024, 0x02208b78
-1, 173556, 173556, 512, 1024, 0xd1d7b274
-0, 7888, 7888, 111, 2910, 0x6337ece9
-1, 174063, 174063, 512, 1024, 0xdacd5096
-1, 174592, 174592, 512, 1024, 0x51b71ead
-1, 175099, 175099, 512, 1024, 0xd009a7ca
-1, 175606, 175606, 512, 1024, 0xb6d5a938
-1, 176113, 176113, 512, 1024, 0xf3d45e47
-0, 8000, 8000, 111, 2153, 0xf4e3bc17
-1, 176620, 176620, 512, 1024, 0xea8e04fc
-1, 177150, 177150, 512, 1024, 0x0b928bd8
-1, 177657, 177657, 512, 1024, 0x0f02caec
-1, 178164, 178164, 512, 1024, 0xe2b137a8
-1, 178671, 178671, 512, 1024, 0xd5f94892
diff --git a/tests/ref/fate/smjpeg-demux b/tests/ref/fate/smjpeg-demux
new file mode 100644
index 0000000000..637f28c663
--- /dev/null
+++ b/tests/ref/fate/smjpeg-demux
@@ -0,0 +1,425 @@
+#tb 0: 1/1000
+#tb 1: 1/1000
+0, 0, 0, 0, 734, 0x5a042c2c
+1, 0, 0, 23, 260, 0x00000000
+1, 23, 23, 23, 260, 0x00000000
+1, 46, 46, 23, 260, 0xac9e0a9b
+1, 69, 69, 23, 260, 0x89256f5b
+1, 92, 92, 23, 260, 0x8e646e36
+0, 111, 111, 0, 763, 0xb5893f2f
+1, 116, 116, 23, 260, 0x3ab972fc
+1, 139, 139, 23, 260, 0xaea86bb2
+1, 162, 162, 23, 260, 0x2366447a
+1, 185, 185, 23, 260, 0x82c14f9c
+1, 208, 208, 23, 260, 0xcdcf6fa8
+0, 222, 222, 0, 3023, 0x0f3907d3
+1, 232, 232, 23, 260, 0xb3ed64bd
+1, 255, 255, 23, 260, 0xac304b92
+1, 278, 278, 23, 260, 0xc8bc553b
+1, 301, 301, 23, 260, 0xd35572b4
+1, 325, 325, 23, 260, 0x182f6190
+0, 333, 333, 0, 4800, 0x22e6e18a
+1, 348, 348, 23, 260, 0xbf9145c0
+1, 371, 371, 23, 260, 0x0ec85a7e
+1, 394, 394, 23, 260, 0x3684720e
+1, 417, 417, 23, 260, 0xe985616a
+1, 441, 441, 23, 260, 0x12b147dc
+0, 444, 444, 0, 6417, 0x427adde5
+1, 464, 464, 23, 260, 0xb8b55dd9
+1, 487, 487, 23, 260, 0xfd4a7007
+1, 510, 510, 23, 260, 0xfcc05c9a
+1, 534, 534, 23, 260, 0x20f74aea
+0, 555, 555, 0, 6776, 0x7a74c6ad
+1, 557, 557, 23, 260, 0x025359ca
+1, 580, 580, 23, 260, 0xace44ba1
+1, 603, 603, 23, 260, 0x03506929
+1, 626, 626, 23, 260, 0x8a926f17
+1, 650, 650, 23, 260, 0x4a7061e7
+0, 666, 666, 0, 6808, 0x1f6eb7c3
+1, 673, 673, 23, 260, 0xf8b66cc9
+1, 696, 696, 23, 260, 0xe8c96dec
+1, 719, 719, 23, 260, 0x672a54a6
+1, 743, 743, 23, 260, 0xe97b5698
+1, 766, 766, 23, 260, 0x377f684d
+0, 777, 777, 0, 6726, 0x452087e6
+1, 789, 789, 23, 260, 0xe9a66786
+1, 812, 812, 23, 260, 0xf8e17080
+1, 835, 835, 23, 260, 0x65eb662a
+1, 859, 859, 23, 260, 0xd8d361e9
+1, 882, 882, 23, 260, 0xb8115a0b
+0, 888, 888, 0, 6829, 0xee82b109
+1, 905, 905, 23, 260, 0xa5a85461
+1, 928, 928, 23, 260, 0xf401663b
+1, 952, 952, 23, 260, 0x042f714e
+1, 975, 975, 23, 260, 0xdf195820
+1, 998, 998, 23, 260, 0x0a67653c
+0, 999, 999, 0, 7055, 0xf41f1108
+1, 1021, 1021, 23, 260, 0xe9b44d02
+1, 1044, 1044, 23, 260, 0xbd4747b9
+1, 1068, 1068, 23, 260, 0x3ef66738
+1, 1091, 1091, 23, 260, 0x0f4a6e44
+0, 1111, 1111, 0, 6977, 0xf8fe1ede
+1, 1114, 1114, 23, 260, 0xaa3d6eb6
+1, 1137, 1137, 23, 260, 0xb9a46c4a
+1, 1160, 1160, 23, 260, 0x4f974c2e
+1, 1184, 1184, 23, 260, 0x9e714a00
+1, 1207, 1207, 23, 260, 0x601a7152
+0, 1222, 1222, 0, 6942, 0x9ad105c6
+1, 1230, 1230, 23, 260, 0xaf317064
+1, 1253, 1253, 23, 260, 0x163d4829
+1, 1277, 1277, 23, 260, 0xc56b4f1a
+1, 1300, 1300, 23, 260, 0x7623729c
+1, 1323, 1323, 23, 260, 0xa514694f
+0, 1333, 1333, 0, 6926, 0xe239dad6
+1, 1346, 1346, 23, 260, 0x93ee4ad8
+1, 1369, 1369, 23, 260, 0x6d8e573f
+1, 1393, 1393, 23, 260, 0x13256d68
+1, 1416, 1416, 23, 260, 0x187761a2
+1, 1439, 1439, 23, 260, 0x426045e7
+0, 1444, 1444, 0, 6966, 0x81dcfab1
+1, 1462, 1462, 23, 260, 0x7e7e5891
+1, 1486, 1486, 23, 260, 0xd6926dcc
+1, 1509, 1509, 23, 260, 0xf0196061
+1, 1532, 1532, 23, 260, 0x7cac49a3
+0, 1555, 1555, 0, 6896, 0x31e6cc02
+1, 1555, 1555, 23, 260, 0x24f4549a
+1, 1578, 1578, 23, 260, 0x937f551d
+1, 1602, 1602, 23, 260, 0x9bf462c5
+1, 1625, 1625, 23, 260, 0xd1e07436
+1, 1648, 1648, 23, 260, 0xdab36215
+0, 1666, 1666, 0, 6889, 0x1cc1006e
+1, 1671, 1671, 23, 260, 0xabc5662b
+1, 1695, 1695, 23, 260, 0xa24f6bf1
+1, 1718, 1718, 23, 260, 0x39e664b2
+1, 1741, 1741, 23, 260, 0xf5dc54ca
+1, 1764, 1764, 23, 260, 0xc3b16974
+0, 1777, 1777, 0, 6933, 0xc303f87f
+1, 1787, 1787, 23, 260, 0x6cf46bca
+1, 1811, 1811, 23, 260, 0x7a6b69b9
+1, 1834, 1834, 23, 260, 0xc02f69b9
+1, 1857, 1857, 23, 260, 0x7fc764a9
+1, 1880, 1880, 23, 260, 0xd9705b09
+0, 1888, 1888, 0, 7034, 0xb4970a20
+1, 1904, 1904, 23, 260, 0x17b05f49
+1, 1927, 1927, 23, 260, 0x10ad647c
+1, 1950, 1950, 23, 260, 0xf9636d69
+1, 1973, 1973, 23, 260, 0x622b5ad9
+1, 1996, 1996, 23, 260, 0x175b646d
+0, 1999, 1999, 0, 6961, 0xf064095d
+1, 2020, 2020, 23, 260, 0x722b5827
+1, 2043, 2043, 23, 260, 0x83614974
+1, 2066, 2066, 23, 260, 0x80366587
+1, 2089, 2089, 23, 260, 0x050f6bf9
+0, 2111, 2111, 0, 7089, 0x5ba350f9
+1, 2113, 2113, 23, 260, 0x949d6735
+1, 2136, 2136, 23, 260, 0x62cd7184
+1, 2159, 2159, 23, 260, 0x21e45713
+1, 2182, 2182, 23, 260, 0x56314509
+1, 2205, 2205, 23, 260, 0x7a1570d3
+0, 2222, 2222, 0, 7078, 0xa83f3e88
+1, 2229, 2229, 23, 260, 0x205a6ffb
+1, 2252, 2252, 23, 260, 0xead94483
+1, 2275, 2275, 23, 260, 0x93c84f10
+1, 2298, 2298, 23, 260, 0xdf45726f
+1, 2321, 2321, 23, 260, 0x35016f1e
+0, 2333, 2333, 0, 7147, 0xcda66cfc
+1, 2345, 2345, 23, 260, 0xa8114bcd
+1, 2368, 2368, 23, 260, 0x14c45130
+1, 2391, 2391, 23, 260, 0x97b07052
+1, 2414, 2414, 23, 260, 0x039b6c77
+1, 2438, 2438, 23, 260, 0x46f74635
+0, 2444, 2444, 0, 7173, 0xb7455859
+1, 2461, 2461, 23, 260, 0x4116540d
+1, 2484, 2484, 23, 260, 0x26747067
+1, 2507, 2507, 23, 260, 0x37f16485
+1, 2530, 2530, 23, 260, 0x631d4a33
+1, 2554, 2554, 23, 260, 0x14ed598d
+0, 2555, 2555, 0, 7213, 0x97b89994
+1, 2577, 2577, 23, 260, 0x3f9349e7
+1, 2600, 2600, 23, 260, 0x91295757
+1, 2623, 2623, 23, 260, 0x95de72bc
+1, 2647, 2647, 23, 260, 0xc7ee5ddb
+0, 2666, 2666, 0, 7170, 0xca8b2948
+1, 2670, 2670, 23, 260, 0x38e965cd
+1, 2693, 2693, 23, 260, 0xfae169e9
+1, 2716, 2716, 23, 260, 0x9c226143
+1, 2739, 2739, 23, 260, 0x1a804dbe
+1, 2763, 2763, 23, 260, 0x4aeb633c
+0, 2777, 2777, 0, 7174, 0xc7cc6bbb
+1, 2786, 2786, 23, 260, 0xa66e6bbb
+1, 2809, 2809, 23, 260, 0x51d17109
+1, 2832, 2832, 23, 260, 0x2bc86b9b
+1, 2856, 2856, 23, 260, 0xe56e6378
+1, 2879, 2879, 23, 260, 0x95665b47
+0, 2888, 2888, 0, 7235, 0xc2e68d2b
+1, 2902, 2902, 23, 260, 0x1c255fdb
+1, 2925, 2925, 23, 260, 0x3a2456cb
+1, 2948, 2948, 23, 260, 0xe18e7270
+1, 2972, 2972, 23, 260, 0x55b65c60
+1, 2995, 2995, 23, 260, 0x62be6515
+0, 3000, 3000, 0, 7261, 0x8204a423
+1, 3018, 3018, 23, 260, 0xdba25d09
+1, 3041, 3041, 23, 260, 0xd7cc4e40
+1, 3065, 3065, 23, 260, 0x335661be
+1, 3088, 3088, 23, 260, 0xc3286de3
+0, 3111, 3111, 0, 7353, 0xacc7e7c0
+1, 3111, 3111, 23, 260, 0x47e76e35
+1, 3134, 3134, 23, 260, 0x4b716f77
+1, 3157, 3157, 23, 260, 0x0716519e
+1, 3181, 3181, 23, 260, 0x032b4490
+1, 3204, 3204, 23, 260, 0x15f067e8
+0, 3222, 3222, 0, 7065, 0x45035c5c
+1, 3227, 3227, 23, 260, 0x16766ffa
+1, 3250, 3250, 23, 260, 0xc94154ac
+1, 3274, 3274, 23, 260, 0x74764bcd
+1, 3297, 3297, 23, 260, 0x3fad6f8f
+1, 3320, 3320, 23, 260, 0x5fa972a9
+0, 3333, 3333, 0, 7269, 0x72edbb76
+1, 3343, 3343, 23, 260, 0xde2a4b7b
+1, 3366, 3366, 23, 260, 0xd8494408
+1, 3390, 3390, 23, 260, 0x843d71a6
+1, 3413, 3413, 23, 260, 0x87fd6b60
+1, 3436, 3436, 23, 260, 0x1cc04a39
+0, 3444, 3444, 0, 7220, 0xb926772f
+1, 3459, 3459, 23, 260, 0x9ca24d94
+1, 3482, 3482, 23, 260, 0x820a7087
+1, 3506, 3506, 23, 260, 0x631166b2
+1, 3529, 3529, 23, 260, 0x2f20492a
+1, 3552, 3552, 23, 260, 0x932156d0
+0, 3555, 3555, 0, 7326, 0x0a66c632
+1, 3575, 3575, 23, 260, 0xdad54c90
+1, 3599, 3599, 23, 260, 0xcce84fc9
+1, 3622, 3622, 23, 260, 0xba317486
+1, 3645, 3645, 23, 260, 0xf5a4626a
+0, 3666, 3666, 0, 7225, 0xe39076ab
+1, 3668, 3668, 23, 260, 0x324669fd
+1, 3691, 3691, 23, 260, 0xc7d37113
+1, 3715, 3715, 23, 260, 0xc6e0644f
+1, 3738, 3738, 23, 260, 0x1b91522e
+1, 3761, 3761, 23, 260, 0x9b84667d
+0, 3777, 3777, 0, 7265, 0xe0209036
+1, 3784, 3784, 23, 260, 0xed7e66eb
+1, 3808, 3808, 23, 260, 0xaf806d1f
+1, 3831, 3831, 23, 260, 0x13a66941
+1, 3854, 3854, 23, 260, 0x13095a41
+1, 3877, 3877, 23, 260, 0x5ba05491
+0, 3888, 3888, 0, 7337, 0x7a5dc093
+1, 3900, 3900, 23, 260, 0xbf785887
+1, 3924, 3924, 23, 260, 0x21965973
+1, 3947, 3947, 23, 260, 0xd9aa7134
+1, 3970, 3970, 23, 260, 0x3add62bc
+1, 3993, 3993, 23, 260, 0xb9626260
+0, 4000, 4000, 0, 7246, 0x519a7a3c
+1, 4017, 4017, 23, 260, 0x5b08629f
+1, 4040, 4040, 23, 260, 0x43a34659
+1, 4063, 4063, 23, 260, 0x68575bda
+1, 4086, 4086, 23, 260, 0xd98b715a
+1, 4109, 4109, 23, 260, 0x7d816a77
+0, 4111, 4111, 0, 7266, 0x352c8078
+1, 4133, 4133, 23, 260, 0x16af6ff1
+1, 4156, 4156, 23, 260, 0x6d4557a7
+1, 4179, 4179, 23, 260, 0x0743401a
+1, 4202, 4202, 23, 260, 0x410563d8
+0, 4222, 4222, 0, 7323, 0xcaf69d7c
+1, 4226, 4226, 23, 260, 0x561371d1
+1, 4249, 4249, 23, 260, 0x3ef15872
+1, 4272, 4272, 23, 260, 0x1dd04972
+1, 4295, 4295, 23, 260, 0xed226c62
+1, 4318, 4318, 23, 260, 0x20857046
+0, 4333, 4333, 0, 7309, 0x98c1e6f7
+1, 4342, 4342, 23, 260, 0xed7f4724
+1, 4365, 4365, 23, 260, 0x7a7445cf
+1, 4388, 4388, 23, 260, 0x06ad6a93
+1, 4411, 4411, 23, 260, 0xdd1b6c91
+1, 4435, 4435, 23, 260, 0x05b94d27
+0, 4444, 4444, 0, 7121, 0x913d5bd6
+1, 4458, 4458, 23, 260, 0x12cc5062
+1, 4481, 4481, 23, 260, 0x44526d0f
+1, 4504, 4504, 23, 260, 0xf2ac6d95
+1, 4527, 4527, 23, 260, 0x27174b0f
+1, 4551, 4551, 23, 260, 0xcf125efe
+0, 4555, 4555, 111, 7088, 0x56302362
+1, 4574, 4574, 23, 260, 0xb8ce45a1
+1, 4597, 4597, 23, 260, 0x91895627
+1, 4620, 4620, 23, 260, 0x6edb706a
+1, 4643, 4643, 23, 260, 0x4e16674b
+0, 4666, 4666, 111, 7104, 0xc0d14f78
+1, 4667, 4667, 23, 260, 0xa9d66370
+1, 4690, 4690, 23, 260, 0x8f007043
+1, 4713, 4713, 23, 260, 0xdc1a5583
+1, 4736, 4736, 23, 260, 0x2f025511
+1, 4760, 4760, 23, 260, 0x2a4d6ddb
+0, 4777, 4777, 111, 7169, 0xd03c825b
+1, 4783, 4783, 23, 260, 0x54806f14
+1, 4806, 4806, 23, 260, 0xe0ac6d80
+1, 4829, 4829, 23, 260, 0xd9cf6c97
+1, 4852, 4852, 23, 260, 0xba705b6d
+1, 4876, 4876, 23, 260, 0x0be158e0
+0, 4888, 4888, 111, 7038, 0x1ecc201d
+1, 4899, 4899, 23, 260, 0x32b3645d
+1, 4922, 4922, 23, 260, 0x4a0a55b4
+1, 4945, 4945, 23, 260, 0x078b6fd8
+1, 4969, 4969, 23, 260, 0xc2816368
+1, 4992, 4992, 23, 260, 0xbdee5e4d
+0, 5000, 5000, 111, 7015, 0x83c94454
+1, 5015, 5015, 23, 260, 0x475366aa
+1, 5038, 5038, 23, 260, 0x2f9a44b9
+1, 5061, 5061, 23, 260, 0x91745ee5
+1, 5085, 5085, 23, 260, 0xc29b6e16
+1, 5108, 5108, 23, 260, 0x6ebb6b0e
+0, 5111, 5111, 111, 6983, 0x9e51f54d
+1, 5131, 5131, 23, 260, 0x4e7d7043
+1, 5154, 5154, 23, 260, 0x10b45caf
+1, 5178, 5178, 23, 260, 0x1b1e4e54
+1, 5201, 5201, 23, 260, 0xcc7b6443
+0, 5222, 5222, 111, 7088, 0x70d33de1
+1, 5224, 5224, 23, 260, 0x29936fdd
+1, 5247, 5247, 23, 260, 0x395256e3
+1, 5270, 5270, 23, 260, 0x50fb459f
+1, 5294, 5294, 23, 260, 0x0bef64ec
+1, 5317, 5317, 23, 260, 0xadd372dd
+0, 5333, 5333, 111, 7096, 0x4d0f81b5
+1, 5340, 5340, 23, 260, 0xc49e56dc
+1, 5363, 5363, 23, 260, 0x44e749c1
+1, 5387, 5387, 23, 260, 0x030e6c8a
+1, 5410, 5410, 23, 260, 0x82a47261
+1, 5433, 5433, 23, 260, 0xa3764fcc
+0, 5444, 5444, 111, 7106, 0xd1a83ddc
+1, 5456, 5456, 23, 260, 0xb1a1498a
+1, 5479, 5479, 23, 260, 0xbf9c7184
+1, 5503, 5503, 23, 260, 0xa45f6da8
+1, 5526, 5526, 23, 260, 0x9a2e4d51
+1, 5549, 5549, 23, 260, 0xa15c56ed
+0, 5555, 5555, 111, 7219, 0x20f47fe4
+1, 5572, 5572, 23, 260, 0x7029496c
+1, 5596, 5596, 23, 260, 0xf3595213
+1, 5619, 5619, 23, 260, 0x0dab6c5a
+1, 5642, 5642, 23, 260, 0x0e2367da
+1, 5665, 5665, 23, 260, 0xbb56610a
+0, 5666, 5666, 111, 7184, 0x45dc6a0e
+1, 5688, 5688, 23, 260, 0xcc916c92
+1, 5712, 5712, 23, 260, 0x886c5ba9
+1, 5735, 5735, 23, 260, 0x1b255a69
+1, 5758, 5758, 23, 260, 0xb7a66792
+0, 5777, 5777, 111, 7222, 0x488c6499
+1, 5781, 5781, 23, 260, 0x7d946b0e
+1, 5804, 5804, 23, 260, 0x07d16714
+1, 5828, 5828, 23, 260, 0x77ef6755
+1, 5851, 5851, 23, 260, 0xb2fe6849
+1, 5874, 5874, 23, 260, 0x601b5325
+0, 5888, 5888, 111, 7254, 0xbd097ba7
+1, 5897, 5897, 23, 260, 0x309c68d0
+1, 5921, 5921, 23, 260, 0x7bbe5d49
+1, 5944, 5944, 23, 260, 0x77bc6e47
+1, 5967, 5967, 23, 260, 0x3e0a6b0b
+1, 5990, 5990, 23, 260, 0x2ae458c4
+0, 6000, 6000, 111, 7189, 0x46e06d43
+1, 6013, 6013, 23, 260, 0x17576d4f
+1, 6037, 6037, 23, 260, 0x496c4bbd
+1, 6060, 6060, 23, 260, 0x972758a0
+1, 6083, 6083, 23, 260, 0xa9897452
+1, 6106, 6106, 23, 260, 0xf58c6b92
+0, 6111, 6111, 111, 7283, 0x19dd7319
+1, 6130, 6130, 23, 260, 0x8368709a
+1, 6153, 6153, 23, 260, 0x3890643f
+1, 6176, 6176, 23, 260, 0xdcc1472c
+1, 6199, 6199, 23, 260, 0xb601605c
+0, 6222, 6222, 111, 7161, 0x23171d02
+1, 6222, 6222, 23, 260, 0xfafd6e13
+1, 6246, 6246, 23, 260, 0x20a55dbf
+1, 6269, 6269, 23, 260, 0x84a147e6
+1, 6292, 6292, 23, 260, 0xe2c75bfd
+1, 6315, 6315, 23, 260, 0x52f672c4
+0, 6333, 6333, 111, 6976, 0xcc610c26
+1, 6339, 6339, 23, 260, 0x98af579a
+1, 6362, 6362, 23, 260, 0xf2034f37
+1, 6385, 6385, 23, 260, 0x75576856
+1, 6408, 6408, 23, 260, 0x4a796f1b
+1, 6431, 6431, 23, 260, 0x3a7a5612
+0, 6444, 6444, 111, 7056, 0x6cd917b0
+1, 6455, 6455, 23, 260, 0x1c0646bd
+1, 6478, 6478, 23, 260, 0xfccd6e2c
+1, 6501, 6501, 23, 260, 0x2bdd7139
+1, 6524, 6524, 23, 260, 0xadb4519a
+1, 6548, 6548, 23, 260, 0x8ef655b5
+0, 6555, 6555, 111, 6736, 0x02b78951
+1, 6571, 6571, 23, 260, 0x157852f6
+1, 6594, 6594, 23, 260, 0xec3a4aa8
+1, 6617, 6617, 23, 260, 0x5fa77041
+1, 6640, 6640, 23, 260, 0xe862690f
+1, 6664, 6664, 23, 260, 0xad1759ce
+0, 6666, 6666, 111, 6540, 0x767e0854
+1, 6687, 6687, 23, 260, 0x856f6d2e
+1, 6710, 6710, 23, 260, 0x19496938
+1, 6733, 6733, 23, 260, 0xf3135c06
+1, 6757, 6757, 23, 260, 0xbec861ab
+0, 6777, 6777, 111, 6170, 0xc84962fb
+1, 6780, 6780, 23, 260, 0x97486f09
+1, 6803, 6803, 23, 260, 0x2dcb64ed
+1, 6826, 6826, 23, 260, 0xac196fe8
+1, 6849, 6849, 23, 260, 0xa7d460f8
+1, 6873, 6873, 23, 260, 0x02e55631
+0, 6888, 6888, 111, 6169, 0x27e06c03
+1, 6896, 6896, 23, 260, 0x92556737
+1, 6919, 6919, 23, 260, 0x9ab25599
+1, 6942, 6942, 23, 260, 0x48017498
+1, 6965, 6965, 23, 260, 0x3f376d65
+1, 6989, 6989, 23, 260, 0x553750e2
+0, 7000, 7000, 111, 5864, 0xd14db83f
+1, 7012, 7012, 23, 260, 0x430a6cb9
+1, 7035, 7035, 23, 260, 0x0d4f3b7e
+1, 7058, 7058, 23, 260, 0xc5ee5733
+1, 7082, 7082, 23, 260, 0xec33744f
+1, 7105, 7105, 23, 260, 0xb7ca6c50
+0, 7111, 7111, 111, 5375, 0x4a21055d
+1, 7128, 7128, 23, 260, 0xca8e6e09
+1, 7151, 7151, 23, 260, 0xde7b67d9
+1, 7174, 7174, 23, 260, 0x1eeb47c6
+1, 7198, 7198, 23, 260, 0x97e355f6
+1, 7221, 7221, 23, 260, 0x4cb871da
+0, 7222, 7222, 111, 5206, 0x95ead3cb
+1, 7244, 7244, 23, 260, 0xf9d65f42
+1, 7267, 7267, 23, 260, 0x4df447f9
+1, 7291, 7291, 23, 260, 0x6da55c39
+1, 7314, 7314, 23, 260, 0xf8487192
+0, 7333, 7333, 111, 5220, 0xcfdcc37e
+1, 7337, 7337, 23, 260, 0xa5ef5e84
+1, 7360, 7360, 23, 260, 0xc750404d
+1, 7383, 7383, 23, 260, 0xe62d5ba7
+1, 7407, 7407, 23, 260, 0xa362739c
+1, 7430, 7430, 23, 260, 0x784c57f9
+0, 7444, 7444, 111, 4946, 0x2d864a77
+1, 7453, 7453, 23, 260, 0xac224b6f
+1, 7476, 7476, 23, 260, 0x34506907
+1, 7500, 7500, 23, 260, 0x94207121
+1, 7523, 7523, 23, 260, 0x018754e6
+1, 7546, 7546, 23, 260, 0xa5355133
+0, 7555, 7555, 111, 4390, 0x2ab9f462
+1, 7569, 7569, 23, 260, 0x93724dac
+1, 7592, 7592, 23, 260, 0x41e24c4c
+1, 7616, 7616, 23, 260, 0x1b2a7301
+1, 7639, 7639, 23, 260, 0xcce36e61
+1, 7662, 7662, 23, 260, 0xb323585a
+0, 7666, 7666, 111, 4051, 0x1d09592e
+1, 7685, 7685, 23, 260, 0x6f7c624d
+1, 7709, 7709, 23, 260, 0x87b96a4a
+1, 7732, 7732, 23, 260, 0xf567622a
+1, 7755, 7755, 23, 260, 0x52ce5d35
+0, 7777, 7777, 111, 3680, 0x39bd6a12
+1, 7778, 7778, 23, 260, 0x58a46c28
+1, 7801, 7801, 23, 260, 0x8e3e6d9a
+1, 7825, 7825, 23, 260, 0x5ef66906
+1, 7848, 7848, 23, 260, 0x351b5f9f
+1, 7871, 7871, 23, 260, 0x90b9588a
+0, 7888, 7888, 111, 2910, 0x6337ece9
+1, 7894, 7894, 23, 260, 0x34e8615f
+1, 7918, 7918, 23, 260, 0xcef75ab9
+1, 7941, 7941, 23, 260, 0x471f6bc8
+1, 7964, 7964, 23, 260, 0xd4756c62
+1, 7987, 7987, 23, 260, 0x7c554702
+0, 8000, 8000, 111, 2153, 0xf4e3bc17
+1, 8010, 8010, 23, 260, 0x185272f1
+1, 8034, 8034, 23, 260, 0x0c364348
+1, 8057, 8057, 23, 260, 0x24354467
+1, 8080, 8080, 23, 260, 0x837d5472
+1, 8103, 8103, 23, 260, 0xece2344f
diff --git a/tools/lavfi-showfiltfmts.c b/tools/lavfi-showfiltfmts.c
index 9f9029dcfd..b33ff1c36e 100644
--- a/tools/lavfi-showfiltfmts.c
+++ b/tools/lavfi-showfiltfmts.c
@@ -46,7 +46,7 @@ static void print_formats(AVFilterContext *filter_ctx)
i, filter_ctx->filter->inout##puts[i].name, \
av_get_sample_fmt_name(fmts->formats[j])); \
\
- fmts = filter_ctx->inout##puts[i]->outin##_chlayouts; \
+ fmts = filter_ctx->inout##puts[i]->outin##_channel_layouts; \
for (j = 0; j < fmts->format_count; j++) { \
char buf[256]; \
av_get_channel_layout_string(buf, sizeof(buf), -1, \