Browse code

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: Michael Niedermayer <michaelni@gmx.at>

Michael Niedermayer authored on 2012/06/24 09:09:53
Showing 44 changed files
... ...
@@ -12,6 +12,8 @@ version next:
12 12
 - RTMPT protocol support
13 13
 - iLBC encoding/decoding via libilbc
14 14
 - Microsoft Screen 1 decoder
15
+- join audio filter
16
+- audio channel mapping filter
15 17
 - showwaves filter
16 18
 - LucasArts SMUSH playback support
17 19
 
... ...
@@ -4,7 +4,7 @@ since the last major version increase.
4 4
 The last version increases were:
5 5
 libavcodec:    2012-01-27
6 6
 libavdevice:   2011-04-18
7
-libavfilter:   2011-04-18
7
+libavfilter:   2012-06-22
8 8
 libavformat:   2012-01-27
9 9
 libavresample: 2012-04-24
10 10
 libpostproc:   2011-04-18
... ...
@@ -649,6 +649,76 @@ front_center.wav -map '[LFE]' lfe.wav -map '[SL]' side_left.wav -map '[SR]'
649 649
 side_right.wav
650 650
 @end example
651 651
 
652
+@section channelmap
653
+Remap input channels to new locations.
654
+
655
+This filter accepts the following named parameters:
656
+@table @option
657
+@item channel_layout
658
+Channel layout of the output stream.
659
+
660
+@item map
661
+Map channels from input to output. The argument is a comma-separated list of
662
+mappings, each in the @code{@var{in_channel}-@var{out_channel}} or
663
+@var{in_channel} form. @var{in_channel} can be either the name of the input
664
+channel (e.g. FL for front left) or its index in the input channel layout.
665
+@var{out_channel} is the name of the output channel or its index in the output
666
+channel layout. If @var{out_channel} is not given then it is implicitly an
667
+index, starting with zero and increasing by one for each mapping.
668
+@end table
669
+
670
+If no mapping is present, the filter will implicitly map input channels to
671
+output channels preserving index.
672
+
673
+For example, assuming a 5.1+downmix input MOV file
674
+@example
675
+ffmpeg -i in.mov -filter 'channelmap=map=DL-FL\,DR-FR' out.wav
676
+@end example
677
+will create an output WAV file tagged as stereo from the downmix channels of
678
+the input.
679
+
680
+To fix a 5.1 WAV improperly encoded in AAC's native channel order
681
+@example
682
+ffmpeg -i in.wav -filter 'channelmap=1\,2\,0\,5\,3\,4:channel_layout=5.1' out.wav
683
+@end example
684
+
685
+@section join
686
+Join multiple input streams into one multi-channel stream.
687
+
688
+The filter accepts the following named parameters:
689
+@table @option
690
+
691
+@item inputs
692
+Number of input streams. Defaults to 2.
693
+
694
+@item channel_layout
695
+Desired output channel layout. Defaults to stereo.
696
+
697
+@item map
698
+Map channels from inputs to output. The argument is a comma-separated list of
699
+mappings, each in the @code{@var{input_idx}.@var{in_channel}-@var{out_channel}}
700
+form. @var{input_idx} is the 0-based index of the input stream. @var{in_channel}
701
+can be either the name of the input channel (e.g. FR for front left) or its
702
+index in the specified input stream. @var{out_channel} is the name of the output
703
+channel.
704
+@end table
705
+
706
+The filter will attempt to guess the mappings when those are not specified
707
+explicitly. It does so by first trying to find an unused matching input channel
708
+and if that fails it picks the first unused input channel.
709
+
710
+E.g. to join 3 inputs (with properly set channel layouts)
711
+@example
712
+ffmpeg -i INPUT1 -i INPUT2 -i INPUT3 -filter_complex join=inputs=3 OUTPUT
713
+@end example
714
+
715
+To build a 5.1 output from 6 single-channel streams:
716
+@example
717
+ffmpeg -i fl -i fr -i fc -i sl -i sr -i lfe -filter_complex
718
+'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'
719
+out
720
+@end example
721
+
652 722
 @section resample
653 723
 Convert the audio sample format, sample rate and channel layout. This filter is
654 724
 not meant to be used directly.
... ...
@@ -29,6 +29,12 @@
29 29
 #include "libavcodec/cavsdsp.h"
30 30
 #include "dsputil_mmx.h"
31 31
 
32
+/* in/out: mma=mma+mmb, mmb=mmb-mma */
33
+#define SUMSUB_BA( a, b ) \
34
+    "paddw "#b", "#a" \n\t"\
35
+    "paddw "#b", "#b" \n\t"\
36
+    "psubw "#a", "#b" \n\t"
37
+
32 38
 /*****************************************************************************
33 39
  *
34 40
  * inverse transform
... ...
@@ -631,6 +631,34 @@ static void add_hfyu_median_prediction_cmov(uint8_t *dst, const uint8_t *top,
631 631
 }
632 632
 #endif
633 633
 
634
+static inline void transpose4x4(uint8_t *dst, uint8_t *src, x86_reg dst_stride, x86_reg src_stride){
635
+    __asm__ volatile( //FIXME could save 1 instruction if done as 8x4 ...
636
+        "movd  (%1), %%mm0              \n\t"
637
+        "add   %3, %1                   \n\t"
638
+        "movd  (%1), %%mm1              \n\t"
639
+        "movd  (%1,%3,1), %%mm2         \n\t"
640
+        "movd  (%1,%3,2), %%mm3         \n\t"
641
+        "punpcklbw %%mm1, %%mm0         \n\t"
642
+        "punpcklbw %%mm3, %%mm2         \n\t"
643
+        "movq %%mm0, %%mm1              \n\t"
644
+        "punpcklwd %%mm2, %%mm0         \n\t"
645
+        "punpckhwd %%mm2, %%mm1         \n\t"
646
+        "movd  %%mm0, (%0)              \n\t"
647
+        "add   %2, %0                   \n\t"
648
+        "punpckhdq %%mm0, %%mm0         \n\t"
649
+        "movd  %%mm0, (%0)              \n\t"
650
+        "movd  %%mm1, (%0,%2,1)         \n\t"
651
+        "punpckhdq %%mm1, %%mm1         \n\t"
652
+        "movd  %%mm1, (%0,%2,2)         \n\t"
653
+
654
+        :  "+&r" (dst),
655
+           "+&r" (src)
656
+        :  "r" (dst_stride),
657
+           "r" (src_stride)
658
+        :  "memory"
659
+    );
660
+}
661
+
634 662
 #define H263_LOOP_FILTER                        \
635 663
     "pxor      %%mm7, %%mm7             \n\t"   \
636 664
     "movq         %0, %%mm0             \n\t"   \
... ...
@@ -2902,7 +2930,8 @@ static void dsputil_init_3dnow(DSPContext *c, AVCodecContext *avctx,
2902 2902
     c->vorbis_inverse_coupling = vorbis_inverse_coupling_3dnow;
2903 2903
 
2904 2904
 #if HAVE_7REGS
2905
-    c->add_hfyu_median_prediction = add_hfyu_median_prediction_cmov;
2905
+    if (mm_flags & AV_CPU_FLAG_CMOV)
2906
+        c->add_hfyu_median_prediction = add_hfyu_median_prediction_cmov;
2906 2907
 #endif
2907 2908
 }
2908 2909
 
... ...
@@ -66,24 +66,6 @@ extern const xmm_reg  ff_pb_FE;
66 66
 extern const double ff_pd_1[2];
67 67
 extern const double ff_pd_2[2];
68 68
 
69
-#define LOAD4(stride,in,a,b,c,d)\
70
-    "movq 0*"#stride"+"#in", "#a"\n\t"\
71
-    "movq 1*"#stride"+"#in", "#b"\n\t"\
72
-    "movq 2*"#stride"+"#in", "#c"\n\t"\
73
-    "movq 3*"#stride"+"#in", "#d"\n\t"
74
-
75
-#define STORE4(stride,out,a,b,c,d)\
76
-    "movq "#a", 0*"#stride"+"#out"\n\t"\
77
-    "movq "#b", 1*"#stride"+"#out"\n\t"\
78
-    "movq "#c", 2*"#stride"+"#out"\n\t"\
79
-    "movq "#d", 3*"#stride"+"#out"\n\t"
80
-
81
-/* in/out: mma=mma+mmb, mmb=mmb-mma */
82
-#define SUMSUB_BA( a, b ) \
83
-    "paddw "#b", "#a" \n\t"\
84
-    "paddw "#b", "#b" \n\t"\
85
-    "psubw "#a", "#b" \n\t"
86
-
87 69
 #define SBUTTERFLY(a,b,t,n,m)\
88 70
     "mov" #m " " #a ", " #t "         \n\t" /* abcd */\
89 71
     "punpckl" #n " " #b ", " #a "     \n\t" /* aebf */\
... ...
@@ -95,90 +77,6 @@ extern const double ff_pd_2[2];
95 95
     SBUTTERFLY(a,c,d,dq,q) /* a=aeim d=bfjn */\
96 96
     SBUTTERFLY(t,b,c,dq,q) /* t=cgko c=dhlp */
97 97
 
98
-static inline void transpose4x4(uint8_t *dst, uint8_t *src, x86_reg dst_stride, x86_reg src_stride){
99
-    __asm__ volatile( //FIXME could save 1 instruction if done as 8x4 ...
100
-        "movd  (%1), %%mm0              \n\t"
101
-        "add   %3, %1                   \n\t"
102
-        "movd  (%1), %%mm1              \n\t"
103
-        "movd  (%1,%3,1), %%mm2         \n\t"
104
-        "movd  (%1,%3,2), %%mm3         \n\t"
105
-        "punpcklbw %%mm1, %%mm0         \n\t"
106
-        "punpcklbw %%mm3, %%mm2         \n\t"
107
-        "movq %%mm0, %%mm1              \n\t"
108
-        "punpcklwd %%mm2, %%mm0         \n\t"
109
-        "punpckhwd %%mm2, %%mm1         \n\t"
110
-        "movd  %%mm0, (%0)              \n\t"
111
-        "add   %2, %0                   \n\t"
112
-        "punpckhdq %%mm0, %%mm0         \n\t"
113
-        "movd  %%mm0, (%0)              \n\t"
114
-        "movd  %%mm1, (%0,%2,1)         \n\t"
115
-        "punpckhdq %%mm1, %%mm1         \n\t"
116
-        "movd  %%mm1, (%0,%2,2)         \n\t"
117
-
118
-        :  "+&r" (dst),
119
-           "+&r" (src)
120
-        :  "r" (dst_stride),
121
-           "r" (src_stride)
122
-        :  "memory"
123
-    );
124
-}
125
-
126
-// e,f,g,h can be memory
127
-// out: a,d,t,c
128
-#define TRANSPOSE8x4(a,b,c,d,e,f,g,h,t)\
129
-    "punpcklbw " #e ", " #a " \n\t" /* a0 e0 a1 e1 a2 e2 a3 e3 */\
130
-    "punpcklbw " #f ", " #b " \n\t" /* b0 f0 b1 f1 b2 f2 b3 f3 */\
131
-    "punpcklbw " #g ", " #c " \n\t" /* c0 g0 c1 g1 c2 g2 d3 g3 */\
132
-    "punpcklbw " #h ", " #d " \n\t" /* d0 h0 d1 h1 d2 h2 d3 h3 */\
133
-    SBUTTERFLY(a, b, t, bw, q)   /* a= a0 b0 e0 f0 a1 b1 e1 f1 */\
134
-                                 /* t= a2 b2 e2 f2 a3 b3 e3 f3 */\
135
-    SBUTTERFLY(c, d, b, bw, q)   /* c= c0 d0 g0 h0 c1 d1 g1 h1 */\
136
-                                 /* b= c2 d2 g2 h2 c3 d3 g3 h3 */\
137
-    SBUTTERFLY(a, c, d, wd, q)   /* a= a0 b0 c0 d0 e0 f0 g0 h0 */\
138
-                                 /* d= a1 b1 c1 d1 e1 f1 g1 h1 */\
139
-    SBUTTERFLY(t, b, c, wd, q)   /* t= a2 b2 c2 d2 e2 f2 g2 h2 */\
140
-                                 /* c= a3 b3 c3 d3 e3 f3 g3 h3 */
141
-
142
-#if ARCH_X86_64
143
-// permutes 01234567 -> 05736421
144
-#define TRANSPOSE8(a,b,c,d,e,f,g,h,t)\
145
-    SBUTTERFLY(a,b,%%xmm8,wd,dqa)\
146
-    SBUTTERFLY(c,d,b,wd,dqa)\
147
-    SBUTTERFLY(e,f,d,wd,dqa)\
148
-    SBUTTERFLY(g,h,f,wd,dqa)\
149
-    SBUTTERFLY(a,c,h,dq,dqa)\
150
-    SBUTTERFLY(%%xmm8,b,c,dq,dqa)\
151
-    SBUTTERFLY(e,g,b,dq,dqa)\
152
-    SBUTTERFLY(d,f,g,dq,dqa)\
153
-    SBUTTERFLY(a,e,f,qdq,dqa)\
154
-    SBUTTERFLY(%%xmm8,d,e,qdq,dqa)\
155
-    SBUTTERFLY(h,b,d,qdq,dqa)\
156
-    SBUTTERFLY(c,g,b,qdq,dqa)\
157
-    "movdqa %%xmm8, "#g"              \n\t"
158
-#else
159
-#define TRANSPOSE8(a,b,c,d,e,f,g,h,t)\
160
-    "movdqa "#h", "#t"                \n\t"\
161
-    SBUTTERFLY(a,b,h,wd,dqa)\
162
-    "movdqa "#h", 16"#t"              \n\t"\
163
-    "movdqa "#t", "#h"                \n\t"\
164
-    SBUTTERFLY(c,d,b,wd,dqa)\
165
-    SBUTTERFLY(e,f,d,wd,dqa)\
166
-    SBUTTERFLY(g,h,f,wd,dqa)\
167
-    SBUTTERFLY(a,c,h,dq,dqa)\
168
-    "movdqa "#h", "#t"                \n\t"\
169
-    "movdqa 16"#t", "#h"              \n\t"\
170
-    SBUTTERFLY(h,b,c,dq,dqa)\
171
-    SBUTTERFLY(e,g,b,dq,dqa)\
172
-    SBUTTERFLY(d,f,g,dq,dqa)\
173
-    SBUTTERFLY(a,e,f,qdq,dqa)\
174
-    SBUTTERFLY(h,d,e,qdq,dqa)\
175
-    "movdqa "#h", 16"#t"              \n\t"\
176
-    "movdqa "#t", "#h"                \n\t"\
177
-    SBUTTERFLY(h,b,d,qdq,dqa)\
178
-    SBUTTERFLY(c,g,b,qdq,dqa)\
179
-    "movdqa 16"#t", "#g"              \n\t"
180
-#endif
181
-
182 98
 #define MOVQ_WONE(regd) \
183 99
     __asm__ volatile ( \
184 100
     "pcmpeqd %%" #regd ", %%" #regd " \n\t" \
... ...
@@ -362,7 +362,7 @@ void ff_h264dsp_init_x86(H264DSPContext *c, const int bit_depth, const int chrom
362 362
             c->h264_idct_add8       = ff_h264_idct_add8_8_mmx;
363 363
         c->h264_idct_add16intra     = ff_h264_idct_add16intra_8_mmx;
364 364
         if (mm_flags & AV_CPU_FLAG_CMOV)
365
-            c->h264_luma_dc_dequant_idct= ff_h264_luma_dc_dequant_idct_mmx;
365
+            c->h264_luma_dc_dequant_idct = ff_h264_luma_dc_dequant_idct_mmx;
366 366
 
367 367
         if (mm_flags & AV_CPU_FLAG_MMX2) {
368 368
             c->h264_idct_dc_add    = ff_h264_idct_dc_add_8_mmx2;
... ...
@@ -59,8 +59,10 @@ OBJS-$(CONFIG_ASPLIT_FILTER)                 += split.o
59 59
 OBJS-$(CONFIG_ASTREAMSYNC_FILTER)            += af_astreamsync.o
60 60
 OBJS-$(CONFIG_ASYNCTS_FILTER)                += af_asyncts.o
61 61
 OBJS-$(CONFIG_ATEMPO_FILTER)                 += af_atempo.o
62
+OBJS-$(CONFIG_CHANNELMAP_FILTER)             += af_channelmap.o
62 63
 OBJS-$(CONFIG_CHANNELSPLIT_FILTER)           += af_channelsplit.o
63 64
 OBJS-$(CONFIG_EARWAX_FILTER)                 += af_earwax.o
65
+OBJS-$(CONFIG_JOIN_FILTER)                   += af_join.o
64 66
 OBJS-$(CONFIG_PAN_FILTER)                    += af_pan.o
65 67
 OBJS-$(CONFIG_RESAMPLE_FILTER)               += af_resample.o
66 68
 OBJS-$(CONFIG_SILENCEDETECT_FILTER)          += af_silencedetect.o
... ...
@@ -75,14 +75,14 @@ static int query_formats(AVFilterContext *ctx)
75 75
     AVFilterLink *outlink = ctx->outputs[0];
76 76
     AVFilterChannelLayouts *layouts;
77 77
 
78
-    ff_formats_ref(avfilter_make_all_formats(AVMEDIA_TYPE_AUDIO),
78
+    ff_formats_ref(ff_all_formats(AVMEDIA_TYPE_AUDIO),
79 79
                          &inlink->out_formats);
80 80
     if (aconvert->out_sample_fmt != AV_SAMPLE_FMT_NONE) {
81 81
         formats = NULL;
82 82
         ff_add_format(&formats, aconvert->out_sample_fmt);
83 83
         ff_formats_ref(formats, &outlink->in_formats);
84 84
     } else
85
-        ff_formats_ref(avfilter_make_all_formats(AVMEDIA_TYPE_AUDIO),
85
+        ff_formats_ref(ff_all_formats(AVMEDIA_TYPE_AUDIO),
86 86
                              &outlink->in_formats);
87 87
 
88 88
     ff_channel_layouts_ref(ff_all_channel_layouts(),
... ...
@@ -134,8 +134,7 @@ AVFilter avfilter_af_aformat = {
134 134
     .priv_size     = sizeof(AFormatContext),
135 135
 
136 136
     .inputs        = (AVFilterPad[]) {{ .name            = "default",
137
-                                        .type            = AVMEDIA_TYPE_AUDIO,
138
-                                        .filter_samples  = ff_null_filter_samples },
137
+                                        .type            = AVMEDIA_TYPE_AUDIO, },
139 138
                                       { .name = NULL}},
140 139
     .outputs       = (AVFilterPad[]) {{ .name            = "default",
141 140
                                         .type            = AVMEDIA_TYPE_AUDIO},
... ...
@@ -169,7 +169,7 @@ static int request_frame(AVFilterLink *outlink)
169 169
 
170 170
     for (i = 0; i < am->nb_inputs; i++)
171 171
         if (!am->in[i].nb_samples)
172
-            if ((ret = avfilter_request_frame(ctx->inputs[i])) < 0)
172
+            if ((ret = ff_request_frame(ctx->inputs[i])) < 0)
173 173
                 return ret;
174 174
     return 0;
175 175
 }
... ...
@@ -34,8 +34,7 @@ AVFilter avfilter_af_anull = {
34 34
 
35 35
     .inputs    = (const AVFilterPad[]) {{ .name       = "default",
36 36
                                     .type             = AVMEDIA_TYPE_AUDIO,
37
-                                    .get_audio_buffer = ff_null_get_audio_buffer,
38
-                                    .filter_samples   = ff_null_filter_samples },
37
+                                    .get_audio_buffer = ff_null_get_audio_buffer, },
39 38
                                   { .name = NULL}},
40 39
 
41 40
     .outputs   = (const AVFilterPad[]) {{ .name       = "default",
... ...
@@ -112,7 +112,7 @@ static int query_formats(AVFilterContext *ctx)
112 112
     if(out_format != AV_SAMPLE_FMT_NONE) {
113 113
         out_formats = ff_make_format_list((int[]){ out_format, -1 });
114 114
     } else
115
-        out_formats = avfilter_make_all_formats(AVMEDIA_TYPE_AUDIO);
115
+        out_formats = ff_all_formats(AVMEDIA_TYPE_AUDIO);
116 116
     ff_formats_ref(out_formats, &outlink->in_formats);
117 117
 
118 118
     if(out_layout) {
... ...
@@ -211,7 +211,7 @@ static int request_frame(AVFilterLink *outlink)
211 211
 
212 212
     aresample->req_fullfilled = 0;
213 213
     do{
214
-        ret = avfilter_request_frame(ctx->inputs[0]);
214
+        ret = ff_request_frame(ctx->inputs[0]);
215 215
     }while(!aresample->req_fullfilled && ret>=0);
216 216
 
217 217
     if (ret == AVERROR_EOF) {
... ...
@@ -164,7 +164,7 @@ static int request_frame(AVFilterLink *outlink)
164 164
 
165 165
     asns->req_fullfilled = 0;
166 166
     do {
167
-        ret = avfilter_request_frame(inlink);
167
+        ret = ff_request_frame(inlink);
168 168
     } while (!asns->req_fullfilled && ret >= 0);
169 169
 
170 170
     if (ret == AVERROR_EOF)
... ...
@@ -157,7 +157,7 @@ static int request_frame(AVFilterLink *outlink)
157 157
             send_next(ctx);
158 158
         } else {
159 159
             as->eof |= 1 << as->next_out;
160
-            avfilter_request_frame(ctx->inputs[as->next_out]);
160
+            ff_request_frame(ctx->inputs[as->next_out]);
161 161
             if (as->eof & (1 << as->next_out))
162 162
                 as->next_out = !as->next_out;
163 163
         }
... ...
@@ -1083,7 +1083,7 @@ static int request_frame(AVFilterLink *outlink)
1083 1083
 
1084 1084
     atempo->request_fulfilled = 0;
1085 1085
     do {
1086
-        ret = avfilter_request_frame(ctx->inputs[0]);
1086
+        ret = ff_request_frame(ctx->inputs[0]);
1087 1087
     }
1088 1088
     while (!atempo->request_fulfilled && ret >= 0);
1089 1089
 
1090 1090
new file mode 100644
... ...
@@ -0,0 +1,402 @@
0
+/*
1
+ * Copyright (c) 2012 Google, Inc.
2
+ *
3
+ * This file is part of FFmpeg.
4
+ *
5
+ * FFmpeg is free software; you can redistribute it and/or
6
+ * modify it under the terms of the GNU Lesser General Public
7
+ * License as published by the Free Software Foundation; either
8
+ * version 2.1 of the License, or (at your option) any later version.
9
+ *
10
+ * FFmpeg is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13
+ * Lesser General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU Lesser General Public
16
+ * License along with FFmpeg; if not, write to the Free Software
17
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
+ */
19
+
20
+/**
21
+ * @file
22
+ * audio channel mapping filter
23
+ */
24
+
25
+#include <ctype.h>
26
+
27
+#include "libavutil/audioconvert.h"
28
+#include "libavutil/avstring.h"
29
+#include "libavutil/mathematics.h"
30
+#include "libavutil/opt.h"
31
+#include "libavutil/samplefmt.h"
32
+
33
+#include "audio.h"
34
+#include "avfilter.h"
35
+#include "formats.h"
36
+#include "internal.h"
37
+
38
+struct ChannelMap {
39
+    uint64_t in_channel;
40
+    uint64_t out_channel;
41
+    int in_channel_idx;
42
+    int out_channel_idx;
43
+};
44
+
45
+enum MappingMode {
46
+    MAP_NONE,
47
+    MAP_ONE_INT,
48
+    MAP_ONE_STR,
49
+    MAP_PAIR_INT_INT,
50
+    MAP_PAIR_INT_STR,
51
+    MAP_PAIR_STR_INT,
52
+    MAP_PAIR_STR_STR
53
+};
54
+
55
+#define MAX_CH 64
56
+typedef struct ChannelMapContext {
57
+    const AVClass *class;
58
+    AVFilterChannelLayouts *channel_layouts;
59
+    char *mapping_str;
60
+    char *channel_layout_str;
61
+    uint64_t output_layout;
62
+    struct ChannelMap map[MAX_CH];
63
+    int nch;
64
+    enum MappingMode mode;
65
+} ChannelMapContext;
66
+
67
+#define OFFSET(x) offsetof(ChannelMapContext, x)
68
+#define A AV_OPT_FLAG_AUDIO_PARAM
69
+static const AVOption options[] = {
70
+    { "map", "A comma-separated list of input channel numbers in output order.",
71
+          OFFSET(mapping_str),        AV_OPT_TYPE_STRING, .flags = A },
72
+    { "channel_layout", "Output channel layout.",
73
+          OFFSET(channel_layout_str), AV_OPT_TYPE_STRING, .flags = A },
74
+    { NULL },
75
+};
76
+
77
+static const AVClass channelmap_class = {
78
+    .class_name = "channel map filter",
79
+    .item_name  = av_default_item_name,
80
+    .option     = options,
81
+    .version    = LIBAVUTIL_VERSION_INT,
82
+};
83
+
84
+static char* split(char *message, char delim) {
85
+    char *next = strchr(message, delim);
86
+    if (next)
87
+      *next++ = '\0';
88
+    return next;
89
+}
90
+
91
+static int get_channel_idx(char **map, int *ch, char delim, int max_ch)
92
+{
93
+    char *next = split(*map, delim);
94
+    int len;
95
+    int n = 0;
96
+    if (!next && delim == '-')
97
+        return AVERROR(EINVAL);
98
+    len = strlen(*map);
99
+    sscanf(*map, "%d%n", ch, &n);
100
+    if (n != len)
101
+        return AVERROR(EINVAL);
102
+    if (*ch < 0 || *ch > max_ch)
103
+        return AVERROR(EINVAL);
104
+    *map = next;
105
+    return 0;
106
+}
107
+
108
+static int get_channel(char **map, uint64_t *ch, char delim)
109
+{
110
+    char *next = split(*map, delim);
111
+    if (!next && delim == '-')
112
+        return AVERROR(EINVAL);
113
+    *ch = av_get_channel_layout(*map);
114
+    if (av_get_channel_layout_nb_channels(*ch) != 1)
115
+        return AVERROR(EINVAL);
116
+    *map = next;
117
+    return 0;
118
+}
119
+
120
+static av_cold int channelmap_init(AVFilterContext *ctx, const char *args,
121
+                                   void *opaque)
122
+{
123
+    ChannelMapContext *s = ctx->priv;
124
+    int ret;
125
+    char *mapping;
126
+    enum mode;
127
+    int map_entries = 0;
128
+    char buf[256];
129
+    enum MappingMode mode;
130
+    uint64_t out_ch_mask = 0;
131
+    int i;
132
+
133
+    if (!args) {
134
+        av_log(ctx, AV_LOG_ERROR, "No parameters supplied.\n");
135
+        return AVERROR(EINVAL);
136
+    }
137
+
138
+    s->class = &channelmap_class;
139
+    av_opt_set_defaults(s);
140
+
141
+    if ((ret = av_set_options_string(s, args, "=", ":")) < 0) {
142
+        av_log(ctx, AV_LOG_ERROR, "Error parsing options string '%s'.\n", args);
143
+        return ret;
144
+    }
145
+
146
+    mapping = s->mapping_str;
147
+
148
+    if (!mapping) {
149
+        mode = MAP_NONE;
150
+    } else {
151
+        char *dash = strchr(mapping, '-');
152
+        if (!dash) {  // short mapping
153
+            if (isdigit(*mapping))
154
+                mode = MAP_ONE_INT;
155
+            else
156
+                mode = MAP_ONE_STR;
157
+        } else if (isdigit(*mapping)) {
158
+            if (isdigit(*(dash+1)))
159
+                mode = MAP_PAIR_INT_INT;
160
+            else
161
+                mode = MAP_PAIR_INT_STR;
162
+        } else {
163
+            if (isdigit(*(dash+1)))
164
+                mode = MAP_PAIR_STR_INT;
165
+            else
166
+                mode = MAP_PAIR_STR_STR;
167
+        }
168
+    }
169
+
170
+    if (mode != MAP_NONE) {
171
+        char *comma = mapping;
172
+        map_entries = 1;
173
+        while ((comma = strchr(comma, ','))) {
174
+            if (*++comma)  // Allow trailing comma
175
+                map_entries++;
176
+        }
177
+    }
178
+
179
+    if (map_entries > MAX_CH) {
180
+        av_log(ctx, AV_LOG_ERROR, "Too many channels mapped: '%d'.\n", map_entries);
181
+        ret = AVERROR(EINVAL);
182
+        goto fail;
183
+    }
184
+
185
+    for (i = 0; i < map_entries; i++) {
186
+        int in_ch_idx = -1, out_ch_idx = -1;
187
+        uint64_t in_ch = 0, out_ch = 0;
188
+        static const char err[] = "Failed to parse channel map\n";
189
+        switch (mode) {
190
+        case MAP_ONE_INT:
191
+            if (get_channel_idx(&mapping, &in_ch_idx, ',', MAX_CH) < 0) {
192
+                ret = AVERROR(EINVAL);
193
+                av_log(ctx, AV_LOG_ERROR, err);
194
+                goto fail;
195
+            }
196
+            s->map[i].in_channel_idx  = in_ch_idx;
197
+            s->map[i].out_channel_idx = i;
198
+            break;
199
+        case MAP_ONE_STR:
200
+            if (!get_channel(&mapping, &in_ch, ',')) {
201
+                av_log(ctx, AV_LOG_ERROR, err);
202
+                ret = AVERROR(EINVAL);
203
+                goto fail;
204
+            }
205
+            s->map[i].in_channel      = in_ch;
206
+            s->map[i].out_channel_idx = i;
207
+            break;
208
+        case MAP_PAIR_INT_INT:
209
+            if (get_channel_idx(&mapping, &in_ch_idx, '-', MAX_CH) < 0 ||
210
+                get_channel_idx(&mapping, &out_ch_idx, ',', MAX_CH) < 0) {
211
+                av_log(ctx, AV_LOG_ERROR, err);
212
+                ret = AVERROR(EINVAL);
213
+                goto fail;
214
+            }
215
+            s->map[i].in_channel_idx  = in_ch_idx;
216
+            s->map[i].out_channel_idx = out_ch_idx;
217
+            break;
218
+        case MAP_PAIR_INT_STR:
219
+            if (get_channel_idx(&mapping, &in_ch_idx, '-', MAX_CH) < 0 ||
220
+                get_channel(&mapping, &out_ch, ',') < 0 ||
221
+                out_ch & out_ch_mask) {
222
+                av_log(ctx, AV_LOG_ERROR, err);
223
+                ret = AVERROR(EINVAL);
224
+                goto fail;
225
+            }
226
+            s->map[i].in_channel_idx  = in_ch_idx;
227
+            s->map[i].out_channel     = out_ch;
228
+            out_ch_mask |= out_ch;
229
+            break;
230
+        case MAP_PAIR_STR_INT:
231
+            if (get_channel(&mapping, &in_ch, '-') < 0 ||
232
+                get_channel_idx(&mapping, &out_ch_idx, ',', MAX_CH) < 0) {
233
+                av_log(ctx, AV_LOG_ERROR, err);
234
+                ret = AVERROR(EINVAL);
235
+                goto fail;
236
+            }
237
+            s->map[i].in_channel      = in_ch;
238
+            s->map[i].out_channel_idx = out_ch_idx;
239
+            break;
240
+        case MAP_PAIR_STR_STR:
241
+            if (get_channel(&mapping, &in_ch, '-') < 0 ||
242
+                get_channel(&mapping, &out_ch, ',') < 0 ||
243
+                out_ch & out_ch_mask) {
244
+                av_log(ctx, AV_LOG_ERROR, err);
245
+                ret = AVERROR(EINVAL);
246
+                goto fail;
247
+            }
248
+            s->map[i].in_channel = in_ch;
249
+            s->map[i].out_channel = out_ch;
250
+            out_ch_mask |= out_ch;
251
+            break;
252
+        }
253
+    }
254
+    s->mode          = mode;
255
+    s->nch           = map_entries;
256
+    s->output_layout = out_ch_mask ? out_ch_mask :
257
+                       av_get_default_channel_layout(map_entries);
258
+
259
+    if (s->channel_layout_str) {
260
+        uint64_t fmt;
261
+        if ((fmt = av_get_channel_layout(s->channel_layout_str)) == 0) {
262
+            av_log(ctx, AV_LOG_ERROR, "Error parsing channel layout: '%s'.\n",
263
+                   s->channel_layout_str);
264
+            ret = AVERROR(EINVAL);
265
+            goto fail;
266
+        }
267
+        if (mode == MAP_NONE) {
268
+            int i;
269
+            s->nch = av_get_channel_layout_nb_channels(fmt);
270
+            for (i = 0; i < s->nch; i++) {
271
+                s->map[i].in_channel_idx  = i;
272
+                s->map[i].out_channel_idx = i;
273
+            }
274
+        } else if (out_ch_mask && out_ch_mask != fmt) {
275
+            av_get_channel_layout_string(buf, sizeof(buf), 0, out_ch_mask);
276
+            av_log(ctx, AV_LOG_ERROR,
277
+                   "Output channel layout '%s' does not match the list of channel mapped: '%s'.\n",
278
+                   s->channel_layout_str, buf);
279
+            ret = AVERROR(EINVAL);
280
+            goto fail;
281
+        } else if (s->nch != av_get_channel_layout_nb_channels(fmt)) {
282
+            av_log(ctx, AV_LOG_ERROR,
283
+                   "Output channel layout %s does not match the number of channels mapped %d.\n",
284
+                   s->channel_layout_str, s->nch);
285
+            ret = AVERROR(EINVAL);
286
+            goto fail;
287
+        }
288
+        s->output_layout = fmt;
289
+    }
290
+    ff_add_channel_layout(&s->channel_layouts, s->output_layout);
291
+
292
+    if (mode == MAP_PAIR_INT_STR || mode == MAP_PAIR_STR_STR) {
293
+        for (i = 0; i < s->nch; i++) {
294
+            s->map[i].out_channel_idx = av_get_channel_layout_channel_index(
295
+                s->output_layout, s->map[i].out_channel);
296
+        }
297
+    }
298
+
299
+fail:
300
+    av_opt_free(s);
301
+    return ret;
302
+}
303
+
304
+static int channelmap_query_formats(AVFilterContext *ctx)
305
+{
306
+    ChannelMapContext *s = ctx->priv;
307
+
308
+    ff_set_common_formats(ctx, ff_planar_sample_fmts());
309
+    ff_set_common_samplerates(ctx, ff_all_samplerates());
310
+    ff_channel_layouts_ref(ff_all_channel_layouts(), &ctx->inputs[0]->out_channel_layouts);
311
+    ff_channel_layouts_ref(s->channel_layouts,       &ctx->outputs[0]->in_channel_layouts);
312
+
313
+    return 0;
314
+}
315
+
316
+static void channelmap_filter_samples(AVFilterLink *inlink, AVFilterBufferRef *buf)
317
+{
318
+    AVFilterContext  *ctx = inlink->dst;
319
+    AVFilterLink *outlink = ctx->outputs[0];
320
+    const ChannelMapContext *s = ctx->priv;
321
+    const int nch_in = av_get_channel_layout_nb_channels(inlink->channel_layout);
322
+    const int nch_out = s->nch;
323
+    int ch;
324
+    uint8_t *source_planes[MAX_CH];
325
+
326
+    memcpy(source_planes, buf->extended_data,
327
+           nch_in * sizeof(source_planes[0]));
328
+
329
+    if (nch_out > nch_in) {
330
+        if (nch_out > FF_ARRAY_ELEMS(buf->data)) {
331
+            uint8_t **new_extended_data =
332
+                av_mallocz(nch_out * sizeof(*buf->extended_data));
333
+            if (!new_extended_data)
334
+                return;
335
+            if (buf->extended_data == buf->data) {
336
+                buf->extended_data = new_extended_data;
337
+            } else {
338
+                buf->extended_data = new_extended_data;
339
+                av_free(buf->extended_data);
340
+            }
341
+        } else if (buf->extended_data != buf->data) {
342
+            av_free(buf->extended_data);
343
+            buf->extended_data = buf->data;
344
+        }
345
+    }
346
+
347
+    for (ch = 0; ch < nch_out; ch++) {
348
+        buf->extended_data[s->map[ch].out_channel_idx] =
349
+            source_planes[s->map[ch].in_channel_idx];
350
+    }
351
+
352
+    if (buf->data != buf->extended_data)
353
+        memcpy(buf->data, buf->extended_data,
354
+           FFMIN(FF_ARRAY_ELEMS(buf->data), nch_out) * sizeof(buf->data[0]));
355
+
356
+    ff_filter_samples(outlink, buf);
357
+}
358
+
359
+static int channelmap_config_input(AVFilterLink *inlink)
360
+{
361
+    AVFilterContext *ctx = inlink->dst;
362
+    ChannelMapContext *s = ctx->priv;
363
+    int i, err = 0;
364
+    const char *channel_name;
365
+    char layout_name[256];
366
+
367
+    if (s->mode == MAP_PAIR_STR_INT || s->mode == MAP_PAIR_STR_STR) {
368
+        for (i = 0; i < s->nch; i++) {
369
+            s->map[i].in_channel_idx = av_get_channel_layout_channel_index(
370
+                inlink->channel_layout, s->map[i].in_channel);
371
+            if (s->map[i].in_channel_idx < 0) {
372
+                channel_name = av_get_channel_name(s->map[i].in_channel);
373
+                av_get_channel_layout_string(layout_name, sizeof(layout_name),
374
+                                             0, inlink->channel_layout);
375
+                av_log(ctx, AV_LOG_ERROR,
376
+                       "input channel '%s' not available from input layout '%s'\n",
377
+                       channel_name, layout_name);
378
+                err = AVERROR(EINVAL);
379
+            }
380
+        }
381
+    }
382
+
383
+    return err;
384
+}
385
+
386
+AVFilter avfilter_af_channelmap = {
387
+    .name          = "channelmap",
388
+    .description   = NULL_IF_CONFIG_SMALL("Remap audio channels."),
389
+    .init          = channelmap_init,
390
+    .query_formats = channelmap_query_formats,
391
+    .priv_size     = sizeof(ChannelMapContext),
392
+
393
+    .inputs        = (AVFilterPad[]) {{ .name            = "default",
394
+                                        .type            = AVMEDIA_TYPE_AUDIO,
395
+                                        .filter_samples  = channelmap_filter_samples,
396
+                                        .config_props    = channelmap_config_input },
397
+                                      { .name = NULL }},
398
+    .outputs       = (AVFilterPad[]) {{ .name            = "default",
399
+                                        .type            = AVMEDIA_TYPE_AUDIO },
400
+                                      { .name = NULL }},
401
+};
0 402
new file mode 100644
... ...
@@ -0,0 +1,500 @@
0
+/*
1
+ *
2
+ * This file is part of Libav.
3
+ *
4
+ * Libav is free software; you can redistribute it and/or
5
+ * modify it under the terms of the GNU Lesser General Public
6
+ * License as published by the Free Software Foundation; either
7
+ * version 2.1 of the License, or (at your option) any later version.
8
+ *
9
+ * Libav is distributed in the hope that it will be useful,
10
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
+ * Lesser General Public License for more details.
13
+ *
14
+ * You should have received a copy of the GNU Lesser General Public
15
+ * License along with Libav; if not, write to the Free Software
16
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17
+ */
18
+
19
+/**
20
+ * @file
21
+ * Audio join filter
22
+ *
23
+ * Join multiple audio inputs as different channels in
24
+ * a single output
25
+ */
26
+
27
+#include "libavutil/audioconvert.h"
28
+#include "libavutil/avassert.h"
29
+#include "libavutil/opt.h"
30
+
31
+#include "audio.h"
32
+#include "avfilter.h"
33
+#include "formats.h"
34
+#include "internal.h"
35
+
36
+typedef struct ChannelMap {
37
+    int input;                ///< input stream index
38
+    int       in_channel_idx; ///< index of in_channel in the input stream data
39
+    uint64_t  in_channel;     ///< layout describing the input channel
40
+    uint64_t out_channel;     ///< layout describing the output channel
41
+} ChannelMap;
42
+
43
+typedef struct JoinContext {
44
+    const AVClass *class;
45
+
46
+    int inputs;
47
+    char *map;
48
+    char    *channel_layout_str;
49
+    uint64_t channel_layout;
50
+
51
+    int      nb_channels;
52
+    ChannelMap *channels;
53
+
54
+    /**
55
+     * Temporary storage for input frames, until we get one on each input.
56
+     */
57
+    AVFilterBufferRef **input_frames;
58
+
59
+    /**
60
+     *  Temporary storage for data pointers, for assembling the output buffer.
61
+     */
62
+    uint8_t **data;
63
+} JoinContext;
64
+
65
+/**
66
+ * To avoid copying the data from input buffers, this filter creates
67
+ * a custom output buffer that stores references to all inputs and
68
+ * unrefs them on free.
69
+ */
70
+typedef struct JoinBufferPriv {
71
+    AVFilterBufferRef **in_buffers;
72
+    int              nb_in_buffers;
73
+} JoinBufferPriv;
74
+
75
+#define OFFSET(x) offsetof(JoinContext, x)
76
+#define A AV_OPT_FLAG_AUDIO_PARAM
77
+static const AVOption join_options[] = {
78
+    { "inputs",         "Number of input streams.", OFFSET(inputs),             AV_OPT_TYPE_INT,    { 2 }, 1, INT_MAX,       A },
79
+    { "channel_layout", "Channel layout of the "
80
+                        "output stream.",           OFFSET(channel_layout_str), AV_OPT_TYPE_STRING, {.str = "stereo"}, 0, 0, A },
81
+    { "map",            "A comma-separated list of channels maps in the format "
82
+                        "'input_stream.input_channel-output_channel.",
83
+                                                    OFFSET(map),                AV_OPT_TYPE_STRING,                 .flags = A },
84
+    { NULL },
85
+};
86
+
87
+static const AVClass join_class = {
88
+    .class_name = "join filter",
89
+    .item_name  = av_default_item_name,
90
+    .option     = join_options,
91
+    .version    = LIBAVUTIL_VERSION_INT,
92
+};
93
+
94
+static void filter_samples(AVFilterLink *link, AVFilterBufferRef *buf)
95
+{
96
+    AVFilterContext *ctx = link->dst;
97
+    JoinContext       *s = ctx->priv;
98
+    int i;
99
+
100
+    for (i = 0; i < ctx->nb_inputs; i++)
101
+        if (link == ctx->inputs[i])
102
+            break;
103
+    av_assert0(i < ctx->nb_inputs);
104
+    av_assert0(!s->input_frames[i]);
105
+    s->input_frames[i] = buf;
106
+}
107
+
108
+static int parse_maps(AVFilterContext *ctx)
109
+{
110
+    JoinContext *s = ctx->priv;
111
+    char *cur      = s->map;
112
+
113
+    while (cur && *cur) {
114
+        char *sep, *next, *p;
115
+        uint64_t in_channel = 0, out_channel = 0;
116
+        int input_idx, out_ch_idx, in_ch_idx;
117
+
118
+        next = strchr(cur, ',');
119
+        if (next)
120
+            *next++ = 0;
121
+
122
+        /* split the map into input and output parts */
123
+        if (!(sep = strchr(cur, '-'))) {
124
+            av_log(ctx, AV_LOG_ERROR, "Missing separator '-' in channel "
125
+                   "map '%s'\n", cur);
126
+            return AVERROR(EINVAL);
127
+        }
128
+        *sep++ = 0;
129
+
130
+#define PARSE_CHANNEL(str, var, inout)                                         \
131
+        if (!(var = av_get_channel_layout(str))) {                             \
132
+            av_log(ctx, AV_LOG_ERROR, "Invalid " inout " channel: %s.\n", str);\
133
+            return AVERROR(EINVAL);                                            \
134
+        }                                                                      \
135
+        if (av_get_channel_layout_nb_channels(var) != 1) {                     \
136
+            av_log(ctx, AV_LOG_ERROR, "Channel map describes more than one "   \
137
+                   inout " channel.\n");                                       \
138
+            return AVERROR(EINVAL);                                            \
139
+        }
140
+
141
+        /* parse output channel */
142
+        PARSE_CHANNEL(sep, out_channel, "output");
143
+        if (!(out_channel & s->channel_layout)) {
144
+            av_log(ctx, AV_LOG_ERROR, "Output channel '%s' is not present in "
145
+                   "requested channel layout.\n", sep);
146
+            return AVERROR(EINVAL);
147
+        }
148
+
149
+        out_ch_idx = av_get_channel_layout_channel_index(s->channel_layout,
150
+                                                         out_channel);
151
+        if (s->channels[out_ch_idx].input >= 0) {
152
+            av_log(ctx, AV_LOG_ERROR, "Multiple maps for output channel "
153
+                   "'%s'.\n", sep);
154
+            return AVERROR(EINVAL);
155
+        }
156
+
157
+        /* parse input channel */
158
+        input_idx = strtol(cur, &cur, 0);
159
+        if (input_idx < 0 || input_idx >= s->inputs) {
160
+            av_log(ctx, AV_LOG_ERROR, "Invalid input stream index: %d.\n",
161
+                   input_idx);
162
+            return AVERROR(EINVAL);
163
+        }
164
+
165
+        if (*cur)
166
+            cur++;
167
+
168
+        in_ch_idx = strtol(cur, &p, 0);
169
+        if (p == cur) {
170
+            /* channel specifier is not a number,
171
+             * try to parse as channel name */
172
+            PARSE_CHANNEL(cur, in_channel, "input");
173
+        }
174
+
175
+        s->channels[out_ch_idx].input      = input_idx;
176
+        if (in_channel)
177
+            s->channels[out_ch_idx].in_channel = in_channel;
178
+        else
179
+            s->channels[out_ch_idx].in_channel_idx = in_ch_idx;
180
+
181
+        cur = next;
182
+    }
183
+    return 0;
184
+}
185
+
186
+static int join_init(AVFilterContext *ctx, const char *args, void *opaque)
187
+{
188
+    JoinContext *s = ctx->priv;
189
+    int ret, i;
190
+
191
+    s->class = &join_class;
192
+    av_opt_set_defaults(s);
193
+    if ((ret = av_set_options_string(s, args, "=", ":")) < 0) {
194
+        av_log(ctx, AV_LOG_ERROR, "Error parsing options string '%s'.\n", args);
195
+        return ret;
196
+    }
197
+
198
+    if (!(s->channel_layout = av_get_channel_layout(s->channel_layout_str))) {
199
+        av_log(ctx, AV_LOG_ERROR, "Error parsing channel layout '%s'.\n",
200
+               s->channel_layout_str);
201
+        ret = AVERROR(EINVAL);
202
+        goto fail;
203
+    }
204
+
205
+    s->nb_channels  = av_get_channel_layout_nb_channels(s->channel_layout);
206
+    s->channels     = av_mallocz(sizeof(*s->channels) * s->nb_channels);
207
+    s->data         = av_mallocz(sizeof(*s->data)     * s->nb_channels);
208
+    s->input_frames = av_mallocz(sizeof(*s->input_frames) * s->inputs);
209
+    if (!s->channels || !s->data || !s->input_frames) {
210
+        ret = AVERROR(ENOMEM);
211
+        goto fail;
212
+    }
213
+
214
+    for (i = 0; i < s->nb_channels; i++) {
215
+        s->channels[i].out_channel = av_channel_layout_extract_channel(s->channel_layout, i);
216
+        s->channels[i].input       = -1;
217
+    }
218
+
219
+    if ((ret = parse_maps(ctx)) < 0)
220
+        goto fail;
221
+
222
+    for (i = 0; i < s->inputs; i++) {
223
+        char name[32];
224
+        AVFilterPad pad = { 0 };
225
+
226
+        snprintf(name, sizeof(name), "input%d", i);
227
+        pad.type           = AVMEDIA_TYPE_AUDIO;
228
+        pad.name           = av_strdup(name);
229
+        pad.filter_samples = filter_samples;
230
+
231
+        pad.needs_fifo = 1;
232
+
233
+        ff_insert_inpad(ctx, i, &pad);
234
+    }
235
+
236
+fail:
237
+    av_opt_free(s);
238
+    return ret;
239
+}
240
+
241
+static void join_uninit(AVFilterContext *ctx)
242
+{
243
+    JoinContext *s = ctx->priv;
244
+    int i;
245
+
246
+    for (i = 0; i < ctx->nb_inputs; i++) {
247
+        av_freep(&ctx->input_pads[i].name);
248
+        avfilter_unref_buffer(s->input_frames[i]);
249
+    }
250
+
251
+    av_freep(&s->channels);
252
+    av_freep(&s->data);
253
+    av_freep(&s->input_frames);
254
+}
255
+
256
+static int join_query_formats(AVFilterContext *ctx)
257
+{
258
+    JoinContext *s = ctx->priv;
259
+    AVFilterChannelLayouts *layouts = NULL;
260
+    int i;
261
+
262
+    ff_add_channel_layout(&layouts, s->channel_layout);
263
+    ff_channel_layouts_ref(layouts, &ctx->outputs[0]->in_channel_layouts);
264
+
265
+    for (i = 0; i < ctx->nb_inputs; i++)
266
+        ff_channel_layouts_ref(ff_all_channel_layouts(),
267
+                               &ctx->inputs[i]->out_channel_layouts);
268
+
269
+    ff_set_common_formats    (ctx, ff_planar_sample_fmts());
270
+    ff_set_common_samplerates(ctx, ff_all_samplerates());
271
+
272
+    return 0;
273
+}
274
+
275
+static void guess_map_matching(AVFilterContext *ctx, ChannelMap *ch,
276
+                               uint64_t *inputs)
277
+{
278
+    int i;
279
+
280
+    for (i = 0; i < ctx->nb_inputs; i++) {
281
+        AVFilterLink *link = ctx->inputs[i];
282
+
283
+        if (ch->out_channel & link->channel_layout &&
284
+            !(ch->out_channel & inputs[i])) {
285
+            ch->input      = i;
286
+            ch->in_channel = ch->out_channel;
287
+            inputs[i]     |= ch->out_channel;
288
+            return;
289
+        }
290
+    }
291
+}
292
+
293
+static void guess_map_any(AVFilterContext *ctx, ChannelMap *ch,
294
+                          uint64_t *inputs)
295
+{
296
+    int i;
297
+
298
+    for (i = 0; i < ctx->nb_inputs; i++) {
299
+        AVFilterLink *link = ctx->inputs[i];
300
+
301
+        if ((inputs[i] & link->channel_layout) != link->channel_layout) {
302
+            uint64_t unused = link->channel_layout & ~inputs[i];
303
+
304
+            ch->input      = i;
305
+            ch->in_channel = av_channel_layout_extract_channel(unused, 0);
306
+            inputs[i]     |= ch->in_channel;
307
+            return;
308
+        }
309
+    }
310
+}
311
+
312
+static int join_config_output(AVFilterLink *outlink)
313
+{
314
+    AVFilterContext *ctx = outlink->src;
315
+    JoinContext       *s = ctx->priv;
316
+    uint64_t *inputs;   // nth element tracks which channels are used from nth input
317
+    int i, ret = 0;
318
+
319
+    /* initialize inputs to user-specified mappings */
320
+    if (!(inputs = av_mallocz(sizeof(*inputs) * ctx->nb_inputs)))
321
+        return AVERROR(ENOMEM);
322
+    for (i = 0; i < s->nb_channels; i++) {
323
+        ChannelMap *ch = &s->channels[i];
324
+        AVFilterLink *inlink;
325
+
326
+        if (ch->input < 0)
327
+            continue;
328
+
329
+        inlink = ctx->inputs[ch->input];
330
+
331
+        if (!ch->in_channel)
332
+            ch->in_channel = av_channel_layout_extract_channel(inlink->channel_layout,
333
+                                                               ch->in_channel_idx);
334
+
335
+        if (!(ch->in_channel & inlink->channel_layout)) {
336
+            av_log(ctx, AV_LOG_ERROR, "Requested channel %s is not present in "
337
+                   "input stream #%d.\n", av_get_channel_name(ch->in_channel),
338
+                   ch->input);
339
+            ret = AVERROR(EINVAL);
340
+            goto fail;
341
+        }
342
+
343
+        inputs[ch->input] |= ch->in_channel;
344
+    }
345
+
346
+    /* guess channel maps when not explicitly defined */
347
+    /* first try unused matching channels */
348
+    for (i = 0; i < s->nb_channels; i++) {
349
+        ChannelMap *ch = &s->channels[i];
350
+
351
+        if (ch->input < 0)
352
+            guess_map_matching(ctx, ch, inputs);
353
+    }
354
+
355
+    /* if the above failed, try to find _any_ unused input channel */
356
+    for (i = 0; i < s->nb_channels; i++) {
357
+        ChannelMap *ch = &s->channels[i];
358
+
359
+        if (ch->input < 0)
360
+            guess_map_any(ctx, ch, inputs);
361
+
362
+        if (ch->input < 0) {
363
+            av_log(ctx, AV_LOG_ERROR, "Could not find input channel for "
364
+                   "output channel '%s'.\n",
365
+                   av_get_channel_name(ch->out_channel));
366
+            goto fail;
367
+        }
368
+
369
+        ch->in_channel_idx = av_get_channel_layout_channel_index(ctx->inputs[ch->input]->channel_layout,
370
+                                                                 ch->in_channel);
371
+    }
372
+
373
+    /* print mappings */
374
+    av_log(ctx, AV_LOG_VERBOSE, "mappings: ");
375
+    for (i = 0; i < s->nb_channels; i++) {
376
+        ChannelMap *ch = &s->channels[i];
377
+        av_log(ctx, AV_LOG_VERBOSE, "%d.%s => %s ", ch->input,
378
+               av_get_channel_name(ch->in_channel),
379
+               av_get_channel_name(ch->out_channel));
380
+    }
381
+    av_log(ctx, AV_LOG_VERBOSE, "\n");
382
+
383
+    for (i = 0; i < ctx->nb_inputs; i++) {
384
+        if (!inputs[i])
385
+            av_log(ctx, AV_LOG_WARNING, "No channels are used from input "
386
+                   "stream %d.\n", i);
387
+    }
388
+
389
+fail:
390
+    av_freep(&inputs);
391
+    return ret;
392
+}
393
+
394
+static void join_free_buffer(AVFilterBuffer *buf)
395
+{
396
+    JoinBufferPriv *priv = buf->priv;
397
+
398
+    if (priv) {
399
+        int i;
400
+
401
+        for (i = 0; i < priv->nb_in_buffers; i++)
402
+            avfilter_unref_buffer(priv->in_buffers[i]);
403
+
404
+        av_freep(&priv->in_buffers);
405
+        av_freep(&buf->priv);
406
+    }
407
+
408
+    if (buf->extended_data != buf->data)
409
+        av_freep(&buf->extended_data);
410
+    av_freep(&buf);
411
+}
412
+
413
+static int join_request_frame(AVFilterLink *outlink)
414
+{
415
+    AVFilterContext *ctx = outlink->src;
416
+    JoinContext *s       = ctx->priv;
417
+    AVFilterBufferRef *buf;
418
+    JoinBufferPriv *priv;
419
+    int linesize   = INT_MAX;
420
+    int perms      = ~0;
421
+    int nb_samples;
422
+    int i, j, ret;
423
+
424
+    /* get a frame on each input */
425
+    for (i = 0; i < ctx->nb_inputs; i++) {
426
+        AVFilterLink *inlink = ctx->inputs[i];
427
+
428
+        if (!s->input_frames[i] &&
429
+            (ret = ff_request_frame(inlink)) < 0)
430
+            return ret;
431
+
432
+        /* request the same number of samples on all inputs */
433
+        if (i == 0) {
434
+            nb_samples = s->input_frames[0]->audio->nb_samples;
435
+
436
+            for (j = 1; !i && j < ctx->nb_inputs; j++)
437
+                ctx->inputs[j]->request_samples = nb_samples;
438
+        }
439
+    }
440
+
441
+    for (i = 0; i < s->nb_channels; i++) {
442
+        ChannelMap *ch = &s->channels[i];
443
+        AVFilterBufferRef *cur_buf = s->input_frames[ch->input];
444
+
445
+        s->data[i] = cur_buf->extended_data[ch->in_channel_idx];
446
+        linesize   = FFMIN(linesize, cur_buf->linesize[0]);
447
+        perms     &= cur_buf->perms;
448
+    }
449
+
450
+    buf = avfilter_get_audio_buffer_ref_from_arrays(s->data, linesize, perms,
451
+                                                    nb_samples, outlink->format,
452
+                                                    outlink->channel_layout);
453
+    if (!buf)
454
+        return AVERROR(ENOMEM);
455
+
456
+    buf->buf->free = join_free_buffer;
457
+    buf->pts       = s->input_frames[0]->pts;
458
+
459
+    if (!(priv = av_mallocz(sizeof(*priv))))
460
+        goto fail;
461
+    if (!(priv->in_buffers = av_mallocz(sizeof(*priv->in_buffers) * ctx->nb_inputs)))
462
+        goto fail;
463
+
464
+    for (i = 0; i < ctx->nb_inputs; i++)
465
+        priv->in_buffers[i] = s->input_frames[i];
466
+    priv->nb_in_buffers = ctx->nb_inputs;
467
+    buf->buf->priv      = priv;
468
+
469
+    ff_filter_samples(outlink, buf);
470
+
471
+    memset(s->input_frames, 0, sizeof(*s->input_frames) * ctx->nb_inputs);
472
+
473
+    return 0;
474
+
475
+fail:
476
+    avfilter_unref_buffer(buf);
477
+    if (priv)
478
+        av_freep(&priv->in_buffers);
479
+    av_freep(&priv);
480
+    return AVERROR(ENOMEM);
481
+}
482
+
483
+AVFilter avfilter_af_join = {
484
+    .name           = "join",
485
+    .description    = NULL_IF_CONFIG_SMALL("Join multiple audio streams into "
486
+                                           "multi-channel output"),
487
+    .priv_size      = sizeof(JoinContext),
488
+
489
+    .init           = join_init,
490
+    .uninit         = join_uninit,
491
+    .query_formats  = join_query_formats,
492
+
493
+    .inputs  = (const AVFilterPad[]){{ NULL }},
494
+    .outputs = (const AVFilterPad[]){{ .name          = "default",
495
+                                       .type          = AVMEDIA_TYPE_AUDIO,
496
+                                       .config_props  = join_config_output,
497
+                                       .request_frame = join_request_frame, },
498
+                                     { NULL }},
499
+};
... ...
@@ -217,7 +217,7 @@ static int query_formats(AVFilterContext *ctx)
217 217
 
218 218
     pan->pure_gains = are_gains_pure(pan);
219 219
     /* libswr supports any sample and packing formats */
220
-    ff_set_common_formats(ctx, avfilter_make_all_formats(AVMEDIA_TYPE_AUDIO));
220
+    ff_set_common_formats(ctx, ff_all_formats(AVMEDIA_TYPE_AUDIO));
221 221
 
222 222
     formats = ff_all_samplerates();
223 223
     if (!formats)
... ...
@@ -47,8 +47,10 @@ void avfilter_register_all(void)
47 47
     REGISTER_FILTER (ASTREAMSYNC, astreamsync, af);
48 48
     REGISTER_FILTER (ASYNCTS,     asyncts,     af);
49 49
     REGISTER_FILTER (ATEMPO,      atempo,      af);
50
+    REGISTER_FILTER (CHANNELMAP,  channelmap,  af);
50 51
     REGISTER_FILTER (CHANNELSPLIT,channelsplit,af);
51 52
     REGISTER_FILTER (EARWAX,      earwax,      af);
53
+    REGISTER_FILTER (JOIN,        join,        af);
52 54
     REGISTER_FILTER (PAN,         pan,         af);
53 55
     REGISTER_FILTER (SILENCEDETECT, silencedetect, af);
54 56
     REGISTER_FILTER (VOLUME,      volume,      af);
... ...
@@ -150,32 +150,12 @@ fail:
150 150
     return NULL;
151 151
 }
152 152
 
153
-void ff_null_filter_samples(AVFilterLink *link, AVFilterBufferRef *samplesref)
153
+static void default_filter_samples(AVFilterLink *link,
154
+                                   AVFilterBufferRef *samplesref)
154 155
 {
155 156
     ff_filter_samples(link->dst->outputs[0], samplesref);
156 157
 }
157 158
 
158
-/* FIXME: samplesref is same as link->cur_buf. Need to consider removing the redundant parameter. */
159
-void ff_default_filter_samples(AVFilterLink *inlink, AVFilterBufferRef *samplesref)
160
-{
161
-    AVFilterLink *outlink = NULL;
162
-
163
-    if (inlink->dst->nb_outputs)
164
-        outlink = inlink->dst->outputs[0];
165
-
166
-    if (outlink) {
167
-        outlink->out_buf = ff_default_get_audio_buffer(inlink, AV_PERM_WRITE,
168
-                                                       samplesref->audio->nb_samples);
169
-        outlink->out_buf->pts                = samplesref->pts;
170
-        outlink->out_buf->audio->sample_rate = samplesref->audio->sample_rate;
171
-        ff_filter_samples(outlink, avfilter_ref_buffer(outlink->out_buf, ~0));
172
-        avfilter_unref_buffer(outlink->out_buf);
173
-        outlink->out_buf = NULL;
174
-    }
175
-    avfilter_unref_buffer(samplesref);
176
-    inlink->cur_buf = NULL;
177
-}
178
-
179 159
 void ff_filter_samples(AVFilterLink *link, AVFilterBufferRef *samplesref)
180 160
 {
181 161
     void (*filter_samples)(AVFilterLink *, AVFilterBufferRef *);
... ...
@@ -186,7 +166,7 @@ void ff_filter_samples(AVFilterLink *link, AVFilterBufferRef *samplesref)
186 186
     FF_TPRINTF_START(NULL, filter_samples); ff_tlog_link(NULL, link, 1);
187 187
 
188 188
     if (!(filter_samples = dst->filter_samples))
189
-        filter_samples = ff_default_filter_samples;
189
+        filter_samples = default_filter_samples;
190 190
 
191 191
     /* prepare to copy the samples if the buffer has insufficient permissions */
192 192
     if ((dst->min_perms & samplesref->perms) != dst->min_perms ||
... ...
@@ -63,12 +63,6 @@ AVFilterBufferRef *ff_null_get_audio_buffer(AVFilterLink *link, int perms,
63 63
 AVFilterBufferRef *ff_get_audio_buffer(AVFilterLink *link, int perms,
64 64
                                              int nb_samples);
65 65
 
66
-/** default handler for filter_samples() for audio inputs */
67
-void ff_default_filter_samples(AVFilterLink *link, AVFilterBufferRef *samplesref);
68
-
69
-/** filter_samples() handler for filters which simply pass audio along */
70
-void ff_null_filter_samples(AVFilterLink *link, AVFilterBufferRef *samplesref);
71
-
72 66
 /**
73 67
  * Send a buffer of audio samples to the next filter.
74 68
  *
... ...
@@ -170,7 +170,7 @@ static int request_frame(AVFilterLink *outlink)
170 170
 
171 171
     showwaves->req_fullfilled = 0;
172 172
     do {
173
-        ret = avfilter_request_frame(inlink);
173
+        ret = ff_request_frame(inlink);
174 174
     } while (!showwaves->req_fullfilled && ret >= 0);
175 175
 
176 176
     if (ret == AVERROR_EOF && showwaves->outpicref)
... ...
@@ -211,7 +211,6 @@ AVFilterBufferRef *avfilter_ref_buffer(AVFilterBufferRef *ref, int pmask);
211 211
  */
212 212
 void avfilter_unref_buffer(AVFilterBufferRef *ref);
213 213
 
214
-#if FF_API_FILTERS_PUBLIC
215 214
 /**
216 215
  * Remove a reference to a buffer and set the pointer to NULL.
217 216
  * If this is the last reference to the buffer, the buffer itself
... ...
@@ -221,6 +220,7 @@ void avfilter_unref_buffer(AVFilterBufferRef *ref);
221 221
  */
222 222
 void avfilter_unref_bufferp(AVFilterBufferRef **ref);
223 223
 
224
+#if FF_API_FILTERS_PUBLIC
224 225
 /**
225 226
  * A list of supported formats for one end of a filter link. This is used
226 227
  * 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 291
  *
292 292
  * @return a non negative value in case of success, or a negative
293 293
  * value corresponding to an AVERROR code in case of error
294
- * @deprecated Use avfilter_make_all_formats() instead.
294
+ * @deprecated Use ff_all_formats() instead.
295 295
  */
296 296
 attribute_deprecated
297 297
 int avfilter_add_format(AVFilterFormats **avff, int64_t fmt);
... ...
@@ -479,7 +479,7 @@ struct AVFilterPad {
479 479
      * Frame request callback. A call to this should result in at least one
480 480
      * frame being output over the given link. This should return zero on
481 481
      * success, and another value on error.
482
-     * See avfilter_request_frame() for the error codes with a specific
482
+     * See ff_request_frame() for the error codes with a specific
483 483
      * meaning.
484 484
      *
485 485
      * Output pads only.
... ...
@@ -504,6 +504,14 @@ struct AVFilterPad {
504 504
      * and another value on error.
505 505
      */
506 506
     int (*config_props)(AVFilterLink *link);
507
+
508
+    /**
509
+     * The filter expects a fifo to be inserted on its input link,
510
+     * typically because it has a delay.
511
+     *
512
+     * input pads only.
513
+     */
514
+    int needs_fifo;
507 515
 };
508 516
 #endif
509 517
 
... ...
@@ -529,6 +537,10 @@ const char *avfilter_pad_get_name(AVFilterPad *pads, int pad_idx);
529 529
  */
530 530
 enum AVMediaType avfilter_pad_get_type(AVFilterPad *pads, int pad_idx);
531 531
 
532
+/** default handler for end_frame() for video inputs */
533
+attribute_deprecated
534
+void avfilter_default_end_frame(AVFilterLink *link);
535
+
532 536
 #if FF_API_FILTERS_PUBLIC
533 537
 /** default handler for start_frame() for video inputs */
534 538
 attribute_deprecated
... ...
@@ -538,10 +550,6 @@ void avfilter_default_start_frame(AVFilterLink *link, AVFilterBufferRef *picref)
538 538
 attribute_deprecated
539 539
 void avfilter_default_draw_slice(AVFilterLink *link, int y, int h, int slice_dir);
540 540
 
541
-/** default handler for end_frame() for video inputs */
542
-attribute_deprecated
543
-void avfilter_default_end_frame(AVFilterLink *link);
544
-
545 541
 /** default handler for get_video_buffer() for video inputs */
546 542
 attribute_deprecated
547 543
 AVFilterBufferRef *avfilter_default_get_video_buffer(AVFilterLink *link,
... ...
@@ -756,6 +764,15 @@ struct AVFilterLink {
756 756
     struct AVFilterChannelLayouts  *in_channel_layouts;
757 757
     struct AVFilterChannelLayouts *out_channel_layouts;
758 758
 
759
+    /**
760
+     * Audio only, the destination filter sets this to a non-zero value to
761
+     * request that buffers with the given number of samples should be sent to
762
+     * it. AVFilterPad.needs_fifo must also be set on the corresponding input
763
+     * pad.
764
+     * Last buffer before EOF will be padded with silence.
765
+     */
766
+    int request_samples;
767
+
759 768
     struct AVFilterPool *pool;
760 769
 
761 770
     /**
... ...
@@ -785,7 +802,6 @@ struct AVFilterLink {
785 785
      * It is similar to the r_frae_rate field in AVStream.
786 786
      */
787 787
     AVRational frame_rate;
788
-
789 788
 };
790 789
 
791 790
 /**
... ...
@@ -187,7 +187,7 @@ static int filter_query_formats(AVFilterContext *ctx)
187 187
     if ((ret = ctx->filter->query_formats(ctx)) < 0)
188 188
         return ret;
189 189
 
190
-    formats = avfilter_make_all_formats(type);
190
+    formats = ff_all_formats(type);
191 191
     if (!formats)
192 192
         return AVERROR(ENOMEM);
193 193
     ff_set_common_formats(ctx, formats);
... ...
@@ -815,12 +815,52 @@ static int ff_avfilter_graph_config_pointers(AVFilterGraph *graph,
815 815
     return 0;
816 816
 }
817 817
 
818
+static int graph_insert_fifos(AVFilterGraph *graph, AVClass *log_ctx)
819
+{
820
+    AVFilterContext *f;
821
+    int i, j, ret;
822
+    int fifo_count = 0;
823
+
824
+    for (i = 0; i < graph->filter_count; i++) {
825
+        f = graph->filters[i];
826
+
827
+        for (j = 0; j < f->nb_inputs; j++) {
828
+            AVFilterLink *link = f->inputs[j];
829
+            AVFilterContext *fifo_ctx;
830
+            AVFilter *fifo;
831
+            char name[32];
832
+
833
+            if (!link->dstpad->needs_fifo)
834
+                continue;
835
+
836
+            fifo = f->inputs[j]->type == AVMEDIA_TYPE_VIDEO ?
837
+                   avfilter_get_by_name("fifo") :
838
+                   avfilter_get_by_name("afifo");
839
+
840
+            snprintf(name, sizeof(name), "auto-inserted fifo %d", fifo_count++);
841
+
842
+            ret = avfilter_graph_create_filter(&fifo_ctx, fifo, name, NULL,
843
+                                               NULL, graph);
844
+            if (ret < 0)
845
+                return ret;
846
+
847
+            ret = avfilter_insert_filter(link, fifo_ctx, 0, 0);
848
+            if (ret < 0)
849
+                return ret;
850
+        }
851
+    }
852
+
853
+    return 0;
854
+}
855
+
818 856
 int avfilter_graph_config(AVFilterGraph *graphctx, void *log_ctx)
819 857
 {
820 858
     int ret;
821 859
 
822 860
     if ((ret = graph_check_validity(graphctx, log_ctx)))
823 861
         return ret;
862
+    if ((ret = graph_insert_fifos(graphctx, log_ctx)) < 0)
863
+        return ret;
824 864
     if ((ret = graph_config_formats(graphctx, log_ctx)))
825 865
         return ret;
826 866
     if ((ret = graph_config_links(graphctx, log_ctx)))
... ...
@@ -939,7 +979,7 @@ int avfilter_graph_request_oldest(AVFilterGraph *graph)
939 939
 {
940 940
     while (graph->sink_links_count) {
941 941
         AVFilterLink *oldest = graph->sink_links[0];
942
-        int r = avfilter_request_frame(oldest);
942
+        int r = ff_request_frame(oldest);
943 943
         if (r != AVERROR_EOF)
944 944
             return r;
945 945
         /* EOF: remove the link from the heap */
... ...
@@ -257,7 +257,7 @@ char *avfilter_graph_dump(AVFilterGraph *graph, const char *options);
257 257
  * of a filtergraph, only a convenience function to help drain a filtergraph
258 258
  * in a balanced way under normal circumstances.
259 259
  *
260
- * @return  the return value of avfilter_request_frame,
260
+ * @return  the return value of ff_request_frame,
261 261
  *          or AVERROR_EOF of all links returned AVERROR_EOF.
262 262
  */
263 263
 int avfilter_graph_request_oldest(AVFilterGraph *graph);
... ...
@@ -25,7 +25,7 @@
25 25
 
26 26
 #include "libavutil/audio_fifo.h"
27 27
 #include "libavutil/audioconvert.h"
28
-#include "libavutil/fifo.h"
28
+#include "libavutil/avassert.h"
29 29
 #include "libavutil/mathematics.h"
30 30
 
31 31
 #include "audio.h"
... ...
@@ -34,86 +34,45 @@
34 34
 #include "internal.h"
35 35
 
36 36
 typedef struct {
37
-    AVFifoBuffer *fifo;          ///< FIFO buffer of frame references
38
-
37
+    AVFilterBufferRef *cur_buf;  ///< last buffer delivered on the sink
39 38
     AVAudioFifo  *audio_fifo;    ///< FIFO for audio samples
40 39
     int64_t next_pts;            ///< interpolating audio pts
41 40
 } BufferSinkContext;
42 41
 
43
-#define FIFO_INIT_SIZE 8
44
-
45 42
 static av_cold void uninit(AVFilterContext *ctx)
46 43
 {
47 44
     BufferSinkContext *sink = ctx->priv;
48 45
 
49
-    while (sink->fifo && av_fifo_size(sink->fifo)) {
50
-        AVFilterBufferRef *buf;
51
-        av_fifo_generic_read(sink->fifo, &buf, sizeof(buf), NULL);
52
-        avfilter_unref_buffer(buf);
53
-    }
54
-    av_fifo_free(sink->fifo);
55
-
56 46
     if (sink->audio_fifo)
57 47
         av_audio_fifo_free(sink->audio_fifo);
58 48
 }
59 49
 
60
-static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque)
61
-{
62
-    BufferSinkContext *sink = ctx->priv;
63
-
64
-    if (!(sink->fifo = av_fifo_alloc(FIFO_INIT_SIZE*sizeof(AVFilterBufferRef*)))) {
65
-        av_log(ctx, AV_LOG_ERROR, "Failed to allocate fifo\n");
66
-        return AVERROR(ENOMEM);
67
-    }
68
-
69
-    return 0;
70
-}
71
-
72
-static void write_buf(AVFilterContext *ctx, AVFilterBufferRef *buf)
50
+static void start_frame(AVFilterLink *link, AVFilterBufferRef *buf)
73 51
 {
74
-    BufferSinkContext *sink = ctx->priv;
75
-
76
-    if (av_fifo_space(sink->fifo) < sizeof(AVFilterBufferRef *) &&
77
-        (av_fifo_realloc2(sink->fifo, av_fifo_size(sink->fifo) * 2) < 0)) {
78
-            av_log(ctx, AV_LOG_ERROR, "Error reallocating the FIFO.\n");
79
-            return;
80
-    }
52
+    BufferSinkContext *s = link->dst->priv;
81 53
 
82
-    av_fifo_generic_write(sink->fifo, &buf, sizeof(buf), NULL);
83
-}
84
-
85
-static void end_frame(AVFilterLink *link)
86
-{
87
-    write_buf(link->dst, link->cur_buf);
54
+//     av_assert0(!s->cur_buf);
55
+    s->cur_buf    = buf;
88 56
     link->cur_buf = NULL;
89
-}
90
-
91
-static void filter_samples(AVFilterLink *link, AVFilterBufferRef *buf)
92
-{
93
-    write_buf(link->dst, buf);
94
-}
57
+};
95 58
 
96 59
 int av_buffersink_read(AVFilterContext *ctx, AVFilterBufferRef **buf)
97 60
 {
98
-    BufferSinkContext *sink = ctx->priv;
61
+    BufferSinkContext *s    = ctx->priv;
99 62
     AVFilterLink      *link = ctx->inputs[0];
100 63
     int ret;
101 64
 
102
-    if (!buf) {
103
-        if (av_fifo_size(sink->fifo))
104
-            return av_fifo_size(sink->fifo)/sizeof(*buf);
105
-        else
106
-            return ff_poll_frame(ctx->inputs[0]);
107
-    }
65
+    if (!buf)
66
+        return ff_poll_frame(ctx->inputs[0]);
108 67
 
109
-    if (!av_fifo_size(sink->fifo) &&
110
-        (ret = ff_request_frame(link)) < 0)
68
+    if ((ret = ff_request_frame(link)) < 0)
111 69
         return ret;
112 70
 
113
-    if (!av_fifo_size(sink->fifo))
71
+    if (!s->cur_buf)
114 72
         return AVERROR(EINVAL);
115 73
 
116
-    av_fifo_generic_read(sink->fifo, buf, sizeof(*buf), NULL);
74
+    *buf       = s->cur_buf;
75
+    s->cur_buf = NULL;
117 76
 
118 77
     return 0;
119 78
 }
... ...
@@ -182,13 +141,13 @@ AVFilter avfilter_vsink_buffer = {
182 182
     .name      = "buffersink_old",
183 183
     .description = NULL_IF_CONFIG_SMALL("Buffer video frames, and make them available to the end of the filter graph."),
184 184
     .priv_size = sizeof(BufferSinkContext),
185
-    .init      = init,
186 185
     .uninit    = uninit,
187 186
 
188 187
     .inputs    = (AVFilterPad[]) {{ .name          = "default",
189 188
                                     .type          = AVMEDIA_TYPE_VIDEO,
190
-                                    .end_frame     = end_frame,
191
-                                    .min_perms     = AV_PERM_READ, },
189
+                                    .start_frame   = start_frame,
190
+                                    .min_perms     = AV_PERM_READ,
191
+                                    .needs_fifo    = 1 },
192 192
                                   { .name = NULL }},
193 193
     .outputs   = (AVFilterPad[]) {{ .name = NULL }},
194 194
 };
... ...
@@ -197,13 +156,13 @@ AVFilter avfilter_asink_abuffer = {
197 197
     .name      = "abuffersink_old",
198 198
     .description = NULL_IF_CONFIG_SMALL("Buffer audio frames, and make them available to the end of the filter graph."),
199 199
     .priv_size = sizeof(BufferSinkContext),
200
-    .init      = init,
201 200
     .uninit    = uninit,
202 201
 
203 202
     .inputs    = (AVFilterPad[]) {{ .name           = "default",
204 203
                                     .type           = AVMEDIA_TYPE_AUDIO,
205
-                                    .filter_samples = filter_samples,
206
-                                    .min_perms      = AV_PERM_READ, },
204
+                                    .filter_samples = start_frame,
205
+                                    .min_perms      = AV_PERM_READ,
206
+                                    .needs_fifo     = 1 },
207 207
                                   { .name = NULL }},
208 208
     .outputs   = (AVFilterPad[]) {{ .name = NULL }},
209 209
 };
... ...
@@ -47,27 +47,6 @@ static void set_common_formats(AVFilterContext *ctx, AVFilterFormats *fmts,
47 47
     }
48 48
 }
49 49
 
50
-void avfilter_set_common_pixel_formats(AVFilterContext *ctx, AVFilterFormats *formats)
51
-{
52
-    set_common_formats(ctx, formats, AVMEDIA_TYPE_VIDEO,
53
-                       offsetof(AVFilterLink, in_formats),
54
-                       offsetof(AVFilterLink, out_formats));
55
-}
56
-
57
-void avfilter_set_common_sample_formats(AVFilterContext *ctx, AVFilterFormats *formats)
58
-{
59
-    set_common_formats(ctx, formats, AVMEDIA_TYPE_AUDIO,
60
-                       offsetof(AVFilterLink, in_formats),
61
-                       offsetof(AVFilterLink, out_formats));
62
-}
63
-
64
-void avfilter_set_common_channel_layouts(AVFilterContext *ctx, AVFilterFormats *formats)
65
-{
66
-    set_common_formats(ctx, formats, AVMEDIA_TYPE_AUDIO,
67
-                       offsetof(AVFilterLink, in_channel_layouts),
68
-                       offsetof(AVFilterLink, out_channel_layouts));
69
-}
70
-
71 50
 #if FF_API_PACKING
72 51
 void avfilter_set_common_packing_formats(AVFilterContext *ctx, AVFilterFormats *formats)
73 52
 {
... ...
@@ -23,6 +23,11 @@
23 23
  * FIFO buffering filter
24 24
  */
25 25
 
26
+#include "libavutil/avassert.h"
27
+#include "libavutil/audioconvert.h"
28
+#include "libavutil/mathematics.h"
29
+#include "libavutil/samplefmt.h"
30
+
26 31
 #include "audio.h"
27 32
 #include "avfilter.h"
28 33
 #include "internal.h"
... ...
@@ -36,6 +41,13 @@ typedef struct Buf {
36 36
 typedef struct {
37 37
     Buf  root;
38 38
     Buf *last;   ///< last buffered frame
39
+
40
+    /**
41
+     * When a specific number of output samples is requested, the partial
42
+     * buffer is stored here
43
+     */
44
+    AVFilterBufferRef *buf_out;
45
+    int allocated_samples;      ///< number of samples buf_out was allocated for
39 46
 } FifoContext;
40 47
 
41 48
 static av_cold int init(AVFilterContext *ctx, const char *args, void *opaque)
... ...
@@ -57,6 +69,8 @@ static av_cold void uninit(AVFilterContext *ctx)
57 57
         avfilter_unref_buffer(buf->buf);
58 58
         av_free(buf);
59 59
     }
60
+
61
+    avfilter_unref_buffer(fifo->buf_out);
60 62
 }
61 63
 
62 64
 static void add_to_queue(AVFilterLink *inlink, AVFilterBufferRef *buf)
... ...
@@ -68,14 +82,143 @@ static void add_to_queue(AVFilterLink *inlink, AVFilterBufferRef *buf)
68 68
     fifo->last->buf = buf;
69 69
 }
70 70
 
71
+static void queue_pop(FifoContext *s)
72
+{
73
+    Buf *tmp = s->root.next->next;
74
+    if (s->last == s->root.next)
75
+        s->last = &s->root;
76
+    av_freep(&s->root.next);
77
+    s->root.next = tmp;
78
+}
79
+
71 80
 static void end_frame(AVFilterLink *inlink) { }
72 81
 
73 82
 static void draw_slice(AVFilterLink *inlink, int y, int h, int slice_dir) { }
74 83
 
84
+/**
85
+ * Move data pointers and pts offset samples forward.
86
+ */
87
+static void buffer_offset(AVFilterLink *link, AVFilterBufferRef *buf,
88
+                          int offset)
89
+{
90
+    int nb_channels = av_get_channel_layout_nb_channels(link->channel_layout);
91
+    int planar = av_sample_fmt_is_planar(link->format);
92
+    int planes = planar ? nb_channels : 1;
93
+    int block_align = av_get_bytes_per_sample(link->format) * (planar ? 1 : nb_channels);
94
+    int i;
95
+
96
+    av_assert0(buf->audio->nb_samples > offset);
97
+
98
+    for (i = 0; i < planes; i++)
99
+        buf->extended_data[i] += block_align*offset;
100
+    if (buf->data != buf->extended_data)
101
+        memcpy(buf->data, buf->extended_data,
102
+               FFMIN(planes, FF_ARRAY_ELEMS(buf->data)) * sizeof(*buf->data));
103
+    buf->linesize[0] -= block_align*offset;
104
+    buf->audio->nb_samples -= offset;
105
+
106
+    if (buf->pts != AV_NOPTS_VALUE) {
107
+        buf->pts += av_rescale_q(offset, (AVRational){1, link->sample_rate},
108
+                                 link->time_base);
109
+    }
110
+}
111
+
112
+static int calc_ptr_alignment(AVFilterBufferRef *buf)
113
+{
114
+    int planes = av_sample_fmt_is_planar(buf->format) ?
115
+                 av_get_channel_layout_nb_channels(buf->audio->channel_layout) : 1;
116
+    int min_align = 128;
117
+    int p;
118
+
119
+    for (p = 0; p < planes; p++) {
120
+        int cur_align = 128;
121
+        while ((intptr_t)buf->extended_data[p] % cur_align)
122
+            cur_align >>= 1;
123
+        if (cur_align < min_align)
124
+            min_align = cur_align;
125
+    }
126
+    return min_align;
127
+}
128
+
129
+static int return_audio_frame(AVFilterContext *ctx)
130
+{
131
+    AVFilterLink *link = ctx->outputs[0];
132
+    FifoContext *s = ctx->priv;
133
+    AVFilterBufferRef *head = s->root.next->buf;
134
+    AVFilterBufferRef *buf_out;
135
+    int ret;
136
+
137
+    if (!s->buf_out &&
138
+        head->audio->nb_samples >= link->request_samples &&
139
+        calc_ptr_alignment(head) >= 32) {
140
+        if (head->audio->nb_samples == link->request_samples) {
141
+            buf_out = head;
142
+            queue_pop(s);
143
+        } else {
144
+            buf_out = avfilter_ref_buffer(head, AV_PERM_READ);
145
+            buf_out->audio->nb_samples = link->request_samples;
146
+            buffer_offset(link, head, link->request_samples);
147
+        }
148
+    } else {
149
+        int nb_channels = av_get_channel_layout_nb_channels(link->channel_layout);
150
+
151
+        if (!s->buf_out) {
152
+            s->buf_out = ff_get_audio_buffer(link, AV_PERM_WRITE,
153
+                                             link->request_samples);
154
+            if (!s->buf_out)
155
+                return AVERROR(ENOMEM);
156
+
157
+            s->buf_out->audio->nb_samples = 0;
158
+            s->buf_out->pts               = head->pts;
159
+            s->allocated_samples          = link->request_samples;
160
+        } else if (link->request_samples != s->allocated_samples) {
161
+            av_log(ctx, AV_LOG_ERROR, "request_samples changed before the "
162
+                   "buffer was returned.\n");
163
+            return AVERROR(EINVAL);
164
+        }
165
+
166
+        while (s->buf_out->audio->nb_samples < s->allocated_samples) {
167
+            int len = FFMIN(s->allocated_samples - s->buf_out->audio->nb_samples,
168
+                            head->audio->nb_samples);
169
+
170
+            av_samples_copy(s->buf_out->extended_data, head->extended_data,
171
+                            s->buf_out->audio->nb_samples, 0, len, nb_channels,
172
+                            link->format);
173
+            s->buf_out->audio->nb_samples += len;
174
+
175
+            if (len == head->audio->nb_samples) {
176
+                avfilter_unref_buffer(head);
177
+                queue_pop(s);
178
+
179
+                if (!s->root.next &&
180
+                    (ret = ff_request_frame(ctx->inputs[0])) < 0) {
181
+                    if (ret == AVERROR_EOF) {
182
+                        av_samples_set_silence(s->buf_out->extended_data,
183
+                                               s->buf_out->audio->nb_samples,
184
+                                               s->allocated_samples -
185
+                                               s->buf_out->audio->nb_samples,
186
+                                               nb_channels, link->format);
187
+                        s->buf_out->audio->nb_samples = s->allocated_samples;
188
+                        break;
189
+                    }
190
+                    return ret;
191
+                }
192
+                head = s->root.next->buf;
193
+            } else {
194
+                buffer_offset(link, head, len);
195
+            }
196
+        }
197
+        buf_out = s->buf_out;
198
+        s->buf_out = NULL;
199
+    }
200
+    ff_filter_samples(link, buf_out);
201
+
202
+    return 0;
203
+}
204
+
75 205
 static int request_frame(AVFilterLink *outlink)
76 206
 {
77 207
     FifoContext *fifo = outlink->src->priv;
78
-    Buf *tmp;
79 208
     int ret;
80 209
 
81 210
     if (!fifo->root.next) {
... ...
@@ -90,20 +233,20 @@ static int request_frame(AVFilterLink *outlink)
90 90
         ff_start_frame(outlink, fifo->root.next->buf);
91 91
         ff_draw_slice (outlink, 0, outlink->h, 1);
92 92
         ff_end_frame  (outlink);
93
+        queue_pop(fifo);
93 94
         break;
94 95
     case AVMEDIA_TYPE_AUDIO:
95
-        ff_filter_samples(outlink, fifo->root.next->buf);
96
+        if (outlink->request_samples) {
97
+            return return_audio_frame(outlink->src);
98
+        } else {
99
+            ff_filter_samples(outlink, fifo->root.next->buf);
100
+            queue_pop(fifo);
101
+        }
96 102
         break;
97 103
     default:
98 104
         return AVERROR(EINVAL);
99 105
     }
100 106
 
101
-    if (fifo->last == fifo->root.next)
102
-        fifo->last = &fifo->root;
103
-    tmp = fifo->root.next->next;
104
-    av_free(fifo->root.next);
105
-    fifo->root.next = tmp;
106
-
107 107
     return 0;
108 108
 }
109 109
 
... ...
@@ -262,11 +262,6 @@ int ff_add_channel_layout(AVFilterChannelLayouts **l, uint64_t channel_layout)
262 262
 
263 263
 AVFilterFormats *ff_all_formats(enum AVMediaType type)
264 264
 {
265
-    return avfilter_make_all_formats(type);
266
-}
267
-
268
-AVFilterFormats *avfilter_make_all_formats(enum AVMediaType type)
269
-{
270 265
     AVFilterFormats *ret = NULL;
271 266
     int fmt;
272 267
     int num_formats = type == AVMEDIA_TYPE_VIDEO ? PIX_FMT_NB    :
... ...
@@ -173,6 +173,14 @@ struct AVFilterPad {
173 173
      * and another value on error.
174 174
      */
175 175
     int (*config_props)(AVFilterLink *link);
176
+
177
+    /**
178
+     * The filter expects a fifo to be inserted on its input link,
179
+     * typically because it has a delay.
180
+     *
181
+     * input pads only.
182
+     */
183
+    int needs_fifo;
176 184
 };
177 185
 #endif
178 186
 
... ...
@@ -94,7 +94,7 @@ static const uint8_t offset[511][2]= {
94 94
 { 7, 1}, {15, 1}, { 7, 9}, {15, 9}, { 7, 3}, {15, 3}, { 7,11}, {15,11},
95 95
 { 7, 5}, {15, 5}, { 7,13}, {15,13}, { 7, 7}, {15, 7}, { 7,15}, {15,15},
96 96
 
97
-{ 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},
97
+{ 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},
98 98
 };
99 99
 
100 100
 struct vf_priv_s {
... ...
@@ -127,7 +127,7 @@ int av_buffersink_get_buffer_ref(AVFilterContext *ctx,
127 127
     if (!av_fifo_size(buf->fifo)) {
128 128
         if (flags & AV_BUFFERSINK_FLAG_NO_REQUEST)
129 129
             return AVERROR(EAGAIN);
130
-        if ((ret = avfilter_request_frame(inlink)) < 0)
130
+        if ((ret = ff_request_frame(inlink)) < 0)
131 131
             return ret;
132 132
     }
133 133
 
... ...
@@ -28,8 +28,8 @@
28 28
 
29 29
 #include "libavutil/avutil.h"
30 30
 
31
-#define LIBAVFILTER_VERSION_MAJOR  2
32
-#define LIBAVFILTER_VERSION_MINOR 82
31
+#define LIBAVFILTER_VERSION_MAJOR  3
32
+#define LIBAVFILTER_VERSION_MINOR  0
33 33
 #define LIBAVFILTER_VERSION_MICRO 100
34 34
 
35 35
 #define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \
... ...
@@ -136,7 +136,7 @@ static int request_frame(AVFilterLink *outlink)
136 136
     AVFilterContext *ctx = outlink->src;
137 137
     BlackDetectContext *blackdetect = ctx->priv;
138 138
     AVFilterLink *inlink = ctx->inputs[0];
139
-    int ret = avfilter_request_frame(inlink);
139
+    int ret = ff_request_frame(inlink);
140 140
 
141 141
     if (ret == AVERROR_EOF && blackdetect->black_started) {
142 142
         // FIXME: black_end should be set to last_picref_pts + last_picref_duration
... ...
@@ -216,7 +216,7 @@ static int request_frame(AVFilterLink *link)
216 216
     do {
217 217
         int ret;
218 218
 
219
-        if ((ret = avfilter_request_frame(link->src->inputs[0])))
219
+        if ((ret = ff_request_frame(link->src->inputs[0])))
220 220
             return ret;
221 221
     } while (!idet->cur);
222 222
 
... ...
@@ -231,7 +231,7 @@ static int poll_frame(AVFilterLink *link)
231 231
     val = ff_poll_frame(link->src->inputs[0]);
232 232
 
233 233
     if (val >= 1 && !idet->next) { //FIXME change API to not requre this red tape
234
-        if ((ret = avfilter_request_frame(link->src->inputs[0])) < 0)
234
+        if ((ret = ff_request_frame(link->src->inputs[0])) < 0)
235 235
             return ret;
236 236
         val = ff_poll_frame(link->src->inputs[0]);
237 237
     }
... ...
@@ -25,6 +25,9 @@
25 25
  */
26 26
 
27 27
 #include "avfilter.h"
28
+#include "video.h"
29
+#include "formats.h"
30
+#include "internal.h"
28 31
 #include "libavutil/avassert.h"
29 32
 #include "libavutil/pixdesc.h"
30 33
 #include "libavutil/intreadwrite.h"
... ...
@@ -633,9 +636,9 @@ int vf_next_put_image(struct vf_instance *vf,mp_image_t *mpi, double pts){
633 633
     if(pts != MP_NOPTS_VALUE)
634 634
         picref->pts= pts * av_q2d(outlink->time_base);
635 635
 
636
-    avfilter_start_frame(outlink, avfilter_ref_buffer(picref, ~0));
637
-    avfilter_draw_slice(outlink, 0, picref->video->h, 1);
638
-    avfilter_end_frame(outlink);
636
+    ff_start_frame(outlink, avfilter_ref_buffer(picref, ~0));
637
+    ff_draw_slice(outlink, 0, picref->video->h, 1);
638
+    ff_end_frame(outlink);
639 639
     avfilter_unref_buffer(picref);
640 640
     m->frame_returned++;
641 641
 
... ...
@@ -788,14 +791,14 @@ static int query_formats(AVFilterContext *ctx)
788 788
         if(m->vf.query_format(&m->vf, conversion_map[i].fmt)){
789 789
             av_log(ctx, AV_LOG_DEBUG, "supported,adding\n");
790 790
             if (conversion_map[i].pix_fmt != lastpixfmt) {
791
-                avfilter_add_format(&avfmts, conversion_map[i].pix_fmt);
791
+                ff_add_format(&avfmts, conversion_map[i].pix_fmt);
792 792
                 lastpixfmt = conversion_map[i].pix_fmt;
793 793
             }
794 794
         }
795 795
     }
796 796
 
797 797
     //We assume all allowed input formats are also allowed output formats
798
-    avfilter_set_common_pixel_formats(ctx, avfmts);
798
+    ff_set_common_formats(ctx, avfmts);
799 799
     return 0;
800 800
 }
801 801
 
... ...
@@ -836,7 +839,7 @@ static int request_frame(AVFilterLink *outlink)
836 836
     av_log(m->avfctx, AV_LOG_DEBUG, "mp request_frame\n");
837 837
 
838 838
     for(m->frame_returned=0; !m->frame_returned;){
839
-        ret=avfilter_request_frame(outlink->src->inputs[0]);
839
+        ret=ff_request_frame(outlink->src->inputs[0]);
840 840
         if(ret<0)
841 841
             break;
842 842
     }
... ...
@@ -178,7 +178,7 @@ static int request_frame(AVFilterLink *link)
178 178
     /* loop until a frame thumbnail is available (when a frame is queued,
179 179
      * thumb->n is reset to zero) */
180 180
     do {
181
-        int ret = avfilter_request_frame(link->src->inputs[0]);
181
+        int ret = ff_request_frame(link->src->inputs[0]);
182 182
         if (ret < 0)
183 183
             return ret;
184 184
     } while (thumb->n);
... ...
@@ -203,7 +203,7 @@ static int poll_frame(AVFilterLink *link)
203 203
 
204 204
     /* we have some frame(s) available in the input link, but not yet enough to
205 205
      * output a thumbnail, so we request more */
206
-    ret = avfilter_request_frame(inlink);
206
+    ret = ff_request_frame(inlink);
207 207
     return ret < 0 ? ret : 0;
208 208
 }
209 209
 
... ...
@@ -28,6 +28,7 @@
28 28
 #include "drawutils.h"
29 29
 #include "formats.h"
30 30
 #include "video.h"
31
+#include "internal.h"
31 32
 
32 33
 typedef struct {
33 34
     unsigned w, h;
... ...
@@ -170,7 +171,7 @@ static int request_frame(AVFilterLink *outlink)
170 170
     int r;
171 171
 
172 172
     while (1) {
173
-        r = avfilter_request_frame(inlink);
173
+        r = ff_request_frame(inlink);
174 174
         if (r < 0) {
175 175
             if (r == AVERROR_EOF && tile->current)
176 176
                 end_last_frame(ctx);
... ...
@@ -334,7 +334,7 @@ static int poll_frame(AVFilterLink *outlink)
334 334
     val = ff_poll_frame(inlink);
335 335
 
336 336
     if (val == 1 && !tinterlace->next) {
337
-        if ((ret = avfilter_request_frame(inlink)) < 0)
337
+        if ((ret = ff_request_frame(inlink)) < 0)
338 338
             return ret;
339 339
         val = ff_poll_frame(inlink);
340 340
     }
... ...
@@ -351,7 +351,7 @@ static int request_frame(AVFilterLink *outlink)
351 351
     do {
352 352
         int ret;
353 353
 
354
-        if ((ret = avfilter_request_frame(inlink)) < 0)
354
+        if ((ret = ff_request_frame(inlink)) < 0)
355 355
             return ret;
356 356
     } while (!tinterlace->cur);
357 357
 
... ...
@@ -321,6 +321,11 @@ void ff_draw_slice(AVFilterLink *link, int y, int h, int slice_dir)
321 321
     draw_slice(link, y, h, slice_dir);
322 322
 }
323 323
 
324
+void avfilter_default_end_frame(AVFilterLink *inlink)
325
+{
326
+    default_end_frame(inlink);
327
+}
328
+
324 329
 #if FF_API_FILTERS_PUBLIC
325 330
 AVFilterBufferRef *avfilter_default_get_video_buffer(AVFilterLink *link, int perms, int w, int h)
326 331
 {
... ...
@@ -330,10 +335,6 @@ void avfilter_default_start_frame(AVFilterLink *inlink, AVFilterBufferRef *picre
330 330
 {
331 331
     default_start_frame(inlink, picref);
332 332
 }
333
-void avfilter_default_end_frame(AVFilterLink *inlink)
334
-{
335
-    default_end_frame(inlink);
336
-}
337 333
 void avfilter_default_draw_slice(AVFilterLink *inlink, int y, int h, int slice_dir)
338 334
 {
339 335
     default_draw_slice(inlink, y, h, slice_dir);
... ...
@@ -49,7 +49,7 @@ void av_set_cpu_flags_mask(int mask)
49 49
 
50 50
 int av_parse_cpu_flags(const char *s)
51 51
 {
52
-#define CPUFLAG_MMX2     (AV_CPU_FLAG_MMX      | AV_CPU_FLAG_MMX2)
52
+#define CPUFLAG_MMX2     (AV_CPU_FLAG_MMX      | AV_CPU_FLAG_MMX2 | AV_CPU_FLAG_CMOV)
53 53
 #define CPUFLAG_3DNOW    (AV_CPU_FLAG_3DNOW    | AV_CPU_FLAG_MMX)
54 54
 #define CPUFLAG_3DNOWEXT (AV_CPU_FLAG_3DNOWEXT | CPUFLAG_3DNOW)
55 55
 #define CPUFLAG_SSE      (AV_CPU_FLAG_SSE      | CPUFLAG_MMX2)
... ...
@@ -84,6 +84,7 @@ int av_parse_cpu_flags(const char *s)
84 84
         { "fma4"    , NULL, 0, AV_OPT_TYPE_CONST, { CPUFLAG_FMA4         },    .unit = "flags" },
85 85
         { "3dnow"   , NULL, 0, AV_OPT_TYPE_CONST, { CPUFLAG_3DNOW        },    .unit = "flags" },
86 86
         { "3dnowext", NULL, 0, AV_OPT_TYPE_CONST, { CPUFLAG_3DNOWEXT     },    .unit = "flags" },
87
+        { "cmov",     NULL, 0, AV_OPT_TYPE_CONST, { AV_CPU_FLAG_CMOV     },    .unit = "flags" },
87 88
 #elif ARCH_ARM
88 89
         { "armv5te",  NULL, 0, AV_OPT_TYPE_CONST, { AV_CPU_FLAG_ARMV5TE  },    .unit = "flags" },
89 90
         { "armv6",    NULL, 0, AV_OPT_TYPE_CONST, { AV_CPU_FLAG_ARMV6    },    .unit = "flags" },
... ...
@@ -188,6 +189,7 @@ static const struct {
188 188
     { AV_CPU_FLAG_FMA4,      "fma4"       },
189 189
     { AV_CPU_FLAG_3DNOW,     "3dnow"      },
190 190
     { AV_CPU_FLAG_3DNOWEXT,  "3dnowext"   },
191
+    { AV_CPU_FLAG_CMOV,      "cmov"       },
191 192
 #endif
192 193
     { 0 }
193 194
 };
... ...
@@ -40,9 +40,14 @@
40 40
 #define AV_CPU_FLAG_SSE4         0x0100 ///< Penryn SSE4.1 functions
41 41
 #define AV_CPU_FLAG_SSE42        0x0200 ///< Nehalem SSE4.2 functions
42 42
 #define AV_CPU_FLAG_AVX          0x4000 ///< AVX functions: requires OS support even if YMM registers aren't used
43
-#define AV_CPU_FLAG_CMOV      0x1000000 ///< supports cmov instruction
44 43
 #define AV_CPU_FLAG_XOP          0x0400 ///< Bulldozer XOP functions
45 44
 #define AV_CPU_FLAG_FMA4         0x0800 ///< Bulldozer FMA4 functions
45
+#if LIBAVUTIL_VERSION_MAJOR <52
46
+#define AV_CPU_FLAG_CMOV      0x1001000 ///< supports cmov instruction
47
+#else
48
+#define AV_CPU_FLAG_CMOV         0x1000 ///< supports cmov instruction
49
+#endif
50
+
46 51
 #define AV_CPU_FLAG_ALTIVEC      0x0001 ///< standard
47 52
 
48 53
 #define AV_CPU_FLAG_ARMV5TE      (1 << 0)
... ...
@@ -83,7 +83,7 @@ int ff_get_cpu_flags_x86(void)
83 83
         cpuid(1, eax, ebx, ecx, std_caps);
84 84
         family = ((eax>>8)&0xf) + ((eax>>20)&0xff);
85 85
         model  = ((eax>>4)&0xf) + ((eax>>12)&0xf0);
86
-        if (std_caps & (1<<15))
86
+        if (std_caps & (1 << 15))
87 87
             rval |= AV_CPU_FLAG_CMOV;
88 88
         if (std_caps & (1<<23))
89 89
             rval |= AV_CPU_FLAG_MMX;