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.
Showing the changes to libavfilter/framesync2.c (1 of 2 files). Show all
Unified · Split
| @@ -18,12 +18,9 @@ · 17 unmodified lines | ||
| 18 | 18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| 19 | 19 | */ |
| 20 | 20 | |
| 21 | −#define FF_INTERNAL_FIELDS 1 | |
| 22 | −#include "framequeue.h" | |
| 23 | − | |
| 24 | 21 | #include "libavutil/avassert.h" |
| 25 | 22 | #include "avfilter.h" |
| 26 | −#include "bufferqueue.h" | |
| 23 | +#include "filters.h" | |
| 27 | 24 | #include "framesync2.h" |
| 28 | 25 | #include "internal.h" |
| 29 | 26 | |
| @@ -49,8 +46,13 @@ enum { · 19 unmodified lines | ||
| 49 | 46 | STATE_EOF, |
| 50 | 47 | }; |
| 51 | 48 | |
| 52 | −int ff_framesync2_init(FFFrameSync *fs, void *parent, unsigned nb_in) | |
| 49 | +int ff_framesync2_init(FFFrameSync *fs, AVFilterContext *parent, unsigned nb_in) | |
| 53 | 50 | { |
| 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 | + | |
| 54 | 56 | fs->class = &framesync_class; |
| 55 | 57 | fs->parent = parent; |
| 56 | 58 | fs->nb_in = nb_in; |
| @@ -61,6 +63,13 @@ int ff_framesync2_init(FFFrameSync *fs, void *parent, unsigned nb_in) · 4 unmodified lines | ||
| 61 | 63 | return 0; |
| 62 | 64 | } |
| 63 | 65 | |
| 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 | + | |
| 64 | 73 | static void framesync_sync_level_update(FFFrameSync *fs) |
| 65 | 74 | { |
| 66 | 75 | unsigned i, level = 0; |
| @@ -74,7 +83,7 @@ static void framesync_sync_level_update(FFFrameSync *fs) · 7 unmodified lines | ||
| 74 | 83 | if (level) |
| 75 | 84 | fs->sync_level = level; |
| 76 | 85 | else |
| 77 | − fs->eof = 1; | |
| 86 | + framesync_eof(fs); | |
| 78 | 87 | } |
| 79 | 88 | |
| 80 | 89 | int ff_framesync2_configure(FFFrameSync *fs) |
| @@ -144,7 +153,7 @@ static void framesync_advance(FFFrameSync *fs) · 63 unmodified lines | ||
| 144 | 153 | if (fs->in[i].pts_next < pts) |
| 145 | 154 | pts = fs->in[i].pts_next; |
| 146 | 155 | if (pts == INT64_MAX) { |
| 147 | − fs->eof = 1; | |
| 156 | + framesync_eof(fs); | |
| 148 | 157 | break; |
| 149 | 158 | } |
| 150 | 159 | for (i = 0; i < fs->nb_in; i++) { |
| @@ -162,11 +171,9 @@ static void framesync_advance(FFFrameSync *fs) · 11 unmodified lines | ||
| 162 | 171 | fs->frame_ready = 1; |
| 163 | 172 | if (fs->in[i].state == STATE_EOF && |
| 164 | 173 | fs->in[i].after == EXT_STOP) |
| 165 | − fs->eof = 1; | |
| 174 | + framesync_eof(fs); | |
| 166 | 175 | } |
| 167 | 176 | } |
| 168 | − if (fs->eof) | |
| 169 | − fs->frame_ready = 0; | |
| 170 | 177 | if (fs->frame_ready) |
| 171 | 178 | for (i = 0; i < fs->nb_in; i++) |
| 172 | 179 | 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 | ||
| 188 | 195 | int64_t pts; |
| 189 | 196 | |
| 190 | 197 | 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; | |
| 200 | 201 | fs->in[in].frame_next = frame; |
| 201 | 202 | fs->in[in].pts_next = pts; |
| 202 | 203 | fs->in[in].have_next = 1; |
| 203 | 204 | } |
| 204 | 205 | |
| 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) | |
| 228 | 207 | { |
| 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; | |
| 230 | 216 | } |
| 231 | 217 | |
| 232 | 218 | int ff_framesync2_get_frame(FFFrameSync *fs, unsigned in, AVFrame **rframe, |
| @@ -273,71 +259,55 @@ void ff_framesync2_uninit(FFFrameSync *fs) · 40 unmodified lines | ||
| 273 | 259 | for (i = 0; i < fs->nb_in; i++) { |
| 274 | 260 | av_frame_free(&fs->in[i].frame); |
| 275 | 261 | av_frame_free(&fs->in[i].frame_next); |
| 276 | − ff_bufqueue_discard_all(&fs->in[i].queue); | |
| 277 | 262 | } |
| 278 | 263 | |
| 279 | 264 | av_freep(&fs->in); |
| 280 | 265 | } |
| 281 | 266 | |
| 282 | −int ff_framesync2_process_frame(FFFrameSync *fs, unsigned all) | |
| 267 | +int ff_framesync2_activate(FFFrameSync *fs) | |
| 283 | 268 | { |
| 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; | |
| 285 | 274 | |
| 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) | |
| 292 | 282 | 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; | |
| 297 | 302 | } |
| 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; | |
| 307 | 303 | |
| 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) | |
| 313 | 309 | 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; | |
| 321 | 311 | |
| 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; | |
| 343 | 313 | } |