| Line | Branch | Exec | Source |
|---|---|---|---|
| 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 | #include "libavutil/avassert.h" | ||
| 22 | #include "libavutil/mem.h" | ||
| 23 | #include "libavutil/opt.h" | ||
| 24 | #include "avfilter.h" | ||
| 25 | #include "filters.h" | ||
| 26 | #include "framesync.h" | ||
| 27 | |||
| 28 | #define OFFSET(member) offsetof(FFFrameSync, member) | ||
| 29 | #define FLAGS AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_FILTERING_PARAM | ||
| 30 | |||
| 31 | ✗ | static const char *framesync_name(void *ptr) | |
| 32 | { | ||
| 33 | ✗ | return "framesync"; | |
| 34 | } | ||
| 35 | |||
| 36 | static const AVOption framesync_options[] = { | ||
| 37 | { "eof_action", "Action to take when encountering EOF from secondary input ", | ||
| 38 | OFFSET(opt_eof_action), AV_OPT_TYPE_INT, { .i64 = EOF_ACTION_REPEAT }, | ||
| 39 | EOF_ACTION_REPEAT, EOF_ACTION_PASS, .flags = FLAGS, .unit = "eof_action" }, | ||
| 40 | { "repeat", "Repeat the previous frame.", 0, AV_OPT_TYPE_CONST, { .i64 = EOF_ACTION_REPEAT }, .flags = FLAGS, .unit = "eof_action" }, | ||
| 41 | { "endall", "End both streams.", 0, AV_OPT_TYPE_CONST, { .i64 = EOF_ACTION_ENDALL }, .flags = FLAGS, .unit = "eof_action" }, | ||
| 42 | { "pass", "Pass through the main input.", 0, AV_OPT_TYPE_CONST, { .i64 = EOF_ACTION_PASS }, .flags = FLAGS, .unit = "eof_action" }, | ||
| 43 | { "shortest", "force termination when the shortest input terminates", OFFSET(opt_shortest), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, FLAGS }, | ||
| 44 | { "repeatlast", "extend last frame of secondary streams beyond EOF", OFFSET(opt_repeatlast), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, FLAGS }, | ||
| 45 | { "ts_sync_mode", "How strictly to sync streams based on secondary input timestamps", | ||
| 46 | OFFSET(opt_ts_sync_mode), AV_OPT_TYPE_INT, { .i64 = TS_DEFAULT }, | ||
| 47 | TS_DEFAULT, TS_NEAREST, .flags = FLAGS, .unit = "ts_sync_mode" }, | ||
| 48 | { "default", "Frame from secondary input with the nearest lower or equal timestamp to the primary input frame", | ||
| 49 | 0, AV_OPT_TYPE_CONST, { .i64 = TS_DEFAULT }, .flags = FLAGS, .unit = "ts_sync_mode" }, | ||
| 50 | { "nearest", "Frame from secondary input with the absolute nearest timestamp to the primary input frame", | ||
| 51 | 0, AV_OPT_TYPE_CONST, { .i64 = TS_NEAREST }, .flags = FLAGS, .unit = "ts_sync_mode" }, | ||
| 52 | { NULL } | ||
| 53 | }; | ||
| 54 | const AVClass ff_framesync_class = { | ||
| 55 | .version = LIBAVUTIL_VERSION_INT, | ||
| 56 | .class_name = "framesync", | ||
| 57 | .item_name = framesync_name, | ||
| 58 | .category = AV_CLASS_CATEGORY_FILTER, | ||
| 59 | .option = framesync_options, | ||
| 60 | .parent_log_context_offset = OFFSET(parent), | ||
| 61 | }; | ||
| 62 | |||
| 63 | ✗ | const AVClass *ff_framesync_child_class_iterate(void **iter) | |
| 64 | { | ||
| 65 | ✗ | const AVClass *c = *iter ? NULL : &ff_framesync_class; | |
| 66 | ✗ | *iter = (void *)(uintptr_t)c; | |
| 67 | ✗ | return c; | |
| 68 | } | ||
| 69 | |||
| 70 | enum { | ||
| 71 | STATE_BOF, | ||
| 72 | STATE_RUN, | ||
| 73 | STATE_EOF, | ||
| 74 | }; | ||
| 75 | |||
| 76 | static int consume_from_fifos(FFFrameSync *fs); | ||
| 77 | |||
| 78 | 18004 | void ff_framesync_preinit(FFFrameSync *fs) | |
| 79 | { | ||
| 80 |
2/2✓ Branch 0 taken 6702 times.
✓ Branch 1 taken 11302 times.
|
18004 | if (fs->class) |
| 81 | 6702 | return; | |
| 82 | 11302 | fs->class = &ff_framesync_class; | |
| 83 | 11302 | av_opt_set_defaults(fs); | |
| 84 | } | ||
| 85 | |||
| 86 | 6713 | int ff_framesync_init(FFFrameSync *fs, AVFilterContext *parent, unsigned nb_in) | |
| 87 | { | ||
| 88 | /* For filters with several outputs, we will not be able to assume which | ||
| 89 | output is relevant for ff_outlink_frame_wanted() and | ||
| 90 | ff_outlink_set_status(). To be designed when needed. */ | ||
| 91 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6713 times.
|
6713 | av_assert0(parent->nb_outputs == 1); |
| 92 | |||
| 93 | 6713 | ff_framesync_preinit(fs); | |
| 94 | 6713 | fs->parent = parent; | |
| 95 | 6713 | fs->nb_in = nb_in; | |
| 96 | |||
| 97 | 6713 | fs->in = av_calloc(nb_in, sizeof(*fs->in)); | |
| 98 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6713 times.
|
6713 | if (!fs->in) { |
| 99 | ✗ | fs->nb_in = 0; | |
| 100 | ✗ | return AVERROR(ENOMEM); | |
| 101 | } | ||
| 102 | |||
| 103 | 6713 | return 0; | |
| 104 | } | ||
| 105 | |||
| 106 | 2362 | static void framesync_eof(FFFrameSync *fs, int64_t pts) | |
| 107 | { | ||
| 108 | 2362 | fs->eof = 1; | |
| 109 | 2362 | fs->frame_ready = 0; | |
| 110 | 2362 | ff_outlink_set_status(fs->parent->outputs[0], AVERROR_EOF, pts); | |
| 111 | 2362 | } | |
| 112 | |||
| 113 | 7944 | static void framesync_sync_level_update(FFFrameSync *fs, int64_t eof_pts) | |
| 114 | { | ||
| 115 | 7944 | unsigned i, level = 0; | |
| 116 | |||
| 117 |
2/2✓ Branch 0 taken 8105 times.
✓ Branch 1 taken 7944 times.
|
16049 | for (i = 0; i < fs->nb_in; i++) |
| 118 |
1/2✓ Branch 0 taken 8105 times.
✗ Branch 1 not taken.
|
8105 | if (fs->in[i].state != STATE_EOF) |
| 119 | 8105 | level = FFMAX(level, fs->in[i].sync); | |
| 120 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7944 times.
|
7944 | av_assert0(level <= fs->sync_level); |
| 121 |
2/2✓ Branch 0 taken 7911 times.
✓ Branch 1 taken 33 times.
|
7944 | if (level < fs->sync_level) |
| 122 | 7911 | av_log(fs, AV_LOG_VERBOSE, "Sync level %u\n", level); | |
| 123 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7944 times.
|
7944 | if (fs->opt_ts_sync_mode > TS_DEFAULT) { |
| 124 | ✗ | for (i = 0; i < fs->nb_in; i++) { | |
| 125 | ✗ | if (fs->in[i].sync < level) | |
| 126 | ✗ | fs->in[i].ts_mode = fs->opt_ts_sync_mode; | |
| 127 | else | ||
| 128 | ✗ | fs->in[i].ts_mode = TS_DEFAULT; | |
| 129 | } | ||
| 130 | } | ||
| 131 |
2/2✓ Branch 0 taken 6763 times.
✓ Branch 1 taken 1181 times.
|
7944 | if (level) |
| 132 | 6763 | fs->sync_level = level; | |
| 133 | else | ||
| 134 | 1181 | framesync_eof(fs, eof_pts); | |
| 135 | 7944 | } | |
| 136 | |||
| 137 | 6713 | int ff_framesync_configure(FFFrameSync *fs) | |
| 138 | { | ||
| 139 | unsigned i; | ||
| 140 | |||
| 141 |
2/4✓ Branch 0 taken 6713 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 6713 times.
|
6713 | if (!fs->opt_repeatlast || fs->opt_eof_action == EOF_ACTION_PASS) { |
| 142 | ✗ | fs->opt_repeatlast = 0; | |
| 143 | ✗ | fs->opt_eof_action = EOF_ACTION_PASS; | |
| 144 | } | ||
| 145 |
2/4✓ Branch 0 taken 6713 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 6713 times.
|
6713 | if (fs->opt_shortest || fs->opt_eof_action == EOF_ACTION_ENDALL) { |
| 146 | ✗ | fs->opt_shortest = 1; | |
| 147 | ✗ | fs->opt_eof_action = EOF_ACTION_ENDALL; | |
| 148 | } | ||
| 149 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6713 times.
|
6713 | if (!fs->opt_repeatlast) { |
| 150 | ✗ | for (i = 1; i < fs->nb_in; i++) { | |
| 151 | ✗ | fs->in[i].after = EXT_NULL; | |
| 152 | ✗ | fs->in[i].sync = 0; | |
| 153 | } | ||
| 154 | } | ||
| 155 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6713 times.
|
6713 | if (fs->opt_shortest) { |
| 156 | ✗ | for (i = 0; i < fs->nb_in; i++) | |
| 157 | ✗ | fs->in[i].after = EXT_STOP; | |
| 158 | } | ||
| 159 | |||
| 160 |
2/2✓ Branch 0 taken 6656 times.
✓ Branch 1 taken 57 times.
|
6713 | if (!fs->time_base.num) { |
| 161 |
2/2✓ Branch 0 taken 6710 times.
✓ Branch 1 taken 6656 times.
|
13366 | for (i = 0; i < fs->nb_in; i++) { |
| 162 |
2/2✓ Branch 0 taken 6709 times.
✓ Branch 1 taken 1 times.
|
6710 | if (fs->in[i].sync) { |
| 163 |
2/2✓ Branch 0 taken 53 times.
✓ Branch 1 taken 6656 times.
|
6709 | if (fs->time_base.num) { |
| 164 | 53 | fs->time_base = av_gcd_q(fs->time_base, fs->in[i].time_base, | |
| 165 | 53 | AV_TIME_BASE / 2, AV_TIME_BASE_Q); | |
| 166 | } else { | ||
| 167 | 6656 | fs->time_base = fs->in[i].time_base; | |
| 168 | } | ||
| 169 | } | ||
| 170 | } | ||
| 171 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6656 times.
|
6656 | if (!fs->time_base.num) { |
| 172 | ✗ | av_log(fs, AV_LOG_ERROR, "Impossible to set time base\n"); | |
| 173 | ✗ | return AVERROR(EINVAL); | |
| 174 | } | ||
| 175 | 6656 | av_log(fs, AV_LOG_VERBOSE, "Selected %d/%d time base\n", | |
| 176 | fs->time_base.num, fs->time_base.den); | ||
| 177 | } | ||
| 178 | |||
| 179 |
2/2✓ Branch 0 taken 6767 times.
✓ Branch 1 taken 6713 times.
|
13480 | for (i = 0; i < fs->nb_in; i++) |
| 180 | 6767 | fs->in[i].pts = fs->in[i].pts_next = AV_NOPTS_VALUE; | |
| 181 | 6713 | fs->sync_level = UINT_MAX; | |
| 182 | 6713 | framesync_sync_level_update(fs, AV_NOPTS_VALUE); | |
| 183 | |||
| 184 | 6713 | return 0; | |
| 185 | } | ||
| 186 | |||
| 187 | 223835 | static int framesync_advance(FFFrameSync *fs) | |
| 188 | { | ||
| 189 | unsigned i; | ||
| 190 | int64_t pts; | ||
| 191 | int ret; | ||
| 192 | |||
| 193 |
4/4✓ Branch 0 taken 225065 times.
✓ Branch 1 taken 111745 times.
✓ Branch 2 taken 223923 times.
✓ Branch 3 taken 1142 times.
|
336810 | while (!(fs->frame_ready || fs->eof)) { |
| 194 | 223923 | ret = consume_from_fifos(fs); | |
| 195 |
2/2✓ Branch 0 taken 110909 times.
✓ Branch 1 taken 113014 times.
|
223923 | if (ret <= 0) |
| 196 | 110909 | return ret; | |
| 197 | |||
| 198 | 113014 | pts = INT64_MAX; | |
| 199 |
2/2✓ Branch 0 taken 114561 times.
✓ Branch 1 taken 113014 times.
|
227575 | for (i = 0; i < fs->nb_in; i++) |
| 200 |
3/4✓ Branch 0 taken 114561 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 113063 times.
✓ Branch 3 taken 1498 times.
|
114561 | if (fs->in[i].have_next && fs->in[i].pts_next < pts) |
| 201 | 113063 | pts = fs->in[i].pts_next; | |
| 202 |
2/2✓ Branch 0 taken 39 times.
✓ Branch 1 taken 112975 times.
|
113014 | if (pts == INT64_MAX) { |
| 203 | 39 | framesync_eof(fs, AV_NOPTS_VALUE); | |
| 204 | 39 | break; | |
| 205 | } | ||
| 206 |
2/2✓ Branch 0 taken 114483 times.
✓ Branch 1 taken 112975 times.
|
227458 | for (i = 0; i < fs->nb_in; i++) { |
| 207 |
2/2✓ Branch 0 taken 732 times.
✓ Branch 1 taken 113751 times.
|
114483 | if (fs->in[i].pts_next == pts || |
| 208 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 732 times.
|
732 | (fs->in[i].ts_mode == TS_NEAREST && |
| 209 | ✗ | fs->in[i].have_next && | |
| 210 | ✗ | fs->in[i].pts_next != INT64_MAX && fs->in[i].pts != AV_NOPTS_VALUE && | |
| 211 | ✗ | fs->in[i].pts_next - pts < pts - fs->in[i].pts) || | |
| 212 |
2/2✓ Branch 0 taken 280 times.
✓ Branch 1 taken 452 times.
|
732 | (fs->in[i].before == EXT_INFINITY && |
| 213 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 280 times.
|
280 | fs->in[i].state == STATE_BOF)) { |
| 214 | 113751 | av_frame_free(&fs->in[i].frame); | |
| 215 | 113751 | fs->in[i].frame = fs->in[i].frame_next; | |
| 216 | 113751 | fs->in[i].pts = fs->in[i].pts_next; | |
| 217 | 113751 | fs->in[i].frame_next = NULL; | |
| 218 | 113751 | fs->in[i].pts_next = AV_NOPTS_VALUE; | |
| 219 | 113751 | fs->in[i].have_next = 0; | |
| 220 |
2/2✓ Branch 0 taken 112609 times.
✓ Branch 1 taken 1142 times.
|
113751 | fs->in[i].state = fs->in[i].frame ? STATE_RUN : STATE_EOF; |
| 221 |
3/4✓ Branch 0 taken 111904 times.
✓ Branch 1 taken 1847 times.
✓ Branch 2 taken 111904 times.
✗ Branch 3 not taken.
|
113751 | if (fs->in[i].sync == fs->sync_level && fs->in[i].frame) |
| 222 | 111904 | fs->frame_ready = 1; | |
| 223 |
2/2✓ Branch 0 taken 1142 times.
✓ Branch 1 taken 112609 times.
|
113751 | if (fs->in[i].state == STATE_EOF && |
| 224 |
1/2✓ Branch 0 taken 1142 times.
✗ Branch 1 not taken.
|
1142 | fs->in[i].after == EXT_STOP) |
| 225 | 1142 | framesync_eof(fs, AV_NOPTS_VALUE); | |
| 226 | } | ||
| 227 | } | ||
| 228 |
2/2✓ Branch 0 taken 111745 times.
✓ Branch 1 taken 1230 times.
|
112975 | if (fs->frame_ready) |
| 229 |
2/2✓ Branch 0 taken 113165 times.
✓ Branch 1 taken 111745 times.
|
224910 | for (i = 0; i < fs->nb_in; i++) |
| 230 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 113162 times.
|
113165 | if ((fs->in[i].state == STATE_BOF && |
| 231 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | fs->in[i].before == EXT_STOP)) |
| 232 | ✗ | fs->frame_ready = 0; | |
| 233 | 112975 | fs->pts = pts; | |
| 234 | } | ||
| 235 | 112926 | return 0; | |
| 236 | } | ||
| 237 | |||
| 238 | 1142 | static int64_t framesync_pts_extrapolate(FFFrameSync *fs, unsigned in, | |
| 239 | int64_t pts) | ||
| 240 | { | ||
| 241 | /* Possible enhancement: use the link's frame rate */ | ||
| 242 | 1142 | return pts + 1; | |
| 243 | } | ||
| 244 | |||
| 245 | 112609 | static void framesync_inject_frame(FFFrameSync *fs, unsigned in, AVFrame *frame) | |
| 246 | { | ||
| 247 | int64_t pts; | ||
| 248 | |||
| 249 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 112609 times.
|
112609 | av_assert0(!fs->in[in].have_next); |
| 250 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 112609 times.
|
112609 | av_assert0(frame); |
| 251 | 112609 | pts = av_rescale_q_rnd(frame->pts, fs->in[in].time_base, fs->time_base, AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX); | |
| 252 | 112609 | frame->pts = pts; | |
| 253 | 112609 | fs->in[in].frame_next = frame; | |
| 254 | 112609 | fs->in[in].pts_next = pts; | |
| 255 | 112609 | fs->in[in].have_next = 1; | |
| 256 | 112609 | } | |
| 257 | |||
| 258 | 1231 | static void framesync_inject_status(FFFrameSync *fs, unsigned in, int status, int64_t eof_pts) | |
| 259 | { | ||
| 260 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1231 times.
|
1231 | av_assert0(!fs->in[in].have_next); |
| 261 | 1231 | fs->in[in].sync = 0; | |
| 262 |
1/2✓ Branch 0 taken 1231 times.
✗ Branch 1 not taken.
|
1231 | framesync_sync_level_update(fs, status == AVERROR_EOF ? eof_pts : AV_NOPTS_VALUE); |
| 263 | 1231 | fs->in[in].frame_next = NULL; | |
| 264 |
2/2✓ Branch 0 taken 1142 times.
✓ Branch 1 taken 83 times.
|
1225 | fs->in[in].pts_next = fs->in[in].state != STATE_RUN || fs->in[in].after == EXT_INFINITY |
| 265 |
2/2✓ Branch 0 taken 1225 times.
✓ Branch 1 taken 6 times.
|
2456 | ? INT64_MAX : framesync_pts_extrapolate(fs, in, fs->in[in].pts); |
| 266 | 1231 | fs->in[in].have_next = 1; | |
| 267 | 1231 | } | |
| 268 | |||
| 269 | 113165 | int ff_framesync_get_frame(FFFrameSync *fs, unsigned in, AVFrame **rframe, | |
| 270 | unsigned get) | ||
| 271 | { | ||
| 272 | AVFrame *frame; | ||
| 273 | 113165 | unsigned need_copy = 0, i; | |
| 274 | int64_t pts_next; | ||
| 275 | |||
| 276 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 113162 times.
|
113165 | if (!fs->in[in].frame) { |
| 277 | 3 | *rframe = NULL; | |
| 278 | 3 | return 0; | |
| 279 | } | ||
| 280 | 113162 | frame = fs->in[in].frame; | |
| 281 |
2/2✓ Branch 0 taken 111542 times.
✓ Branch 1 taken 1620 times.
|
113162 | if (get) { |
| 282 | /* Find out if we need to copy the frame: is there another sync | ||
| 283 | stream, and do we know if its current frame will outlast this one? */ | ||
| 284 |
2/2✓ Branch 0 taken 88 times.
✓ Branch 1 taken 111454 times.
|
111542 | pts_next = fs->in[in].have_next ? fs->in[in].pts_next : INT64_MAX; |
| 285 |
3/4✓ Branch 0 taken 112803 times.
✓ Branch 1 taken 111542 times.
✓ Branch 2 taken 112803 times.
✗ Branch 3 not taken.
|
224345 | for (i = 0; i < fs->nb_in && !need_copy; i++) |
| 286 |
4/4✓ Branch 0 taken 1261 times.
✓ Branch 1 taken 111542 times.
✓ Branch 2 taken 956 times.
✓ Branch 3 taken 305 times.
|
112803 | if (i != in && fs->in[i].sync && |
| 287 |
3/4✓ Branch 0 taken 256 times.
✓ Branch 1 taken 700 times.
✓ Branch 2 taken 256 times.
✗ Branch 3 not taken.
|
956 | (!fs->in[i].have_next || fs->in[i].pts_next < pts_next)) |
| 288 | 956 | need_copy = 1; | |
| 289 |
2/2✓ Branch 0 taken 956 times.
✓ Branch 1 taken 110586 times.
|
111542 | if (need_copy) { |
| 290 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 956 times.
|
956 | if (!(frame = av_frame_clone(frame))) |
| 291 | ✗ | return AVERROR(ENOMEM); | |
| 292 | } else { | ||
| 293 | 110586 | fs->in[in].frame = NULL; | |
| 294 | } | ||
| 295 | 111542 | fs->frame_ready = 0; | |
| 296 | } | ||
| 297 | 113162 | *rframe = frame; | |
| 298 | 113162 | return 0; | |
| 299 | } | ||
| 300 | |||
| 301 | 17983 | void ff_framesync_uninit(FFFrameSync *fs) | |
| 302 | { | ||
| 303 | unsigned i; | ||
| 304 | |||
| 305 |
2/2✓ Branch 0 taken 6767 times.
✓ Branch 1 taken 17983 times.
|
24750 | for (i = 0; i < fs->nb_in; i++) { |
| 306 | 6767 | av_frame_free(&fs->in[i].frame); | |
| 307 | 6767 | av_frame_free(&fs->in[i].frame_next); | |
| 308 | } | ||
| 309 | |||
| 310 | 17983 | av_freep(&fs->in); | |
| 311 | 17983 | } | |
| 312 | |||
| 313 | 223923 | static int consume_from_fifos(FFFrameSync *fs) | |
| 314 | { | ||
| 315 | 223923 | AVFilterContext *ctx = fs->parent; | |
| 316 | 223923 | AVFrame *frame = NULL; | |
| 317 | int64_t pts; | ||
| 318 | unsigned i, nb_active, nb_miss; | ||
| 319 | int ret, status; | ||
| 320 | |||
| 321 | 223923 | nb_active = nb_miss = 0; | |
| 322 |
2/2✓ Branch 0 taken 228723 times.
✓ Branch 1 taken 223923 times.
|
452646 | for (i = 0; i < fs->nb_in; i++) { |
| 323 |
3/4✓ Branch 0 taken 225495 times.
✓ Branch 1 taken 3228 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 225495 times.
|
228723 | if (fs->in[i].have_next || fs->in[i].state == STATE_EOF) |
| 324 | 3228 | continue; | |
| 325 | 225495 | nb_active++; | |
| 326 | 225495 | ret = ff_inlink_consume_frame(ctx->inputs[i], &frame); | |
| 327 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 225495 times.
|
225495 | if (ret < 0) |
| 328 | ✗ | return ret; | |
| 329 |
2/2✓ Branch 0 taken 112609 times.
✓ Branch 1 taken 112886 times.
|
225495 | if (ret) { |
| 330 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 112609 times.
|
112609 | av_assert0(frame); |
| 331 | 112609 | framesync_inject_frame(fs, i, frame); | |
| 332 | } else { | ||
| 333 | 112886 | ret = ff_inlink_acknowledge_status(ctx->inputs[i], &status, &pts); | |
| 334 |
2/2✓ Branch 0 taken 1231 times.
✓ Branch 1 taken 111655 times.
|
112886 | if (ret > 0) { |
| 335 | 1231 | framesync_inject_status(fs, i, status, pts); | |
| 336 |
1/2✓ Branch 0 taken 111655 times.
✗ Branch 1 not taken.
|
111655 | } else if (!ret) { |
| 337 | 111655 | nb_miss++; | |
| 338 | } | ||
| 339 | } | ||
| 340 | } | ||
| 341 |
2/2✓ Branch 0 taken 110909 times.
✓ Branch 1 taken 113014 times.
|
223923 | if (nb_miss) { |
| 342 |
4/4✓ Branch 0 taken 110269 times.
✓ Branch 1 taken 640 times.
✓ Branch 3 taken 4 times.
✓ Branch 4 taken 110265 times.
|
110909 | if (nb_miss == nb_active && !ff_outlink_frame_wanted(ctx->outputs[0])) |
| 343 | 4 | return FFERROR_NOT_READY; | |
| 344 |
2/2✓ Branch 0 taken 114154 times.
✓ Branch 1 taken 110905 times.
|
225059 | for (i = 0; i < fs->nb_in; i++) |
| 345 |
3/4✓ Branch 0 taken 111651 times.
✓ Branch 1 taken 2503 times.
✓ Branch 2 taken 111651 times.
✗ Branch 3 not taken.
|
114154 | if (!fs->in[i].have_next && fs->in[i].state != STATE_EOF) |
| 346 | 111651 | ff_inlink_request_frame(ctx->inputs[i]); | |
| 347 | 110905 | return 0; | |
| 348 | } | ||
| 349 | 113014 | return 1; | |
| 350 | } | ||
| 351 | |||
| 352 | 225002 | int ff_framesync_activate(FFFrameSync *fs) | |
| 353 | { | ||
| 354 | 225002 | AVFilterContext *ctx = fs->parent; | |
| 355 | int ret; | ||
| 356 | |||
| 357 |
4/4✓ Branch 1 taken 1167 times.
✓ Branch 2 taken 223835 times.
✓ Branch 4 taken 1181 times.
✓ Branch 5 taken 1167 times.
|
226183 | FF_FILTER_FORWARD_STATUS_BACK_ALL(ctx->outputs[0], ctx); |
| 358 | |||
| 359 | 223835 | ret = framesync_advance(fs); | |
| 360 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 223831 times.
|
223835 | if (ret < 0) |
| 361 | 4 | return ret; | |
| 362 |
4/4✓ Branch 0 taken 222650 times.
✓ Branch 1 taken 1181 times.
✓ Branch 2 taken 110905 times.
✓ Branch 3 taken 111745 times.
|
223831 | if (fs->eof || !fs->frame_ready) |
| 363 | 112086 | return 0; | |
| 364 | 111745 | ret = fs->on_event(fs); | |
| 365 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 111745 times.
|
111745 | if (ret < 0) |
| 366 | ✗ | return ret; | |
| 367 | 111745 | fs->frame_ready = 0; | |
| 368 | |||
| 369 | 111745 | return 0; | |
| 370 | } | ||
| 371 | |||
| 372 | 41 | int ff_framesync_init_dualinput(FFFrameSync *fs, AVFilterContext *parent) | |
| 373 | { | ||
| 374 | int ret; | ||
| 375 | |||
| 376 | 41 | ret = ff_framesync_init(fs, parent, 2); | |
| 377 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 41 times.
|
41 | if (ret < 0) |
| 378 | ✗ | return ret; | |
| 379 | 41 | fs->in[0].time_base = parent->inputs[0]->time_base; | |
| 380 | 41 | fs->in[1].time_base = parent->inputs[1]->time_base; | |
| 381 | 41 | fs->in[0].sync = 2; | |
| 382 | 41 | fs->in[0].before = EXT_STOP; | |
| 383 | 41 | fs->in[0].after = EXT_INFINITY; | |
| 384 | 41 | fs->in[1].sync = 1; | |
| 385 | 41 | fs->in[1].before = EXT_NULL; | |
| 386 | 41 | fs->in[1].after = EXT_INFINITY; | |
| 387 | 41 | return 0; | |
| 388 | } | ||
| 389 | |||
| 390 | 1256 | int ff_framesync_dualinput_get(FFFrameSync *fs, AVFrame **f0, AVFrame **f1) | |
| 391 | { | ||
| 392 | 1256 | AVFilterContext *ctx = fs->parent; | |
| 393 | 1256 | AVFrame *mainpic = NULL, *secondpic = NULL; | |
| 394 | int ret; | ||
| 395 | |||
| 396 |
2/4✓ Branch 1 taken 1256 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 1256 times.
|
2512 | if ((ret = ff_framesync_get_frame(fs, 0, &mainpic, 1)) < 0 || |
| 397 | 1256 | (ret = ff_framesync_get_frame(fs, 1, &secondpic, 0)) < 0) { | |
| 398 | ✗ | av_frame_free(&mainpic); | |
| 399 | ✗ | return ret; | |
| 400 | } | ||
| 401 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1256 times.
|
1256 | av_assert0(mainpic); |
| 402 | 1256 | mainpic->pts = av_rescale_q(fs->pts, fs->time_base, ctx->outputs[0]->time_base); | |
| 403 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1256 times.
|
1256 | if (ctx->is_disabled) |
| 404 | ✗ | secondpic = NULL; | |
| 405 | 1256 | *f0 = mainpic; | |
| 406 | 1256 | *f1 = secondpic; | |
| 407 | 1256 | return 0; | |
| 408 | } | ||
| 409 | |||
| 410 | 1222 | int ff_framesync_dualinput_get_writable(FFFrameSync *fs, AVFrame **f0, AVFrame **f1) | |
| 411 | { | ||
| 412 | int ret; | ||
| 413 | |||
| 414 | 1222 | ret = ff_framesync_dualinput_get(fs, f0, f1); | |
| 415 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1222 times.
|
1222 | if (ret < 0) |
| 416 | ✗ | return ret; | |
| 417 | 1222 | ret = ff_inlink_make_frame_writable(fs->parent->inputs[0], f0); | |
| 418 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1222 times.
|
1222 | if (ret < 0) { |
| 419 | ✗ | av_frame_free(f0); | |
| 420 | ✗ | *f1 = NULL; | |
| 421 | ✗ | return ret; | |
| 422 | } | ||
| 423 | 1222 | return 0; | |
| 424 | } | ||
| 425 |