History

lavfi/framesync2: implement "activate" design.

With this helper API, filters that used the first framesync helper API can easily be changed to use the new and more extensible design for filters with a single activate() callback.

Nicolas George committed 9 years ago

Commit 4e0e9ce1 parent ed1c8842 files · +82 −161Browse files

Unified · Split

2 files
  1. libavfilter/framesync2.c +68 −98
  2. libavfilter/framesync2.h +14 −63
libavfilter/framesync2.c+68−98
@@ -18,12 +18,9 @@ · 17 unmodified lines
1818 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
1919 */
2020
21−#define FF_INTERNAL_FIELDS 1
22−#include "framequeue.h"
23−
2421 #include "libavutil/avassert.h"
2522 #include "avfilter.h"
26−#include "bufferqueue.h"
23+#include "filters.h"
2724 #include "framesync2.h"
2825 #include "internal.h"
2926
@@ -49,8 +46,13 @@ enum { · 19 unmodified lines
4946 STATE_EOF,
5047 };
5148
52−int ff_framesync2_init(FFFrameSync *fs, void *parent, unsigned nb_in)
49+int ff_framesync2_init(FFFrameSync *fs, AVFilterContext *parent, unsigned nb_in)
5350 {
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+
5456 fs->class = &framesync_class;
5557 fs->parent = parent;
5658 fs->nb_in = nb_in;
@@ -61,6 +63,13 @@ int ff_framesync2_init(FFFrameSync *fs, void *parent, unsigned nb_in) · 4 unmodified lines
6163 return 0;
6264 }
6365
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+
6473 static void framesync_sync_level_update(FFFrameSync *fs)
6574 {
6675 unsigned i, level = 0;
@@ -74,7 +83,7 @@ static void framesync_sync_level_update(FFFrameSync *fs) · 7 unmodified lines
7483 if (level)
7584 fs->sync_level = level;
7685 else
77− fs->eof = 1;
86+ framesync_eof(fs);
7887 }
7988
8089 int ff_framesync2_configure(FFFrameSync *fs)
@@ -144,7 +153,7 @@ static void framesync_advance(FFFrameSync *fs) · 63 unmodified lines
144153 if (fs->in[i].pts_next < pts)
145154 pts = fs->in[i].pts_next;
146155 if (pts == INT64_MAX) {
147− fs->eof = 1;
156+ framesync_eof(fs);
148157 break;
149158 }
150159 for (i = 0; i < fs->nb_in; i++) {
@@ -162,11 +171,9 @@ static void framesync_advance(FFFrameSync *fs) · 11 unmodified lines
162171 fs->frame_ready = 1;
163172 if (fs->in[i].state == STATE_EOF &&
164173 fs->in[i].after == EXT_STOP)
165− fs->eof = 1;
174+ framesync_eof(fs);
166175 }
167176 }
168− if (fs->eof)
169− fs->frame_ready = 0;
170177 if (fs->frame_ready)
171178 for (i = 0; i < fs->nb_in; i++)
172179 if ((fs->in[i].state == STATE_BOF &&
@@ -188,45 +195,24 @@ static void framesync_inject_frame(FFFrameSync *fs, unsigned in, AVFrame *frame) · 15 unmodified lines
188195 int64_t pts;
189196
190197 av_assert0(!fs->in[in].have_next);
191− if (frame) {
192− pts = av_rescale_q(frame->pts, fs->in[in].time_base, fs->time_base);
193− frame->pts = pts;
194− } else {
195− pts = fs->in[in].state != STATE_RUN || fs->in[in].after == EXT_INFINITY
196− ? INT64_MAX : framesync_pts_extrapolate(fs, in, fs->in[in].pts);
197− fs->in[in].sync = 0;
198− framesync_sync_level_update(fs);
199− }
198+ av_assert0(frame);
199+ pts = av_rescale_q(frame->pts, fs->in[in].time_base, fs->time_base);
200+ frame->pts = pts;
200201 fs->in[in].frame_next = frame;
201202 fs->in[in].pts_next = pts;
202203 fs->in[in].have_next = 1;
203204 }
204205
205−int ff_framesync2_add_frame(FFFrameSync *fs, unsigned in, AVFrame *frame)
206−{
207− av_assert1(in < fs->nb_in);
208− if (!fs->in[in].have_next)
209− framesync_inject_frame(fs, in, frame);
210− else
211− ff_bufqueue_add(fs, &fs->in[in].queue, frame);
212− return 0;
213−}
214−
215−void ff_framesync2_next(FFFrameSync *fs)
216−{
217− unsigned i;
218−
219− av_assert0(!fs->frame_ready);
220− for (i = 0; i < fs->nb_in; i++)
221− if (!fs->in[i].have_next && fs->in[i].queue.available)
222− framesync_inject_frame(fs, i, ff_bufqueue_get(&fs->in[i].queue));
223− fs->frame_ready = 0;
224− framesync_advance(fs);
225−}
226−
227−void ff_framesync2_drop(FFFrameSync *fs)
206+static void framesync_inject_status(FFFrameSync *fs, unsigned in, int status, int64_t pts)
228207 {
229− fs->frame_ready = 0;
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;
230216 }
231217
232218 int ff_framesync2_get_frame(FFFrameSync *fs, unsigned in, AVFrame **rframe,
@@ -273,71 +259,55 @@ void ff_framesync2_uninit(FFFrameSync *fs) · 40 unmodified lines
273259 for (i = 0; i < fs->nb_in; i++) {
274260 av_frame_free(&fs->in[i].frame);
275261 av_frame_free(&fs->in[i].frame_next);
276− ff_bufqueue_discard_all(&fs->in[i].queue);
277262 }
278263
279264 av_freep(&fs->in);
280265 }
281266
282−int ff_framesync2_process_frame(FFFrameSync *fs, unsigned all)
267+int ff_framesync2_activate(FFFrameSync *fs)
283268 {
284− int ret, count = 0;
269+ AVFilterContext *ctx = fs->parent;
270+ AVFrame *frame = NULL;
271+ int64_t pts;
272+ unsigned i, nb_active, nb_miss;
273+ int ret, status;
285274
286− av_assert0(fs->on_event);
287− while (1) {
288− ff_framesync2_next(fs);
289− if (fs->eof || !fs->frame_ready)
290− break;
291− if ((ret = fs->on_event(fs)) < 0)
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)
292282 return ret;
293− ff_framesync2_drop(fs);
294− count++;
295− if (!all)
296− break;
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;
297302 }
298− if (!count && fs->eof)
299− return AVERROR_EOF;
300− return count;
301−}
302−
303−int ff_framesync2_filter_frame(FFFrameSync *fs, AVFilterLink *inlink,
304− AVFrame *in)
305−{
306− int ret;
307303
308− if ((ret = ff_framesync2_process_frame(fs, 1)) < 0)
309− return ret;
310− if ((ret = ff_framesync2_add_frame(fs, FF_INLINK_IDX(inlink), in)) < 0)
311− return ret;
312− if ((ret = ff_framesync2_process_frame(fs, 0)) < 0)
304+ framesync_advance(fs);
305+ if (fs->eof || !fs->frame_ready)
306+ return 0;
307+ ret = fs->on_event(fs);
308+ if (ret < 0)
313309 return ret;
314− return 0;
315−}
316−
317−int ff_framesync2_request_frame(FFFrameSync *fs, AVFilterLink *outlink)
318−{
319− AVFilterContext *ctx = outlink->src;
320− int input, ret, i;
310+ fs->frame_ready = 0;
321311
322− if ((ret = ff_framesync2_process_frame(fs, 0)) < 0)
323− return ret;
324− if (ret > 0)
325− return 0;
326− if (fs->eof)
327− return AVERROR_EOF;
328− input = fs->in_request;
329− /* Detect status change early */
330− for (i = 0; i < fs->nb_in; i++)
331− if (!ff_framequeue_queued_frames(&ctx->inputs[i]->fifo) &&
332− ctx->inputs[i]->status_in && !ctx->inputs[i]->status_out)
333− input = i;
334− ret = ff_request_frame(ctx->inputs[input]);
335− if (ret == AVERROR_EOF) {
336− if ((ret = ff_framesync2_add_frame(fs, input, NULL)) < 0)
337− return ret;
338− if ((ret = ff_framesync2_process_frame(fs, 0)) < 0)
339− return ret;
340− ret = 0;
341− }
342− return ret;
312+ return 0;
343313 }
libavfilter/framesync2.h+14−63
@@ -25,7 +25,6 @@ · 24 unmodified lines
2525
2626 /*
2727 * TODO
28− * Callback-based API similar to dualinput.
2928 * Export convenient options.
3029 */
3130
@@ -41,16 +40,9 @@ · 9 unmodified lines
4140 * situations where some stream extend beyond the beginning or the end of
4241 * others can be configured.
4342 *
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_framesync2_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_framesync2_next();
52− * - if fs->frame_ready is true, process the frames;
53− * - call ff_framesync2_drop().
43+ * The basic working of this API is the following: set the on_event
44+ * callback, then call ff_framesync2_activate() from the filter's activate
45+ * callback.
5446 */
5547
5648 /**
@@ -82,11 +74,6 @@ enum FFFrameSyncExtMode { · 25 unmodified lines
8274 */
8375 typedef struct FFFrameSyncIn {
8476
85− /**
86− * Queue of incoming AVFrame, and NULL to mark EOF
87− */
88− struct FFBufQueue queue;
89−
9077 /**
9178 * Extrapolation mode for timestamps before the first frame
9279 */
@@ -152,7 +139,11 @@ typedef struct FFFrameSyncIn { · 59 unmodified lines
152139 */
153140 typedef struct FFFrameSync {
154141 const AVClass *class;
155− void *parent;
142+
143+ /**
144+ * Parent filter context.
145+ */
146+ AVFilterContext *parent;
156147
157148 /**
158149 * Number of input streams
@@ -213,11 +204,11 @@ typedef struct FFFrameSync { · 54 unmodified lines
213204 * The entire structure is expected to be already set to 0.
214205 *
215206 * @param fs frame sync structure to initialize
216− * @param parent parent object, used for logging
207+ * @param parent parent AVFilterContext object
217208 * @param nb_in number of inputs
218209 * @return >= 0 for success or a negative error code
219210 */
220−int ff_framesync2_init(FFFrameSync *fs, void *parent, unsigned nb_in);
211+int ff_framesync2_init(FFFrameSync *fs, AVFilterContext *parent, unsigned nb_in);
221212
222213 /**
223214 * Configure a frame sync structure.
@@ -233,29 +224,6 @@ int ff_framesync2_configure(FFFrameSync *fs); · 9 unmodified lines
233224 */
234225 void ff_framesync2_uninit(FFFrameSync *fs);
235226
236−/**
237− * Add a frame to an input
238− *
239− * Typically called from the filter_frame() method.
240− *
241− * @param fs frame sync structure
242− * @param in index of the input
243− * @param frame input frame, or NULL for EOF
244− */
245−int ff_framesync2_add_frame(FFFrameSync *fs, unsigned in, AVFrame *frame);
246−
247−/**
248− * Prepare the next frame event.
249− *
250− * The status of the operation can be found in fs->frame_ready and fs->eof.
251− */
252−void ff_framesync2_next(FFFrameSync *fs);
253−
254−/**
255− * Drop the current frame event.
256− */
257−void ff_framesync2_drop(FFFrameSync *fs);
258−
259227 /**
260228 * Get the current frame in an input.
261229 *
@@ -270,28 +238,11 @@ int ff_framesync2_get_frame(FFFrameSync *fs, unsigned in, AVFrame **rframe, · 8 unmodified lines
270238 unsigned get);
271239
272240 /**
273− * Process one or several frame using the on_event callback.
274− *
275− * @return number of frames processed or negative error code
276− */
277−int ff_framesync2_process_frame(FFFrameSync *fs, unsigned all);
278−
279−
280−/**
281− * Accept a frame on a filter input.
282− *
283− * This function can be the complete implementation of all filter_frame
284− * methods of a filter using framesync.
285− */
286−int ff_framesync2_filter_frame(FFFrameSync *fs, AVFilterLink *inlink,
287− AVFrame *in);
288−
289−/**
290− * Request a frame on the filter output.
241+ * Examine the frames in the filter's input and try to produce output.
291242 *
292− * This function can be the complete implementation of all filter_frame
293− * methods of a filter using framesync if it has only one output.
243+ * This function can be the complete implementation of the activate
244+ * method of a filter using framesync2.
294245 */
295−int ff_framesync2_request_frame(FFFrameSync *fs, AVFilterLink *outlink);
246+int ff_framesync2_activate(FFFrameSync *fs);
296247
297248 #endif /* AVFILTER_FRAMESYNC2_H */

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t