]> git.sesse.net Git - ffmpeg/blob - libavfilter/framesync.c
Merge commit '5b6f42da98c26a8aee8d2c2edfcbd0633ad1c607'
[ffmpeg] / libavfilter / framesync.c
1 /*
2  * Copyright (c) 2013 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 License
8  * 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 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 #include "libavutil/avassert.h"
22 #include "avfilter.h"
23 #include "bufferqueue.h"
24 #include "framesync.h"
25 #include "internal.h"
26
27 #define OFFSET(member) offsetof(FFFrameSync, member)
28
29 static const char *framesync_name(void *ptr)
30 {
31     return "framesync";
32 }
33
34 static const AVClass framesync_class = {
35     .version                   = LIBAVUTIL_VERSION_INT,
36     .class_name                = "framesync",
37     .item_name                 = framesync_name,
38     .category                  = AV_CLASS_CATEGORY_FILTER,
39     .option                    = NULL,
40     .parent_log_context_offset = OFFSET(parent),
41 };
42
43 enum {
44     STATE_BOF,
45     STATE_RUN,
46     STATE_EOF,
47 };
48
49 int ff_framesync_init(FFFrameSync *fs, void *parent, unsigned nb_in)
50 {
51     fs->class  = &framesync_class;
52     fs->parent = parent;
53     fs->nb_in  = nb_in;
54
55     fs->in = av_calloc(nb_in, sizeof(*fs->in));
56     if (!fs->in)
57         return AVERROR(ENOMEM);
58     return 0;
59 }
60
61 static void framesync_sync_level_update(FFFrameSync *fs)
62 {
63     unsigned i, level = 0;
64
65     for (i = 0; i < fs->nb_in; i++)
66         if (fs->in[i].state != STATE_EOF)
67             level = FFMAX(level, fs->in[i].sync);
68     av_assert0(level <= fs->sync_level);
69     if (level < fs->sync_level)
70         av_log(fs, AV_LOG_VERBOSE, "Sync level %u\n", level);
71     if (level)
72         fs->sync_level = level;
73     else
74         fs->eof = 1;
75 }
76
77 int ff_framesync_configure(FFFrameSync *fs)
78 {
79     unsigned i;
80     int64_t gcd, lcm;
81
82     if (!fs->time_base.num) {
83         for (i = 0; i < fs->nb_in; i++) {
84             if (fs->in[i].sync) {
85                 if (fs->time_base.num) {
86                     gcd = av_gcd(fs->time_base.den, fs->in[i].time_base.den);
87                     lcm = (fs->time_base.den / gcd) * fs->in[i].time_base.den;
88                     if (lcm < AV_TIME_BASE / 2) {
89                         fs->time_base.den = lcm;
90                         fs->time_base.num = av_gcd(fs->time_base.num,
91                                                    fs->in[i].time_base.num);
92                     } else {
93                         fs->time_base.num = 1;
94                         fs->time_base.den = AV_TIME_BASE;
95                         break;
96                     }
97                 } else {
98                     fs->time_base = fs->in[i].time_base;
99                 }
100             }
101         }
102         if (!fs->time_base.num) {
103             av_log(fs, AV_LOG_ERROR, "Impossible to set time base\n");
104             return AVERROR(EINVAL);
105         }
106         av_log(fs, AV_LOG_VERBOSE, "Selected %d/%d time base\n",
107                fs->time_base.num, fs->time_base.den);
108     }
109
110     for (i = 0; i < fs->nb_in; i++)
111         fs->in[i].pts = fs->in[i].pts_next = AV_NOPTS_VALUE;
112     fs->sync_level = UINT_MAX;
113     framesync_sync_level_update(fs);
114
115     return 0;
116 }
117
118 static void framesync_advance(FFFrameSync *fs)
119 {
120     int latest;
121     unsigned i;
122     int64_t pts;
123
124     if (fs->eof)
125         return;
126     while (!fs->frame_ready) {
127         latest = -1;
128         for (i = 0; i < fs->nb_in; i++) {
129             if (!fs->in[i].have_next) {
130                 if (latest < 0 || fs->in[i].pts < fs->in[latest].pts)
131                     latest = i;
132             }
133         }
134         if (latest >= 0) {
135             fs->in_request = latest;
136             break;
137         }
138
139         pts = fs->in[0].pts_next;
140         for (i = 1; i < fs->nb_in; i++)
141             if (fs->in[i].pts_next < pts)
142                 pts = fs->in[i].pts_next;
143         if (pts == INT64_MAX) {
144             fs->eof = 1;
145             break;
146         }
147         for (i = 0; i < fs->nb_in; i++) {
148             if (fs->in[i].pts_next == pts ||
149                 (fs->in[i].before == EXT_INFINITY &&
150                  fs->in[i].state == STATE_BOF)) {
151                 av_frame_free(&fs->in[i].frame);
152                 fs->in[i].frame      = fs->in[i].frame_next;
153                 fs->in[i].pts        = fs->in[i].pts_next;
154                 fs->in[i].frame_next = NULL;
155                 fs->in[i].pts_next   = AV_NOPTS_VALUE;
156                 fs->in[i].have_next  = 0;
157                 fs->in[i].state      = fs->in[i].frame ? STATE_RUN : STATE_EOF;
158                 if (fs->in[i].sync == fs->sync_level && fs->in[i].frame)
159                     fs->frame_ready = 1;
160                 if (fs->in[i].state == STATE_EOF &&
161                     fs->in[i].after == EXT_STOP)
162                     fs->eof = 1;
163             }
164         }
165         if (fs->eof)
166             fs->frame_ready = 0;
167         if (fs->frame_ready)
168             for (i = 0; i < fs->nb_in; i++)
169                 if ((fs->in[i].state == STATE_BOF &&
170                      fs->in[i].before == EXT_STOP))
171                     fs->frame_ready = 0;
172         fs->pts = pts;
173     }
174 }
175
176 static int64_t framesync_pts_extrapolate(FFFrameSync *fs, unsigned in,
177                                          int64_t pts)
178 {
179     /* Possible enhancement: use the link's frame rate */
180     return pts + 1;
181 }
182
183 static void framesync_inject_frame(FFFrameSync *fs, unsigned in, AVFrame *frame)
184 {
185     int64_t pts;
186
187     av_assert0(!fs->in[in].have_next);
188     if (frame) {
189         pts = av_rescale_q(frame->pts, fs->in[in].time_base, fs->time_base);
190         frame->pts = pts;
191     } else {
192         pts = fs->in[in].state != STATE_RUN || fs->in[in].after == EXT_INFINITY
193             ? INT64_MAX : framesync_pts_extrapolate(fs, in, fs->in[in].pts);
194         fs->in[in].sync = 0;
195         framesync_sync_level_update(fs);
196     }
197     fs->in[in].frame_next = frame;
198     fs->in[in].pts_next   = pts;
199     fs->in[in].have_next  = 1;
200 }
201
202 int ff_framesync_add_frame(FFFrameSync *fs, unsigned in, AVFrame *frame)
203 {
204     av_assert1(in < fs->nb_in);
205     if (!fs->in[in].have_next)
206         framesync_inject_frame(fs, in, frame);
207     else
208         ff_bufqueue_add(fs, &fs->in[in].queue, frame);
209     return 0;
210 }
211
212 void ff_framesync_next(FFFrameSync *fs)
213 {
214     unsigned i;
215
216     av_assert0(!fs->frame_ready);
217     for (i = 0; i < fs->nb_in; i++)
218         if (!fs->in[i].have_next && fs->in[i].queue.available)
219             framesync_inject_frame(fs, i, ff_bufqueue_get(&fs->in[i].queue));
220     fs->frame_ready = 0;
221     framesync_advance(fs);
222 }
223
224 void ff_framesync_drop(FFFrameSync *fs)
225 {
226     fs->frame_ready = 0;
227 }
228
229 int ff_framesync_get_frame(FFFrameSync *fs, unsigned in, AVFrame **rframe,
230                            unsigned get)
231 {
232     AVFrame *frame;
233     unsigned need_copy = 0, i;
234     int64_t pts_next;
235     int ret;
236
237     if (!fs->in[in].frame) {
238         *rframe = NULL;
239         return 0;
240     }
241     frame = fs->in[in].frame;
242     if (get) {
243         /* Find out if we need to copy the frame: is there another sync
244            stream, and do we know if its current frame will outlast this one? */
245         pts_next = fs->in[in].have_next ? fs->in[in].pts_next : INT64_MAX;
246         for (i = 0; i < fs->nb_in && !need_copy; i++)
247             if (i != in && fs->in[i].sync &&
248                 (!fs->in[i].have_next || fs->in[i].pts_next < pts_next))
249                 need_copy = 1;
250         if (need_copy) {
251             if (!(frame = av_frame_clone(frame)))
252                 return AVERROR(ENOMEM);
253             if ((ret = av_frame_make_writable(frame)) < 0) {
254                 av_frame_free(&frame);
255                 return ret;
256             }
257         } else {
258             fs->in[in].frame = NULL;
259         }
260         fs->frame_ready = 0;
261     }
262     *rframe = frame;
263     return 0;
264 }
265
266 void ff_framesync_uninit(FFFrameSync *fs)
267 {
268     unsigned i;
269
270     for (i = 0; i < fs->nb_in; i++) {
271         av_frame_free(&fs->in[i].frame);
272         av_frame_free(&fs->in[i].frame_next);
273         ff_bufqueue_discard_all(&fs->in[i].queue);
274     }
275
276     av_freep(&fs->in);
277 }
278
279 int ff_framesync_process_frame(FFFrameSync *fs, unsigned all)
280 {
281     int ret, count = 0;
282
283     av_assert0(fs->on_event);
284     while (1) {
285         ff_framesync_next(fs);
286         if (fs->eof || !fs->frame_ready)
287             break;
288         if ((ret = fs->on_event(fs)) < 0)
289             return ret;
290         ff_framesync_drop(fs);
291         count++;
292         if (!all)
293             break;
294     }
295     if (!count && fs->eof)
296         return AVERROR_EOF;
297     return count;
298 }
299
300 int ff_framesync_filter_frame(FFFrameSync *fs, AVFilterLink *inlink,
301                               AVFrame *in)
302 {
303     int ret;
304
305     if ((ret = ff_framesync_process_frame(fs, 1)) < 0)
306         return ret;
307     if ((ret = ff_framesync_add_frame(fs, FF_INLINK_IDX(inlink), in)) < 0)
308         return ret;
309     if ((ret = ff_framesync_process_frame(fs, 0)) < 0)
310         return ret;
311     return 0;
312 }
313
314 int ff_framesync_request_frame(FFFrameSync *fs, AVFilterLink *outlink)
315 {
316     AVFilterContext *ctx = outlink->src;
317     int input, ret;
318
319     if ((ret = ff_framesync_process_frame(fs, 0)) < 0)
320         return ret;
321     if (ret > 0)
322         return 0;
323     if (fs->eof)
324         return AVERROR_EOF;
325     input = fs->in_request;
326     ret = ff_request_frame(ctx->inputs[input]);
327     if (ret == AVERROR_EOF) {
328         if ((ret = ff_framesync_add_frame(fs, input, NULL)) < 0)
329             return ret;
330         if ((ret = ff_framesync_process_frame(fs, 0)) < 0)
331             return ret;
332         ret = 0;
333     }
334     return ret;
335 }