• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #ifndef AVFILTER_FRAMESYNC_H
22 #define AVFILTER_FRAMESYNC_H
23 
24 #include "bufferqueue.h"
25 
26 enum EOFAction {
27     EOF_ACTION_REPEAT,
28     EOF_ACTION_ENDALL,
29     EOF_ACTION_PASS
30 };
31 
32 /*
33  * TODO
34  * Export convenient options.
35  */
36 
37 /**
38  * This API is intended as a helper for filters that have several video
39  * input and need to combine them somehow. If the inputs have different or
40  * variable frame rate, getting the input frames to match requires a rather
41  * complex logic and a few user-tunable options.
42  *
43  * In this API, when a set of synchronized input frames is ready to be
44  * procesed is called a frame event. Frame event can be generated in
45  * response to input frames on any or all inputs and the handling of
46  * situations where some stream extend beyond the beginning or the end of
47  * others can be configured.
48  *
49  * The basic working of this API is the following: set the on_event
50  * callback, then call ff_framesync_activate() from the filter's activate
51  * callback.
52  */
53 
54 /**
55  * Stream extrapolation mode
56  *
57  * Describe how the frames of a stream are extrapolated before the first one
58  * and after EOF to keep sync with possibly longer other streams.
59  */
60 enum FFFrameSyncExtMode {
61 
62     /**
63      * Completely stop all streams with this one.
64      */
65     EXT_STOP,
66 
67     /**
68      * Ignore this stream and continue processing the other ones.
69      */
70     EXT_NULL,
71 
72     /**
73      * Extend the frame to infinity.
74      */
75     EXT_INFINITY,
76 };
77 
78 /**
79  * Input stream structure
80  */
81 typedef struct FFFrameSyncIn {
82 
83     /**
84      * Extrapolation mode for timestamps before the first frame
85      */
86     enum FFFrameSyncExtMode before;
87 
88     /**
89      * Extrapolation mode for timestamps after the last frame
90      */
91     enum FFFrameSyncExtMode after;
92 
93     /**
94      * Time base for the incoming frames
95      */
96     AVRational time_base;
97 
98     /**
99      * Current frame, may be NULL before the first one or after EOF
100      */
101     AVFrame *frame;
102 
103     /**
104      * Next frame, for internal use
105      */
106     AVFrame *frame_next;
107 
108     /**
109      * PTS of the current frame
110      */
111     int64_t pts;
112 
113     /**
114      * PTS of the next frame, for internal use
115      */
116     int64_t pts_next;
117 
118     /**
119      * Boolean flagging the next frame, for internal use
120      */
121     uint8_t have_next;
122 
123     /**
124      * State: before first, in stream or after EOF, for internal use
125      */
126     uint8_t state;
127 
128     /**
129      * Synchronization level: frames on input at the highest sync level will
130      * generate output frame events.
131      *
132      * For example, if inputs #0 and #1 have sync level 2 and input #2 has
133      * sync level 1, then a frame on either input #0 or #1 will generate a
134      * frame event, but not a frame on input #2 until both inputs #0 and #1
135      * have reached EOF.
136      *
137      * If sync is 0, no frame event will be generated.
138      */
139     unsigned sync;
140 
141 } FFFrameSyncIn;
142 
143 /**
144  * Frame sync structure.
145  */
146 typedef struct FFFrameSync {
147     const AVClass *class;
148 
149     /**
150      * Parent filter context.
151      */
152     AVFilterContext *parent;
153 
154     /**
155      * Number of input streams
156      */
157     unsigned nb_in;
158 
159     /**
160      * Time base for the output events
161      */
162     AVRational time_base;
163 
164     /**
165      * Timestamp of the current event
166      */
167     int64_t pts;
168 
169     /**
170      * Callback called when a frame event is ready
171      */
172     int (*on_event)(struct FFFrameSync *fs);
173 
174     /**
175      * Opaque pointer, not used by the API
176      */
177     void *opaque;
178 
179     /**
180      * Index of the input that requires a request
181      */
182     unsigned in_request;
183 
184     /**
185      * Synchronization level: only inputs with the same sync level are sync
186      * sources.
187      */
188     unsigned sync_level;
189 
190     /**
191      * Flag indicating that a frame event is ready
192      */
193     uint8_t frame_ready;
194 
195     /**
196      * Flag indicating that output has reached EOF.
197      */
198     uint8_t eof;
199 
200     /**
201      * Pointer to array of inputs.
202      */
203     FFFrameSyncIn *in;
204 
205     int opt_repeatlast;
206     int opt_shortest;
207     int opt_eof_action;
208 
209 } FFFrameSync;
210 
211 /**
212  * Pre-initialize a frame sync structure.
213  *
214  * It sets the class pointer and inits the options to their default values.
215  * The entire structure is expected to be already set to 0.
216  * This step is optional, but necessary to use the options.
217  */
218 void ff_framesync_preinit(FFFrameSync *fs);
219 
220 /**
221  * Initialize a frame sync structure.
222  *
223  * The entire structure is expected to be already set to 0 or preinited.
224  *
225  * @param  fs      frame sync structure to initialize
226  * @param  parent  parent AVFilterContext object
227  * @param  nb_in   number of inputs
228  * @return  >= 0 for success or a negative error code
229  */
230 int ff_framesync_init(FFFrameSync *fs, AVFilterContext *parent, unsigned nb_in);
231 
232 /**
233  * Configure a frame sync structure.
234  *
235  * Must be called after all options are set but before all use.
236  *
237  * @return  >= 0 for success or a negative error code
238  */
239 int ff_framesync_configure(FFFrameSync *fs);
240 
241 /**
242  * Free all memory currently allocated.
243  */
244 void ff_framesync_uninit(FFFrameSync *fs);
245 
246 /**
247  * Get the current frame in an input.
248  *
249  * @param fs      frame sync structure
250  * @param in      index of the input
251  * @param rframe  used to return the current frame (or NULL)
252  * @param get     if not zero, the calling code needs to get ownership of
253  *                the returned frame; the current frame will either be
254  *                duplicated or removed from the framesync structure
255  */
256 int ff_framesync_get_frame(FFFrameSync *fs, unsigned in, AVFrame **rframe,
257                             unsigned get);
258 
259 /**
260  * Examine the frames in the filter's input and try to produce output.
261  *
262  * This function can be the complete implementation of the activate
263  * method of a filter using framesync.
264  */
265 int ff_framesync_activate(FFFrameSync *fs);
266 
267 /**
268  * Initialize a frame sync structure for dualinput.
269  *
270  * Compared to generic framesync, dualinput assumes the first input is the
271  * main one and the filtering is performed on it. The first input will be
272  * the only one with sync set and generic timeline support will just pass it
273  * unchanged when disabled.
274  *
275  * Equivalent to ff_framesync_init(fs, parent, 2) then setting the time
276  * base, sync and ext modes on the inputs.
277  */
278 int ff_framesync_init_dualinput(FFFrameSync *fs, AVFilterContext *parent);
279 
280 /**
281  * @param f0  used to return the main frame
282  * @param f1  used to return the second frame, or NULL if disabled
283  * @return  >=0 for success or AVERROR code
284  * @note  The frame returned in f0 belongs to the caller (get = 1 in
285  * ff_framesync_get_frame()) while the frame returned in f1 is still owned
286  * by the framesync structure.
287  */
288 int ff_framesync_dualinput_get(FFFrameSync *fs, AVFrame **f0, AVFrame **f1);
289 
290 /**
291  * Same as ff_framesync_dualinput_get(), but make sure that f0 is writable.
292  */
293 int ff_framesync_dualinput_get_writable(FFFrameSync *fs, AVFrame **f0, AVFrame **f1);
294 
295 const AVClass *ff_framesync_child_class_iterate(void **iter);
296 
297 #define FRAMESYNC_DEFINE_PURE_CLASS(name, desc, func_prefix, options) \
298 static const AVClass name##_class = {                                 \
299     .class_name          = desc,                                      \
300     .item_name           = av_default_item_name,                      \
301     .option              = options,                                   \
302     .version             = LIBAVUTIL_VERSION_INT,                     \
303     .category            = AV_CLASS_CATEGORY_FILTER,                  \
304     .child_class_iterate = ff_framesync_child_class_iterate,          \
305     .child_next          = func_prefix##_child_next,                  \
306 }
307 
308 /* A filter that uses the *_child_next-function from this macro
309  * is required to initialize the FFFrameSync structure in AVFilter.preinit
310  * via the *_framesync_preinit function defined alongside it. */
311 #define FRAMESYNC_AUXILIARY_FUNCS(func_prefix, context, field)        \
312 static int func_prefix##_framesync_preinit(AVFilterContext *ctx)      \
313 {                                                                     \
314     context *s = ctx->priv; \
315     ff_framesync_preinit(&s->field); \
316     return 0; \
317 } \
318 static void *func_prefix##_child_next(void *obj, void *prev)          \
319 {                                                                     \
320     context *s = obj; \
321     return prev ? NULL : &s->field; \
322 }
323 
324 #define FRAMESYNC_DEFINE_CLASS_EXT(name, context, field, options)     \
325 FRAMESYNC_AUXILIARY_FUNCS(name, context, field)                       \
326 FRAMESYNC_DEFINE_PURE_CLASS(name, #name, name, options)
327 
328 #define FRAMESYNC_DEFINE_CLASS(name, context, field)                  \
329 FRAMESYNC_DEFINE_CLASS_EXT(name, context, field, name##_options)
330 
331 #endif /* AVFILTER_FRAMESYNC_H */
332