Commit 1cbf7fb4 authored by Michael Niedermayer's avatar Michael Niedermayer

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: 's avatarMichael Niedermayer <michaelni@gmx.at>
parents a48abf5e 0ff0af73
......@@ -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:
......
......@@ -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
......
......@@ -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}
......
......@@ -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
......
......@@ -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;
......
......@@ -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,
......
......@@ -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
......
......@@ -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);
......
......@@ -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;
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;
int ret;
#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 },
};
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); \
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; \
} \
av_freep(&fmts_str); \
if (*args) \
args++; \
} while (0)
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);
static int get_sample_rate(const char *samplerate)
{
int ret = strtol(samplerate, NULL, 0);
return FFMAX(ret, 0);
}
return 0;
static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque)
{
AFormatContext *s = ctx->priv;
int 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);
if (!args) {
av_log(ctx, AV_LOG_ERROR, "No parameters supplied.\n");
return AVERROR(EINVAL);
}
s->class = &aformat_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;
}
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}},
};
......@@ -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;
}
......
......@@ -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",
......
......@@ -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;
}
......
/*
* 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 }},
};
......@@ -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;
}
......
......@@ -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;
}
......
......@@ -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;
}
......
......@@ -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;
}
......
......@@ -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;
}
......
......@@ -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);
......@@ -129,10 +129,18 @@ void avfilter_register_all(void)
extern AVFilter avfilter_vsrc_buffer;
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);
......
......@@ -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;
......
......@@ -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)
{
......
This diff is collapsed.
......@@ -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.
......@@ -304,11 +303,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.
*/
......@@ -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;
};
/**
......
This diff is collapsed.
/*
* 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;
}
}
......@@ -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 }},
};
......@@ -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 */
This diff is collapsed.
......@@ -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 */
......@@ -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);
}
This diff is collapsed.
/*
* 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
......@@ -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);
......
......@@ -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;
}
......
......@@ -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
......@@ -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;
}
......
......@@ -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
......@@ -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}},
};
This diff is collapsed.
......@@ -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, \
......
......@@ -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(){
......
......@@ -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
......
......@@ -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
......
......@@ -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
......
This diff is collapsed.
#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
This diff is collapsed.
This diff is collapsed.
......@@ -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, \
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment