1 /*
2 * Copyright (c) 2012 Nicolas George
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.
14 * See the GNU Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with FFmpeg; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21 /**
22 * @file
23 * concat audio-video filter
24 */
25
31 #define FF_BUFQUEUE_SIZE 256
36
38
43 unsigned cur_idx;
/**< index of the first input of current segment */
44 int64_t
delta_ts;
/**< timestamp to add to produce output timestamps */
45 unsigned nb_in_active;
/**< number of active inputs in current segment */
54
55 #define OFFSET(x) offsetof(ConcatContext, x)
56 #define A AV_OPT_FLAG_AUDIO_PARAM
57 #define F AV_OPT_FLAG_FILTERING_PARAM
58 #define V AV_OPT_FLAG_VIDEO_PARAM
59
61 {
"n",
"specify the number of segments",
OFFSET(nb_segments),
63 { "v", "specify the number of video streams",
66 { "a", "specify the number of audio streams",
69 { "unsafe", "enable unsafe mode",
73 };
74
76
78 {
80 unsigned type, nb_str, idx0 = 0, idx, str, seg;
83
84 for (type = 0; type <
TYPE_ALL; type++) {
86 for (str = 0; str < nb_str; str++) {
87 idx = idx0;
88
89 /* Set the output formats */
91 if (!formats)
96 if (!rates)
100 if (!layouts)
103 }
104
105 /* Set the same formats for each corresponding input */
111 }
113 }
114
115 idx0++;
116 }
117 }
118 return 0;
119 }
120
122 {
126 unsigned in_no = out_no, seg;
128
129 /* enhancement: find a common one */
131 outlink->
w = inlink->
w;
132 outlink->
h = inlink->
h;
139 /* possible enhancement: unsafe mode, do not check */
140 if (outlink->
w != inlink->
w ||
141 outlink->
h != inlink->
h ||
146 "(size %dx%d, SAR %d:%d) do not match the corresponding "
147 "output link %s parameters (%dx%d, SAR %d:%d)\n",
156 }
157 }
158
159 return 0;
160 }
161
163 {
168 struct concat_in *
in = &cat->
in[in_no];
169
172 in->nb_frames++;
173 /* add duration to input PTS */
175 /* use number of audio samples */
179 else if (in->nb_frames >= 2)
180 /* use mean duration */
181 in->pts =
av_rescale(in->pts, in->nb_frames, in->nb_frames - 1);
182
185 }
186
188 {
192
193 if (in_no < cat->cur_idx) {
199 } else {
201 }
202 return 0;
203 }
204
206 {
210
212 }
213
215 {
219
221 }
222
224 {
226 }
227
229 {
231
232 cat->
in[in_no].
eof = 1;
236 }
237
239 {
244
245 pts = cat->
in[i++].
pts;
246 for (; i < imax; i++)
250 }
251
253 int64_t seg_delta)
254 {
257 int64_t base_pts = cat->
in[in_no].
pts + cat->
delta_ts - seg_delta;
258 int64_t nb_samples, sent = 0;
259 int frame_nb_samples,
ret;
263
268 frame_nb_samples =
FFMAX(9600, rate_tb.
den / 5);
/* arbitrary */
269 while (nb_samples) {
270 frame_nb_samples =
FFMIN(frame_nb_samples, nb_samples);
272 if (!buf)
275 nb_channels, outlink->
format);
278 if (ret < 0)
280 sent += frame_nb_samples;
281 nb_samples -= frame_nb_samples;
282 }
283 return 0;
284 }
285
287 {
290 unsigned str, str_max;
291 int64_t seg_delta;
292
298
300 /* pad audio streams with silence */
303 for (; str < str_max; str++) {
305 seg_delta);
306 if (ret < 0)
308 }
309 /* flush queued buffers */
310 /* possible enhancement: flush in PTS order */
312 for (str = cat->
cur_idx; str < str_max; str++) {
315 if (ret < 0)
317 }
318 }
319 }
320 return 0;
321 }
322
324 {
328 unsigned in_no = out_no + cat->
cur_idx;
329 unsigned str, str_max;
331
332 while (1) {
335 if (!cat->
in[in_no].
eof) {
340 }
341 /* cycle on all inputs to finish the segment */
342 /* possible enhancement: request in PTS order */
345 str = str == str_max ? cat->
cur_idx : str + 1) {
346 if (cat->
in[str].
eof)
347 continue;
351 else if (ret < 0)
353 }
355 if (ret < 0)
358 }
359 }
360
362 {
364 unsigned seg,
type, str;
365
366 /* create input pads */
368 for (type = 0; type <
TYPE_ALL; type++) {
375 };
378 }
379 }
380 }
381 /* create output pads */
382 for (type = 0; type <
TYPE_ALL; type++) {
388 };
391 }
392 }
393
398 return 0;
399 }
400
402 {
404 unsigned i;
405
409 }
413 }
414
426 };