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
41 unsigned nb_streams[
TYPE_ALL];
/**< number of out streams of each type */
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",
72 { 0 }
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;
137 /* possible enhancement: unsafe mode, do not check */
138 if (outlink->
w != inlink->
w ||
139 outlink->
h != inlink->
h ||
143 "(size %dx%d, SAR %d:%d) do not match the corresponding "
144 "output link %s parameters (%dx%d, SAR %d:%d)\n",
153 }
154 }
155
156 return 0;
157 }
158
160 {
165 struct concat_in *
in = &cat->
in[in_no];
166
169 in->nb_frames++;
170 /* add duration to input PTS */
172 /* use number of audio samples */
175 outlink->time_base);
176 else if (
in->nb_frames >= 2)
177 /* use mean duration */
179
180 buf->pts += cat->delta_ts;
182 }
183
185 {
189
190 if (in_no < cat->cur_idx) {
196 } else {
198 }
199 return 0;
200 }
201
203 {
207
209 }
210
212 {
216
218 }
219
221 {
223 }
224
226 {
228
229 cat->
in[in_no].
eof = 1;
233 }
234
236 {
240 int64_t pts;
241
242 pts = cat->
in[i++].
pts;
243 for (; i < imax; i++)
246 *seg_delta = pts;
247 }
248
250 int64_t seg_delta)
251 {
254 int64_t base_pts = cat->
in[in_no].
pts + cat->
delta_ts - seg_delta;
255 int64_t nb_samples, sent = 0;
256 int frame_nb_samples,
ret;
260
265 frame_nb_samples =
FFMAX(9600, rate_tb.
den / 5);
/* arbitrary */
266 while (nb_samples) {
267 frame_nb_samples =
FFMIN(frame_nb_samples, nb_samples);
269 if (!buf)
272 nb_channels, outlink->
format);
275 if (ret < 0)
277 sent += frame_nb_samples;
278 nb_samples -= frame_nb_samples;
279 }
280 return 0;
281 }
282
284 {
287 unsigned str, str_max;
288 int64_t seg_delta;
289
295
297 /* pad audio streams with silence */
300 for (; str < str_max; str++) {
302 seg_delta);
303 if (ret < 0)
305 }
306 /* flush queued buffers */
307 /* possible enhancement: flush in PTS order */
309 for (str = cat->
cur_idx; str < str_max; str++) {
312 if (ret < 0)
314 }
315 }
316 }
317 return 0;
318 }
319
321 {
325 unsigned in_no = out_no + cat->
cur_idx;
326 unsigned str, str_max;
328
329 while (1) {
332 if (!cat->
in[in_no].
eof) {
337 }
338 /* cycle on all inputs to finish the segment */
339 /* possible enhancement: request in PTS order */
342 str = str == str_max ? cat->
cur_idx : str + 1) {
343 if (cat->
in[str].
eof)
344 continue;
348 else if (ret < 0)
350 }
352 if (ret < 0)
355 }
356 }
357
359 {
361 unsigned seg,
type, str;
362
363 /* create input pads */
365 for (type = 0; type <
TYPE_ALL; type++) {
366 for (str = 0; str < cat->
nb_streams[type]; str++) {
372 };
375 }
376 }
377 }
378 /* create output pads */
379 for (type = 0; type <
TYPE_ALL; type++) {
380 for (str = 0; str < cat->
nb_streams[type]; str++) {
385 };
388 }
389 }
390
395 return 0;
396 }
397
399 {
401 unsigned i;
402
406 }
410 }
411
423 };