]> git.sesse.net Git - ffmpeg/blob - libavfilter/framesync2.c
ops_pvq_search: remove dead macro
[ffmpeg] / libavfilter / framesync2.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 "filters.h"
24 #include "framesync2.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_framesync2_init(FFFrameSync *fs, AVFilterContext *parent, unsigned nb_in)
50 {
51     /* For filters with several outputs, we will not be able to assume which
52        output is relevant for ff_outlink_frame_wanted() and
53        ff_outlink_set_status(). To be designed when needed. */
54     av_assert0(parent->nb_outputs == 1);
55
56     fs->class  = &framesync_class;
57     fs->parent = parent;
58     fs->nb_in  = nb_in;
59
60     fs->in = av_calloc(nb_in, sizeof(*fs->in));
61     if (!fs->in)
62         return AVERROR(ENOMEM);
63     return 0;
64 }
65
66 static void framesync_eof(FFFrameSync *fs)
67 {
68     fs->eof = 1;
69     fs->frame_ready = 0;
70     ff_outlink_set_status(fs->parent->outputs[0], AVERROR_EOF, AV_NOPTS_VALUE);
71 }
72
73 static void framesync_sync_level_update(FFFrameSync *fs)
74 {
75     unsigned i, level = 0;
76
77     for (i = 0; i < fs->nb_in; i++)
78         if (fs->in[i].state != STATE_EOF)
79             level = FFMAX(level, fs->in[i].sync);
80     av_assert0(level <= fs->sync_level);
81     if (level < fs->sync_level)
82         av_log(fs, AV_LOG_VERBOSE, "Sync level %u\n", level);
83     if (level)
84         fs->sync_level = level;
85     else
86         framesync_eof(fs);
87 }
88
89 int ff_framesync2_configure(FFFrameSync *fs)
90 {
91     unsigned i;
92     int64_t gcd, lcm;
93
94     if (!fs->time_base.num) {
95         for (i = 0; i < fs->nb_in; i++) {
96             if (fs->in[i].sync) {
97                 if (fs->time_base.num) {
98                     gcd = av_gcd(fs->time_base.den, fs->in[i].time_base.den);
99                     lcm = (fs->time_base.den / gcd) * fs->in[i].time_base.den;
100                     if (lcm < AV_TIME_BASE / 2) {
101                         fs->time_base.den = lcm;
102                         fs->time_base.num = av_gcd(fs->time_base.num,
103                                                    fs->in[i].time_base.num);
104                     } else {
105                         fs->time_base.num = 1;
106                         fs->time_base.den = AV_TIME_BASE;
107                         break;
108                     }
109                 } else {
110                     fs->time_base = fs->in[i].time_base;
111                 }
112             }
113         }
114         if (!fs->time_base.num) {
115             av_log(fs, AV_LOG_ERROR, "Impossible to set time base\n");
116             return AVERROR(EINVAL);
117         }
118         av_log(fs, AV_LOG_VERBOSE, "Selected %d/%d time base\n",
119                fs->time_base.num, fs->time_base.den);
120     }
121
122     for (i = 0; i < fs->nb_in; i++)
123         fs->in[i].pts = fs->in[i].pts_next = AV_NOPTS_VALUE;
124     fs->sync_level = UINT_MAX;
125     framesync_sync_level_update(fs);
126
127     return 0;
128 }
129
130 static void framesync_advance(FFFrameSync *fs)
131 {
132     int latest;
133     unsigned i;
134     int64_t pts;
135
136     if (fs->eof)
137         return;
138     while (!fs->frame_ready) {
139         latest = -1;
140         for (i = 0; i < fs->nb_in; i++) {
141             if (!fs->in[i].have_next) {
142                 if (latest < 0 || fs->in[i].pts < fs->in[latest].pts)
143                     latest = i;
144             }
145         }
146         if (latest >= 0) {
147             fs->in_request = latest;
148             break;
149         }
150
151         pts = fs->in[0].pts_next;
152         for (i = 1; i < fs->nb_in; i++)
153             if (fs->in[i].pts_next < pts)
154                 pts = fs->in[i].pts_next;
155         if (pts == INT64_MAX) {
156             framesync_eof(fs);
157             break;
158         }
159         for (i = 0; i < fs->nb_in; i++) {
160             if (fs->in[i].pts_next == pts ||
161                 (fs->in[i].before == EXT_INFINITY &&
162                  fs->in[i].state == STATE_BOF)) {
163                 av_frame_free(&fs->in[i].frame);
164                 fs->in[i].frame      = fs->in[i].frame_next;
165                 fs->in[i].pts        = fs->in[i].pts_next;
166                 fs->in[i].frame_next = NULL;
167                 fs->in[i].pts_next   = AV_NOPTS_VALUE;
168                 fs->in[i].have_next  = 0;
169                 fs->in[i].state      = fs->in[i].frame ? STATE_RUN : STATE_EOF;
170                 if (fs->in[i].sync == fs->sync_level && fs->in[i].frame)
171                     fs->frame_ready = 1;
172                 if (fs->in[i].state == STATE_EOF &&
173                     fs->in[i].after == EXT_STOP)
174                     framesync_eof(fs);
175             }
176         }
177         if (fs->frame_ready)
178             for (i = 0; i < fs->nb_in; i++)
179                 if ((fs->in[i].state == STATE_BOF &&
180                      fs->in[i].before == EXT_STOP))
181                     fs->frame_ready = 0;
182         fs->pts = pts;
183     }
184 }
185
186 static int64_t framesync_pts_extrapolate(FFFrameSync *fs, unsigned in,
187                                          int64_t pts)
188 {
189     /* Possible enhancement: use the link's frame rate */
190     return pts + 1;
191 }
192
193 static void framesync_inject_frame(FFFrameSync *fs, unsigned in, AVFrame *frame)
194 {
195     int64_t pts;
196
197     av_assert0(!fs->in[in].have_next);
198     av_assert0(frame);
199     pts = av_rescale_q(frame->pts, fs->in[in].time_base, fs->time_base);
200     frame->pts = pts;
201     fs->in[in].frame_next = frame;
202     fs->in[in].pts_next   = pts;
203     fs->in[in].have_next  = 1;
204 }
205
206 static void framesync_inject_status(FFFrameSync *fs, unsigned in, int status, int64_t pts)
207 {
208     av_assert0(!fs->in[in].have_next);
209     pts = fs->in[in].state != STATE_RUN || fs->in[in].after == EXT_INFINITY
210         ? INT64_MAX : framesync_pts_extrapolate(fs, in, fs->in[in].pts);
211     fs->in[in].sync = 0;
212     framesync_sync_level_update(fs);
213     fs->in[in].frame_next = NULL;
214     fs->in[in].pts_next   = pts;
215     fs->in[in].have_next  = 1;
216 }
217
218 int ff_framesync2_get_frame(FFFrameSync *fs, unsigned in, AVFrame **rframe,
219                             unsigned get)
220 {
221     AVFrame *frame;
222     unsigned need_copy = 0, i;
223     int64_t pts_next;
224     int ret;
225
226     if (!fs->in[in].frame) {
227         *rframe = NULL;
228         return 0;
229     }
230     frame = fs->in[in].frame;
231     if (get) {
232         /* Find out if we need to copy the frame: is there another sync
233            stream, and do we know if its current frame will outlast this one? */
234         pts_next = fs->in[in].have_next ? fs->in[in].pts_next : INT64_MAX;
235         for (i = 0; i < fs->nb_in && !need_copy; i++)
236             if (i != in && fs->in[i].sync &&
237                 (!fs->in[i].have_next || fs->in[i].pts_next < pts_next))
238                 need_copy = 1;
239         if (need_copy) {
240             if (!(frame = av_frame_clone(frame)))
241                 return AVERROR(ENOMEM);
242             if ((ret = av_frame_make_writable(frame)) < 0) {
243                 av_frame_free(&frame);
244                 return ret;
245             }
246         } else {
247             fs->in[in].frame = NULL;
248         }
249         fs->frame_ready = 0;
250     }
251     *rframe = frame;
252     return 0;
253 }
254
255 void ff_framesync2_uninit(FFFrameSync *fs)
256 {
257     unsigned i;
258
259     for (i = 0; i < fs->nb_in; i++) {
260         av_frame_free(&fs->in[i].frame);
261         av_frame_free(&fs->in[i].frame_next);
262     }
263
264     av_freep(&fs->in);
265 }
266
267 int ff_framesync2_activate(FFFrameSync *fs)
268 {
269     AVFilterContext *ctx = fs->parent;
270     AVFrame *frame = NULL;
271     int64_t pts;
272     unsigned i, nb_active, nb_miss;
273     int ret, status;
274
275     nb_active = nb_miss = 0;
276     for (i = 0; i < fs->nb_in; i++) {
277         if (fs->in[i].have_next || fs->in[i].state == STATE_EOF)
278             continue;
279         nb_active++;
280         ret = ff_inlink_consume_frame(ctx->inputs[i], &frame);
281         if (ret < 0)
282             return ret;
283         if (ret) {
284             av_assert0(frame);
285             framesync_inject_frame(fs, i, frame);
286         } else {
287             ret = ff_inlink_acknowledge_status(ctx->inputs[i], &status, &pts);
288             if (ret > 0) {
289                 framesync_inject_status(fs, i, status, pts);
290             } else if (!ret) {
291                 nb_miss++;
292             }
293         }
294     }
295     if (nb_miss) {
296         if (nb_miss == nb_active && !ff_outlink_frame_wanted(ctx->outputs[0]))
297             return FFERROR_NOT_READY;
298         for (i = 0; i < fs->nb_in; i++)
299             if (!fs->in[i].have_next && fs->in[i].state != STATE_EOF)
300                 ff_inlink_request_frame(ctx->inputs[i]);
301         return 0;
302     }
303
304     framesync_advance(fs);
305     if (fs->eof || !fs->frame_ready)
306         return 0;
307     ret = fs->on_event(fs);
308     if (ret < 0)
309         return ret;
310     fs->frame_ready = 0;
311
312     return 0;
313 }