2 * Copyright (c) 2013 Nicolas George
4 * This file is part of FFmpeg.
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.
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.
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
21 #ifndef AVFILTER_FRAMESYNC_H
22 #define AVFILTER_FRAMESYNC_H
24 #include "bufferqueue.h"
34 * Export convenient options.
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.
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.
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
55 * Stream extrapolation mode
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.
60 enum FFFrameSyncExtMode {
63 * Completely stop all streams with this one.
68 * Ignore this stream and continue processing the other ones.
73 * Extend the frame to infinity.
79 * Input stream structure
81 typedef struct FFFrameSyncIn {
84 * Extrapolation mode for timestamps before the first frame
86 enum FFFrameSyncExtMode before;
89 * Extrapolation mode for timestamps after the last frame
91 enum FFFrameSyncExtMode after;
94 * Time base for the incoming frames
99 * Current frame, may be NULL before the first one or after EOF
104 * Next frame, for internal use
109 * PTS of the current frame
114 * PTS of the next frame, for internal use
119 * Boolean flagging the next frame, for internal use
124 * State: before first, in stream or after EOF, for internal use
129 * Synchronization level: frames on input at the highest sync level will
130 * generate output frame events.
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
137 * If sync is 0, no frame event will be generated.
144 * Frame sync structure.
146 typedef struct FFFrameSync {
147 const AVClass *class;
150 * Parent filter context.
152 AVFilterContext *parent;
155 * Number of input streams
160 * Time base for the output events
162 AVRational time_base;
165 * Timestamp of the current event
170 * Callback called when a frame event is ready
172 int (*on_event)(struct FFFrameSync *fs);
175 * Opaque pointer, not used by the API
180 * Index of the input that requires a request
185 * Synchronization level: only inputs with the same sync level are sync
191 * Flag indicating that a frame event is ready
196 * Flag indicating that output has reached EOF.
201 * Pointer to array of inputs.
212 * Get the class for the framesync object.
214 const AVClass *ff_framesync_get_class(void);
217 * Pre-initialize a frame sync structure.
219 * It sets the class pointer and inits the options to their default values.
220 * The entire structure is expected to be already set to 0.
221 * This step is optional, but necessary to use the options.
223 void ff_framesync_preinit(FFFrameSync *fs);
226 * Initialize a frame sync structure.
228 * The entire structure is expected to be already set to 0 or preinited.
230 * @param fs frame sync structure to initialize
231 * @param parent parent AVFilterContext object
232 * @param nb_in number of inputs
233 * @return >= 0 for success or a negative error code
235 int ff_framesync_init(FFFrameSync *fs, AVFilterContext *parent, unsigned nb_in);
238 * Configure a frame sync structure.
240 * Must be called after all options are set but before all use.
242 * @return >= 0 for success or a negative error code
244 int ff_framesync_configure(FFFrameSync *fs);
247 * Free all memory currently allocated.
249 void ff_framesync_uninit(FFFrameSync *fs);
252 * Get the current frame in an input.
254 * @param fs frame sync structure
255 * @param in index of the input
256 * @param rframe used to return the current frame (or NULL)
257 * @param get if not zero, the calling code needs to get ownership of
258 * the returned frame; the current frame will either be
259 * duplicated or removed from the framesync structure
261 int ff_framesync_get_frame(FFFrameSync *fs, unsigned in, AVFrame **rframe,
265 * Examine the frames in the filter's input and try to produce output.
267 * This function can be the complete implementation of the activate
268 * method of a filter using framesync.
270 int ff_framesync_activate(FFFrameSync *fs);
273 * Initialize a frame sync structure for dualinput.
275 * Compared to generic framesync, dualinput assumes the first input is the
276 * main one and the filtering is performed on it. The first input will be
277 * the only one with sync set and generic timeline support will just pass it
278 * unchanged when disabled.
280 * Equivalent to ff_framesync_init(fs, parent, 2) then setting the time
281 * base, sync and ext modes on the inputs.
283 int ff_framesync_init_dualinput(FFFrameSync *fs, AVFilterContext *parent);
286 * @param f0 used to return the main frame
287 * @param f1 used to return the second frame, or NULL if disabled
288 * @return >=0 for success or AVERROR code
289 * @note The frame returned in f0 belongs to the caller (get = 1 in
290 * ff_framesync_get_frame()) while the frame returned in f1 is still owned
291 * by the framesync structure.
293 int ff_framesync_dualinput_get(FFFrameSync *fs, AVFrame **f0, AVFrame **f1);
296 * Same as ff_framesync_dualinput_get(), but make sure that f0 is writable.
298 int ff_framesync_dualinput_get_writable(FFFrameSync *fs, AVFrame **f0, AVFrame **f1);
300 const AVClass *ff_framesync_child_class_iterate(void **iter);
302 #define FRAMESYNC_DEFINE_CLASS(name, context, field) \
303 static int name##_framesync_preinit(AVFilterContext *ctx) { \
304 context *s = ctx->priv; \
305 ff_framesync_preinit(&s->field); \
308 static const AVClass *name##_child_class_next(const AVClass *prev) { \
309 return prev ? NULL : ff_framesync_get_class(); \
311 static void *name##_child_next(void *obj, void *prev) { \
313 s->fs.class = ff_framesync_get_class(); /* FIXME */ \
314 return prev ? NULL : &s->field; \
316 static const AVClass name##_class = { \
317 .class_name = #name, \
318 .item_name = av_default_item_name, \
319 .option = name##_options, \
320 .version = LIBAVUTIL_VERSION_INT, \
321 .category = AV_CLASS_CATEGORY_FILTER, \
322 .child_class_next = name##_child_class_next, \
323 .child_class_iterate = ff_framesync_child_class_iterate, \
324 .child_next = name##_child_next, \
327 #endif /* AVFILTER_FRAMESYNC_H */