]> git.sesse.net Git - ffmpeg/blob - libavfilter/af_amerge.c
lavfi: fix mp and mandelbrot descriptions to make them complete sentences
[ffmpeg] / libavfilter / af_amerge.c
1 /*
2  * Copyright (c) 2011 Nicolas George <nicolas.george@normalesup.org>
3  *
4  * This file is part of FFmpeg.
5  *
6  * FFmpeg is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * FFmpeg is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with FFmpeg; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20
21 /**
22  * @file
23  * Audio merging filter
24  */
25
26 #include "libswresample/swresample.h" // only for SWR_CH_MAX
27 #include "avfilter.h"
28 #include "internal.h"
29
30 #define QUEUE_SIZE 16
31
32 typedef struct {
33     int nb_in_ch[2];       /**< number of channels for each input */
34     int route[SWR_CH_MAX]; /**< channels routing, see copy_samples */
35     int bps;
36     struct amerge_queue {
37         AVFilterBufferRef *buf[QUEUE_SIZE];
38         int nb_buf, nb_samples, pos;
39     } queue[2];
40 } AMergeContext;
41
42 static av_cold void uninit(AVFilterContext *ctx)
43 {
44     AMergeContext *am = ctx->priv;
45     int i, j;
46
47     for (i = 0; i < 2; i++)
48         for (j = 0; j < am->queue[i].nb_buf; j++)
49             avfilter_unref_buffer(am->queue[i].buf[j]);
50 }
51
52 static int query_formats(AVFilterContext *ctx)
53 {
54     AMergeContext *am = ctx->priv;
55     int64_t inlayout[2], outlayout;
56     const int packing_fmts[] = { AVFILTER_PACKED, -1 };
57     AVFilterFormats *formats;
58     int i;
59
60     for (i = 0; i < 2; i++) {
61         if (!ctx->inputs[i]->in_chlayouts ||
62             !ctx->inputs[i]->in_chlayouts->format_count) {
63             av_log(ctx, AV_LOG_ERROR,
64                    "No channel layout for input %d\n", i + 1);
65             return AVERROR(EINVAL);
66         }
67         inlayout[i] = ctx->inputs[i]->in_chlayouts->formats[0];
68         if (ctx->inputs[i]->in_chlayouts->format_count > 1) {
69             char buf[256];
70             av_get_channel_layout_string(buf, sizeof(buf), 0, inlayout[i]);
71             av_log(ctx, AV_LOG_INFO, "Using \"%s\" for input %d\n", buf, i + 1);
72         }
73         am->nb_in_ch[i] = av_get_channel_layout_nb_channels(inlayout[i]);
74     }
75     if (am->nb_in_ch[0] + am->nb_in_ch[1] > SWR_CH_MAX) {
76         av_log(ctx, AV_LOG_ERROR, "Too many channels (max %d)\n", SWR_CH_MAX);
77         return AVERROR(EINVAL);
78     }
79     if (inlayout[0] & inlayout[1]) {
80         av_log(ctx, AV_LOG_WARNING,
81                "Inputs overlap: output layout will be meaningless\n");
82         for (i = 0; i < am->nb_in_ch[0] + am->nb_in_ch[1]; i++)
83             am->route[i] = i;
84         outlayout = av_get_default_channel_layout(am->nb_in_ch[0] +
85                                                   am->nb_in_ch[1]);
86         if (!outlayout)
87             outlayout = ((int64_t)1 << (am->nb_in_ch[0] + am->nb_in_ch[1])) - 1;
88     } else {
89         int *route[2] = { am->route, am->route + am->nb_in_ch[0] };
90         int c, out_ch_number = 0;
91
92         outlayout = inlayout[0] | inlayout[1];
93         for (c = 0; c < 64; c++)
94             for (i = 0; i < 2; i++)
95                 if ((inlayout[i] >> c) & 1)
96                     *(route[i]++) = out_ch_number++;
97     }
98     formats = avfilter_make_all_formats(AVMEDIA_TYPE_AUDIO);
99     avfilter_set_common_sample_formats(ctx, formats);
100     formats = avfilter_make_format_list(packing_fmts);
101     avfilter_set_common_packing_formats(ctx, formats);
102     for (i = 0; i < 2; i++) {
103         formats = NULL;
104         avfilter_add_format(&formats, inlayout[i]);
105         avfilter_formats_ref(formats, &ctx->inputs[i]->out_chlayouts);
106     }
107     formats = NULL;
108     avfilter_add_format(&formats, outlayout);
109     avfilter_formats_ref(formats, &ctx->outputs[0]->in_chlayouts);
110     return 0;
111 }
112
113 static int config_output(AVFilterLink *outlink)
114 {
115     AVFilterContext *ctx = outlink->src;
116     AMergeContext *am = ctx->priv;
117     int64_t layout;
118     char name[3][256];
119     int i;
120
121     if (ctx->inputs[0]->sample_rate != ctx->inputs[1]->sample_rate) {
122         av_log(ctx, AV_LOG_ERROR,
123                "Inputs must have the same sample rate "
124                "(%"PRIi64" vs %"PRIi64")\n",
125                ctx->inputs[0]->sample_rate, ctx->inputs[1]->sample_rate);
126         return AVERROR(EINVAL);
127     }
128     am->bps = av_get_bytes_per_sample(ctx->outputs[0]->format);
129     outlink->sample_rate = ctx->inputs[0]->sample_rate;
130     outlink->time_base   = ctx->inputs[0]->time_base;
131     for (i = 0; i < 3; i++) {
132         layout = (i < 2 ? ctx->inputs[i] : ctx->outputs[0])->channel_layout;
133         av_get_channel_layout_string(name[i], sizeof(name[i]), -1, layout);
134     }
135     av_log(ctx, AV_LOG_INFO,
136            "in1:%s + in2:%s -> out:%s\n", name[0], name[1], name[2]);
137     return 0;
138 }
139
140 static int request_frame(AVFilterLink *outlink)
141 {
142     AVFilterContext *ctx = outlink->src;
143     AMergeContext *am = ctx->priv;
144     int i;
145
146     for (i = 0; i < 2; i++)
147         if (!am->queue[i].nb_samples)
148             avfilter_request_frame(ctx->inputs[i]);
149     return 0;
150 }
151
152 /**
153  * Copy samples from two input streams to one output stream.
154  * @param nb_in_ch  number of channels in each input stream
155  * @param route     routing values;
156  *                  input channel i goes to output channel route[i];
157  *                  i <  nb_in_ch[0] are the channels from the first output;
158  *                  i >= nb_in_ch[0] are the channels from the second output
159  * @param ins       pointer to the samples of each inputs, in packed format;
160  *                  will be left at the end of the copied samples
161  * @param outs      pointer to the samples of the output, in packet format;
162  *                  must point to a buffer big enough;
163  *                  will be left at the end of the copied samples
164  * @param ns        number of samples to copy
165  * @param bps       bytes per sample
166  */
167 static inline void copy_samples(int nb_in_ch[2], int *route, uint8_t *ins[2],
168                                 uint8_t **outs, int ns, int bps)
169 {
170     int *route_cur;
171     int i, c;
172
173     while (ns--) {
174         route_cur = route;
175         for (i = 0; i < 2; i++) {
176             for (c = 0; c < nb_in_ch[i]; c++) {
177                 memcpy((*outs) + bps * *(route_cur++), ins[i], bps);
178                 ins[i] += bps;
179             }
180         }
181         *outs += (nb_in_ch[0] + nb_in_ch[1]) * bps;
182     }
183 }
184
185 static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamples)
186 {
187     AVFilterContext *ctx = inlink->dst;
188     AMergeContext *am = ctx->priv;
189     int input_number = inlink == ctx->inputs[1];
190     struct amerge_queue *inq = &am->queue[input_number];
191     int nb_samples, ns, i;
192     AVFilterBufferRef *outbuf, **inbuf[2];
193     uint8_t *ins[2], *outs;
194
195     if (inq->nb_buf == QUEUE_SIZE) {
196         av_log(ctx, AV_LOG_ERROR, "Packet queue overflow; dropped\n");
197         avfilter_unref_buffer(insamples);
198         return;
199     }
200     inq->buf[inq->nb_buf++] = avfilter_ref_buffer(insamples, AV_PERM_READ |
201                                                              AV_PERM_PRESERVE);
202     inq->nb_samples += insamples->audio->nb_samples;
203     avfilter_unref_buffer(insamples);
204     if (!am->queue[!input_number].nb_samples)
205         return;
206
207     nb_samples = FFMIN(am->queue[0].nb_samples,
208                        am->queue[1].nb_samples);
209     outbuf = avfilter_get_audio_buffer(ctx->outputs[0], AV_PERM_WRITE,
210                                        nb_samples);
211     outs = outbuf->data[0];
212     for (i = 0; i < 2; i++) {
213         inbuf[i] = am->queue[i].buf;
214         ins[i] = (*inbuf[i])->data[0] +
215                  am->queue[i].pos * am->nb_in_ch[i] * am->bps;
216     }
217     while (nb_samples) {
218         ns = nb_samples;
219         for (i = 0; i < 2; i++)
220             ns = FFMIN(ns, (*inbuf[i])->audio->nb_samples - am->queue[i].pos);
221         /* Unroll the most common sample formats: speed +~350% for the loop,
222            +~13% overall (including two common decoders) */
223         switch (am->bps) {
224             case 1:
225                 copy_samples(am->nb_in_ch, am->route, ins, &outs, ns, 1);
226                 break;
227             case 2:
228                 copy_samples(am->nb_in_ch, am->route, ins, &outs, ns, 2);
229                 break;
230             case 4:
231                 copy_samples(am->nb_in_ch, am->route, ins, &outs, ns, 4);
232                 break;
233             default:
234                 copy_samples(am->nb_in_ch, am->route, ins, &outs, ns, am->bps);
235                 break;
236         }
237
238         nb_samples -= ns;
239         for (i = 0; i < 2; i++) {
240             am->queue[i].nb_samples -= ns;
241             am->queue[i].pos += ns;
242             if (am->queue[i].pos == (*inbuf[i])->audio->nb_samples) {
243                 am->queue[i].pos = 0;
244                 avfilter_unref_buffer(*inbuf[i]);
245                 *inbuf[i] = NULL;
246                 inbuf[i]++;
247                 ins[i] = *inbuf[i] ? (*inbuf[i])->data[0] : NULL;
248             }
249         }
250     }
251     for (i = 0; i < 2; i++) {
252         int nbufused = inbuf[i] - am->queue[i].buf;
253         if (nbufused) {
254             am->queue[i].nb_buf -= nbufused;
255             memmove(am->queue[i].buf, inbuf[i],
256                     am->queue[i].nb_buf * sizeof(**inbuf));
257         }
258     }
259     avfilter_filter_samples(ctx->outputs[0], outbuf);
260 }
261
262 AVFilter avfilter_af_amerge = {
263     .name          = "amerge",
264     .description   = NULL_IF_CONFIG_SMALL("Merge two audio streams into "
265                                           "a single multi-channel stream."),
266     .priv_size     = sizeof(AMergeContext),
267     .uninit        = uninit,
268     .query_formats = query_formats,
269
270     .inputs    = (const AVFilterPad[]) {
271         { .name             = "in1",
272           .type             = AVMEDIA_TYPE_AUDIO,
273           .filter_samples   = filter_samples,
274           .min_perms        = AV_PERM_READ, },
275         { .name             = "in2",
276           .type             = AVMEDIA_TYPE_AUDIO,
277           .filter_samples   = filter_samples,
278           .min_perms        = AV_PERM_READ, },
279         { .name = NULL }
280     },
281     .outputs   = (const AVFilterPad[]) {
282         { .name             = "default",
283           .type             = AVMEDIA_TYPE_AUDIO,
284           .config_props     = config_output,
285           .request_frame    = request_frame, },
286         { .name = NULL }
287     },
288 };