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

Merge remote-tracking branch 'qatar/master'

* qatar/master:
  x86: Only use optimizations with cmov if the CPU supports the instruction
  x86: Add CPU flag for the i686 cmov instruction
  x86: remove unused inline asm macros from dsputil_mmx.h
  x86: move some inline asm macros to the only places they are used
  lavfi: Add the af_channelmap audio channel mapping filter.
  lavfi: add join audio filter.
  lavfi: allow audio filters to request a given number of samples.
  lavfi: support automatically inserting the fifo filter when needed.
  lavfi/audio: eliminate ff_default_filter_samples().

Conflicts:
	Changelog
	libavcodec/x86/h264dsp_mmx.c
	libavfilter/Makefile
	libavfilter/allfilters.c
	libavfilter/avfilter.h
	libavfilter/avfiltergraph.c
	libavfilter/version.h
	libavutil/x86/cpu.c
Merged-by: 's avatarMichael Niedermayer <michaelni@gmx.at>
parents da728d5d fe07c9c6
...@@ -12,6 +12,8 @@ version next: ...@@ -12,6 +12,8 @@ version next:
- RTMPT protocol support - RTMPT protocol support
- iLBC encoding/decoding via libilbc - iLBC encoding/decoding via libilbc
- Microsoft Screen 1 decoder - Microsoft Screen 1 decoder
- join audio filter
- audio channel mapping filter
- showwaves filter - showwaves filter
- LucasArts SMUSH playback support - LucasArts SMUSH playback support
......
...@@ -4,7 +4,7 @@ since the last major version increase. ...@@ -4,7 +4,7 @@ since the last major version increase.
The last version increases were: The last version increases were:
libavcodec: 2012-01-27 libavcodec: 2012-01-27
libavdevice: 2011-04-18 libavdevice: 2011-04-18
libavfilter: 2011-04-18 libavfilter: 2012-06-22
libavformat: 2012-01-27 libavformat: 2012-01-27
libavresample: 2012-04-24 libavresample: 2012-04-24
libpostproc: 2011-04-18 libpostproc: 2011-04-18
......
...@@ -649,6 +649,76 @@ front_center.wav -map '[LFE]' lfe.wav -map '[SL]' side_left.wav -map '[SR]' ...@@ -649,6 +649,76 @@ front_center.wav -map '[LFE]' lfe.wav -map '[SL]' side_left.wav -map '[SR]'
side_right.wav side_right.wav
@end example @end example
@section channelmap
Remap input channels to new locations.
This filter accepts the following named parameters:
@table @option
@item channel_layout
Channel layout of the output stream.
@item map
Map channels from input to output. The argument is a comma-separated list of
mappings, each in the @code{@var{in_channel}-@var{out_channel}} or
@var{in_channel} form. @var{in_channel} can be either the name of the input
channel (e.g. FL for front left) or its index in the input channel layout.
@var{out_channel} is the name of the output channel or its index in the output
channel layout. If @var{out_channel} is not given then it is implicitly an
index, starting with zero and increasing by one for each mapping.
@end table
If no mapping is present, the filter will implicitly map input channels to
output channels preserving index.
For example, assuming a 5.1+downmix input MOV file
@example
ffmpeg -i in.mov -filter 'channelmap=map=DL-FL\,DR-FR' out.wav
@end example
will create an output WAV file tagged as stereo from the downmix channels of
the input.
To fix a 5.1 WAV improperly encoded in AAC's native channel order
@example
ffmpeg -i in.wav -filter 'channelmap=1\,2\,0\,5\,3\,4:channel_layout=5.1' out.wav
@end example
@section join
Join multiple input streams into one multi-channel stream.
The filter accepts the following named parameters:
@table @option
@item inputs
Number of input streams. Defaults to 2.
@item channel_layout
Desired output channel layout. Defaults to stereo.
@item map
Map channels from inputs to output. The argument is a comma-separated list of
mappings, each in the @code{@var{input_idx}.@var{in_channel}-@var{out_channel}}
form. @var{input_idx} is the 0-based index of the input stream. @var{in_channel}
can be either the name of the input channel (e.g. FR for front left) or its
index in the specified input stream. @var{out_channel} is the name of the output
channel.
@end table
The filter will attempt to guess the mappings when those are not specified
explicitly. It does so by first trying to find an unused matching input channel
and if that fails it picks the first unused input channel.
E.g. to join 3 inputs (with properly set channel layouts)
@example
ffmpeg -i INPUT1 -i INPUT2 -i INPUT3 -filter_complex join=inputs=3 OUTPUT
@end example
To build a 5.1 output from 6 single-channel streams:
@example
ffmpeg -i fl -i fr -i fc -i sl -i sr -i lfe -filter_complex
'join=inputs=6:channel_layout=5.1:map=0.0-FL\,1.0-FR\,2.0-FC\,3.0-SL\,4.0-SR\,5.0-LFE'
out
@end example
@section resample @section resample
Convert the audio sample format, sample rate and channel layout. This filter is Convert the audio sample format, sample rate and channel layout. This filter is
not meant to be used directly. not meant to be used directly.
......
...@@ -29,6 +29,12 @@ ...@@ -29,6 +29,12 @@
#include "libavcodec/cavsdsp.h" #include "libavcodec/cavsdsp.h"
#include "dsputil_mmx.h" #include "dsputil_mmx.h"
/* in/out: mma=mma+mmb, mmb=mmb-mma */
#define SUMSUB_BA( a, b ) \
"paddw "#b", "#a" \n\t"\
"paddw "#b", "#b" \n\t"\
"psubw "#a", "#b" \n\t"
/***************************************************************************** /*****************************************************************************
* *
* inverse transform * inverse transform
......
...@@ -631,6 +631,34 @@ static void add_hfyu_median_prediction_cmov(uint8_t *dst, const uint8_t *top, ...@@ -631,6 +631,34 @@ static void add_hfyu_median_prediction_cmov(uint8_t *dst, const uint8_t *top,
} }
#endif #endif
static inline void transpose4x4(uint8_t *dst, uint8_t *src, x86_reg dst_stride, x86_reg src_stride){
__asm__ volatile( //FIXME could save 1 instruction if done as 8x4 ...
"movd (%1), %%mm0 \n\t"
"add %3, %1 \n\t"
"movd (%1), %%mm1 \n\t"
"movd (%1,%3,1), %%mm2 \n\t"
"movd (%1,%3,2), %%mm3 \n\t"
"punpcklbw %%mm1, %%mm0 \n\t"
"punpcklbw %%mm3, %%mm2 \n\t"
"movq %%mm0, %%mm1 \n\t"
"punpcklwd %%mm2, %%mm0 \n\t"
"punpckhwd %%mm2, %%mm1 \n\t"
"movd %%mm0, (%0) \n\t"
"add %2, %0 \n\t"
"punpckhdq %%mm0, %%mm0 \n\t"
"movd %%mm0, (%0) \n\t"
"movd %%mm1, (%0,%2,1) \n\t"
"punpckhdq %%mm1, %%mm1 \n\t"
"movd %%mm1, (%0,%2,2) \n\t"
: "+&r" (dst),
"+&r" (src)
: "r" (dst_stride),
"r" (src_stride)
: "memory"
);
}
#define H263_LOOP_FILTER \ #define H263_LOOP_FILTER \
"pxor %%mm7, %%mm7 \n\t" \ "pxor %%mm7, %%mm7 \n\t" \
"movq %0, %%mm0 \n\t" \ "movq %0, %%mm0 \n\t" \
...@@ -2902,7 +2930,8 @@ static void dsputil_init_3dnow(DSPContext *c, AVCodecContext *avctx, ...@@ -2902,7 +2930,8 @@ static void dsputil_init_3dnow(DSPContext *c, AVCodecContext *avctx,
c->vorbis_inverse_coupling = vorbis_inverse_coupling_3dnow; c->vorbis_inverse_coupling = vorbis_inverse_coupling_3dnow;
#if HAVE_7REGS #if HAVE_7REGS
c->add_hfyu_median_prediction = add_hfyu_median_prediction_cmov; if (mm_flags & AV_CPU_FLAG_CMOV)
c->add_hfyu_median_prediction = add_hfyu_median_prediction_cmov;
#endif #endif
} }
......
...@@ -66,24 +66,6 @@ extern const xmm_reg ff_pb_FE; ...@@ -66,24 +66,6 @@ extern const xmm_reg ff_pb_FE;
extern const double ff_pd_1[2]; extern const double ff_pd_1[2];
extern const double ff_pd_2[2]; extern const double ff_pd_2[2];
#define LOAD4(stride,in,a,b,c,d)\
"movq 0*"#stride"+"#in", "#a"\n\t"\
"movq 1*"#stride"+"#in", "#b"\n\t"\
"movq 2*"#stride"+"#in", "#c"\n\t"\
"movq 3*"#stride"+"#in", "#d"\n\t"
#define STORE4(stride,out,a,b,c,d)\
"movq "#a", 0*"#stride"+"#out"\n\t"\
"movq "#b", 1*"#stride"+"#out"\n\t"\
"movq "#c", 2*"#stride"+"#out"\n\t"\
"movq "#d", 3*"#stride"+"#out"\n\t"
/* in/out: mma=mma+mmb, mmb=mmb-mma */
#define SUMSUB_BA( a, b ) \
"paddw "#b", "#a" \n\t"\
"paddw "#b", "#b" \n\t"\
"psubw "#a", "#b" \n\t"
#define SBUTTERFLY(a,b,t,n,m)\ #define SBUTTERFLY(a,b,t,n,m)\
"mov" #m " " #a ", " #t " \n\t" /* abcd */\ "mov" #m " " #a ", " #t " \n\t" /* abcd */\
"punpckl" #n " " #b ", " #a " \n\t" /* aebf */\ "punpckl" #n " " #b ", " #a " \n\t" /* aebf */\
...@@ -95,90 +77,6 @@ extern const double ff_pd_2[2]; ...@@ -95,90 +77,6 @@ extern const double ff_pd_2[2];
SBUTTERFLY(a,c,d,dq,q) /* a=aeim d=bfjn */\ SBUTTERFLY(a,c,d,dq,q) /* a=aeim d=bfjn */\
SBUTTERFLY(t,b,c,dq,q) /* t=cgko c=dhlp */ SBUTTERFLY(t,b,c,dq,q) /* t=cgko c=dhlp */
static inline void transpose4x4(uint8_t *dst, uint8_t *src, x86_reg dst_stride, x86_reg src_stride){
__asm__ volatile( //FIXME could save 1 instruction if done as 8x4 ...
"movd (%1), %%mm0 \n\t"
"add %3, %1 \n\t"
"movd (%1), %%mm1 \n\t"
"movd (%1,%3,1), %%mm2 \n\t"
"movd (%1,%3,2), %%mm3 \n\t"
"punpcklbw %%mm1, %%mm0 \n\t"
"punpcklbw %%mm3, %%mm2 \n\t"
"movq %%mm0, %%mm1 \n\t"
"punpcklwd %%mm2, %%mm0 \n\t"
"punpckhwd %%mm2, %%mm1 \n\t"
"movd %%mm0, (%0) \n\t"
"add %2, %0 \n\t"
"punpckhdq %%mm0, %%mm0 \n\t"
"movd %%mm0, (%0) \n\t"
"movd %%mm1, (%0,%2,1) \n\t"
"punpckhdq %%mm1, %%mm1 \n\t"
"movd %%mm1, (%0,%2,2) \n\t"
: "+&r" (dst),
"+&r" (src)
: "r" (dst_stride),
"r" (src_stride)
: "memory"
);
}
// e,f,g,h can be memory
// out: a,d,t,c
#define TRANSPOSE8x4(a,b,c,d,e,f,g,h,t)\
"punpcklbw " #e ", " #a " \n\t" /* a0 e0 a1 e1 a2 e2 a3 e3 */\
"punpcklbw " #f ", " #b " \n\t" /* b0 f0 b1 f1 b2 f2 b3 f3 */\
"punpcklbw " #g ", " #c " \n\t" /* c0 g0 c1 g1 c2 g2 d3 g3 */\
"punpcklbw " #h ", " #d " \n\t" /* d0 h0 d1 h1 d2 h2 d3 h3 */\
SBUTTERFLY(a, b, t, bw, q) /* a= a0 b0 e0 f0 a1 b1 e1 f1 */\
/* t= a2 b2 e2 f2 a3 b3 e3 f3 */\
SBUTTERFLY(c, d, b, bw, q) /* c= c0 d0 g0 h0 c1 d1 g1 h1 */\
/* b= c2 d2 g2 h2 c3 d3 g3 h3 */\
SBUTTERFLY(a, c, d, wd, q) /* a= a0 b0 c0 d0 e0 f0 g0 h0 */\
/* d= a1 b1 c1 d1 e1 f1 g1 h1 */\
SBUTTERFLY(t, b, c, wd, q) /* t= a2 b2 c2 d2 e2 f2 g2 h2 */\
/* c= a3 b3 c3 d3 e3 f3 g3 h3 */
#if ARCH_X86_64
// permutes 01234567 -> 05736421
#define TRANSPOSE8(a,b,c,d,e,f,g,h,t)\
SBUTTERFLY(a,b,%%xmm8,wd,dqa)\
SBUTTERFLY(c,d,b,wd,dqa)\
SBUTTERFLY(e,f,d,wd,dqa)\
SBUTTERFLY(g,h,f,wd,dqa)\
SBUTTERFLY(a,c,h,dq,dqa)\
SBUTTERFLY(%%xmm8,b,c,dq,dqa)\
SBUTTERFLY(e,g,b,dq,dqa)\
SBUTTERFLY(d,f,g,dq,dqa)\
SBUTTERFLY(a,e,f,qdq,dqa)\
SBUTTERFLY(%%xmm8,d,e,qdq,dqa)\
SBUTTERFLY(h,b,d,qdq,dqa)\
SBUTTERFLY(c,g,b,qdq,dqa)\
"movdqa %%xmm8, "#g" \n\t"
#else
#define TRANSPOSE8(a,b,c,d,e,f,g,h,t)\
"movdqa "#h", "#t" \n\t"\
SBUTTERFLY(a,b,h,wd,dqa)\
"movdqa "#h", 16"#t" \n\t"\
"movdqa "#t", "#h" \n\t"\
SBUTTERFLY(c,d,b,wd,dqa)\
SBUTTERFLY(e,f,d,wd,dqa)\
SBUTTERFLY(g,h,f,wd,dqa)\
SBUTTERFLY(a,c,h,dq,dqa)\
"movdqa "#h", "#t" \n\t"\
"movdqa 16"#t", "#h" \n\t"\
SBUTTERFLY(h,b,c,dq,dqa)\
SBUTTERFLY(e,g,b,dq,dqa)\
SBUTTERFLY(d,f,g,dq,dqa)\
SBUTTERFLY(a,e,f,qdq,dqa)\
SBUTTERFLY(h,d,e,qdq,dqa)\
"movdqa "#h", 16"#t" \n\t"\
"movdqa "#t", "#h" \n\t"\
SBUTTERFLY(h,b,d,qdq,dqa)\
SBUTTERFLY(c,g,b,qdq,dqa)\
"movdqa 16"#t", "#g" \n\t"
#endif
#define MOVQ_WONE(regd) \ #define MOVQ_WONE(regd) \
__asm__ volatile ( \ __asm__ volatile ( \
"pcmpeqd %%" #regd ", %%" #regd " \n\t" \ "pcmpeqd %%" #regd ", %%" #regd " \n\t" \
......
...@@ -362,7 +362,7 @@ void ff_h264dsp_init_x86(H264DSPContext *c, const int bit_depth, const int chrom ...@@ -362,7 +362,7 @@ void ff_h264dsp_init_x86(H264DSPContext *c, const int bit_depth, const int chrom
c->h264_idct_add8 = ff_h264_idct_add8_8_mmx; c->h264_idct_add8 = ff_h264_idct_add8_8_mmx;
c->h264_idct_add16intra = ff_h264_idct_add16intra_8_mmx; c->h264_idct_add16intra = ff_h264_idct_add16intra_8_mmx;
if (mm_flags & AV_CPU_FLAG_CMOV) if (mm_flags & AV_CPU_FLAG_CMOV)
c->h264_luma_dc_dequant_idct= ff_h264_luma_dc_dequant_idct_mmx; c->h264_luma_dc_dequant_idct = ff_h264_luma_dc_dequant_idct_mmx;
if (mm_flags & AV_CPU_FLAG_MMX2) { if (mm_flags & AV_CPU_FLAG_MMX2) {
c->h264_idct_dc_add = ff_h264_idct_dc_add_8_mmx2; c->h264_idct_dc_add = ff_h264_idct_dc_add_8_mmx2;
......
...@@ -59,8 +59,10 @@ OBJS-$(CONFIG_ASPLIT_FILTER) += split.o ...@@ -59,8 +59,10 @@ OBJS-$(CONFIG_ASPLIT_FILTER) += split.o
OBJS-$(CONFIG_ASTREAMSYNC_FILTER) += af_astreamsync.o OBJS-$(CONFIG_ASTREAMSYNC_FILTER) += af_astreamsync.o
OBJS-$(CONFIG_ASYNCTS_FILTER) += af_asyncts.o OBJS-$(CONFIG_ASYNCTS_FILTER) += af_asyncts.o
OBJS-$(CONFIG_ATEMPO_FILTER) += af_atempo.o OBJS-$(CONFIG_ATEMPO_FILTER) += af_atempo.o
OBJS-$(CONFIG_CHANNELMAP_FILTER) += af_channelmap.o
OBJS-$(CONFIG_CHANNELSPLIT_FILTER) += af_channelsplit.o OBJS-$(CONFIG_CHANNELSPLIT_FILTER) += af_channelsplit.o
OBJS-$(CONFIG_EARWAX_FILTER) += af_earwax.o OBJS-$(CONFIG_EARWAX_FILTER) += af_earwax.o
OBJS-$(CONFIG_JOIN_FILTER) += af_join.o
OBJS-$(CONFIG_PAN_FILTER) += af_pan.o OBJS-$(CONFIG_PAN_FILTER) += af_pan.o
OBJS-$(CONFIG_RESAMPLE_FILTER) += af_resample.o OBJS-$(CONFIG_RESAMPLE_FILTER) += af_resample.o
OBJS-$(CONFIG_SILENCEDETECT_FILTER) += af_silencedetect.o OBJS-$(CONFIG_SILENCEDETECT_FILTER) += af_silencedetect.o
......
...@@ -75,14 +75,14 @@ static int query_formats(AVFilterContext *ctx) ...@@ -75,14 +75,14 @@ static int query_formats(AVFilterContext *ctx)
AVFilterLink *outlink = ctx->outputs[0]; AVFilterLink *outlink = ctx->outputs[0];
AVFilterChannelLayouts *layouts; AVFilterChannelLayouts *layouts;
ff_formats_ref(avfilter_make_all_formats(AVMEDIA_TYPE_AUDIO), ff_formats_ref(ff_all_formats(AVMEDIA_TYPE_AUDIO),
&inlink->out_formats); &inlink->out_formats);
if (aconvert->out_sample_fmt != AV_SAMPLE_FMT_NONE) { if (aconvert->out_sample_fmt != AV_SAMPLE_FMT_NONE) {
formats = NULL; formats = NULL;
ff_add_format(&formats, aconvert->out_sample_fmt); ff_add_format(&formats, aconvert->out_sample_fmt);
ff_formats_ref(formats, &outlink->in_formats); ff_formats_ref(formats, &outlink->in_formats);
} else } else
ff_formats_ref(avfilter_make_all_formats(AVMEDIA_TYPE_AUDIO), ff_formats_ref(ff_all_formats(AVMEDIA_TYPE_AUDIO),
&outlink->in_formats); &outlink->in_formats);
ff_channel_layouts_ref(ff_all_channel_layouts(), ff_channel_layouts_ref(ff_all_channel_layouts(),
......
...@@ -134,8 +134,7 @@ AVFilter avfilter_af_aformat = { ...@@ -134,8 +134,7 @@ AVFilter avfilter_af_aformat = {
.priv_size = sizeof(AFormatContext), .priv_size = sizeof(AFormatContext),
.inputs = (AVFilterPad[]) {{ .name = "default", .inputs = (AVFilterPad[]) {{ .name = "default",
.type = AVMEDIA_TYPE_AUDIO, .type = AVMEDIA_TYPE_AUDIO, },
.filter_samples = ff_null_filter_samples },
{ .name = NULL}}, { .name = NULL}},
.outputs = (AVFilterPad[]) {{ .name = "default", .outputs = (AVFilterPad[]) {{ .name = "default",
.type = AVMEDIA_TYPE_AUDIO}, .type = AVMEDIA_TYPE_AUDIO},
......
...@@ -169,7 +169,7 @@ static int request_frame(AVFilterLink *outlink) ...@@ -169,7 +169,7 @@ static int request_frame(AVFilterLink *outlink)
for (i = 0; i < am->nb_inputs; i++) for (i = 0; i < am->nb_inputs; i++)
if (!am->in[i].nb_samples) if (!am->in[i].nb_samples)
if ((ret = avfilter_request_frame(ctx->inputs[i])) < 0) if ((ret = ff_request_frame(ctx->inputs[i])) < 0)
return ret; return ret;
return 0; return 0;
} }
......
...@@ -34,8 +34,7 @@ AVFilter avfilter_af_anull = { ...@@ -34,8 +34,7 @@ AVFilter avfilter_af_anull = {
.inputs = (const AVFilterPad[]) {{ .name = "default", .inputs = (const AVFilterPad[]) {{ .name = "default",
.type = AVMEDIA_TYPE_AUDIO, .type = AVMEDIA_TYPE_AUDIO,
.get_audio_buffer = ff_null_get_audio_buffer, .get_audio_buffer = ff_null_get_audio_buffer, },
.filter_samples = ff_null_filter_samples },
{ .name = NULL}}, { .name = NULL}},
.outputs = (const AVFilterPad[]) {{ .name = "default", .outputs = (const AVFilterPad[]) {{ .name = "default",
......
...@@ -112,7 +112,7 @@ static int query_formats(AVFilterContext *ctx) ...@@ -112,7 +112,7 @@ static int query_formats(AVFilterContext *ctx)
if(out_format != AV_SAMPLE_FMT_NONE) { if(out_format != AV_SAMPLE_FMT_NONE) {
out_formats = ff_make_format_list((int[]){ out_format, -1 }); out_formats = ff_make_format_list((int[]){ out_format, -1 });
} else } else
out_formats = avfilter_make_all_formats(AVMEDIA_TYPE_AUDIO); out_formats = ff_all_formats(AVMEDIA_TYPE_AUDIO);
ff_formats_ref(out_formats, &outlink->in_formats); ff_formats_ref(out_formats, &outlink->in_formats);
if(out_layout) { if(out_layout) {
...@@ -211,7 +211,7 @@ static int request_frame(AVFilterLink *outlink) ...@@ -211,7 +211,7 @@ static int request_frame(AVFilterLink *outlink)
aresample->req_fullfilled = 0; aresample->req_fullfilled = 0;
do{ do{
ret = avfilter_request_frame(ctx->inputs[0]); ret = ff_request_frame(ctx->inputs[0]);
}while(!aresample->req_fullfilled && ret>=0); }while(!aresample->req_fullfilled && ret>=0);
if (ret == AVERROR_EOF) { if (ret == AVERROR_EOF) {
......
...@@ -164,7 +164,7 @@ static int request_frame(AVFilterLink *outlink) ...@@ -164,7 +164,7 @@ static int request_frame(AVFilterLink *outlink)
asns->req_fullfilled = 0; asns->req_fullfilled = 0;
do { do {
ret = avfilter_request_frame(inlink); ret = ff_request_frame(inlink);
} while (!asns->req_fullfilled && ret >= 0); } while (!asns->req_fullfilled && ret >= 0);
if (ret == AVERROR_EOF) if (ret == AVERROR_EOF)
......
...@@ -157,7 +157,7 @@ static int request_frame(AVFilterLink *outlink) ...@@ -157,7 +157,7 @@ static int request_frame(AVFilterLink *outlink)
send_next(ctx); send_next(ctx);
} else { } else {
as->eof |= 1 << as->next_out; as->eof |= 1 << as->next_out;
avfilter_request_frame(ctx->inputs[as->next_out]); ff_request_frame(ctx->inputs[as->next_out]);
if (as->eof & (1 << as->next_out)) if (as->eof & (1 << as->next_out))
as->next_out = !as->next_out; as->next_out = !as->next_out;
} }
......
...@@ -1083,7 +1083,7 @@ static int request_frame(AVFilterLink *outlink) ...@@ -1083,7 +1083,7 @@ static int request_frame(AVFilterLink *outlink)
atempo->request_fulfilled = 0; atempo->request_fulfilled = 0;
do { do {
ret = avfilter_request_frame(ctx->inputs[0]); ret = ff_request_frame(ctx->inputs[0]);
} }
while (!atempo->request_fulfilled && ret >= 0); while (!atempo->request_fulfilled && ret >= 0);
......
This diff is collapsed.
This diff is collapsed.
...@@ -217,7 +217,7 @@ static int query_formats(AVFilterContext *ctx) ...@@ -217,7 +217,7 @@ static int query_formats(AVFilterContext *ctx)
pan->pure_gains = are_gains_pure(pan); pan->pure_gains = are_gains_pure(pan);
/* libswr supports any sample and packing formats */ /* libswr supports any sample and packing formats */
ff_set_common_formats(ctx, avfilter_make_all_formats(AVMEDIA_TYPE_AUDIO)); ff_set_common_formats(ctx, ff_all_formats(AVMEDIA_TYPE_AUDIO));
formats = ff_all_samplerates(); formats = ff_all_samplerates();
if (!formats) if (!formats)
......
...@@ -47,8 +47,10 @@ void avfilter_register_all(void) ...@@ -47,8 +47,10 @@ void avfilter_register_all(void)
REGISTER_FILTER (ASTREAMSYNC, astreamsync, af); REGISTER_FILTER (ASTREAMSYNC, astreamsync, af);
REGISTER_FILTER (ASYNCTS, asyncts, af); REGISTER_FILTER (ASYNCTS, asyncts, af);
REGISTER_FILTER (ATEMPO, atempo, af); REGISTER_FILTER (ATEMPO, atempo, af);
REGISTER_FILTER (CHANNELMAP, channelmap, af);
REGISTER_FILTER (CHANNELSPLIT,channelsplit,af); REGISTER_FILTER (CHANNELSPLIT,channelsplit,af);
REGISTER_FILTER (EARWAX, earwax, af); REGISTER_FILTER (EARWAX, earwax, af);
REGISTER_FILTER (JOIN, join, af);
REGISTER_FILTER (PAN, pan, af); REGISTER_FILTER (PAN, pan, af);
REGISTER_FILTER (SILENCEDETECT, silencedetect, af); REGISTER_FILTER (SILENCEDETECT, silencedetect, af);
REGISTER_FILTER (VOLUME, volume, af); REGISTER_FILTER (VOLUME, volume, af);
......
...@@ -150,32 +150,12 @@ fail: ...@@ -150,32 +150,12 @@ fail:
return NULL; return NULL;
} }
void ff_null_filter_samples(AVFilterLink *link, AVFilterBufferRef *samplesref) static void default_filter_samples(AVFilterLink *link,
AVFilterBufferRef *samplesref)
{ {
ff_filter_samples(link->dst->outputs[0], samplesref); ff_filter_samples(link->dst->outputs[0], samplesref);
} }
/* FIXME: samplesref is same as link->cur_buf. Need to consider removing the redundant parameter. */
void ff_default_filter_samples(AVFilterLink *inlink, AVFilterBufferRef *samplesref)
{
AVFilterLink *outlink = NULL;
if (inlink->dst->nb_outputs)
outlink = inlink->dst->outputs[0];
if (outlink) {
outlink->out_buf = ff_default_get_audio_buffer(inlink, AV_PERM_WRITE,
samplesref->audio->nb_samples);
outlink->out_buf->pts = samplesref->pts;
outlink->out_buf->audio->sample_rate = samplesref->audio->sample_rate;
ff_filter_samples(outlink, avfilter_ref_buffer(outlink->out_buf, ~0));
avfilter_unref_buffer(outlink->out_buf);
outlink->out_buf = NULL;
}
avfilter_unref_buffer(samplesref);
inlink->cur_buf = NULL;
}
void ff_filter_samples(AVFilterLink *link, AVFilterBufferRef *samplesref) void ff_filter_samples(AVFilterLink *link, AVFilterBufferRef *samplesref)
{ {
void (*filter_samples)(AVFilterLink *, AVFilterBufferRef *); void (*filter_samples)(AVFilterLink *, AVFilterBufferRef *);
...@@ -186,7 +166,7 @@ void ff_filter_samples(AVFilterLink *link, AVFilterBufferRef *samplesref) ...@@ -186,7 +166,7 @@ void ff_filter_samples(AVFilterLink *link, AVFilterBufferRef *samplesref)
FF_TPRINTF_START(NULL, filter_samples); ff_tlog_link(NULL, link, 1); FF_TPRINTF_START(NULL, filter_samples); ff_tlog_link(NULL, link, 1);
if (!(filter_samples = dst->filter_samples)) if (!(filter_samples = dst->filter_samples))
filter_samples = ff_default_filter_samples; filter_samples = default_filter_samples;
/* prepare to copy the samples if the buffer has insufficient permissions */ /* prepare to copy the samples if the buffer has insufficient permissions */
if ((dst->min_perms & samplesref->perms) != dst->min_perms || if ((dst->min_perms & samplesref->perms) != dst->min_perms ||
......
...@@ -63,12 +63,6 @@ AVFilterBufferRef *ff_null_get_audio_buffer(AVFilterLink *link, int perms, ...@@ -63,12 +63,6 @@ AVFilterBufferRef *ff_null_get_audio_buffer(AVFilterLink *link, int perms,
AVFilterBufferRef *ff_get_audio_buffer(AVFilterLink *link, int perms, AVFilterBufferRef *ff_get_audio_buffer(AVFilterLink *link, int perms,
int nb_samples); int nb_samples);
/** default handler for filter_samples() for audio inputs */
void ff_default_filter_samples(AVFilterLink *link, AVFilterBufferRef *samplesref);
/** filter_samples() handler for filters which simply pass audio along */
void ff_null_filter_samples(AVFilterLink *link, AVFilterBufferRef *samplesref);
/** /**
* Send a buffer of audio samples to the next filter. * Send a buffer of audio samples to the next filter.
* *
......
...@@ -170,7 +170,7 @@ static int request_frame(AVFilterLink *outlink) ...@@ -170,7 +170,7 @@ static int request_frame(AVFilterLink *outlink)
showwaves->req_fullfilled = 0; showwaves->req_fullfilled = 0;
do { do {
ret = avfilter_request_frame(inlink); ret = ff_request_frame(inlink);
} while (!showwaves->req_fullfilled && ret >= 0); } while (!showwaves->req_fullfilled && ret >= 0);
if (ret == AVERROR_EOF && showwaves->outpicref) if (ret == AVERROR_EOF && showwaves->outpicref)
......
...@@ -211,7 +211,6 @@ AVFilterBufferRef *avfilter_ref_buffer(AVFilterBufferRef *ref, int pmask); ...@@ -211,7 +211,6 @@ AVFilterBufferRef *avfilter_ref_buffer(AVFilterBufferRef *ref, int pmask);
*/ */
void avfilter_unref_buffer(AVFilterBufferRef *ref); void avfilter_unref_buffer(AVFilterBufferRef *ref);
#if FF_API_FILTERS_PUBLIC
/** /**
* Remove a reference to a buffer and set the pointer to NULL. * Remove a reference to a buffer and set the pointer to NULL.
* If this is the last reference to the buffer, the buffer itself * If this is the last reference to the buffer, the buffer itself
...@@ -221,6 +220,7 @@ void avfilter_unref_buffer(AVFilterBufferRef *ref); ...@@ -221,6 +220,7 @@ void avfilter_unref_buffer(AVFilterBufferRef *ref);
*/ */
void avfilter_unref_bufferp(AVFilterBufferRef **ref); void avfilter_unref_bufferp(AVFilterBufferRef **ref);
#if FF_API_FILTERS_PUBLIC
/** /**
* A list of supported formats for one end of a filter link. This is used * A list of supported formats for one end of a filter link. This is used
* during the format negotiation process to try to pick the best format to * during the format negotiation process to try to pick the best format to
...@@ -291,7 +291,7 @@ AVFilterFormats *avfilter_make_format_list(const int *fmts); ...@@ -291,7 +291,7 @@ AVFilterFormats *avfilter_make_format_list(const int *fmts);
* *
* @return a non negative value in case of success, or a negative * @return a non negative value in case of success, or a negative
* value corresponding to an AVERROR code in case of error * value corresponding to an AVERROR code in case of error
* @deprecated Use avfilter_make_all_formats() instead. * @deprecated Use ff_all_formats() instead.
*/ */
attribute_deprecated attribute_deprecated
int avfilter_add_format(AVFilterFormats **avff, int64_t fmt); int avfilter_add_format(AVFilterFormats **avff, int64_t fmt);
...@@ -479,7 +479,7 @@ struct AVFilterPad { ...@@ -479,7 +479,7 @@ struct AVFilterPad {
* Frame request callback. A call to this should result in at least one * Frame request callback. A call to this should result in at least one
* frame being output over the given link. This should return zero on * frame being output over the given link. This should return zero on
* success, and another value on error. * success, and another value on error.
* See avfilter_request_frame() for the error codes with a specific * See ff_request_frame() for the error codes with a specific
* meaning. * meaning.
* *
* Output pads only. * Output pads only.
...@@ -504,6 +504,14 @@ struct AVFilterPad { ...@@ -504,6 +504,14 @@ struct AVFilterPad {
* and another value on error. * and another value on error.
*/ */
int (*config_props)(AVFilterLink *link); int (*config_props)(AVFilterLink *link);
/**
* The filter expects a fifo to be inserted on its input link,
* typically because it has a delay.
*
* input pads only.
*/
int needs_fifo;
}; };
#endif #endif
...@@ -529,6 +537,10 @@ const char *avfilter_pad_get_name(AVFilterPad *pads, int pad_idx); ...@@ -529,6 +537,10 @@ const char *avfilter_pad_get_name(AVFilterPad *pads, int pad_idx);
*/ */
enum AVMediaType avfilter_pad_get_type(AVFilterPad *pads, int pad_idx); enum AVMediaType avfilter_pad_get_type(AVFilterPad *pads, int pad_idx);
/** default handler for end_frame() for video inputs */
attribute_deprecated
void avfilter_default_end_frame(AVFilterLink *link);
#if FF_API_FILTERS_PUBLIC #if FF_API_FILTERS_PUBLIC
/** default handler for start_frame() for video inputs */ /** default handler for start_frame() for video inputs */
attribute_deprecated attribute_deprecated
...@@ -538,10 +550,6 @@ void avfilter_default_start_frame(AVFilterLink *link, AVFilterBufferRef *picref) ...@@ -538,10 +550,6 @@ void avfilter_default_start_frame(AVFilterLink *link, AVFilterBufferRef *picref)
attribute_deprecated attribute_deprecated
void avfilter_default_draw_slice(AVFilterLink *link, int y, int h, int slice_dir); void avfilter_default_draw_slice(AVFilterLink *link, int y, int h, int slice_dir);
/** default handler for end_frame() for video inputs */
attribute_deprecated
void avfilter_default_end_frame(AVFilterLink *link);
/** default handler for get_video_buffer() for video inputs */ /** default handler for get_video_buffer() for video inputs */
attribute_deprecated attribute_deprecated
AVFilterBufferRef *avfilter_default_get_video_buffer(AVFilterLink *link, AVFilterBufferRef *avfilter_default_get_video_buffer(AVFilterLink *link,
...@@ -756,6 +764,15 @@ struct AVFilterLink { ...@@ -756,6 +764,15 @@ struct AVFilterLink {
struct AVFilterChannelLayouts *in_channel_layouts; struct AVFilterChannelLayouts *in_channel_layouts;
struct AVFilterChannelLayouts *out_channel_layouts; struct AVFilterChannelLayouts *out_channel_layouts;
/**
* Audio only, the destination filter sets this to a non-zero value to
* request that buffers with the given number of samples should be sent to
* it. AVFilterPad.needs_fifo must also be set on the corresponding input
* pad.
* Last buffer before EOF will be padded with silence.
*/
int request_samples;
struct AVFilterPool *pool; struct AVFilterPool *pool;
/** /**
...@@ -785,7 +802,6 @@ struct AVFilterLink { ...@@ -785,7 +802,6 @@ struct AVFilterLink {
* It is similar to the r_frae_rate field in AVStream. * It is similar to the r_frae_rate field in AVStream.
*/ */
AVRational frame_rate; AVRational frame_rate;
}; };
/** /**
......
...@@ -187,7 +187,7 @@ static int filter_query_formats(AVFilterContext *ctx) ...@@ -187,7 +187,7 @@ static int filter_query_formats(AVFilterContext *ctx)
if ((ret = ctx->filter->query_formats(ctx)) < 0) if ((ret = ctx->filter->query_formats(ctx)) < 0)
return ret; return ret;
formats = avfilter_make_all_formats(type); formats = ff_all_formats(type);
if (!formats) if (!formats)
return AVERROR(ENOMEM); return AVERROR(ENOMEM);
ff_set_common_formats(ctx, formats); ff_set_common_formats(ctx, formats);
...@@ -815,12 +815,52 @@ static int ff_avfilter_graph_config_pointers(AVFilterGraph *graph, ...@@ -815,12 +815,52 @@ static int ff_avfilter_graph_config_pointers(AVFilterGraph *graph,
return 0; return 0;
} }
static int graph_insert_fifos(AVFilterGraph *graph, AVClass *log_ctx)
{
AVFilterContext *f;
int i, j, ret;
int fifo_count = 0;
for (i = 0; i < graph->filter_count; i++) {
f = graph->filters[i];
for (j = 0; j < f->nb_inputs; j++) {
AVFilterLink *link = f->inputs[j];
AVFilterContext *fifo_ctx;
AVFilter *fifo;
char name[32];
if (!link->dstpad->needs_fifo)
continue;
fifo = f->inputs[j]->type == AVMEDIA_TYPE_VIDEO ?
avfilter_get_by_name("fifo") :
avfilter_get_by_name("afifo");
snprintf(name, sizeof(name), "auto-inserted fifo %d", fifo_count++);
ret = avfilter_graph_create_filter(&fifo_ctx, fifo, name, NULL,
NULL, graph);
if (ret < 0)
return ret;
ret = avfilter_insert_filter(link, fifo_ctx, 0, 0);
if (ret < 0)
return ret;
}
}
return 0;
}
int avfilter_graph_config(AVFilterGraph *graphctx, void *log_ctx) int avfilter_graph_config(AVFilterGraph *graphctx, void *log_ctx)
{ {
int ret; int ret;
if ((ret = graph_check_validity(graphctx, log_ctx))) if ((ret = graph_check_validity(graphctx, log_ctx)))
return ret; return ret;
if ((ret = graph_insert_fifos(graphctx, log_ctx)) < 0)
return ret;
if ((ret = graph_config_formats(graphctx, log_ctx))) if ((ret = graph_config_formats(graphctx, log_ctx)))
return ret; return ret;
if ((ret = graph_config_links(graphctx, log_ctx))) if ((ret = graph_config_links(graphctx, log_ctx)))
...@@ -939,7 +979,7 @@ int avfilter_graph_request_oldest(AVFilterGraph *graph) ...@@ -939,7 +979,7 @@ int avfilter_graph_request_oldest(AVFilterGraph *graph)
{ {
while (graph->sink_links_count) { while (graph->sink_links_count) {
AVFilterLink *oldest = graph->sink_links[0]; AVFilterLink *oldest = graph->sink_links[0];
int r = avfilter_request_frame(oldest); int r = ff_request_frame(oldest);
if (r != AVERROR_EOF) if (r != AVERROR_EOF)
return r; return r;
/* EOF: remove the link from the heap */ /* EOF: remove the link from the heap */
......
...@@ -257,7 +257,7 @@ char *avfilter_graph_dump(AVFilterGraph *graph, const char *options); ...@@ -257,7 +257,7 @@ char *avfilter_graph_dump(AVFilterGraph *graph, const char *options);
* of a filtergraph, only a convenience function to help drain a filtergraph * of a filtergraph, only a convenience function to help drain a filtergraph
* in a balanced way under normal circumstances. * in a balanced way under normal circumstances.
* *
* @return the return value of avfilter_request_frame, * @return the return value of ff_request_frame,
* or AVERROR_EOF of all links returned AVERROR_EOF. * or AVERROR_EOF of all links returned AVERROR_EOF.
*/ */
int avfilter_graph_request_oldest(AVFilterGraph *graph); int avfilter_graph_request_oldest(AVFilterGraph *graph);
......
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
#include "libavutil/audio_fifo.h" #include "libavutil/audio_fifo.h"
#include "libavutil/audioconvert.h" #include "libavutil/audioconvert.h"
#include "libavutil/fifo.h" #include "libavutil/avassert.h"
#include "libavutil/mathematics.h" #include "libavutil/mathematics.h"
#include "audio.h" #include "audio.h"
...@@ -34,86 +34,45 @@ ...@@ -34,86 +34,45 @@
#include "internal.h" #include "internal.h"
typedef struct { typedef struct {
AVFifoBuffer *fifo; ///< FIFO buffer of frame references AVFilterBufferRef *cur_buf; ///< last buffer delivered on the sink
AVAudioFifo *audio_fifo; ///< FIFO for audio samples AVAudioFifo *audio_fifo; ///< FIFO for audio samples
int64_t next_pts; ///< interpolating audio pts int64_t next_pts; ///< interpolating audio pts
} BufferSinkContext; } BufferSinkContext;
#define FIFO_INIT_SIZE 8
static av_cold void uninit(AVFilterContext *ctx) static av_cold void uninit(AVFilterContext *ctx)
{ {
BufferSinkContext *sink = ctx->priv; BufferSinkContext *sink = ctx->priv;
while (sink->fifo && av_fifo_size(sink->fifo)) {
AVFilterBufferRef *buf;
av_fifo_generic_read(sink->fifo, &buf, sizeof(buf), NULL);
avfilter_unref_buffer(buf);
}
av_fifo_free(sink->fifo);
if (sink->audio_fifo) if (sink->audio_fifo)
av_audio_fifo_free(sink->audio_fifo); av_audio_fifo_free(sink->audio_fifo);
} }
static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque) static void start_frame(AVFilterLink *link, AVFilterBufferRef *buf)
{
BufferSinkContext *sink = ctx->priv;
if (!(sink->fifo = av_fifo_alloc(FIFO_INIT_SIZE*sizeof(AVFilterBufferRef*)))) {
av_log(ctx, AV_LOG_ERROR, "Failed to allocate fifo\n");
return AVERROR(ENOMEM);
}
return 0;
}
static void write_buf(AVFilterContext *ctx, AVFilterBufferRef *buf)
{ {
BufferSinkContext *sink = ctx->priv; BufferSinkContext *s = link->dst->priv;
if (av_fifo_space(sink->fifo) < sizeof(AVFilterBufferRef *) &&
(av_fifo_realloc2(sink->fifo, av_fifo_size(sink->fifo) * 2) < 0)) {
av_log(ctx, AV_LOG_ERROR, "Error reallocating the FIFO.\n");
return;
}
av_fifo_generic_write(sink->fifo, &buf, sizeof(buf), NULL); // av_assert0(!s->cur_buf);
} s->cur_buf = buf;
static void end_frame(AVFilterLink *link)
{
write_buf(link->dst, link->cur_buf);
link->cur_buf = NULL; 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) int av_buffersink_read(AVFilterContext *ctx, AVFilterBufferRef **buf)
{ {
BufferSinkContext *sink = ctx->priv; BufferSinkContext *s = ctx->priv;
AVFilterLink *link = ctx->inputs[0]; AVFilterLink *link = ctx->inputs[0];
int ret; int ret;
if (!buf) { if (!buf)
if (av_fifo_size(sink->fifo)) return ff_poll_frame(ctx->inputs[0]);
return av_fifo_size(sink->fifo)/sizeof(*buf);
else
return ff_poll_frame(ctx->inputs[0]);
}
if (!av_fifo_size(sink->fifo) && if ((ret = ff_request_frame(link)) < 0)
(ret = ff_request_frame(link)) < 0)
return ret; return ret;
if (!av_fifo_size(sink->fifo)) if (!s->cur_buf)
return AVERROR(EINVAL); return AVERROR(EINVAL);
av_fifo_generic_read(sink->fifo, buf, sizeof(*buf), NULL); *buf = s->cur_buf;
s->cur_buf = NULL;
return 0; return 0;
} }
...@@ -182,13 +141,13 @@ AVFilter avfilter_vsink_buffer = { ...@@ -182,13 +141,13 @@ AVFilter avfilter_vsink_buffer = {
.name = "buffersink_old", .name = "buffersink_old",
.description = NULL_IF_CONFIG_SMALL("Buffer video frames, and make them available to the end of the filter graph."), .description = NULL_IF_CONFIG_SMALL("Buffer video frames, and make them available to the end of the filter graph."),
.priv_size = sizeof(BufferSinkContext), .priv_size = sizeof(BufferSinkContext),
.init = init,
.uninit = uninit, .uninit = uninit,
.inputs = (AVFilterPad[]) {{ .name = "default", .inputs = (AVFilterPad[]) {{ .name = "default",
.type = AVMEDIA_TYPE_VIDEO, .type = AVMEDIA_TYPE_VIDEO,
.end_frame = end_frame, .start_frame = start_frame,
.min_perms = AV_PERM_READ, }, .min_perms = AV_PERM_READ,
.needs_fifo = 1 },
{ .name = NULL }}, { .name = NULL }},
.outputs = (AVFilterPad[]) {{ .name = NULL }}, .outputs = (AVFilterPad[]) {{ .name = NULL }},
}; };
...@@ -197,13 +156,13 @@ AVFilter avfilter_asink_abuffer = { ...@@ -197,13 +156,13 @@ AVFilter avfilter_asink_abuffer = {
.name = "abuffersink_old", .name = "abuffersink_old",
.description = NULL_IF_CONFIG_SMALL("Buffer audio frames, and make them available to the end of the filter graph."), .description = NULL_IF_CONFIG_SMALL("Buffer audio frames, and make them available to the end of the filter graph."),
.priv_size = sizeof(BufferSinkContext), .priv_size = sizeof(BufferSinkContext),
.init = init,
.uninit = uninit, .uninit = uninit,
.inputs = (AVFilterPad[]) {{ .name = "default", .inputs = (AVFilterPad[]) {{ .name = "default",
.type = AVMEDIA_TYPE_AUDIO, .type = AVMEDIA_TYPE_AUDIO,
.filter_samples = filter_samples, .filter_samples = start_frame,
.min_perms = AV_PERM_READ, }, .min_perms = AV_PERM_READ,
.needs_fifo = 1 },
{ .name = NULL }}, { .name = NULL }},
.outputs = (AVFilterPad[]) {{ .name = NULL }}, .outputs = (AVFilterPad[]) {{ .name = NULL }},
}; };
...@@ -47,27 +47,6 @@ static void set_common_formats(AVFilterContext *ctx, AVFilterFormats *fmts, ...@@ -47,27 +47,6 @@ static void set_common_formats(AVFilterContext *ctx, AVFilterFormats *fmts,
} }
} }
void avfilter_set_common_pixel_formats(AVFilterContext *ctx, AVFilterFormats *formats)
{
set_common_formats(ctx, formats, AVMEDIA_TYPE_VIDEO,
offsetof(AVFilterLink, in_formats),
offsetof(AVFilterLink, out_formats));
}
void avfilter_set_common_sample_formats(AVFilterContext *ctx, AVFilterFormats *formats)
{
set_common_formats(ctx, formats, AVMEDIA_TYPE_AUDIO,
offsetof(AVFilterLink, in_formats),
offsetof(AVFilterLink, out_formats));
}
void avfilter_set_common_channel_layouts(AVFilterContext *ctx, AVFilterFormats *formats)
{
set_common_formats(ctx, formats, AVMEDIA_TYPE_AUDIO,
offsetof(AVFilterLink, in_channel_layouts),
offsetof(AVFilterLink, out_channel_layouts));
}
#if FF_API_PACKING #if FF_API_PACKING
void avfilter_set_common_packing_formats(AVFilterContext *ctx, AVFilterFormats *formats) void avfilter_set_common_packing_formats(AVFilterContext *ctx, AVFilterFormats *formats)
{ {
......
...@@ -23,6 +23,11 @@ ...@@ -23,6 +23,11 @@
* FIFO buffering filter * FIFO buffering filter
*/ */
#include "libavutil/avassert.h"
#include "libavutil/audioconvert.h"
#include "libavutil/mathematics.h"
#include "libavutil/samplefmt.h"
#include "audio.h" #include "audio.h"
#include "avfilter.h" #include "avfilter.h"
#include "internal.h" #include "internal.h"
...@@ -36,6 +41,13 @@ typedef struct Buf { ...@@ -36,6 +41,13 @@ typedef struct Buf {
typedef struct { typedef struct {
Buf root; Buf root;
Buf *last; ///< last buffered frame Buf *last; ///< last buffered frame
/**
* When a specific number of output samples is requested, the partial
* buffer is stored here
*/
AVFilterBufferRef *buf_out;
int allocated_samples; ///< number of samples buf_out was allocated for
} FifoContext; } FifoContext;
static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque) static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque)
...@@ -57,6 +69,8 @@ static av_cold void uninit(AVFilterContext *ctx) ...@@ -57,6 +69,8 @@ static av_cold void uninit(AVFilterContext *ctx)
avfilter_unref_buffer(buf->buf); avfilter_unref_buffer(buf->buf);
av_free(buf); av_free(buf);
} }
avfilter_unref_buffer(fifo->buf_out);
} }
static void add_to_queue(AVFilterLink *inlink, AVFilterBufferRef *buf) static void add_to_queue(AVFilterLink *inlink, AVFilterBufferRef *buf)
...@@ -68,14 +82,143 @@ static void add_to_queue(AVFilterLink *inlink, AVFilterBufferRef *buf) ...@@ -68,14 +82,143 @@ static void add_to_queue(AVFilterLink *inlink, AVFilterBufferRef *buf)
fifo->last->buf = buf; fifo->last->buf = buf;
} }
static void queue_pop(FifoContext *s)
{
Buf *tmp = s->root.next->next;
if (s->last == s->root.next)
s->last = &s->root;
av_freep(&s->root.next);
s->root.next = tmp;
}
static void end_frame(AVFilterLink *inlink) { } static void end_frame(AVFilterLink *inlink) { }
static void draw_slice(AVFilterLink *inlink, int y, int h, int slice_dir) { } static void draw_slice(AVFilterLink *inlink, int y, int h, int slice_dir) { }
/**
* Move data pointers and pts offset samples forward.
*/
static void buffer_offset(AVFilterLink *link, AVFilterBufferRef *buf,
int offset)
{
int nb_channels = av_get_channel_layout_nb_channels(link->channel_layout);
int planar = av_sample_fmt_is_planar(link->format);
int planes = planar ? nb_channels : 1;
int block_align = av_get_bytes_per_sample(link->format) * (planar ? 1 : nb_channels);
int i;
av_assert0(buf->audio->nb_samples > offset);
for (i = 0; i < planes; i++)
buf->extended_data[i] += block_align*offset;
if (buf->data != buf->extended_data)
memcpy(buf->data, buf->extended_data,
FFMIN(planes, FF_ARRAY_ELEMS(buf->data)) * sizeof(*buf->data));
buf->linesize[0] -= block_align*offset;
buf->audio->nb_samples -= offset;
if (buf->pts != AV_NOPTS_VALUE) {
buf->pts += av_rescale_q(offset, (AVRational){1, link->sample_rate},
link->time_base);
}
}
static int calc_ptr_alignment(AVFilterBufferRef *buf)
{
int planes = av_sample_fmt_is_planar(buf->format) ?
av_get_channel_layout_nb_channels(buf->audio->channel_layout) : 1;
int min_align = 128;
int p;
for (p = 0; p < planes; p++) {
int cur_align = 128;
while ((intptr_t)buf->extended_data[p] % cur_align)
cur_align >>= 1;
if (cur_align < min_align)
min_align = cur_align;
}
return min_align;
}
static int return_audio_frame(AVFilterContext *ctx)
{
AVFilterLink *link = ctx->outputs[0];
FifoContext *s = ctx->priv;
AVFilterBufferRef *head = s->root.next->buf;
AVFilterBufferRef *buf_out;
int ret;
if (!s->buf_out &&
head->audio->nb_samples >= link->request_samples &&
calc_ptr_alignment(head) >= 32) {
if (head->audio->nb_samples == link->request_samples) {
buf_out = head;
queue_pop(s);
} else {
buf_out = avfilter_ref_buffer(head, AV_PERM_READ);
buf_out->audio->nb_samples = link->request_samples;
buffer_offset(link, head, link->request_samples);
}
} else {
int nb_channels = av_get_channel_layout_nb_channels(link->channel_layout);
if (!s->buf_out) {
s->buf_out = ff_get_audio_buffer(link, AV_PERM_WRITE,
link->request_samples);
if (!s->buf_out)
return AVERROR(ENOMEM);
s->buf_out->audio->nb_samples = 0;
s->buf_out->pts = head->pts;
s->allocated_samples = link->request_samples;
} else if (link->request_samples != s->allocated_samples) {
av_log(ctx, AV_LOG_ERROR, "request_samples changed before the "
"buffer was returned.\n");
return AVERROR(EINVAL);
}
while (s->buf_out->audio->nb_samples < s->allocated_samples) {
int len = FFMIN(s->allocated_samples - s->buf_out->audio->nb_samples,
head->audio->nb_samples);
av_samples_copy(s->buf_out->extended_data, head->extended_data,
s->buf_out->audio->nb_samples, 0, len, nb_channels,
link->format);
s->buf_out->audio->nb_samples += len;
if (len == head->audio->nb_samples) {
avfilter_unref_buffer(head);
queue_pop(s);
if (!s->root.next &&
(ret = ff_request_frame(ctx->inputs[0])) < 0) {
if (ret == AVERROR_EOF) {
av_samples_set_silence(s->buf_out->extended_data,
s->buf_out->audio->nb_samples,
s->allocated_samples -
s->buf_out->audio->nb_samples,
nb_channels, link->format);
s->buf_out->audio->nb_samples = s->allocated_samples;
break;
}
return ret;
}
head = s->root.next->buf;
} else {
buffer_offset(link, head, len);
}
}
buf_out = s->buf_out;
s->buf_out = NULL;
}
ff_filter_samples(link, buf_out);
return 0;
}
static int request_frame(AVFilterLink *outlink) static int request_frame(AVFilterLink *outlink)
{ {
FifoContext *fifo = outlink->src->priv; FifoContext *fifo = outlink->src->priv;
Buf *tmp;
int ret; int ret;
if (!fifo->root.next) { if (!fifo->root.next) {
...@@ -90,20 +233,20 @@ static int request_frame(AVFilterLink *outlink) ...@@ -90,20 +233,20 @@ static int request_frame(AVFilterLink *outlink)
ff_start_frame(outlink, fifo->root.next->buf); ff_start_frame(outlink, fifo->root.next->buf);
ff_draw_slice (outlink, 0, outlink->h, 1); ff_draw_slice (outlink, 0, outlink->h, 1);
ff_end_frame (outlink); ff_end_frame (outlink);
queue_pop(fifo);
break; break;
case AVMEDIA_TYPE_AUDIO: case AVMEDIA_TYPE_AUDIO:
ff_filter_samples(outlink, fifo->root.next->buf); if (outlink->request_samples) {
return return_audio_frame(outlink->src);
} else {
ff_filter_samples(outlink, fifo->root.next->buf);
queue_pop(fifo);
}
break; break;
default: default:
return AVERROR(EINVAL); return AVERROR(EINVAL);
} }
if (fifo->last == fifo->root.next)
fifo->last = &fifo->root;
tmp = fifo->root.next->next;
av_free(fifo->root.next);
fifo->root.next = tmp;
return 0; return 0;
} }
......
...@@ -261,11 +261,6 @@ int ff_add_channel_layout(AVFilterChannelLayouts **l, uint64_t channel_layout) ...@@ -261,11 +261,6 @@ int ff_add_channel_layout(AVFilterChannelLayouts **l, uint64_t channel_layout)
} }
AVFilterFormats *ff_all_formats(enum AVMediaType type) AVFilterFormats *ff_all_formats(enum AVMediaType type)
{
return avfilter_make_all_formats(type);
}
AVFilterFormats *avfilter_make_all_formats(enum AVMediaType type)
{ {
AVFilterFormats *ret = NULL; AVFilterFormats *ret = NULL;
int fmt; int fmt;
......
...@@ -173,6 +173,14 @@ struct AVFilterPad { ...@@ -173,6 +173,14 @@ struct AVFilterPad {
* and another value on error. * and another value on error.
*/ */
int (*config_props)(AVFilterLink *link); int (*config_props)(AVFilterLink *link);
/**
* The filter expects a fifo to be inserted on its input link,
* typically because it has a delay.
*
* input pads only.
*/
int needs_fifo;
}; };
#endif #endif
......
...@@ -94,7 +94,7 @@ static const uint8_t offset[511][2]= { ...@@ -94,7 +94,7 @@ static const uint8_t offset[511][2]= {
{ 7, 1}, {15, 1}, { 7, 9}, {15, 9}, { 7, 3}, {15, 3}, { 7,11}, {15,11}, { 7, 1}, {15, 1}, { 7, 9}, {15, 9}, { 7, 3}, {15, 3}, { 7,11}, {15,11},
{ 7, 5}, {15, 5}, { 7,13}, {15,13}, { 7, 7}, {15, 7}, { 7,15}, {15,15}, { 7, 5}, {15, 5}, { 7,13}, {15,13}, { 7, 7}, {15, 7}, { 7,15}, {15,15},
{ 0, 0}, { 8, 0}, { 0, 8}, { 8, 8}, { 4, 4}, {12, 4}, { 4,12}, {12,12}, { 0, 4}, { 8, 4}, { 0,12}, { 8,12}, { 4, 0}, {12, 0}, { 4, 8}, {12, 8}, { 2, 2}, {10, 2}, { 2,10}, {10,10}, { 6, 6}, {14, 6}, { 6,14}, {14,14}, { 2, 6}, {10, 6}, { 2,14}, {10,14}, { 6, 2}, {14, 2}, { 6,10}, {14,10}, { 0, 2}, { 8, 2}, { 0,10}, { 8,10}, { 4, 6}, {12, 6}, { 4,14}, {12,14}, { 0, 6}, { 8, 6}, { 0,14}, { 8,14}, { 4, 2}, {12, 2}, { 4,10}, {12,10}, { 2, 0}, {10, 0}, { 2, 8}, {10, 8}, { 6, 4}, {14, 4}, { 6,12}, {14,12}, { 2, 4}, {10, 4}, { 2,12}, {10,12}, { 6, 0}, {14, 0}, { 6, 8}, {14, 8}, { 1, 1}, { 9, 1}, { 1, 9}, { 9, 9}, { 5, 5}, {13, 5}, { 5,13}, {13,13}, { 1, 5}, { 9, 5}, { 1,13}, { 9,13}, { 5, 1}, {13, 1}, { 5, 9}, {13, 9}, { 3, 3}, {11, 3}, { 3,11}, {11,11}, { 7, 7}, {15, 7}, { 7,15}, {15,15}, { 3, 7}, {11, 7}, { 3,15}, {11,15}, { 7, 3}, {15, 3}, { 7,11}, {15,11}, { 1, 3}, { 9, 3}, { 1,11}, { 9,11}, { 5, 7}, {13, 7}, { 5,15}, {13,15}, { 1, 7}, { 9, 7}, { 1,15}, { 9,15}, { 5, 3}, {13, 3}, { 5,11}, {13,11}, { 3, 1}, {11, 1}, { 3, 9}, {11, 9}, { 7, 5}, {15, 5}, { 7,13}, {15,13}, { 3, 5}, {11, 5}, { 3,13}, {11,13}, { 7, 1}, {15, 1}, { 7, 9}, {15, 9}, { 0, 1}, { 8, 1}, { 0, 9}, { 8, 9}, { 4, 5}, {12, 5}, { 4,13}, {12,13}, { 0, 5}, { 8, 5}, { 0,13}, { 8,13}, { 4, 1}, {12, 1}, { 4, 9}, {12, 9}, { 2, 3}, {10, 3}, { 2,11}, {10,11}, { 6, 7}, {14, 7}, { 6,15}, {14,15}, { 2, 7}, {10, 7}, { 2,15}, {10,15}, { 6, 3}, {14, 3}, { 6,11}, {14,11}, { 0, 3}, { 8, 3}, { 0,11}, { 8,11}, { 4, 7}, {12, 7}, { 4,15}, {12,15}, { 0, 7}, { 8, 7}, { 0,15}, { 8,15}, { 4, 3}, {12, 3}, { 4,11}, {12,11}, { 2, 1}, {10, 1}, { 2, 9}, {10, 9}, { 6, 5}, {14, 5}, { 6,13}, {14,13}, { 2, 5}, {10, 5}, { 2,13}, {10,13}, { 6, 1}, {14, 1}, { 6, 9}, {14, 9}, { 1, 0}, { 9, 0}, { 1, 8}, { 9, 8}, { 5, 4}, {13, 4}, { 5,12}, {13,12}, { 1, 4}, { 9, 4}, { 1,12}, { 9,12}, { 5, 0}, {13, 0}, { 5, 8}, {13, 8}, { 3, 2}, {11, 2}, { 3,10}, {11,10}, { 7, 6}, {15, 6}, { 7,14}, {15,14}, { 3, 6}, {11, 6}, { 3,14}, {11,14}, { 7, 2}, {15, 2}, { 7,10}, {15,10}, { 1, 2}, { 9, 2}, { 1,10}, { 9,10}, { 5, 6}, {13, 6}, { 5,14}, {13,14}, { 1, 6}, { 9, 6}, { 1,14}, { 9,14}, { 5, 2}, {13, 2}, { 5,10}, {13,10}, { 3, 0}, {11, 0}, { 3, 8}, {11, 8}, { 7, 4}, {15, 4}, { 7,12}, {15,12}, { 3, 4}, {11, 4}, { 3,12}, {11,12}, { 7, 0}, {15, 0}, { 7, 8}, {15, 8}, { 0, 0}, { 8, 0}, { 0, 8}, { 8, 8}, { 4, 4}, {12, 4}, { 4,12}, {12,12}, { 0, 4}, { 8, 4}, { 0,12}, { 8,12}, { 4, 0}, {12, 0}, { 4, 8}, {12, 8}, { 2, 2}, {10, 2}, { 2,10}, {10,10}, { 6, 6}, {14, 6}, { 6,14}, {14,14}, { 2, 6}, {10, 6}, { 2,14}, {10,14}, { 6, 2}, {14, 2}, { 6,10}, {14,10}, { 0, 2}, { 8, 2}, { 0,10}, { 8,10}, { 4, 6}, {12, 6}, { 4,14}, {12,14}, { 0, 6}, { 8, 6}, { 0,14}, { 8,14}, { 4, 2}, {12, 2}, { 4,10}, {12,10}, { 2, 0}, {10, 0}, { 2, 8}, {10, 8}, { 6, 4}, {14, 4}, { 6,12}, {14,12}, { 2, 4}, {10, 4}, { 2,12}, {10,12}, { 6, 0}, {14, 0}, { 6, 8}, {14, 8}, { 1, 1}, { 9, 1}, { 1, 9}, { 9, 9}, { 5, 5}, {13, 5}, { 5,13}, {13,13}, { 1, 5}, { 9, 5}, { 1,13}, { 9,13}, { 5, 1}, {13, 1}, { 5, 9}, {13, 9}, { 3, 3}, {11, 3}, { 3,11}, {11,11}, { 7, 7}, {15, 7}, { 7,15}, {15,15}, { 3, 7}, {11, 7}, { 3,15}, {11,15}, { 7, 3}, {15, 3}, { 7,11}, {15,11}, { 1, 3}, { 9, 3}, { 1,11}, { 9,11}, { 5, 7}, {13, 7}, { 5,15}, {13,15}, { 1, 7}, { 9, 7}, { 1,15}, { 9,15}, { 5, 3}, {13, 3}, { 5,11}, {13,11}, { 3, 1}, {11,1}, { 3, 9}, {11, 9}, { 7, 5}, {15, 5}, { 7,13}, {15,13}, { 3, 5}, {11, 5}, { 3,13}, {11,13}, { 7, 1}, {15, 1}, { 7, 9}, {15, 9}, { 0, 1}, { 8, 1}, { 0, 9}, { 8, 9}, { 4, 5}, {12, 5}, { 4,13}, {12,13}, { 0, 5}, { 8, 5}, { 0,13}, { 8,13}, { 4, 1}, {12, 1}, { 4, 9}, {12, 9}, { 2, 3}, {10, 3}, { 2,11}, {10,11}, { 6, 7}, {14, 7}, { 6,15}, {14,15}, { 2, 7}, {10, 7}, { 2,15}, {10,15}, { 6, 3}, {14, 3}, { 6,11}, {14,11}, { 0, 3}, { 8, 3}, { 0,11}, { 8,11}, { 4, 7}, {12, 7}, { 4,15}, {12,15}, { 0, 7}, { 8, 7}, { 0,15}, { 8,15}, { 4, 3}, {12, 3}, { 4,11}, {12,11}, { 2, 1}, {10, 1}, { 2, 9}, {10, 9}, { 6, 5}, {14, 5}, { 6,13}, {14,13}, { 2, 5}, {10, 5}, { 2,13}, {10,13}, { 6, 1}, {14, 1}, { 6, 9}, {14, 9}, { 1, 0}, { 9, 0}, { 1, 8}, { 9, 8}, { 5, 4}, {13, 4}, { 5,12}, {13,12}, { 1, 4}, { 9, 4}, { 1,12}, { 9,12}, { 5, 0}, {13, 0}, { 5, 8}, {13, 8}, { 3, 2}, {11, 2}, { 3,10}, {11,10}, { 7, 6}, {15, 6}, { 7,14}, {15,14}, { 3, 6}, {11, 6}, { 3,14}, {11,14}, { 7, 2}, {15, 2}, { 7,10}, {15,10}, { 1, 2}, { 9, 2}, { 1,10}, {9,10}, { 5, 6}, {13, 6}, { 5,14}, {13,14}, { 1, 6}, { 9, 6}, { 1,14}, { 9,14}, { 5, 2}, {13, 2}, { 5,10}, {13,10}, { 3, 0}, {11, 0}, { 3, 8}, {11, 8}, { 7, 4}, {15, 4}, { 7,12}, {15,12}, { 3, 4}, {11, 4}, { 3,12}, {11,12}, { 7, 0}, {15, 0}, { 7, 8}, {15, 8},
}; };
struct vf_priv_s { struct vf_priv_s {
......
...@@ -127,7 +127,7 @@ int av_buffersink_get_buffer_ref(AVFilterContext *ctx, ...@@ -127,7 +127,7 @@ int av_buffersink_get_buffer_ref(AVFilterContext *ctx,
if (!av_fifo_size(buf->fifo)) { if (!av_fifo_size(buf->fifo)) {
if (flags & AV_BUFFERSINK_FLAG_NO_REQUEST) if (flags & AV_BUFFERSINK_FLAG_NO_REQUEST)
return AVERROR(EAGAIN); return AVERROR(EAGAIN);
if ((ret = avfilter_request_frame(inlink)) < 0) if ((ret = ff_request_frame(inlink)) < 0)
return ret; return ret;
} }
......
...@@ -28,8 +28,8 @@ ...@@ -28,8 +28,8 @@
#include "libavutil/avutil.h" #include "libavutil/avutil.h"
#define LIBAVFILTER_VERSION_MAJOR 2 #define LIBAVFILTER_VERSION_MAJOR 3
#define LIBAVFILTER_VERSION_MINOR 82 #define LIBAVFILTER_VERSION_MINOR 0
#define LIBAVFILTER_VERSION_MICRO 100 #define LIBAVFILTER_VERSION_MICRO 100
#define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \ #define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \
......
...@@ -136,7 +136,7 @@ static int request_frame(AVFilterLink *outlink) ...@@ -136,7 +136,7 @@ static int request_frame(AVFilterLink *outlink)
AVFilterContext *ctx = outlink->src; AVFilterContext *ctx = outlink->src;
BlackDetectContext *blackdetect = ctx->priv; BlackDetectContext *blackdetect = ctx->priv;
AVFilterLink *inlink = ctx->inputs[0]; AVFilterLink *inlink = ctx->inputs[0];
int ret = avfilter_request_frame(inlink); int ret = ff_request_frame(inlink);
if (ret == AVERROR_EOF && blackdetect->black_started) { if (ret == AVERROR_EOF && blackdetect->black_started) {
// FIXME: black_end should be set to last_picref_pts + last_picref_duration // FIXME: black_end should be set to last_picref_pts + last_picref_duration
......
...@@ -216,7 +216,7 @@ static int request_frame(AVFilterLink *link) ...@@ -216,7 +216,7 @@ static int request_frame(AVFilterLink *link)
do { do {
int ret; int ret;
if ((ret = avfilter_request_frame(link->src->inputs[0]))) if ((ret = ff_request_frame(link->src->inputs[0])))
return ret; return ret;
} while (!idet->cur); } while (!idet->cur);
...@@ -231,7 +231,7 @@ static int poll_frame(AVFilterLink *link) ...@@ -231,7 +231,7 @@ static int poll_frame(AVFilterLink *link)
val = ff_poll_frame(link->src->inputs[0]); val = ff_poll_frame(link->src->inputs[0]);
if (val >= 1 && !idet->next) { //FIXME change API to not requre this red tape if (val >= 1 && !idet->next) { //FIXME change API to not requre this red tape
if ((ret = avfilter_request_frame(link->src->inputs[0])) < 0) if ((ret = ff_request_frame(link->src->inputs[0])) < 0)
return ret; return ret;
val = ff_poll_frame(link->src->inputs[0]); val = ff_poll_frame(link->src->inputs[0]);
} }
......
...@@ -25,6 +25,9 @@ ...@@ -25,6 +25,9 @@
*/ */
#include "avfilter.h" #include "avfilter.h"
#include "video.h"
#include "formats.h"
#include "internal.h"
#include "libavutil/avassert.h" #include "libavutil/avassert.h"
#include "libavutil/pixdesc.h" #include "libavutil/pixdesc.h"
#include "libavutil/intreadwrite.h" #include "libavutil/intreadwrite.h"
...@@ -633,9 +636,9 @@ int vf_next_put_image(struct vf_instance *vf,mp_image_t *mpi, double pts){ ...@@ -633,9 +636,9 @@ int vf_next_put_image(struct vf_instance *vf,mp_image_t *mpi, double pts){
if(pts != MP_NOPTS_VALUE) if(pts != MP_NOPTS_VALUE)
picref->pts= pts * av_q2d(outlink->time_base); picref->pts= pts * av_q2d(outlink->time_base);
avfilter_start_frame(outlink, avfilter_ref_buffer(picref, ~0)); ff_start_frame(outlink, avfilter_ref_buffer(picref, ~0));
avfilter_draw_slice(outlink, 0, picref->video->h, 1); ff_draw_slice(outlink, 0, picref->video->h, 1);
avfilter_end_frame(outlink); ff_end_frame(outlink);
avfilter_unref_buffer(picref); avfilter_unref_buffer(picref);
m->frame_returned++; m->frame_returned++;
...@@ -788,14 +791,14 @@ static int query_formats(AVFilterContext *ctx) ...@@ -788,14 +791,14 @@ static int query_formats(AVFilterContext *ctx)
if(m->vf.query_format(&m->vf, conversion_map[i].fmt)){ if(m->vf.query_format(&m->vf, conversion_map[i].fmt)){
av_log(ctx, AV_LOG_DEBUG, "supported,adding\n"); av_log(ctx, AV_LOG_DEBUG, "supported,adding\n");
if (conversion_map[i].pix_fmt != lastpixfmt) { if (conversion_map[i].pix_fmt != lastpixfmt) {
avfilter_add_format(&avfmts, conversion_map[i].pix_fmt); ff_add_format(&avfmts, conversion_map[i].pix_fmt);
lastpixfmt = conversion_map[i].pix_fmt; lastpixfmt = conversion_map[i].pix_fmt;
} }
} }
} }
//We assume all allowed input formats are also allowed output formats //We assume all allowed input formats are also allowed output formats
avfilter_set_common_pixel_formats(ctx, avfmts); ff_set_common_formats(ctx, avfmts);
return 0; return 0;
} }
...@@ -836,7 +839,7 @@ static int request_frame(AVFilterLink *outlink) ...@@ -836,7 +839,7 @@ static int request_frame(AVFilterLink *outlink)
av_log(m->avfctx, AV_LOG_DEBUG, "mp request_frame\n"); av_log(m->avfctx, AV_LOG_DEBUG, "mp request_frame\n");
for(m->frame_returned=0; !m->frame_returned;){ for(m->frame_returned=0; !m->frame_returned;){
ret=avfilter_request_frame(outlink->src->inputs[0]); ret=ff_request_frame(outlink->src->inputs[0]);
if(ret<0) if(ret<0)
break; break;
} }
......
...@@ -178,7 +178,7 @@ static int request_frame(AVFilterLink *link) ...@@ -178,7 +178,7 @@ static int request_frame(AVFilterLink *link)
/* loop until a frame thumbnail is available (when a frame is queued, /* loop until a frame thumbnail is available (when a frame is queued,
* thumb->n is reset to zero) */ * thumb->n is reset to zero) */
do { do {
int ret = avfilter_request_frame(link->src->inputs[0]); int ret = ff_request_frame(link->src->inputs[0]);
if (ret < 0) if (ret < 0)
return ret; return ret;
} while (thumb->n); } while (thumb->n);
...@@ -203,7 +203,7 @@ static int poll_frame(AVFilterLink *link) ...@@ -203,7 +203,7 @@ static int poll_frame(AVFilterLink *link)
/* we have some frame(s) available in the input link, but not yet enough to /* we have some frame(s) available in the input link, but not yet enough to
* output a thumbnail, so we request more */ * output a thumbnail, so we request more */
ret = avfilter_request_frame(inlink); ret = ff_request_frame(inlink);
return ret < 0 ? ret : 0; return ret < 0 ? ret : 0;
} }
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include "drawutils.h" #include "drawutils.h"
#include "formats.h" #include "formats.h"
#include "video.h" #include "video.h"
#include "internal.h"
typedef struct { typedef struct {
unsigned w, h; unsigned w, h;
...@@ -170,7 +171,7 @@ static int request_frame(AVFilterLink *outlink) ...@@ -170,7 +171,7 @@ static int request_frame(AVFilterLink *outlink)
int r; int r;
while (1) { while (1) {
r = avfilter_request_frame(inlink); r = ff_request_frame(inlink);
if (r < 0) { if (r < 0) {
if (r == AVERROR_EOF && tile->current) if (r == AVERROR_EOF && tile->current)
end_last_frame(ctx); end_last_frame(ctx);
......
...@@ -334,7 +334,7 @@ static int poll_frame(AVFilterLink *outlink) ...@@ -334,7 +334,7 @@ static int poll_frame(AVFilterLink *outlink)
val = ff_poll_frame(inlink); val = ff_poll_frame(inlink);
if (val == 1 && !tinterlace->next) { if (val == 1 && !tinterlace->next) {
if ((ret = avfilter_request_frame(inlink)) < 0) if ((ret = ff_request_frame(inlink)) < 0)
return ret; return ret;
val = ff_poll_frame(inlink); val = ff_poll_frame(inlink);
} }
...@@ -351,7 +351,7 @@ static int request_frame(AVFilterLink *outlink) ...@@ -351,7 +351,7 @@ static int request_frame(AVFilterLink *outlink)
do { do {
int ret; int ret;
if ((ret = avfilter_request_frame(inlink)) < 0) if ((ret = ff_request_frame(inlink)) < 0)
return ret; return ret;
} while (!tinterlace->cur); } while (!tinterlace->cur);
......
...@@ -321,6 +321,11 @@ void ff_draw_slice(AVFilterLink *link, int y, int h, int slice_dir) ...@@ -321,6 +321,11 @@ void ff_draw_slice(AVFilterLink *link, int y, int h, int slice_dir)
draw_slice(link, y, h, slice_dir); draw_slice(link, y, h, slice_dir);
} }
void avfilter_default_end_frame(AVFilterLink *inlink)
{
default_end_frame(inlink);
}
#if FF_API_FILTERS_PUBLIC #if FF_API_FILTERS_PUBLIC
AVFilterBufferRef *avfilter_default_get_video_buffer(AVFilterLink *link, int perms, int w, int h) AVFilterBufferRef *avfilter_default_get_video_buffer(AVFilterLink *link, int perms, int w, int h)
{ {
...@@ -330,10 +335,6 @@ void avfilter_default_start_frame(AVFilterLink *inlink, AVFilterBufferRef *picre ...@@ -330,10 +335,6 @@ void avfilter_default_start_frame(AVFilterLink *inlink, AVFilterBufferRef *picre
{ {
default_start_frame(inlink, picref); default_start_frame(inlink, picref);
} }
void avfilter_default_end_frame(AVFilterLink *inlink)
{
default_end_frame(inlink);
}
void avfilter_default_draw_slice(AVFilterLink *inlink, int y, int h, int slice_dir) void avfilter_default_draw_slice(AVFilterLink *inlink, int y, int h, int slice_dir)
{ {
default_draw_slice(inlink, y, h, slice_dir); default_draw_slice(inlink, y, h, slice_dir);
......
...@@ -49,7 +49,7 @@ void av_set_cpu_flags_mask(int mask) ...@@ -49,7 +49,7 @@ void av_set_cpu_flags_mask(int mask)
int av_parse_cpu_flags(const char *s) int av_parse_cpu_flags(const char *s)
{ {
#define CPUFLAG_MMX2 (AV_CPU_FLAG_MMX | AV_CPU_FLAG_MMX2) #define CPUFLAG_MMX2 (AV_CPU_FLAG_MMX | AV_CPU_FLAG_MMX2 | AV_CPU_FLAG_CMOV)
#define CPUFLAG_3DNOW (AV_CPU_FLAG_3DNOW | AV_CPU_FLAG_MMX) #define CPUFLAG_3DNOW (AV_CPU_FLAG_3DNOW | AV_CPU_FLAG_MMX)
#define CPUFLAG_3DNOWEXT (AV_CPU_FLAG_3DNOWEXT | CPUFLAG_3DNOW) #define CPUFLAG_3DNOWEXT (AV_CPU_FLAG_3DNOWEXT | CPUFLAG_3DNOW)
#define CPUFLAG_SSE (AV_CPU_FLAG_SSE | CPUFLAG_MMX2) #define CPUFLAG_SSE (AV_CPU_FLAG_SSE | CPUFLAG_MMX2)
...@@ -84,6 +84,7 @@ int av_parse_cpu_flags(const char *s) ...@@ -84,6 +84,7 @@ int av_parse_cpu_flags(const char *s)
{ "fma4" , NULL, 0, AV_OPT_TYPE_CONST, { CPUFLAG_FMA4 }, .unit = "flags" }, { "fma4" , NULL, 0, AV_OPT_TYPE_CONST, { CPUFLAG_FMA4 }, .unit = "flags" },
{ "3dnow" , NULL, 0, AV_OPT_TYPE_CONST, { CPUFLAG_3DNOW }, .unit = "flags" }, { "3dnow" , NULL, 0, AV_OPT_TYPE_CONST, { CPUFLAG_3DNOW }, .unit = "flags" },
{ "3dnowext", NULL, 0, AV_OPT_TYPE_CONST, { CPUFLAG_3DNOWEXT }, .unit = "flags" }, { "3dnowext", NULL, 0, AV_OPT_TYPE_CONST, { CPUFLAG_3DNOWEXT }, .unit = "flags" },
{ "cmov", NULL, 0, AV_OPT_TYPE_CONST, { AV_CPU_FLAG_CMOV }, .unit = "flags" },
#elif ARCH_ARM #elif ARCH_ARM
{ "armv5te", NULL, 0, AV_OPT_TYPE_CONST, { AV_CPU_FLAG_ARMV5TE }, .unit = "flags" }, { "armv5te", NULL, 0, AV_OPT_TYPE_CONST, { AV_CPU_FLAG_ARMV5TE }, .unit = "flags" },
{ "armv6", NULL, 0, AV_OPT_TYPE_CONST, { AV_CPU_FLAG_ARMV6 }, .unit = "flags" }, { "armv6", NULL, 0, AV_OPT_TYPE_CONST, { AV_CPU_FLAG_ARMV6 }, .unit = "flags" },
...@@ -188,6 +189,7 @@ static const struct { ...@@ -188,6 +189,7 @@ static const struct {
{ AV_CPU_FLAG_FMA4, "fma4" }, { AV_CPU_FLAG_FMA4, "fma4" },
{ AV_CPU_FLAG_3DNOW, "3dnow" }, { AV_CPU_FLAG_3DNOW, "3dnow" },
{ AV_CPU_FLAG_3DNOWEXT, "3dnowext" }, { AV_CPU_FLAG_3DNOWEXT, "3dnowext" },
{ AV_CPU_FLAG_CMOV, "cmov" },
#endif #endif
{ 0 } { 0 }
}; };
......
...@@ -40,9 +40,14 @@ ...@@ -40,9 +40,14 @@
#define AV_CPU_FLAG_SSE4 0x0100 ///< Penryn SSE4.1 functions #define AV_CPU_FLAG_SSE4 0x0100 ///< Penryn SSE4.1 functions
#define AV_CPU_FLAG_SSE42 0x0200 ///< Nehalem SSE4.2 functions #define AV_CPU_FLAG_SSE42 0x0200 ///< Nehalem SSE4.2 functions
#define AV_CPU_FLAG_AVX 0x4000 ///< AVX functions: requires OS support even if YMM registers aren't used #define AV_CPU_FLAG_AVX 0x4000 ///< AVX functions: requires OS support even if YMM registers aren't used
#define AV_CPU_FLAG_CMOV 0x1000000 ///< supports cmov instruction
#define AV_CPU_FLAG_XOP 0x0400 ///< Bulldozer XOP functions #define AV_CPU_FLAG_XOP 0x0400 ///< Bulldozer XOP functions
#define AV_CPU_FLAG_FMA4 0x0800 ///< Bulldozer FMA4 functions #define AV_CPU_FLAG_FMA4 0x0800 ///< Bulldozer FMA4 functions
#if LIBAVUTIL_VERSION_MAJOR <52
#define AV_CPU_FLAG_CMOV 0x1001000 ///< supports cmov instruction
#else
#define AV_CPU_FLAG_CMOV 0x1000 ///< supports cmov instruction
#endif
#define AV_CPU_FLAG_ALTIVEC 0x0001 ///< standard #define AV_CPU_FLAG_ALTIVEC 0x0001 ///< standard
#define AV_CPU_FLAG_ARMV5TE (1 << 0) #define AV_CPU_FLAG_ARMV5TE (1 << 0)
......
...@@ -83,7 +83,7 @@ int ff_get_cpu_flags_x86(void) ...@@ -83,7 +83,7 @@ int ff_get_cpu_flags_x86(void)
cpuid(1, eax, ebx, ecx, std_caps); cpuid(1, eax, ebx, ecx, std_caps);
family = ((eax>>8)&0xf) + ((eax>>20)&0xff); family = ((eax>>8)&0xf) + ((eax>>20)&0xff);
model = ((eax>>4)&0xf) + ((eax>>12)&0xf0); model = ((eax>>4)&0xf) + ((eax>>12)&0xf0);
if (std_caps & (1<<15)) if (std_caps & (1 << 15))
rval |= AV_CPU_FLAG_CMOV; rval |= AV_CPU_FLAG_CMOV;
if (std_caps & (1<<23)) if (std_caps & (1<<23))
rval |= AV_CPU_FLAG_MMX; rval |= AV_CPU_FLAG_MMX;
......
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