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 * Get the class for the framesync object. 213 */ 214 const AVClass *ff_framesync_get_class(void); 215 216 /** 217 * Pre-initialize a frame sync structure. 218 * 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. 222 */ 223 void ff_framesync_preinit(FFFrameSync *fs); 224 225 /** 226 * Initialize a frame sync structure. 227 * 228 * The entire structure is expected to be already set to 0 or preinited. 229 * 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 234 */ 235 int ff_framesync_init(FFFrameSync *fs, AVFilterContext *parent, unsigned nb_in); 236 237 /** 238 * Configure a frame sync structure. 239 * 240 * Must be called after all options are set but before all use. 241 * 242 * @return >= 0 for success or a negative error code 243 */ 244 int ff_framesync_configure(FFFrameSync *fs); 245 246 /** 247 * Free all memory currently allocated. 248 */ 249 void ff_framesync_uninit(FFFrameSync *fs); 250 251 /** 252 * Get the current frame in an input. 253 * 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 260 */ 261 int ff_framesync_get_frame(FFFrameSync *fs, unsigned in, AVFrame **rframe, 262 unsigned get); 263 264 /** 265 * Examine the frames in the filter's input and try to produce output. 266 * 267 * This function can be the complete implementation of the activate 268 * method of a filter using framesync. 269 */ 270 int ff_framesync_activate(FFFrameSync *fs); 271 272 /** 273 * Initialize a frame sync structure for dualinput. 274 * 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. 279 * 280 * Equivalent to ff_framesync_init(fs, parent, 2) then setting the time 281 * base, sync and ext modes on the inputs. 282 */ 283 int ff_framesync_init_dualinput(FFFrameSync *fs, AVFilterContext *parent); 284 285 /** 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. 292 */ 293 int ff_framesync_dualinput_get(FFFrameSync *fs, AVFrame **f0, AVFrame **f1); 294 295 /** 296 * Same as ff_framesync_dualinput_get(), but make sure that f0 is writable. 297 */ 298 int ff_framesync_dualinput_get_writable(FFFrameSync *fs, AVFrame **f0, AVFrame **f1); 299 300 const AVClass *ff_framesync_child_class_iterate(void **iter); 301 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); \ 306 return 0; \ 307 } \ 308 static const AVClass *name##_child_class_next(const AVClass *prev) { \ 309 return prev ? NULL : ff_framesync_get_class(); \ 310 } \ 311 static void *name##_child_next(void *obj, void *prev) { \ 312 context *s = obj; \ 313 s->fs.class = ff_framesync_get_class(); /* FIXME */ \ 314 return prev ? NULL : &s->field; \ 315 } \ 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, \ 325 } 326 327 #endif /* AVFILTER_FRAMESYNC_H */ 328