Commit | Line | Data |
---|---|---|
2ba45a60 DM |
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 | /* | |
27 | * TODO | |
28 | * Callback-based API similar to dualinput. | |
29 | * Export convenient options. | |
30 | */ | |
31 | ||
32 | /** | |
33 | * This API is intended as a helper for filters that have several video | |
34 | * input and need to combine them somehow. If the inputs have different or | |
35 | * variable frame rate, getting the input frames to match requires a rather | |
36 | * complex logic and a few user-tunable options. | |
37 | * | |
38 | * In this API, when a set of synchronized input frames is ready to be | |
39 | * procesed is called a frame event. Frame event can be generated in | |
40 | * response to input frames on any or all inputs and the handling of | |
41 | * situations where some stream extend beyond the beginning or the end of | |
42 | * others can be configured. | |
43 | * | |
44 | * The basic working of this API is the following: | |
45 | * | |
46 | * - When a frame is available on any input, add it using | |
47 | * ff_framesync_add_frame(). | |
48 | * | |
49 | * - When a frame event is ready to be processed (i.e. after adding a frame | |
50 | * or when requested on input): | |
51 | * - call ff_framesync_next(); | |
52 | * - if fs->frame_ready is true, process the frames; | |
53 | * - call ff_framesync_drop(). | |
54 | */ | |
55 | ||
56 | /** | |
57 | * Stream extrapolation mode | |
58 | * | |
59 | * Describe how the frames of a stream are extrapolated before the first one | |
60 | * and after EOF to keep sync with possibly longer other streams. | |
61 | */ | |
62 | enum FFFrameSyncExtMode { | |
63 | ||
64 | /** | |
65 | * Completely stop all streams with this one. | |
66 | */ | |
67 | EXT_STOP, | |
68 | ||
69 | /** | |
70 | * Ignore this stream and continue processing the other ones. | |
71 | */ | |
72 | EXT_NULL, | |
73 | ||
74 | /** | |
75 | * Extend the frame to infinity. | |
76 | */ | |
77 | EXT_INFINITY, | |
78 | }; | |
79 | ||
80 | /** | |
81 | * Input stream structure | |
82 | */ | |
83 | typedef struct FFFrameSyncIn { | |
84 | ||
85 | /** | |
86 | * Queue of incoming AVFrame, and NULL to mark EOF | |
87 | */ | |
88 | struct FFBufQueue queue; | |
89 | ||
90 | /** | |
91 | * Extrapolation mode for timestamps before the first frame | |
92 | */ | |
93 | enum FFFrameSyncExtMode before; | |
94 | ||
95 | /** | |
96 | * Extrapolation mode for timestamps after the last frame | |
97 | */ | |
98 | enum FFFrameSyncExtMode after; | |
99 | ||
100 | /** | |
101 | * Time base for the incoming frames | |
102 | */ | |
103 | AVRational time_base; | |
104 | ||
105 | /** | |
106 | * Current frame, may be NULL before the first one or after EOF | |
107 | */ | |
108 | AVFrame *frame; | |
109 | ||
110 | /** | |
111 | * Next frame, for internal use | |
112 | */ | |
113 | AVFrame *frame_next; | |
114 | ||
115 | /** | |
116 | * PTS of the current frame | |
117 | */ | |
118 | int64_t pts; | |
119 | ||
120 | /** | |
121 | * PTS of the next frame, for internal use | |
122 | */ | |
123 | int64_t pts_next; | |
124 | ||
125 | /** | |
126 | * Boolean flagging the next frame, for internal use | |
127 | */ | |
128 | uint8_t have_next; | |
129 | ||
130 | /** | |
131 | * State: before first, in stream or after EOF, for internal use | |
132 | */ | |
133 | uint8_t state; | |
134 | ||
135 | /** | |
136 | * Synchronization level: frames on input at the highest sync level will | |
137 | * generate output frame events. | |
138 | * | |
139 | * For example, if inputs #0 and #1 have sync level 2 and input #2 has | |
140 | * sync level 1, then a frame on either input #0 or #1 will generate a | |
141 | * frame event, but not a frame on input #2 until both inputs #0 and #1 | |
142 | * have reached EOF. | |
143 | * | |
144 | * If sync is 0, no frame event will be generated. | |
145 | */ | |
146 | unsigned sync; | |
147 | ||
148 | } FFFrameSyncIn; | |
149 | ||
150 | /** | |
151 | * Frame sync structure. | |
152 | */ | |
153 | typedef struct FFFrameSync { | |
154 | const AVClass *class; | |
155 | void *parent; | |
156 | ||
157 | /** | |
158 | * Number of input streams | |
159 | */ | |
160 | unsigned nb_in; | |
161 | ||
162 | /** | |
163 | * Time base for the output events | |
164 | */ | |
165 | AVRational time_base; | |
166 | ||
167 | /** | |
168 | * Timestamp of the current event | |
169 | */ | |
170 | int64_t pts; | |
171 | ||
172 | /** | |
173 | * Callback called when a frame event is ready | |
174 | */ | |
175 | int (*on_event)(struct FFFrameSync *fs); | |
176 | ||
177 | /** | |
178 | * Opaque pointer, not used by the API | |
179 | */ | |
180 | void *opaque; | |
181 | ||
182 | /** | |
183 | * Index of the input that requires a request | |
184 | */ | |
185 | unsigned in_request; | |
186 | ||
187 | /** | |
188 | * Synchronization level: only inputs with the same sync level are sync | |
189 | * sources. | |
190 | */ | |
191 | unsigned sync_level; | |
192 | ||
193 | /** | |
194 | * Flag indicating that a frame event is ready | |
195 | */ | |
196 | uint8_t frame_ready; | |
197 | ||
198 | /** | |
199 | * Flag indicating that output has reached EOF. | |
200 | */ | |
201 | uint8_t eof; | |
202 | ||
203 | /** | |
204 | * Array of inputs; all inputs must be in consecutive memory | |
205 | */ | |
206 | FFFrameSyncIn in[1]; /* must be the last field */ | |
207 | ||
208 | } FFFrameSync; | |
209 | ||
210 | /** | |
211 | * Initialize a frame sync structure. | |
212 | * | |
213 | * The entire structure is expected to be already set to 0. | |
214 | * | |
215 | * @param fs frame sync structure to initialize | |
216 | * @param parent parent object, used for logging | |
217 | * @param nb_in number of inputs | |
218 | */ | |
219 | void ff_framesync_init(FFFrameSync *fs, void *parent, unsigned nb_in); | |
220 | ||
221 | /** | |
222 | * Configure a frame sync structure. | |
223 | * | |
224 | * Must be called after all options are set but before all use. | |
225 | * | |
226 | * @return >= 0 for success or a negative error code | |
227 | */ | |
228 | int ff_framesync_configure(FFFrameSync *fs); | |
229 | ||
230 | /** | |
231 | * Free all memory currently allocated. | |
232 | */ | |
233 | void ff_framesync_uninit(FFFrameSync *fs); | |
234 | ||
235 | /** | |
236 | * Add a frame to an input | |
237 | * | |
238 | * Typically called from the filter_frame() method. | |
239 | * | |
240 | * @param fs frame sync structure | |
241 | * @param in index of the input | |
242 | * @param frame input frame, or NULL for EOF | |
243 | */ | |
244 | int ff_framesync_add_frame(FFFrameSync *fs, unsigned in, AVFrame *frame); | |
245 | ||
246 | /** | |
247 | * Prepare the next frame event. | |
248 | * | |
249 | * The status of the operation can be found in fs->frame_ready and fs->eof. | |
250 | */ | |
251 | void ff_framesync_next(FFFrameSync *fs); | |
252 | ||
253 | /** | |
254 | * Drop the current frame event. | |
255 | */ | |
256 | void ff_framesync_drop(FFFrameSync *fs); | |
257 | ||
258 | /** | |
259 | * Get the current frame in an input. | |
260 | * | |
261 | * @param fs frame sync structure | |
262 | * @param in index of the input | |
263 | * @param rframe used to return the current frame (or NULL) | |
264 | * @param get if not zero, the calling code needs to get ownership of | |
265 | * the returned frame; the current frame will either be | |
266 | * duplicated or removed from the framesync structure | |
267 | */ | |
268 | int ff_framesync_get_frame(FFFrameSync *fs, unsigned in, AVFrame **rframe, | |
269 | unsigned get); | |
270 | ||
271 | /** | |
272 | * Process one or several frame using the on_event callback. | |
273 | * | |
274 | * @return number of frames processed or negative error code | |
275 | */ | |
276 | int ff_framesync_process_frame(FFFrameSync *fs, unsigned all); | |
277 | ||
278 | ||
279 | /** | |
280 | * Accept a frame on a filter input. | |
281 | * | |
282 | * This function can be the complete implementation of all filter_frame | |
283 | * methods of a filter using framesync. | |
284 | */ | |
285 | int ff_framesync_filter_frame(FFFrameSync *fs, AVFilterLink *inlink, | |
286 | AVFrame *in); | |
287 | ||
288 | /** | |
289 | * Request a frame on the filter output. | |
290 | * | |
291 | * This function can be the complete implementation of all filter_frame | |
292 | * methods of a filter using framesync if it has only one output. | |
293 | */ | |
294 | int ff_framesync_request_frame(FFFrameSync *fs, AVFilterLink *outlink); | |
295 | ||
296 | #endif /* AVFILTER_FRAMESYNC_H */ |