Line | Branch | Exec | Source |
---|---|---|---|
1 | /* | ||
2 | * ffmpeg filter configuration | ||
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 | ||
8 | * License 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 GNU | ||
14 | * Lesser General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU Lesser General Public | ||
17 | * License along with FFmpeg; if not, write to the Free Software | ||
18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
19 | */ | ||
20 | |||
21 | #include <stdint.h> | ||
22 | |||
23 | #include "ffmpeg.h" | ||
24 | |||
25 | #include "libavfilter/avfilter.h" | ||
26 | #include "libavfilter/buffersink.h" | ||
27 | #include "libavfilter/buffersrc.h" | ||
28 | |||
29 | #include "libavutil/avassert.h" | ||
30 | #include "libavutil/avstring.h" | ||
31 | #include "libavutil/bprint.h" | ||
32 | #include "libavutil/channel_layout.h" | ||
33 | #include "libavutil/mem.h" | ||
34 | #include "libavutil/opt.h" | ||
35 | #include "libavutil/pixdesc.h" | ||
36 | #include "libavutil/pixfmt.h" | ||
37 | #include "libavutil/samplefmt.h" | ||
38 | #include "libavutil/time.h" | ||
39 | #include "libavutil/timestamp.h" | ||
40 | |||
41 | // FIXME private header, used for mid_pred() | ||
42 | #include "libavcodec/mathops.h" | ||
43 | |||
44 | typedef struct FilterGraphPriv { | ||
45 | FilterGraph fg; | ||
46 | |||
47 | // name used for logging | ||
48 | char log_name[32]; | ||
49 | |||
50 | int is_simple; | ||
51 | // true when the filtergraph contains only meta filters | ||
52 | // that do not modify the frame data | ||
53 | int is_meta; | ||
54 | // source filters are present in the graph | ||
55 | int have_sources; | ||
56 | int disable_conversions; | ||
57 | |||
58 | unsigned nb_outputs_done; | ||
59 | |||
60 | const char *graph_desc; | ||
61 | |||
62 | char *nb_threads; | ||
63 | |||
64 | // frame for temporarily holding output from the filtergraph | ||
65 | AVFrame *frame; | ||
66 | // frame for sending output to the encoder | ||
67 | AVFrame *frame_enc; | ||
68 | |||
69 | Scheduler *sch; | ||
70 | unsigned sch_idx; | ||
71 | } FilterGraphPriv; | ||
72 | |||
73 | 1476011 | static FilterGraphPriv *fgp_from_fg(FilterGraph *fg) | |
74 | { | ||
75 | 1476011 | return (FilterGraphPriv*)fg; | |
76 | } | ||
77 | |||
78 | 32039 | static const FilterGraphPriv *cfgp_from_cfg(const FilterGraph *fg) | |
79 | { | ||
80 | 32039 | return (const FilterGraphPriv*)fg; | |
81 | } | ||
82 | |||
83 | // data that is local to the filter thread and not visible outside of it | ||
84 | typedef struct FilterGraphThread { | ||
85 | AVFilterGraph *graph; | ||
86 | |||
87 | AVFrame *frame; | ||
88 | |||
89 | // Temporary buffer for output frames, since on filtergraph reset | ||
90 | // we cannot send them to encoders immediately. | ||
91 | // The output index is stored in frame opaque. | ||
92 | AVFifo *frame_queue_out; | ||
93 | |||
94 | // index of the next input to request from the scheduler | ||
95 | unsigned next_in; | ||
96 | // set to 1 after at least one frame passed through this output | ||
97 | int got_frame; | ||
98 | |||
99 | // EOF status of each input/output, as received by the thread | ||
100 | uint8_t *eof_in; | ||
101 | uint8_t *eof_out; | ||
102 | } FilterGraphThread; | ||
103 | |||
104 | typedef struct InputFilterPriv { | ||
105 | InputFilter ifilter; | ||
106 | |||
107 | InputFilterOptions opts; | ||
108 | |||
109 | int index; | ||
110 | |||
111 | AVFilterContext *filter; | ||
112 | |||
113 | // used to hold submitted input | ||
114 | AVFrame *frame; | ||
115 | |||
116 | /* for filters that are not yet bound to an input stream, | ||
117 | * this stores the input linklabel, if any */ | ||
118 | uint8_t *linklabel; | ||
119 | |||
120 | // filter data type | ||
121 | enum AVMediaType type; | ||
122 | // source data type: AVMEDIA_TYPE_SUBTITLE for sub2video, | ||
123 | // same as type otherwise | ||
124 | enum AVMediaType type_src; | ||
125 | |||
126 | int eof; | ||
127 | int bound; | ||
128 | |||
129 | // parameters configured for this input | ||
130 | int format; | ||
131 | |||
132 | int width, height; | ||
133 | AVRational sample_aspect_ratio; | ||
134 | enum AVColorSpace color_space; | ||
135 | enum AVColorRange color_range; | ||
136 | |||
137 | int sample_rate; | ||
138 | AVChannelLayout ch_layout; | ||
139 | |||
140 | AVRational time_base; | ||
141 | |||
142 | AVFifo *frame_queue; | ||
143 | |||
144 | AVBufferRef *hw_frames_ctx; | ||
145 | |||
146 | int displaymatrix_present; | ||
147 | int displaymatrix_applied; | ||
148 | int32_t displaymatrix[9]; | ||
149 | |||
150 | struct { | ||
151 | AVFrame *frame; | ||
152 | |||
153 | int64_t last_pts; | ||
154 | int64_t end_pts; | ||
155 | |||
156 | ///< marks if sub2video_update should force an initialization | ||
157 | unsigned int initialize; | ||
158 | } sub2video; | ||
159 | } InputFilterPriv; | ||
160 | |||
161 | 1156687 | static InputFilterPriv *ifp_from_ifilter(InputFilter *ifilter) | |
162 | { | ||
163 | 1156687 | return (InputFilterPriv*)ifilter; | |
164 | } | ||
165 | |||
166 | typedef struct FPSConvContext { | ||
167 | AVFrame *last_frame; | ||
168 | /* number of frames emitted by the video-encoding sync code */ | ||
169 | int64_t frame_number; | ||
170 | /* history of nb_frames_prev, i.e. the number of times the | ||
171 | * previous frame was duplicated by vsync code in recent | ||
172 | * do_video_out() calls */ | ||
173 | int64_t frames_prev_hist[3]; | ||
174 | |||
175 | uint64_t dup_warning; | ||
176 | |||
177 | int last_dropped; | ||
178 | int dropped_keyframe; | ||
179 | |||
180 | enum VideoSyncMethod vsync_method; | ||
181 | |||
182 | AVRational framerate; | ||
183 | AVRational framerate_max; | ||
184 | const AVRational *framerate_supported; | ||
185 | int framerate_clip; | ||
186 | } FPSConvContext; | ||
187 | |||
188 | typedef struct OutputFilterPriv { | ||
189 | OutputFilter ofilter; | ||
190 | |||
191 | int index; | ||
192 | |||
193 | void *log_parent; | ||
194 | char log_name[32]; | ||
195 | |||
196 | char *name; | ||
197 | |||
198 | AVFilterContext *filter; | ||
199 | |||
200 | /* desired output stream properties */ | ||
201 | int format; | ||
202 | int width, height; | ||
203 | int sample_rate; | ||
204 | AVChannelLayout ch_layout; | ||
205 | |||
206 | // time base in which the output is sent to our downstream | ||
207 | // does not need to match the filtersink's timebase | ||
208 | AVRational tb_out; | ||
209 | // at least one frame with the above timebase was sent | ||
210 | // to our downstream, so it cannot change anymore | ||
211 | int tb_out_locked; | ||
212 | |||
213 | AVRational sample_aspect_ratio; | ||
214 | |||
215 | AVDictionary *sws_opts; | ||
216 | AVDictionary *swr_opts; | ||
217 | |||
218 | // those are only set if no format is specified and the encoder gives us multiple options | ||
219 | // They point directly to the relevant lists of the encoder. | ||
220 | const int *formats; | ||
221 | const AVChannelLayout *ch_layouts; | ||
222 | const int *sample_rates; | ||
223 | |||
224 | AVRational enc_timebase; | ||
225 | int64_t trim_start_us; | ||
226 | int64_t trim_duration_us; | ||
227 | // offset for output timestamps, in AV_TIME_BASE_Q | ||
228 | int64_t ts_offset; | ||
229 | int64_t next_pts; | ||
230 | FPSConvContext fps; | ||
231 | |||
232 | unsigned flags; | ||
233 | } OutputFilterPriv; | ||
234 | |||
235 | 417230 | static OutputFilterPriv *ofp_from_ofilter(OutputFilter *ofilter) | |
236 | { | ||
237 | 417230 | return (OutputFilterPriv*)ofilter; | |
238 | } | ||
239 | |||
240 | typedef struct FilterCommand { | ||
241 | char *target; | ||
242 | char *command; | ||
243 | char *arg; | ||
244 | |||
245 | double time; | ||
246 | int all_filters; | ||
247 | } FilterCommand; | ||
248 | |||
249 | ✗ | static void filter_command_free(void *opaque, uint8_t *data) | |
250 | { | ||
251 | ✗ | FilterCommand *fc = (FilterCommand*)data; | |
252 | |||
253 | ✗ | av_freep(&fc->target); | |
254 | ✗ | av_freep(&fc->command); | |
255 | ✗ | av_freep(&fc->arg); | |
256 | |||
257 | ✗ | av_free(data); | |
258 | ✗ | } | |
259 | |||
260 | 180 | static int sub2video_get_blank_frame(InputFilterPriv *ifp) | |
261 | { | ||
262 | 180 | AVFrame *frame = ifp->sub2video.frame; | |
263 | int ret; | ||
264 | |||
265 | 180 | av_frame_unref(frame); | |
266 | |||
267 | 180 | frame->width = ifp->width; | |
268 | 180 | frame->height = ifp->height; | |
269 | 180 | frame->format = ifp->format; | |
270 | 180 | frame->colorspace = ifp->color_space; | |
271 | 180 | frame->color_range = ifp->color_range; | |
272 | |||
273 | 180 | ret = av_frame_get_buffer(frame, 0); | |
274 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 180 times.
|
180 | if (ret < 0) |
275 | ✗ | return ret; | |
276 | |||
277 | 180 | memset(frame->data[0], 0, frame->height * frame->linesize[0]); | |
278 | |||
279 | 180 | return 0; | |
280 | } | ||
281 | |||
282 | 89 | static void sub2video_copy_rect(uint8_t *dst, int dst_linesize, int w, int h, | |
283 | AVSubtitleRect *r) | ||
284 | { | ||
285 | uint32_t *pal, *dst2; | ||
286 | uint8_t *src, *src2; | ||
287 | int x, y; | ||
288 | |||
289 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 89 times.
|
89 | if (r->type != SUBTITLE_BITMAP) { |
290 | ✗ | av_log(NULL, AV_LOG_WARNING, "sub2video: non-bitmap subtitle\n"); | |
291 | ✗ | return; | |
292 | } | ||
293 |
4/8✓ Branch 0 taken 89 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 89 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 89 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 89 times.
|
89 | if (r->x < 0 || r->x + r->w > w || r->y < 0 || r->y + r->h > h) { |
294 | ✗ | av_log(NULL, AV_LOG_WARNING, "sub2video: rectangle (%d %d %d %d) overflowing %d %d\n", | |
295 | r->x, r->y, r->w, r->h, w, h | ||
296 | ); | ||
297 | ✗ | return; | |
298 | } | ||
299 | |||
300 | 89 | dst += r->y * dst_linesize + r->x * 4; | |
301 | 89 | src = r->data[0]; | |
302 | 89 | pal = (uint32_t *)r->data[1]; | |
303 |
2/2✓ Branch 0 taken 3291 times.
✓ Branch 1 taken 89 times.
|
3380 | for (y = 0; y < r->h; y++) { |
304 | 3291 | dst2 = (uint32_t *)dst; | |
305 | 3291 | src2 = src; | |
306 |
2/2✓ Branch 0 taken 1036075 times.
✓ Branch 1 taken 3291 times.
|
1039366 | for (x = 0; x < r->w; x++) |
307 | 1036075 | *(dst2++) = pal[*(src2++)]; | |
308 | 3291 | dst += dst_linesize; | |
309 | 3291 | src += r->linesize[0]; | |
310 | } | ||
311 | } | ||
312 | |||
313 | 271 | static void sub2video_push_ref(InputFilterPriv *ifp, int64_t pts) | |
314 | { | ||
315 | 271 | AVFrame *frame = ifp->sub2video.frame; | |
316 | int ret; | ||
317 | |||
318 | av_assert1(frame->data[0]); | ||
319 | 271 | ifp->sub2video.last_pts = frame->pts = pts; | |
320 | 271 | ret = av_buffersrc_add_frame_flags(ifp->filter, frame, | |
321 | AV_BUFFERSRC_FLAG_KEEP_REF | | ||
322 | AV_BUFFERSRC_FLAG_PUSH); | ||
323 |
2/4✓ Branch 0 taken 271 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 271 times.
|
271 | if (ret != AVERROR_EOF && ret < 0) |
324 | ✗ | av_log(NULL, AV_LOG_WARNING, "Error while add the frame to buffer source(%s).\n", | |
325 | ✗ | av_err2str(ret)); | |
326 | 271 | } | |
327 | |||
328 | 180 | static void sub2video_update(InputFilterPriv *ifp, int64_t heartbeat_pts, | |
329 | const AVSubtitle *sub) | ||
330 | { | ||
331 | 180 | AVFrame *frame = ifp->sub2video.frame; | |
332 | int8_t *dst; | ||
333 | int dst_linesize; | ||
334 | int num_rects; | ||
335 | int64_t pts, end_pts; | ||
336 | |||
337 |
2/2✓ Branch 0 taken 88 times.
✓ Branch 1 taken 92 times.
|
180 | if (sub) { |
338 | 88 | pts = av_rescale_q(sub->pts + sub->start_display_time * 1000LL, | |
339 | 88 | AV_TIME_BASE_Q, ifp->time_base); | |
340 | 88 | end_pts = av_rescale_q(sub->pts + sub->end_display_time * 1000LL, | |
341 | 88 | AV_TIME_BASE_Q, ifp->time_base); | |
342 | 88 | num_rects = sub->num_rects; | |
343 | } else { | ||
344 | /* If we are initializing the system, utilize current heartbeat | ||
345 | PTS as the start time, and show until the following subpicture | ||
346 | is received. Otherwise, utilize the previous subpicture's end time | ||
347 | as the fall-back value. */ | ||
348 | 184 | pts = ifp->sub2video.initialize ? | |
349 |
2/2✓ Branch 0 taken 88 times.
✓ Branch 1 taken 4 times.
|
92 | heartbeat_pts : ifp->sub2video.end_pts; |
350 | 92 | end_pts = INT64_MAX; | |
351 | 92 | num_rects = 0; | |
352 | } | ||
353 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 180 times.
|
180 | if (sub2video_get_blank_frame(ifp) < 0) { |
354 | ✗ | av_log(NULL, AV_LOG_ERROR, | |
355 | "Impossible to get a blank canvas.\n"); | ||
356 | ✗ | return; | |
357 | } | ||
358 | 180 | dst = frame->data [0]; | |
359 | 180 | dst_linesize = frame->linesize[0]; | |
360 |
2/2✓ Branch 0 taken 89 times.
✓ Branch 1 taken 180 times.
|
269 | for (int i = 0; i < num_rects; i++) |
361 | 89 | sub2video_copy_rect(dst, dst_linesize, frame->width, frame->height, sub->rects[i]); | |
362 | 180 | sub2video_push_ref(ifp, pts); | |
363 | 180 | ifp->sub2video.end_pts = end_pts; | |
364 | 180 | ifp->sub2video.initialize = 0; | |
365 | } | ||
366 | |||
367 | /* *dst may return be set to NULL (no pixel format found), a static string or a | ||
368 | * string backed by the bprint. Nothing has been written to the AVBPrint in case | ||
369 | * NULL is returned. The AVBPrint provided should be clean. */ | ||
370 | 5232 | static int choose_pix_fmts(OutputFilter *ofilter, AVBPrint *bprint, | |
371 | const char **dst) | ||
372 | { | ||
373 | 5232 | OutputFilterPriv *ofp = ofp_from_ofilter(ofilter); | |
374 | |||
375 | 5232 | *dst = NULL; | |
376 | |||
377 |
3/4✓ Branch 0 taken 5232 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3779 times.
✓ Branch 3 taken 1453 times.
|
5232 | if (ofp->flags & OFILTER_FLAG_DISABLE_CONVERT || ofp->format != AV_PIX_FMT_NONE) { |
378 |
1/2✓ Branch 0 taken 3779 times.
✗ Branch 1 not taken.
|
7558 | *dst = ofp->format == AV_PIX_FMT_NONE ? NULL : |
379 | 3779 | av_get_pix_fmt_name(ofp->format); | |
380 |
2/2✓ Branch 0 taken 339 times.
✓ Branch 1 taken 1114 times.
|
1453 | } else if (ofp->formats) { |
381 | 339 | const enum AVPixelFormat *p = ofp->formats; | |
382 | |||
383 |
2/2✓ Branch 0 taken 1920 times.
✓ Branch 1 taken 339 times.
|
2259 | for (; *p != AV_PIX_FMT_NONE; p++) { |
384 | 1920 | const char *name = av_get_pix_fmt_name(*p); | |
385 |
2/2✓ Branch 0 taken 339 times.
✓ Branch 1 taken 1581 times.
|
1920 | av_bprintf(bprint, "%s%c", name, p[1] == AV_PIX_FMT_NONE ? '\0' : '|'); |
386 | } | ||
387 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 339 times.
|
339 | if (!av_bprint_is_complete(bprint)) |
388 | ✗ | return AVERROR(ENOMEM); | |
389 | |||
390 | 339 | *dst = bprint->str; | |
391 | } | ||
392 | |||
393 | 5232 | return 0; | |
394 | } | ||
395 | |||
396 | /* Define a function for appending a list of allowed formats | ||
397 | * to an AVBPrint. If nonempty, the list will have a header. */ | ||
398 | #define DEF_CHOOSE_FORMAT(name, type, var, supported_list, none, printf_format, get_name) \ | ||
399 | static void choose_ ## name (OutputFilterPriv *ofp, AVBPrint *bprint) \ | ||
400 | { \ | ||
401 | if (ofp->var == none && !ofp->supported_list) \ | ||
402 | return; \ | ||
403 | av_bprintf(bprint, #name "="); \ | ||
404 | if (ofp->var != none) { \ | ||
405 | av_bprintf(bprint, printf_format, get_name(ofp->var)); \ | ||
406 | } else { \ | ||
407 | const type *p; \ | ||
408 | \ | ||
409 | for (p = ofp->supported_list; *p != none; p++) { \ | ||
410 | av_bprintf(bprint, printf_format "|", get_name(*p)); \ | ||
411 | } \ | ||
412 | if (bprint->len > 0) \ | ||
413 | bprint->str[--bprint->len] = '\0'; \ | ||
414 | } \ | ||
415 | av_bprint_chars(bprint, ':', 1); \ | ||
416 | } | ||
417 | |||
418 | //DEF_CHOOSE_FORMAT(pix_fmts, enum AVPixelFormat, format, formats, AV_PIX_FMT_NONE, | ||
419 | // GET_PIX_FMT_NAME) | ||
420 | |||
421 |
8/10✓ Branch 0 taken 1242 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1242 times.
✓ Branch 5 taken 1 times.
✓ Branch 6 taken 1242 times.
✓ Branch 11 taken 1327 times.
✓ Branch 12 taken 1242 times.
✓ Branch 13 taken 1242 times.
✗ Branch 14 not taken.
|
2570 | DEF_CHOOSE_FORMAT(sample_fmts, enum AVSampleFormat, format, formats, |
422 | AV_SAMPLE_FMT_NONE, "%s", av_get_sample_fmt_name) | ||
423 | |||
424 |
9/10✓ Branch 0 taken 1228 times.
✓ Branch 1 taken 15 times.
✓ Branch 2 taken 1175 times.
✓ Branch 3 taken 53 times.
✓ Branch 5 taken 15 times.
✓ Branch 6 taken 53 times.
✓ Branch 9 taken 321 times.
✓ Branch 10 taken 53 times.
✓ Branch 11 taken 53 times.
✗ Branch 12 not taken.
|
1564 | DEF_CHOOSE_FORMAT(sample_rates, int, sample_rate, sample_rates, 0, |
425 | "%d", ) | ||
426 | |||
427 | 1243 | static void choose_channel_layouts(OutputFilterPriv *ofp, AVBPrint *bprint) | |
428 | { | ||
429 |
2/2✓ Branch 1 taken 12 times.
✓ Branch 2 taken 1231 times.
|
1243 | if (av_channel_layout_check(&ofp->ch_layout)) { |
430 | 12 | av_bprintf(bprint, "channel_layouts="); | |
431 | 12 | av_channel_layout_describe_bprint(&ofp->ch_layout, bprint); | |
432 |
2/2✓ Branch 0 taken 78 times.
✓ Branch 1 taken 1153 times.
|
1231 | } else if (ofp->ch_layouts) { |
433 | const AVChannelLayout *p; | ||
434 | |||
435 | 78 | av_bprintf(bprint, "channel_layouts="); | |
436 |
2/2✓ Branch 0 taken 370 times.
✓ Branch 1 taken 78 times.
|
448 | for (p = ofp->ch_layouts; p->nb_channels; p++) { |
437 | 370 | av_channel_layout_describe_bprint(p, bprint); | |
438 | 370 | av_bprintf(bprint, "|"); | |
439 | } | ||
440 |
1/2✓ Branch 0 taken 78 times.
✗ Branch 1 not taken.
|
78 | if (bprint->len > 0) |
441 | 78 | bprint->str[--bprint->len] = '\0'; | |
442 | } else | ||
443 | 1153 | return; | |
444 | 90 | av_bprint_chars(bprint, ':', 1); | |
445 | } | ||
446 | |||
447 | ✗ | static int read_binary(const char *path, uint8_t **data, int *len) | |
448 | { | ||
449 | ✗ | AVIOContext *io = NULL; | |
450 | int64_t fsize; | ||
451 | int ret; | ||
452 | |||
453 | ✗ | *data = NULL; | |
454 | ✗ | *len = 0; | |
455 | |||
456 | ✗ | ret = avio_open2(&io, path, AVIO_FLAG_READ, &int_cb, NULL); | |
457 | ✗ | if (ret < 0) { | |
458 | ✗ | av_log(NULL, AV_LOG_ERROR, "Cannot open file '%s': %s\n", | |
459 | ✗ | path, av_err2str(ret)); | |
460 | ✗ | return ret; | |
461 | } | ||
462 | |||
463 | ✗ | fsize = avio_size(io); | |
464 | ✗ | if (fsize < 0 || fsize > INT_MAX) { | |
465 | ✗ | av_log(NULL, AV_LOG_ERROR, "Cannot obtain size of file %s\n", path); | |
466 | ✗ | ret = AVERROR(EIO); | |
467 | ✗ | goto fail; | |
468 | } | ||
469 | |||
470 | ✗ | *data = av_malloc(fsize); | |
471 | ✗ | if (!*data) { | |
472 | ✗ | ret = AVERROR(ENOMEM); | |
473 | ✗ | goto fail; | |
474 | } | ||
475 | |||
476 | ✗ | ret = avio_read(io, *data, fsize); | |
477 | ✗ | if (ret != fsize) { | |
478 | ✗ | av_log(NULL, AV_LOG_ERROR, "Error reading file %s\n", path); | |
479 | ✗ | ret = ret < 0 ? ret : AVERROR(EIO); | |
480 | ✗ | goto fail; | |
481 | } | ||
482 | |||
483 | ✗ | *len = fsize; | |
484 | |||
485 | ✗ | ret = 0; | |
486 | ✗ | fail: | |
487 | ✗ | avio_close(io); | |
488 | ✗ | if (ret < 0) { | |
489 | ✗ | av_freep(data); | |
490 | ✗ | *len = 0; | |
491 | } | ||
492 | ✗ | return ret; | |
493 | } | ||
494 | |||
495 | 19831 | static int filter_opt_apply(AVFilterContext *f, const char *key, const char *val) | |
496 | { | ||
497 | 19831 | const AVOption *o = NULL; | |
498 | int ret; | ||
499 | |||
500 | 19831 | ret = av_opt_set(f, key, val, AV_OPT_SEARCH_CHILDREN); | |
501 |
1/2✓ Branch 0 taken 19831 times.
✗ Branch 1 not taken.
|
19831 | if (ret >= 0) |
502 | 19831 | return 0; | |
503 | |||
504 | ✗ | if (ret == AVERROR_OPTION_NOT_FOUND && key[0] == '/') | |
505 | ✗ | o = av_opt_find(f, key + 1, NULL, 0, AV_OPT_SEARCH_CHILDREN); | |
506 | ✗ | if (!o) | |
507 | ✗ | goto err_apply; | |
508 | |||
509 | // key is a valid option name prefixed with '/' | ||
510 | // interpret value as a path from which to load the actual option value | ||
511 | ✗ | key++; | |
512 | |||
513 | ✗ | if (o->type == AV_OPT_TYPE_BINARY) { | |
514 | uint8_t *data; | ||
515 | int len; | ||
516 | |||
517 | ✗ | ret = read_binary(val, &data, &len); | |
518 | ✗ | if (ret < 0) | |
519 | ✗ | goto err_load; | |
520 | |||
521 | ✗ | ret = av_opt_set_bin(f, key, data, len, AV_OPT_SEARCH_CHILDREN); | |
522 | ✗ | av_freep(&data); | |
523 | } else { | ||
524 | ✗ | char *data = file_read(val); | |
525 | ✗ | if (!data) { | |
526 | ✗ | ret = AVERROR(EIO); | |
527 | ✗ | goto err_load; | |
528 | } | ||
529 | |||
530 | ✗ | ret = av_opt_set(f, key, data, AV_OPT_SEARCH_CHILDREN); | |
531 | ✗ | av_freep(&data); | |
532 | } | ||
533 | ✗ | if (ret < 0) | |
534 | ✗ | goto err_apply; | |
535 | |||
536 | ✗ | return 0; | |
537 | |||
538 | ✗ | err_apply: | |
539 | ✗ | av_log(NULL, AV_LOG_ERROR, | |
540 | "Error applying option '%s' to filter '%s': %s\n", | ||
541 | ✗ | key, f->filter->name, av_err2str(ret)); | |
542 | ✗ | return ret; | |
543 | ✗ | err_load: | |
544 | ✗ | av_log(NULL, AV_LOG_ERROR, | |
545 | "Error loading value for option '%s' from file '%s'\n", | ||
546 | key, val); | ||
547 | ✗ | return ret; | |
548 | } | ||
549 | |||
550 | 12809 | static int graph_opts_apply(AVFilterGraphSegment *seg) | |
551 | { | ||
552 |
2/2✓ Branch 0 taken 13047 times.
✓ Branch 1 taken 12809 times.
|
25856 | for (size_t i = 0; i < seg->nb_chains; i++) { |
553 | 13047 | AVFilterChain *ch = seg->chains[i]; | |
554 | |||
555 |
2/2✓ Branch 0 taken 25412 times.
✓ Branch 1 taken 13047 times.
|
38459 | for (size_t j = 0; j < ch->nb_filters; j++) { |
556 | 25412 | AVFilterParams *p = ch->filters[j]; | |
557 | 25412 | const AVDictionaryEntry *e = NULL; | |
558 | |||
559 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 25412 times.
|
25412 | av_assert0(p->filter); |
560 | |||
561 |
2/2✓ Branch 1 taken 19831 times.
✓ Branch 2 taken 25412 times.
|
45243 | while ((e = av_dict_iterate(p->opts, e))) { |
562 | 19831 | int ret = filter_opt_apply(p->filter, e->key, e->value); | |
563 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 19831 times.
|
19831 | if (ret < 0) |
564 | ✗ | return ret; | |
565 | } | ||
566 | |||
567 | 25412 | av_dict_free(&p->opts); | |
568 | } | ||
569 | } | ||
570 | |||
571 | 12809 | return 0; | |
572 | } | ||
573 | |||
574 | 12809 | static int graph_parse(AVFilterGraph *graph, const char *desc, | |
575 | AVFilterInOut **inputs, AVFilterInOut **outputs, | ||
576 | AVBufferRef *hw_device) | ||
577 | { | ||
578 | AVFilterGraphSegment *seg; | ||
579 | int ret; | ||
580 | |||
581 | 12809 | *inputs = NULL; | |
582 | 12809 | *outputs = NULL; | |
583 | |||
584 | 12809 | ret = avfilter_graph_segment_parse(graph, desc, 0, &seg); | |
585 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 12809 times.
|
12809 | if (ret < 0) |
586 | ✗ | return ret; | |
587 | |||
588 | 12809 | ret = avfilter_graph_segment_create_filters(seg, 0); | |
589 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 12809 times.
|
12809 | if (ret < 0) |
590 | ✗ | goto fail; | |
591 | |||
592 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 12809 times.
|
12809 | if (hw_device) { |
593 | ✗ | for (int i = 0; i < graph->nb_filters; i++) { | |
594 | ✗ | AVFilterContext *f = graph->filters[i]; | |
595 | |||
596 | ✗ | if (!(f->filter->flags & AVFILTER_FLAG_HWDEVICE)) | |
597 | ✗ | continue; | |
598 | ✗ | f->hw_device_ctx = av_buffer_ref(hw_device); | |
599 | ✗ | if (!f->hw_device_ctx) { | |
600 | ✗ | ret = AVERROR(ENOMEM); | |
601 | ✗ | goto fail; | |
602 | } | ||
603 | } | ||
604 | } | ||
605 | |||
606 | 12809 | ret = graph_opts_apply(seg); | |
607 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 12809 times.
|
12809 | if (ret < 0) |
608 | ✗ | goto fail; | |
609 | |||
610 | 12809 | ret = avfilter_graph_segment_apply(seg, 0, inputs, outputs); | |
611 | |||
612 | 12809 | fail: | |
613 | 12809 | avfilter_graph_segment_free(&seg); | |
614 | 12809 | return ret; | |
615 | } | ||
616 | |||
617 | // Filters can be configured only if the formats of all inputs are known. | ||
618 | 12951 | static int ifilter_has_all_input_formats(FilterGraph *fg) | |
619 | { | ||
620 |
2/2✓ Branch 0 taken 13256 times.
✓ Branch 1 taken 6425 times.
|
19681 | for (int i = 0; i < fg->nb_inputs; i++) { |
621 | 13256 | InputFilterPriv *ifp = ifp_from_ifilter(fg->inputs[i]); | |
622 |
2/2✓ Branch 0 taken 6526 times.
✓ Branch 1 taken 6730 times.
|
13256 | if (ifp->format < 0) |
623 | 6526 | return 0; | |
624 | } | ||
625 | 6425 | return 1; | |
626 | } | ||
627 | |||
628 | static int filter_thread(void *arg); | ||
629 | |||
630 | 12833 | static char *describe_filter_link(FilterGraph *fg, AVFilterInOut *inout, int in) | |
631 | { | ||
632 | 12833 | AVFilterContext *ctx = inout->filter_ctx; | |
633 |
2/2✓ Branch 0 taken 6399 times.
✓ Branch 1 taken 6434 times.
|
12833 | AVFilterPad *pads = in ? ctx->input_pads : ctx->output_pads; |
634 |
2/2✓ Branch 0 taken 6399 times.
✓ Branch 1 taken 6434 times.
|
12833 | int nb_pads = in ? ctx->nb_inputs : ctx->nb_outputs; |
635 | |||
636 |
2/2✓ Branch 0 taken 69 times.
✓ Branch 1 taken 12764 times.
|
12833 | if (nb_pads > 1) |
637 | 69 | return av_strdup(ctx->filter->name); | |
638 | 12764 | return av_asprintf("%s:%s", ctx->filter->name, | |
639 | avfilter_pad_get_name(pads, inout->pad_idx)); | ||
640 | } | ||
641 | |||
642 | 3 | static const char *ofilter_item_name(void *obj) | |
643 | { | ||
644 | 3 | OutputFilterPriv *ofp = obj; | |
645 | 3 | return ofp->log_name; | |
646 | } | ||
647 | |||
648 | static const AVClass ofilter_class = { | ||
649 | .class_name = "OutputFilter", | ||
650 | .version = LIBAVUTIL_VERSION_INT, | ||
651 | .item_name = ofilter_item_name, | ||
652 | .parent_log_context_offset = offsetof(OutputFilterPriv, log_parent), | ||
653 | .category = AV_CLASS_CATEGORY_FILTER, | ||
654 | }; | ||
655 | |||
656 | 6434 | static OutputFilter *ofilter_alloc(FilterGraph *fg, enum AVMediaType type) | |
657 | { | ||
658 | OutputFilterPriv *ofp; | ||
659 | OutputFilter *ofilter; | ||
660 | |||
661 | 6434 | ofp = allocate_array_elem(&fg->outputs, sizeof(*ofp), &fg->nb_outputs); | |
662 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6434 times.
|
6434 | if (!ofp) |
663 | ✗ | return NULL; | |
664 | |||
665 | 6434 | ofilter = &ofp->ofilter; | |
666 | 6434 | ofilter->class = &ofilter_class; | |
667 | 6434 | ofp->log_parent = fg; | |
668 | 6434 | ofilter->graph = fg; | |
669 | 6434 | ofilter->type = type; | |
670 | 6434 | ofp->format = -1; | |
671 | 6434 | ofp->index = fg->nb_outputs - 1; | |
672 | |||
673 | 12868 | snprintf(ofp->log_name, sizeof(ofp->log_name), "%co%d", | |
674 | 6434 | av_get_media_type_string(type)[0], ofp->index); | |
675 | |||
676 | 6434 | return ofilter; | |
677 | } | ||
678 | |||
679 | 6398 | static int ifilter_bind_ist(InputFilter *ifilter, InputStream *ist) | |
680 | { | ||
681 | 6398 | InputFilterPriv *ifp = ifp_from_ifilter(ifilter); | |
682 | 6398 | FilterGraphPriv *fgp = fgp_from_fg(ifilter->graph); | |
683 | int ret, dec_idx; | ||
684 | |||
685 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6398 times.
|
6398 | av_assert0(!ifp->bound); |
686 | 6398 | ifp->bound = 1; | |
687 | |||
688 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 6394 times.
|
6398 | if (ifp->type != ist->par->codec_type && |
689 |
2/4✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
|
4 | !(ifp->type == AVMEDIA_TYPE_VIDEO && ist->par->codec_type == AVMEDIA_TYPE_SUBTITLE)) { |
690 | ✗ | av_log(fgp, AV_LOG_ERROR, "Tried to connect %s stream to %s filtergraph input\n", | |
691 | ✗ | av_get_media_type_string(ist->par->codec_type), av_get_media_type_string(ifp->type)); | |
692 | ✗ | return AVERROR(EINVAL); | |
693 | } | ||
694 | |||
695 | 6398 | ifp->type_src = ist->st->codecpar->codec_type; | |
696 | |||
697 | 6398 | ifp->opts.fallback = av_frame_alloc(); | |
698 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6398 times.
|
6398 | if (!ifp->opts.fallback) |
699 | ✗ | return AVERROR(ENOMEM); | |
700 | |||
701 | 6398 | dec_idx = ist_filter_add(ist, ifilter, filtergraph_is_simple(ifilter->graph), | |
702 | &ifp->opts); | ||
703 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6398 times.
|
6398 | if (dec_idx < 0) |
704 | ✗ | return dec_idx; | |
705 | |||
706 | 6398 | ret = sch_connect(fgp->sch, SCH_DEC(dec_idx), | |
707 | 6398 | SCH_FILTER_IN(fgp->sch_idx, ifp->index)); | |
708 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6398 times.
|
6398 | if (ret < 0) |
709 | ✗ | return ret; | |
710 | |||
711 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 6394 times.
|
6398 | if (ifp->type_src == AVMEDIA_TYPE_SUBTITLE) { |
712 | 4 | ifp->sub2video.frame = av_frame_alloc(); | |
713 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
|
4 | if (!ifp->sub2video.frame) |
714 | ✗ | return AVERROR(ENOMEM); | |
715 | |||
716 | 4 | ifp->width = ifp->opts.sub2video_width; | |
717 | 4 | ifp->height = ifp->opts.sub2video_height; | |
718 | |||
719 | /* rectangles are AV_PIX_FMT_PAL8, but we have no guarantee that the | ||
720 | palettes for all rectangles are identical or compatible */ | ||
721 | 4 | ifp->format = AV_PIX_FMT_RGB32; | |
722 | |||
723 | 4 | ifp->time_base = AV_TIME_BASE_Q; | |
724 | |||
725 | 4 | av_log(fgp, AV_LOG_VERBOSE, "sub2video: using %dx%d canvas\n", | |
726 | ifp->width, ifp->height); | ||
727 | } | ||
728 | |||
729 | 6398 | return 0; | |
730 | } | ||
731 | |||
732 | 1 | static int ifilter_bind_dec(InputFilterPriv *ifp, Decoder *dec) | |
733 | { | ||
734 | 1 | FilterGraphPriv *fgp = fgp_from_fg(ifp->ifilter.graph); | |
735 | int ret, dec_idx; | ||
736 | |||
737 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | av_assert0(!ifp->bound); |
738 | 1 | ifp->bound = 1; | |
739 | |||
740 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (ifp->type != dec->type) { |
741 | ✗ | av_log(fgp, AV_LOG_ERROR, "Tried to connect %s decoder to %s filtergraph input\n", | |
742 | av_get_media_type_string(dec->type), av_get_media_type_string(ifp->type)); | ||
743 | ✗ | return AVERROR(EINVAL); | |
744 | } | ||
745 | |||
746 | 1 | ifp->type_src = ifp->type; | |
747 | |||
748 | 1 | dec_idx = dec_filter_add(dec, &ifp->ifilter, &ifp->opts); | |
749 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (dec_idx < 0) |
750 | ✗ | return dec_idx; | |
751 | |||
752 | 1 | ret = sch_connect(fgp->sch, SCH_DEC(dec_idx), | |
753 | 1 | SCH_FILTER_IN(fgp->sch_idx, ifp->index)); | |
754 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (ret < 0) |
755 | ✗ | return ret; | |
756 | |||
757 | 1 | return 0; | |
758 | } | ||
759 | |||
760 | 11 | static int set_channel_layout(OutputFilterPriv *f, const AVChannelLayout *layouts_allowed, | |
761 | const AVChannelLayout *layout_requested) | ||
762 | { | ||
763 | int i, err; | ||
764 | |||
765 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 10 times.
|
11 | if (layout_requested->order != AV_CHANNEL_ORDER_UNSPEC) { |
766 | /* Pass the layout through for all orders but UNSPEC */ | ||
767 | 1 | err = av_channel_layout_copy(&f->ch_layout, layout_requested); | |
768 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (err < 0) |
769 | ✗ | return err; | |
770 | 1 | return 0; | |
771 | } | ||
772 | |||
773 | /* Requested layout is of order UNSPEC */ | ||
774 |
1/2✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
|
10 | if (!layouts_allowed) { |
775 | /* Use the default native layout for the requested amount of channels when the | ||
776 | encoder doesn't have a list of supported layouts */ | ||
777 | 10 | av_channel_layout_default(&f->ch_layout, layout_requested->nb_channels); | |
778 | 10 | return 0; | |
779 | } | ||
780 | /* Encoder has a list of supported layouts. Pick the first layout in it with the | ||
781 | same amount of channels as the requested layout */ | ||
782 | ✗ | for (i = 0; layouts_allowed[i].nb_channels; i++) { | |
783 | ✗ | if (layouts_allowed[i].nb_channels == layout_requested->nb_channels) | |
784 | ✗ | break; | |
785 | } | ||
786 | ✗ | if (layouts_allowed[i].nb_channels) { | |
787 | /* Use it if one is found */ | ||
788 | ✗ | err = av_channel_layout_copy(&f->ch_layout, &layouts_allowed[i]); | |
789 | ✗ | if (err < 0) | |
790 | ✗ | return err; | |
791 | ✗ | return 0; | |
792 | } | ||
793 | /* If no layout for the amount of channels requested was found, use the default | ||
794 | native layout for it. */ | ||
795 | ✗ | av_channel_layout_default(&f->ch_layout, layout_requested->nb_channels); | |
796 | |||
797 | ✗ | return 0; | |
798 | } | ||
799 | |||
800 | 6434 | int ofilter_bind_ost(OutputFilter *ofilter, OutputStream *ost, | |
801 | unsigned sched_idx_enc, | ||
802 | const OutputFilterOptions *opts) | ||
803 | { | ||
804 | 6434 | OutputFilterPriv *ofp = ofp_from_ofilter(ofilter); | |
805 | 6434 | FilterGraph *fg = ofilter->graph; | |
806 | 6434 | FilterGraphPriv *fgp = fgp_from_fg(fg); | |
807 | int ret; | ||
808 | |||
809 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6434 times.
|
6434 | av_assert0(!ofilter->bound); |
810 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6434 times.
|
6434 | av_assert0(ofilter->type == ost->type); |
811 | |||
812 | 6434 | ofilter->bound = 1; | |
813 | 6434 | av_freep(&ofilter->linklabel); | |
814 | |||
815 | 6434 | ofp->flags = opts->flags; | |
816 | 6434 | ofp->ts_offset = opts->ts_offset; | |
817 | 6434 | ofp->enc_timebase = opts->output_tb; | |
818 | |||
819 | 6434 | ofp->trim_start_us = opts->trim_start_us; | |
820 | 6434 | ofp->trim_duration_us = opts->trim_duration_us; | |
821 | |||
822 | 6434 | ofp->name = av_strdup(opts->name); | |
823 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6434 times.
|
6434 | if (!ofp->name) |
824 | ✗ | return AVERROR(EINVAL); | |
825 | |||
826 | 6434 | ret = av_dict_copy(&ofp->sws_opts, opts->sws_opts, 0); | |
827 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6434 times.
|
6434 | if (ret < 0) |
828 | ✗ | return ret; | |
829 | |||
830 | 6434 | ret = av_dict_copy(&ofp->swr_opts, opts->swr_opts, 0); | |
831 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6434 times.
|
6434 | if (ret < 0) |
832 | ✗ | return ret; | |
833 | |||
834 |
2/2✓ Branch 0 taken 59 times.
✓ Branch 1 taken 6375 times.
|
6434 | if (opts->flags & OFILTER_FLAG_AUDIO_24BIT) |
835 | 59 | av_dict_set(&ofp->swr_opts, "output_sample_bits", "24", 0); | |
836 | |||
837 |
2/2✓ Branch 0 taken 6267 times.
✓ Branch 1 taken 167 times.
|
6434 | if (fgp->is_simple) { |
838 | // for simple filtergraph there is just one output, | ||
839 | // so use only graph-level information for logging | ||
840 | 6267 | ofp->log_parent = NULL; | |
841 | 6267 | av_strlcpy(ofp->log_name, fgp->log_name, sizeof(ofp->log_name)); | |
842 | } else | ||
843 | 167 | av_strlcatf(ofp->log_name, sizeof(ofp->log_name), "->%s", ofp->name); | |
844 | |||
845 |
2/3✓ Branch 0 taken 5192 times.
✓ Branch 1 taken 1242 times.
✗ Branch 2 not taken.
|
6434 | switch (ofilter->type) { |
846 | 5192 | case AVMEDIA_TYPE_VIDEO: | |
847 | 5192 | ofp->width = opts->width; | |
848 | 5192 | ofp->height = opts->height; | |
849 |
2/2✓ Branch 0 taken 3739 times.
✓ Branch 1 taken 1453 times.
|
5192 | if (opts->format != AV_PIX_FMT_NONE) { |
850 | 3739 | ofp->format = opts->format; | |
851 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1451 times.
|
1453 | } else if (opts->pix_fmts) |
852 | 2 | ofp->formats = opts->pix_fmts; | |
853 |
1/2✓ Branch 0 taken 1451 times.
✗ Branch 1 not taken.
|
1451 | else if (opts->enc) |
854 | 1451 | ofp->formats = opts->enc->pix_fmts; | |
855 | |||
856 | 5192 | fgp->disable_conversions |= !!(ofp->flags & OFILTER_FLAG_DISABLE_CONVERT); | |
857 | |||
858 | 5192 | ofp->fps.last_frame = av_frame_alloc(); | |
859 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5192 times.
|
5192 | if (!ofp->fps.last_frame) |
860 | ✗ | return AVERROR(ENOMEM); | |
861 | |||
862 | 5192 | ofp->fps.vsync_method = opts->vsync_method; | |
863 | 5192 | ofp->fps.framerate = ost->frame_rate; | |
864 | 5192 | ofp->fps.framerate_max = ost->max_frame_rate; | |
865 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | ofp->fps.framerate_supported = ost->force_fps && opts->enc ? |
866 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 5191 times.
|
5193 | NULL : opts->enc->supported_framerates; |
867 | |||
868 | // reduce frame rate for mpeg4 to be within the spec limits | ||
869 |
3/4✓ Branch 0 taken 5192 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 60 times.
✓ Branch 3 taken 5132 times.
|
5192 | if (opts->enc && opts->enc->id == AV_CODEC_ID_MPEG4) |
870 | 60 | ofp->fps.framerate_clip = 65535; | |
871 | |||
872 | 5192 | ofp->fps.dup_warning = 1000; | |
873 | |||
874 | 5192 | break; | |
875 | 1242 | case AVMEDIA_TYPE_AUDIO: | |
876 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1242 times.
|
1242 | if (opts->format != AV_SAMPLE_FMT_NONE) { |
877 | ✗ | ofp->format = opts->format; | |
878 |
1/2✓ Branch 0 taken 1242 times.
✗ Branch 1 not taken.
|
1242 | } else if (opts->enc) { |
879 | 1242 | ofp->formats = opts->enc->sample_fmts; | |
880 | } | ||
881 |
2/2✓ Branch 0 taken 14 times.
✓ Branch 1 taken 1228 times.
|
1242 | if (opts->sample_rate) { |
882 | 14 | ofp->sample_rate = opts->sample_rate; | |
883 |
1/2✓ Branch 0 taken 1228 times.
✗ Branch 1 not taken.
|
1228 | } else if (opts->enc) { |
884 | 1228 | ofp->sample_rates = opts->enc->supported_samplerates; | |
885 | } | ||
886 |
2/2✓ Branch 0 taken 11 times.
✓ Branch 1 taken 1231 times.
|
1242 | if (opts->ch_layout.nb_channels) { |
887 |
1/2✓ Branch 0 taken 11 times.
✗ Branch 1 not taken.
|
11 | int ret = set_channel_layout(ofp, opts->enc ? opts->enc->ch_layouts : NULL, |
888 | &opts->ch_layout); | ||
889 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
|
11 | if (ret < 0) |
890 | ✗ | return ret; | |
891 |
1/2✓ Branch 0 taken 1231 times.
✗ Branch 1 not taken.
|
1231 | } else if (opts->enc) { |
892 | 1231 | ofp->ch_layouts = opts->enc->ch_layouts; | |
893 | } | ||
894 | 1242 | break; | |
895 | } | ||
896 | |||
897 | 6434 | ret = sch_connect(fgp->sch, SCH_FILTER_OUT(fgp->sch_idx, ofp->index), | |
898 | 6434 | SCH_ENC(sched_idx_enc)); | |
899 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6434 times.
|
6434 | if (ret < 0) |
900 | ✗ | return ret; | |
901 | |||
902 | 6434 | return 0; | |
903 | } | ||
904 | |||
905 | ✗ | static int ofilter_bind_ifilter(OutputFilter *ofilter, InputFilterPriv *ifp, | |
906 | const OutputFilterOptions *opts) | ||
907 | { | ||
908 | ✗ | OutputFilterPriv *ofp = ofp_from_ofilter(ofilter); | |
909 | |||
910 | ✗ | av_assert0(!ofilter->bound); | |
911 | ✗ | av_assert0(ofilter->type == ifp->type); | |
912 | |||
913 | ✗ | ofilter->bound = 1; | |
914 | ✗ | av_freep(&ofilter->linklabel); | |
915 | |||
916 | ✗ | ofp->name = av_strdup(opts->name); | |
917 | ✗ | if (!ofp->name) | |
918 | ✗ | return AVERROR(EINVAL); | |
919 | |||
920 | ✗ | av_strlcatf(ofp->log_name, sizeof(ofp->log_name), "->%s", ofp->name); | |
921 | |||
922 | ✗ | return 0; | |
923 | } | ||
924 | |||
925 | ✗ | static int ifilter_bind_fg(InputFilterPriv *ifp, FilterGraph *fg_src, int out_idx) | |
926 | { | ||
927 | ✗ | FilterGraphPriv *fgp = fgp_from_fg(ifp->ifilter.graph); | |
928 | ✗ | OutputFilter *ofilter_src = fg_src->outputs[out_idx]; | |
929 | OutputFilterOptions opts; | ||
930 | char name[32]; | ||
931 | int ret; | ||
932 | |||
933 | ✗ | av_assert0(!ifp->bound); | |
934 | ✗ | ifp->bound = 1; | |
935 | |||
936 | ✗ | if (ifp->type != ofilter_src->type) { | |
937 | ✗ | av_log(fgp, AV_LOG_ERROR, "Tried to connect %s output to %s input\n", | |
938 | av_get_media_type_string(ofilter_src->type), | ||
939 | av_get_media_type_string(ifp->type)); | ||
940 | ✗ | return AVERROR(EINVAL); | |
941 | } | ||
942 | |||
943 | ✗ | ifp->type_src = ifp->type; | |
944 | |||
945 | ✗ | memset(&opts, 0, sizeof(opts)); | |
946 | |||
947 | ✗ | snprintf(name, sizeof(name), "fg:%d:%d", fgp->fg.index, ifp->index); | |
948 | ✗ | opts.name = name; | |
949 | |||
950 | ✗ | ret = ofilter_bind_ifilter(ofilter_src, ifp, &opts); | |
951 | ✗ | if (ret < 0) | |
952 | ✗ | return ret; | |
953 | |||
954 | ✗ | ret = sch_connect(fgp->sch, SCH_FILTER_OUT(fg_src->index, out_idx), | |
955 | ✗ | SCH_FILTER_IN(fgp->sch_idx, ifp->index)); | |
956 | ✗ | if (ret < 0) | |
957 | ✗ | return ret; | |
958 | |||
959 | ✗ | return 0; | |
960 | } | ||
961 | |||
962 | 6399 | static InputFilter *ifilter_alloc(FilterGraph *fg) | |
963 | { | ||
964 | InputFilterPriv *ifp; | ||
965 | InputFilter *ifilter; | ||
966 | |||
967 | 6399 | ifp = allocate_array_elem(&fg->inputs, sizeof(*ifp), &fg->nb_inputs); | |
968 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6399 times.
|
6399 | if (!ifp) |
969 | ✗ | return NULL; | |
970 | |||
971 | 6399 | ifilter = &ifp->ifilter; | |
972 | 6399 | ifilter->graph = fg; | |
973 | |||
974 | 6399 | ifp->frame = av_frame_alloc(); | |
975 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6399 times.
|
6399 | if (!ifp->frame) |
976 | ✗ | return NULL; | |
977 | |||
978 | 6399 | ifp->index = fg->nb_inputs - 1; | |
979 | 6399 | ifp->format = -1; | |
980 | 6399 | ifp->color_space = AVCOL_SPC_UNSPECIFIED; | |
981 | 6399 | ifp->color_range = AVCOL_RANGE_UNSPECIFIED; | |
982 | |||
983 | 6399 | ifp->frame_queue = av_fifo_alloc2(8, sizeof(AVFrame*), AV_FIFO_FLAG_AUTO_GROW); | |
984 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6399 times.
|
6399 | if (!ifp->frame_queue) |
985 | ✗ | return NULL; | |
986 | |||
987 | 6399 | return ifilter; | |
988 | } | ||
989 | |||
990 | 7225 | void fg_free(FilterGraph **pfg) | |
991 | { | ||
992 | 7225 | FilterGraph *fg = *pfg; | |
993 | FilterGraphPriv *fgp; | ||
994 | |||
995 |
2/2✓ Branch 0 taken 841 times.
✓ Branch 1 taken 6384 times.
|
7225 | if (!fg) |
996 | 841 | return; | |
997 | 6384 | fgp = fgp_from_fg(fg); | |
998 | |||
999 |
2/2✓ Branch 0 taken 6399 times.
✓ Branch 1 taken 6384 times.
|
12783 | for (int j = 0; j < fg->nb_inputs; j++) { |
1000 | 6399 | InputFilter *ifilter = fg->inputs[j]; | |
1001 | 6399 | InputFilterPriv *ifp = ifp_from_ifilter(ifilter); | |
1002 | |||
1003 |
1/2✓ Branch 0 taken 6399 times.
✗ Branch 1 not taken.
|
6399 | if (ifp->frame_queue) { |
1004 | AVFrame *frame; | ||
1005 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 6399 times.
|
6399 | while (av_fifo_read(ifp->frame_queue, &frame, 1) >= 0) |
1006 | ✗ | av_frame_free(&frame); | |
1007 | 6399 | av_fifo_freep2(&ifp->frame_queue); | |
1008 | } | ||
1009 | 6399 | av_frame_free(&ifp->sub2video.frame); | |
1010 | |||
1011 | 6399 | av_frame_free(&ifp->frame); | |
1012 | 6399 | av_frame_free(&ifp->opts.fallback); | |
1013 | |||
1014 | 6399 | av_buffer_unref(&ifp->hw_frames_ctx); | |
1015 | 6399 | av_freep(&ifp->linklabel); | |
1016 | 6399 | av_freep(&ifp->opts.name); | |
1017 | 6399 | av_freep(&ifilter->name); | |
1018 | 6399 | av_freep(&fg->inputs[j]); | |
1019 | } | ||
1020 | 6384 | av_freep(&fg->inputs); | |
1021 |
2/2✓ Branch 0 taken 6434 times.
✓ Branch 1 taken 6384 times.
|
12818 | for (int j = 0; j < fg->nb_outputs; j++) { |
1022 | 6434 | OutputFilter *ofilter = fg->outputs[j]; | |
1023 | 6434 | OutputFilterPriv *ofp = ofp_from_ofilter(ofilter); | |
1024 | |||
1025 | 6434 | av_frame_free(&ofp->fps.last_frame); | |
1026 | 6434 | av_dict_free(&ofp->sws_opts); | |
1027 | 6434 | av_dict_free(&ofp->swr_opts); | |
1028 | |||
1029 | 6434 | av_freep(&ofilter->linklabel); | |
1030 | 6434 | av_freep(&ofilter->name); | |
1031 | 6434 | av_freep(&ofilter->apad); | |
1032 | 6434 | av_freep(&ofp->name); | |
1033 | 6434 | av_channel_layout_uninit(&ofp->ch_layout); | |
1034 | 6434 | av_freep(&fg->outputs[j]); | |
1035 | } | ||
1036 | 6384 | av_freep(&fg->outputs); | |
1037 | 6384 | av_freep(&fgp->graph_desc); | |
1038 | 6384 | av_freep(&fgp->nb_threads); | |
1039 | |||
1040 | 6384 | av_frame_free(&fgp->frame); | |
1041 | 6384 | av_frame_free(&fgp->frame_enc); | |
1042 | |||
1043 | 6384 | av_freep(pfg); | |
1044 | } | ||
1045 | |||
1046 | 49 | static const char *fg_item_name(void *obj) | |
1047 | { | ||
1048 | 49 | const FilterGraphPriv *fgp = obj; | |
1049 | |||
1050 | 49 | return fgp->log_name; | |
1051 | } | ||
1052 | |||
1053 | static const AVClass fg_class = { | ||
1054 | .class_name = "FilterGraph", | ||
1055 | .version = LIBAVUTIL_VERSION_INT, | ||
1056 | .item_name = fg_item_name, | ||
1057 | .category = AV_CLASS_CATEGORY_FILTER, | ||
1058 | }; | ||
1059 | |||
1060 | 6384 | int fg_create(FilterGraph **pfg, char *graph_desc, Scheduler *sch) | |
1061 | { | ||
1062 | FilterGraphPriv *fgp; | ||
1063 | FilterGraph *fg; | ||
1064 | |||
1065 | AVFilterInOut *inputs, *outputs; | ||
1066 | AVFilterGraph *graph; | ||
1067 | 6384 | int ret = 0; | |
1068 | |||
1069 | 6384 | fgp = av_mallocz(sizeof(*fgp)); | |
1070 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6384 times.
|
6384 | if (!fgp) |
1071 | ✗ | return AVERROR(ENOMEM); | |
1072 | 6384 | fg = &fgp->fg; | |
1073 | |||
1074 |
2/2✓ Branch 0 taken 6267 times.
✓ Branch 1 taken 117 times.
|
6384 | if (pfg) { |
1075 | 6267 | *pfg = fg; | |
1076 | 6267 | fg->index = -1; | |
1077 | } else { | ||
1078 | 117 | ret = av_dynarray_add_nofree(&filtergraphs, &nb_filtergraphs, fgp); | |
1079 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 117 times.
|
117 | if (ret < 0) { |
1080 | ✗ | av_freep(&fgp); | |
1081 | ✗ | return ret; | |
1082 | } | ||
1083 | |||
1084 | 117 | fg->index = nb_filtergraphs - 1; | |
1085 | } | ||
1086 | |||
1087 | 6384 | fg->class = &fg_class; | |
1088 | 6384 | fgp->graph_desc = graph_desc; | |
1089 | 6384 | fgp->disable_conversions = !auto_conversion_filters; | |
1090 | 6384 | fgp->sch = sch; | |
1091 | |||
1092 | 6384 | snprintf(fgp->log_name, sizeof(fgp->log_name), "fc#%d", fg->index); | |
1093 | |||
1094 | 6384 | fgp->frame = av_frame_alloc(); | |
1095 | 6384 | fgp->frame_enc = av_frame_alloc(); | |
1096 |
2/4✓ Branch 0 taken 6384 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 6384 times.
|
6384 | if (!fgp->frame || !fgp->frame_enc) |
1097 | ✗ | return AVERROR(ENOMEM); | |
1098 | |||
1099 | /* this graph is only used for determining the kinds of inputs | ||
1100 | * and outputs we have, and is discarded on exit from this function */ | ||
1101 | 6384 | graph = avfilter_graph_alloc(); | |
1102 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6384 times.
|
6384 | if (!graph) |
1103 | ✗ | return AVERROR(ENOMEM);; | |
1104 | 6384 | graph->nb_threads = 1; | |
1105 | |||
1106 | 6384 | ret = graph_parse(graph, fgp->graph_desc, &inputs, &outputs, NULL); | |
1107 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6384 times.
|
6384 | if (ret < 0) |
1108 | ✗ | goto fail; | |
1109 | |||
1110 |
2/2✓ Branch 0 taken 12559 times.
✓ Branch 1 taken 6319 times.
|
18878 | for (unsigned i = 0; i < graph->nb_filters; i++) { |
1111 | 12559 | const AVFilter *f = graph->filters[i]->filter; | |
1112 |
2/2✓ Branch 1 taken 83 times.
✓ Branch 2 taken 12476 times.
|
12559 | if (!avfilter_filter_pad_count(f, 0) && |
1113 |
2/2✓ Branch 0 taken 65 times.
✓ Branch 1 taken 18 times.
|
83 | !(f->flags & AVFILTER_FLAG_DYNAMIC_INPUTS)) { |
1114 | 65 | fgp->have_sources = 1; | |
1115 | 65 | break; | |
1116 | } | ||
1117 | } | ||
1118 | |||
1119 |
2/2✓ Branch 0 taken 6399 times.
✓ Branch 1 taken 6384 times.
|
12783 | for (AVFilterInOut *cur = inputs; cur; cur = cur->next) { |
1120 | 6399 | InputFilter *const ifilter = ifilter_alloc(fg); | |
1121 | InputFilterPriv *ifp; | ||
1122 | |||
1123 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6399 times.
|
6399 | if (!ifilter) { |
1124 | ✗ | ret = AVERROR(ENOMEM); | |
1125 | ✗ | goto fail; | |
1126 | } | ||
1127 | |||
1128 | 6399 | ifp = ifp_from_ifilter(ifilter); | |
1129 | 6399 | ifp->linklabel = cur->name; | |
1130 | 6399 | cur->name = NULL; | |
1131 | |||
1132 | 6399 | ifp->type = avfilter_pad_get_type(cur->filter_ctx->input_pads, | |
1133 | cur->pad_idx); | ||
1134 | |||
1135 |
3/4✓ Branch 0 taken 1240 times.
✓ Branch 1 taken 5159 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1240 times.
|
6399 | if (ifp->type != AVMEDIA_TYPE_VIDEO && ifp->type != AVMEDIA_TYPE_AUDIO) { |
1136 | ✗ | av_log(fg, AV_LOG_FATAL, "Only video and audio filters supported " | |
1137 | "currently.\n"); | ||
1138 | ✗ | ret = AVERROR(ENOSYS); | |
1139 | ✗ | goto fail; | |
1140 | } | ||
1141 | |||
1142 | 6399 | ifilter->name = describe_filter_link(fg, cur, 1); | |
1143 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6399 times.
|
6399 | if (!ifilter->name) { |
1144 | ✗ | ret = AVERROR(ENOMEM); | |
1145 | ✗ | goto fail; | |
1146 | } | ||
1147 | } | ||
1148 | |||
1149 |
2/2✓ Branch 0 taken 6434 times.
✓ Branch 1 taken 6384 times.
|
12818 | for (AVFilterInOut *cur = outputs; cur; cur = cur->next) { |
1150 | 6434 | const enum AVMediaType type = avfilter_pad_get_type(cur->filter_ctx->output_pads, | |
1151 | cur->pad_idx); | ||
1152 | 6434 | OutputFilter *const ofilter = ofilter_alloc(fg, type); | |
1153 | |||
1154 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6434 times.
|
6434 | if (!ofilter) { |
1155 | ✗ | ret = AVERROR(ENOMEM); | |
1156 | ✗ | goto fail; | |
1157 | } | ||
1158 | |||
1159 | 6434 | ofilter->linklabel = cur->name; | |
1160 | 6434 | cur->name = NULL; | |
1161 | |||
1162 | 6434 | ofilter->name = describe_filter_link(fg, cur, 0); | |
1163 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6434 times.
|
6434 | if (!ofilter->name) { |
1164 | ✗ | ret = AVERROR(ENOMEM); | |
1165 | ✗ | goto fail; | |
1166 | } | ||
1167 | } | ||
1168 | |||
1169 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6384 times.
|
6384 | if (!fg->nb_outputs) { |
1170 | ✗ | av_log(fg, AV_LOG_FATAL, "A filtergraph has zero outputs, this is not supported\n"); | |
1171 | ✗ | ret = AVERROR(ENOSYS); | |
1172 | ✗ | goto fail; | |
1173 | } | ||
1174 | |||
1175 | 6384 | ret = sch_add_filtergraph(sch, fg->nb_inputs, fg->nb_outputs, | |
1176 | filter_thread, fgp); | ||
1177 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6384 times.
|
6384 | if (ret < 0) |
1178 | ✗ | goto fail; | |
1179 | 6384 | fgp->sch_idx = ret; | |
1180 | |||
1181 | 6384 | fail: | |
1182 | 6384 | avfilter_inout_free(&inputs); | |
1183 | 6384 | avfilter_inout_free(&outputs); | |
1184 | 6384 | avfilter_graph_free(&graph); | |
1185 | |||
1186 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6384 times.
|
6384 | if (ret < 0) |
1187 | ✗ | return ret; | |
1188 | |||
1189 | 6384 | return 0; | |
1190 | } | ||
1191 | |||
1192 | 6267 | int init_simple_filtergraph(InputStream *ist, OutputStream *ost, | |
1193 | char *graph_desc, | ||
1194 | Scheduler *sch, unsigned sched_idx_enc, | ||
1195 | const OutputFilterOptions *opts) | ||
1196 | { | ||
1197 | FilterGraph *fg; | ||
1198 | FilterGraphPriv *fgp; | ||
1199 | int ret; | ||
1200 | |||
1201 | 6267 | ret = fg_create(&fg, graph_desc, sch); | |
1202 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6267 times.
|
6267 | if (ret < 0) |
1203 | ✗ | return ret; | |
1204 | 6267 | ost->fg_simple = fg; | |
1205 | 6267 | fgp = fgp_from_fg(fg); | |
1206 | |||
1207 | 6267 | fgp->is_simple = 1; | |
1208 | |||
1209 | 6267 | snprintf(fgp->log_name, sizeof(fgp->log_name), "%cf%s", | |
1210 | 6267 | av_get_media_type_string(ost->type)[0], opts->name); | |
1211 | |||
1212 |
2/4✓ Branch 0 taken 6267 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 6267 times.
|
6267 | if (fg->nb_inputs != 1 || fg->nb_outputs != 1) { |
1213 | ✗ | av_log(fg, AV_LOG_ERROR, "Simple filtergraph '%s' was expected " | |
1214 | "to have exactly 1 input and 1 output. " | ||
1215 | "However, it had %d input(s) and %d output(s). Please adjust, " | ||
1216 | "or use a complex filtergraph (-filter_complex) instead.\n", | ||
1217 | ✗ | graph_desc, fg->nb_inputs, fg->nb_outputs); | |
1218 | ✗ | return AVERROR(EINVAL); | |
1219 | } | ||
1220 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6267 times.
|
6267 | if (fg->outputs[0]->type != ost->type) { |
1221 | ✗ | av_log(fg, AV_LOG_ERROR, "Filtergraph has a %s output, cannot connect " | |
1222 | "it to %s output stream\n", | ||
1223 | ✗ | av_get_media_type_string(fg->outputs[0]->type), | |
1224 | av_get_media_type_string(ost->type)); | ||
1225 | ✗ | return AVERROR(EINVAL); | |
1226 | } | ||
1227 | |||
1228 | 6267 | ost->filter = fg->outputs[0]; | |
1229 | |||
1230 | 6267 | ret = ifilter_bind_ist(fg->inputs[0], ist); | |
1231 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6267 times.
|
6267 | if (ret < 0) |
1232 | ✗ | return ret; | |
1233 | |||
1234 | 6267 | ret = ofilter_bind_ost(fg->outputs[0], ost, sched_idx_enc, opts); | |
1235 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6267 times.
|
6267 | if (ret < 0) |
1236 | ✗ | return ret; | |
1237 | |||
1238 |
2/2✓ Branch 0 taken 3769 times.
✓ Branch 1 taken 2498 times.
|
6267 | if (opts->nb_threads) { |
1239 | 3769 | av_freep(&fgp->nb_threads); | |
1240 | 3769 | fgp->nb_threads = av_strdup(opts->nb_threads); | |
1241 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3769 times.
|
3769 | if (!fgp->nb_threads) |
1242 | ✗ | return AVERROR(ENOMEM); | |
1243 | } | ||
1244 | |||
1245 | 6267 | return 0; | |
1246 | } | ||
1247 | |||
1248 | 132 | static int fg_complex_bind_input(FilterGraph *fg, InputFilter *ifilter) | |
1249 | { | ||
1250 | 132 | FilterGraphPriv *fgp = fgp_from_fg(fg); | |
1251 | 132 | InputFilterPriv *ifp = ifp_from_ifilter(ifilter); | |
1252 | 132 | InputStream *ist = NULL; | |
1253 | 132 | enum AVMediaType type = ifp->type; | |
1254 | int i, ret; | ||
1255 | |||
1256 |
4/4✓ Branch 0 taken 77 times.
✓ Branch 1 taken 55 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 76 times.
|
132 | if (ifp->linklabel && !strncmp(ifp->linklabel, "dec:", 4)) { |
1257 | // bind to a standalone decoder | ||
1258 | int dec_idx; | ||
1259 | |||
1260 | 1 | dec_idx = strtol(ifp->linklabel + 4, NULL, 0); | |
1261 |
2/4✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
|
1 | if (dec_idx < 0 || dec_idx >= nb_decoders) { |
1262 | ✗ | av_log(fg, AV_LOG_ERROR, "Invalid decoder index %d in filtergraph description %s\n", | |
1263 | dec_idx, fgp->graph_desc); | ||
1264 | ✗ | return AVERROR(EINVAL); | |
1265 | } | ||
1266 | |||
1267 | 1 | ret = ifilter_bind_dec(ifp, decoders[dec_idx]); | |
1268 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (ret < 0) |
1269 | ✗ | av_log(fg, AV_LOG_ERROR, "Error binding a decoder to filtergraph input %s\n", | |
1270 | ifilter->name); | ||
1271 | 1 | return ret; | |
1272 |
2/2✓ Branch 0 taken 76 times.
✓ Branch 1 taken 55 times.
|
131 | } else if (ifp->linklabel) { |
1273 | AVFormatContext *s; | ||
1274 | 76 | AVStream *st = NULL; | |
1275 | char *p; | ||
1276 | int file_idx; | ||
1277 | |||
1278 | // try finding an unbound filtergraph output with this label | ||
1279 |
2/2✓ Branch 0 taken 76 times.
✓ Branch 1 taken 76 times.
|
152 | for (int i = 0; i < nb_filtergraphs; i++) { |
1280 | 76 | FilterGraph *fg_src = filtergraphs[i]; | |
1281 | |||
1282 |
1/2✓ Branch 0 taken 76 times.
✗ Branch 1 not taken.
|
76 | if (fg == fg_src) |
1283 | 76 | continue; | |
1284 | |||
1285 | ✗ | for (int j = 0; j < fg_src->nb_outputs; j++) { | |
1286 | ✗ | OutputFilter *ofilter = fg_src->outputs[j]; | |
1287 | |||
1288 | ✗ | if (!ofilter->bound && ofilter->linklabel && | |
1289 | ✗ | !strcmp(ofilter->linklabel, ifp->linklabel)) { | |
1290 | ✗ | av_log(fg, AV_LOG_VERBOSE, | |
1291 | "Binding input with label '%s' to filtergraph output %d:%d\n", | ||
1292 | ifp->linklabel, i, j); | ||
1293 | |||
1294 | ✗ | ret = ifilter_bind_fg(ifp, fg_src, j); | |
1295 | ✗ | if (ret < 0) | |
1296 | ✗ | av_log(fg, AV_LOG_ERROR, "Error binding filtergraph input %s\n", | |
1297 | ifp->linklabel); | ||
1298 | ✗ | return ret; | |
1299 | } | ||
1300 | } | ||
1301 | } | ||
1302 | |||
1303 | // bind to an explicitly specified demuxer stream | ||
1304 | 76 | file_idx = strtol(ifp->linklabel, &p, 0); | |
1305 |
2/4✓ Branch 0 taken 76 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 76 times.
|
76 | if (file_idx < 0 || file_idx >= nb_input_files) { |
1306 | ✗ | av_log(fg, AV_LOG_FATAL, "Invalid file index %d in filtergraph description %s.\n", | |
1307 | file_idx, fgp->graph_desc); | ||
1308 | ✗ | return AVERROR(EINVAL); | |
1309 | } | ||
1310 | 76 | s = input_files[file_idx]->ctx; | |
1311 | |||
1312 |
1/2✓ Branch 0 taken 81 times.
✗ Branch 1 not taken.
|
81 | for (i = 0; i < s->nb_streams; i++) { |
1313 | 81 | enum AVMediaType stream_type = s->streams[i]->codecpar->codec_type; | |
1314 |
4/4✓ Branch 0 taken 8 times.
✓ Branch 1 taken 73 times.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 3 times.
|
81 | if (stream_type != type && |
1315 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
|
5 | !(stream_type == AVMEDIA_TYPE_SUBTITLE && |
1316 | type == AVMEDIA_TYPE_VIDEO /* sub2video hack */)) | ||
1317 | 3 | continue; | |
1318 |
4/4✓ Branch 0 taken 74 times.
✓ Branch 1 taken 4 times.
✓ Branch 3 taken 76 times.
✓ Branch 4 taken 2 times.
|
78 | if (check_stream_specifier(s, s->streams[i], *p == ':' ? p + 1 : p) == 1) { |
1319 | 76 | st = s->streams[i]; | |
1320 | 76 | break; | |
1321 | } | ||
1322 | } | ||
1323 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 76 times.
|
76 | if (!st) { |
1324 | ✗ | av_log(fg, AV_LOG_FATAL, "Stream specifier '%s' in filtergraph description %s " | |
1325 | "matches no streams.\n", p, fgp->graph_desc); | ||
1326 | ✗ | return AVERROR(EINVAL); | |
1327 | } | ||
1328 | 76 | ist = input_files[file_idx]->streams[st->index]; | |
1329 | |||
1330 | 76 | av_log(fg, AV_LOG_VERBOSE, | |
1331 | "Binding input with label '%s' to input stream %d:%d\n", | ||
1332 | 76 | ifp->linklabel, ist->file->index, ist->index); | |
1333 | } else { | ||
1334 | 55 | ist = ist_find_unused(type); | |
1335 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 55 times.
|
55 | if (!ist) { |
1336 | ✗ | av_log(fg, AV_LOG_FATAL, "Cannot find a matching stream for " | |
1337 | "unlabeled input pad %s\n", ifilter->name); | ||
1338 | ✗ | return AVERROR(EINVAL); | |
1339 | } | ||
1340 | |||
1341 | 55 | av_log(fg, AV_LOG_VERBOSE, | |
1342 | "Binding unlabeled input %d to input stream %d:%d\n", | ||
1343 | 55 | ifp->index, ist->file->index, ist->index); | |
1344 | } | ||
1345 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 131 times.
|
131 | av_assert0(ist); |
1346 | |||
1347 | 131 | ret = ifilter_bind_ist(ifilter, ist); | |
1348 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 131 times.
|
131 | if (ret < 0) { |
1349 | ✗ | av_log(fg, AV_LOG_ERROR, | |
1350 | "Error binding an input stream to complex filtergraph input %s.\n", | ||
1351 | ifilter->name); | ||
1352 | ✗ | return ret; | |
1353 | } | ||
1354 | |||
1355 | 131 | return 0; | |
1356 | } | ||
1357 | |||
1358 | 117 | static int bind_inputs(FilterGraph *fg) | |
1359 | { | ||
1360 | // bind filtergraph inputs to input streams or other filtergraphs | ||
1361 |
2/2✓ Branch 0 taken 132 times.
✓ Branch 1 taken 117 times.
|
249 | for (int i = 0; i < fg->nb_inputs; i++) { |
1362 | 132 | InputFilterPriv *ifp = ifp_from_ifilter(fg->inputs[i]); | |
1363 | int ret; | ||
1364 | |||
1365 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 132 times.
|
132 | if (ifp->bound) |
1366 | ✗ | continue; | |
1367 | |||
1368 | 132 | ret = fg_complex_bind_input(fg, &ifp->ifilter); | |
1369 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 132 times.
|
132 | if (ret < 0) |
1370 | ✗ | return ret; | |
1371 | } | ||
1372 | |||
1373 | 117 | return 0; | |
1374 | } | ||
1375 | |||
1376 | 6758 | int fg_finalise_bindings(void) | |
1377 | { | ||
1378 | int ret; | ||
1379 | |||
1380 |
2/2✓ Branch 0 taken 117 times.
✓ Branch 1 taken 6758 times.
|
6875 | for (int i = 0; i < nb_filtergraphs; i++) { |
1381 | 117 | ret = bind_inputs(filtergraphs[i]); | |
1382 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 117 times.
|
117 | if (ret < 0) |
1383 | ✗ | return ret; | |
1384 | } | ||
1385 | |||
1386 | // check that all outputs were bound | ||
1387 |
2/2✓ Branch 0 taken 117 times.
✓ Branch 1 taken 6758 times.
|
6875 | for (int i = 0; i < nb_filtergraphs; i++) { |
1388 | 117 | FilterGraph *fg = filtergraphs[i]; | |
1389 | |||
1390 |
2/2✓ Branch 0 taken 167 times.
✓ Branch 1 taken 117 times.
|
284 | for (int j = 0; j < fg->nb_outputs; j++) { |
1391 | 167 | OutputFilter *output = fg->outputs[j]; | |
1392 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 167 times.
|
167 | if (!output->bound) { |
1393 | ✗ | av_log(filtergraphs[j], AV_LOG_FATAL, | |
1394 | "Filter %s has an unconnected output\n", output->name); | ||
1395 | ✗ | return AVERROR(EINVAL); | |
1396 | } | ||
1397 | } | ||
1398 | } | ||
1399 | |||
1400 | 6758 | return 0; | |
1401 | } | ||
1402 | |||
1403 | 12915 | static int insert_trim(int64_t start_time, int64_t duration, | |
1404 | AVFilterContext **last_filter, int *pad_idx, | ||
1405 | const char *filter_name) | ||
1406 | { | ||
1407 | 12915 | AVFilterGraph *graph = (*last_filter)->graph; | |
1408 | AVFilterContext *ctx; | ||
1409 | const AVFilter *trim; | ||
1410 | 12915 | enum AVMediaType type = avfilter_pad_get_type((*last_filter)->output_pads, *pad_idx); | |
1411 |
2/2✓ Branch 0 taken 10431 times.
✓ Branch 1 taken 2484 times.
|
12915 | const char *name = (type == AVMEDIA_TYPE_VIDEO) ? "trim" : "atrim"; |
1412 | 12915 | int ret = 0; | |
1413 | |||
1414 |
4/4✓ Branch 0 taken 12701 times.
✓ Branch 1 taken 214 times.
✓ Branch 2 taken 12684 times.
✓ Branch 3 taken 17 times.
|
12915 | if (duration == INT64_MAX && start_time == AV_NOPTS_VALUE) |
1415 | 12684 | return 0; | |
1416 | |||
1417 | 231 | trim = avfilter_get_by_name(name); | |
1418 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 231 times.
|
231 | if (!trim) { |
1419 | ✗ | av_log(NULL, AV_LOG_ERROR, "%s filter not present, cannot limit " | |
1420 | "recording time.\n", name); | ||
1421 | ✗ | return AVERROR_FILTER_NOT_FOUND; | |
1422 | } | ||
1423 | |||
1424 | 231 | ctx = avfilter_graph_alloc_filter(graph, trim, filter_name); | |
1425 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 231 times.
|
231 | if (!ctx) |
1426 | ✗ | return AVERROR(ENOMEM); | |
1427 | |||
1428 |
2/2✓ Branch 0 taken 214 times.
✓ Branch 1 taken 17 times.
|
231 | if (duration != INT64_MAX) { |
1429 | 214 | ret = av_opt_set_int(ctx, "durationi", duration, | |
1430 | AV_OPT_SEARCH_CHILDREN); | ||
1431 | } | ||
1432 |
3/4✓ Branch 0 taken 231 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 18 times.
✓ Branch 3 taken 213 times.
|
231 | if (ret >= 0 && start_time != AV_NOPTS_VALUE) { |
1433 | 18 | ret = av_opt_set_int(ctx, "starti", start_time, | |
1434 | AV_OPT_SEARCH_CHILDREN); | ||
1435 | } | ||
1436 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 231 times.
|
231 | if (ret < 0) { |
1437 | ✗ | av_log(ctx, AV_LOG_ERROR, "Error configuring the %s filter", name); | |
1438 | ✗ | return ret; | |
1439 | } | ||
1440 | |||
1441 | 231 | ret = avfilter_init_str(ctx, NULL); | |
1442 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 231 times.
|
231 | if (ret < 0) |
1443 | ✗ | return ret; | |
1444 | |||
1445 | 231 | ret = avfilter_link(*last_filter, *pad_idx, ctx, 0); | |
1446 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 231 times.
|
231 | if (ret < 0) |
1447 | ✗ | return ret; | |
1448 | |||
1449 | 231 | *last_filter = ctx; | |
1450 | 231 | *pad_idx = 0; | |
1451 | 231 | return 0; | |
1452 | } | ||
1453 | |||
1454 | 1 | static int insert_filter(AVFilterContext **last_filter, int *pad_idx, | |
1455 | const char *filter_name, const char *args) | ||
1456 | { | ||
1457 | 1 | AVFilterGraph *graph = (*last_filter)->graph; | |
1458 | AVFilterContext *ctx; | ||
1459 | int ret; | ||
1460 | |||
1461 | 1 | ret = avfilter_graph_create_filter(&ctx, | |
1462 | avfilter_get_by_name(filter_name), | ||
1463 | filter_name, args, NULL, graph); | ||
1464 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (ret < 0) |
1465 | ✗ | return ret; | |
1466 | |||
1467 | 1 | ret = avfilter_link(*last_filter, *pad_idx, ctx, 0); | |
1468 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (ret < 0) |
1469 | ✗ | return ret; | |
1470 | |||
1471 | 1 | *last_filter = ctx; | |
1472 | 1 | *pad_idx = 0; | |
1473 | 1 | return 0; | |
1474 | } | ||
1475 | |||
1476 | 5232 | static int configure_output_video_filter(FilterGraph *fg, AVFilterGraph *graph, | |
1477 | OutputFilter *ofilter, AVFilterInOut *out) | ||
1478 | { | ||
1479 | 5232 | OutputFilterPriv *ofp = ofp_from_ofilter(ofilter); | |
1480 | 5232 | AVFilterContext *last_filter = out->filter_ctx; | |
1481 | AVBPrint bprint; | ||
1482 | 5232 | int pad_idx = out->pad_idx; | |
1483 | int ret; | ||
1484 | const char *pix_fmts; | ||
1485 | char name[255]; | ||
1486 | |||
1487 | 5232 | snprintf(name, sizeof(name), "out_%s", ofp->name); | |
1488 | 5232 | ret = avfilter_graph_create_filter(&ofp->filter, | |
1489 | avfilter_get_by_name("buffersink"), | ||
1490 | name, NULL, NULL, graph); | ||
1491 | |||
1492 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5232 times.
|
5232 | if (ret < 0) |
1493 | ✗ | return ret; | |
1494 | |||
1495 |
4/6✓ Branch 0 taken 4961 times.
✓ Branch 1 taken 271 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4961 times.
✓ Branch 4 taken 271 times.
✗ Branch 5 not taken.
|
5232 | if ((ofp->width || ofp->height) && (ofp->flags & OFILTER_FLAG_AUTOSCALE)) { |
1496 | char args[255]; | ||
1497 | AVFilterContext *filter; | ||
1498 | 271 | const AVDictionaryEntry *e = NULL; | |
1499 | |||
1500 | 271 | snprintf(args, sizeof(args), "%d:%d", | |
1501 | ofp->width, ofp->height); | ||
1502 | |||
1503 |
2/2✓ Branch 1 taken 258 times.
✓ Branch 2 taken 271 times.
|
529 | while ((e = av_dict_iterate(ofp->sws_opts, e))) { |
1504 | 258 | av_strlcatf(args, sizeof(args), ":%s=%s", e->key, e->value); | |
1505 | } | ||
1506 | |||
1507 | 271 | snprintf(name, sizeof(name), "scaler_out_%s", ofp->name); | |
1508 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 271 times.
|
271 | if ((ret = avfilter_graph_create_filter(&filter, avfilter_get_by_name("scale"), |
1509 | name, args, NULL, graph)) < 0) | ||
1510 | ✗ | return ret; | |
1511 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 271 times.
|
271 | if ((ret = avfilter_link(last_filter, pad_idx, filter, 0)) < 0) |
1512 | ✗ | return ret; | |
1513 | |||
1514 | 271 | last_filter = filter; | |
1515 | 271 | pad_idx = 0; | |
1516 | } | ||
1517 | |||
1518 | 5232 | av_bprint_init(&bprint, 0, AV_BPRINT_SIZE_UNLIMITED); | |
1519 | 5232 | ret = choose_pix_fmts(ofilter, &bprint, &pix_fmts); | |
1520 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5232 times.
|
5232 | if (ret < 0) |
1521 | ✗ | return ret; | |
1522 | |||
1523 |
2/2✓ Branch 0 taken 4118 times.
✓ Branch 1 taken 1114 times.
|
5232 | if (pix_fmts) { |
1524 | AVFilterContext *filter; | ||
1525 | |||
1526 | 4118 | ret = avfilter_graph_create_filter(&filter, | |
1527 | avfilter_get_by_name("format"), | ||
1528 | "format", pix_fmts, NULL, graph); | ||
1529 | 4118 | av_bprint_finalize(&bprint, NULL); | |
1530 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4118 times.
|
4118 | if (ret < 0) |
1531 | ✗ | return ret; | |
1532 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 4118 times.
|
4118 | if ((ret = avfilter_link(last_filter, pad_idx, filter, 0)) < 0) |
1533 | ✗ | return ret; | |
1534 | |||
1535 | 4118 | last_filter = filter; | |
1536 | 4118 | pad_idx = 0; | |
1537 | } | ||
1538 | |||
1539 | 5232 | snprintf(name, sizeof(name), "trim_out_%s", ofp->name); | |
1540 | 5232 | ret = insert_trim(ofp->trim_start_us, ofp->trim_duration_us, | |
1541 | &last_filter, &pad_idx, name); | ||
1542 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5232 times.
|
5232 | if (ret < 0) |
1543 | ✗ | return ret; | |
1544 | |||
1545 | |||
1546 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 5232 times.
|
5232 | if ((ret = avfilter_link(last_filter, pad_idx, ofp->filter, 0)) < 0) |
1547 | ✗ | return ret; | |
1548 | |||
1549 | 5232 | return 0; | |
1550 | } | ||
1551 | |||
1552 | 1243 | static int configure_output_audio_filter(FilterGraph *fg, AVFilterGraph *graph, | |
1553 | OutputFilter *ofilter, AVFilterInOut *out) | ||
1554 | { | ||
1555 | 1243 | OutputFilterPriv *ofp = ofp_from_ofilter(ofilter); | |
1556 | 1243 | AVFilterContext *last_filter = out->filter_ctx; | |
1557 | 1243 | int pad_idx = out->pad_idx; | |
1558 | AVBPrint args; | ||
1559 | char name[255]; | ||
1560 | int ret; | ||
1561 | |||
1562 | 1243 | snprintf(name, sizeof(name), "out_%s", ofp->name); | |
1563 | 1243 | ret = avfilter_graph_create_filter(&ofp->filter, | |
1564 | avfilter_get_by_name("abuffersink"), | ||
1565 | name, NULL, NULL, graph); | ||
1566 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1243 times.
|
1243 | if (ret < 0) |
1567 | ✗ | return ret; | |
1568 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1243 times.
|
1243 | if ((ret = av_opt_set_int(ofp->filter, "all_channel_counts", 1, AV_OPT_SEARCH_CHILDREN)) < 0) |
1569 | ✗ | return ret; | |
1570 | |||
1571 | #define AUTO_INSERT_FILTER(opt_name, filter_name, arg) do { \ | ||
1572 | AVFilterContext *filt_ctx; \ | ||
1573 | \ | ||
1574 | av_log(ofilter, AV_LOG_INFO, opt_name " is forwarded to lavfi " \ | ||
1575 | "similarly to -af " filter_name "=%s.\n", arg); \ | ||
1576 | \ | ||
1577 | ret = avfilter_graph_create_filter(&filt_ctx, \ | ||
1578 | avfilter_get_by_name(filter_name), \ | ||
1579 | filter_name, arg, NULL, graph); \ | ||
1580 | if (ret < 0) \ | ||
1581 | goto fail; \ | ||
1582 | \ | ||
1583 | ret = avfilter_link(last_filter, pad_idx, filt_ctx, 0); \ | ||
1584 | if (ret < 0) \ | ||
1585 | goto fail; \ | ||
1586 | \ | ||
1587 | last_filter = filt_ctx; \ | ||
1588 | pad_idx = 0; \ | ||
1589 | } while (0) | ||
1590 | 1243 | av_bprint_init(&args, 0, AV_BPRINT_SIZE_UNLIMITED); | |
1591 | |||
1592 | 1243 | choose_sample_fmts(ofp, &args); | |
1593 | 1243 | choose_sample_rates(ofp, &args); | |
1594 | 1243 | choose_channel_layouts(ofp, &args); | |
1595 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1243 times.
|
1243 | if (!av_bprint_is_complete(&args)) { |
1596 | ✗ | ret = AVERROR(ENOMEM); | |
1597 | ✗ | goto fail; | |
1598 | } | ||
1599 |
1/2✓ Branch 0 taken 1243 times.
✗ Branch 1 not taken.
|
1243 | if (args.len) { |
1600 | AVFilterContext *format; | ||
1601 | |||
1602 | 1243 | snprintf(name, sizeof(name), "format_out_%s", ofp->name); | |
1603 | 1243 | ret = avfilter_graph_create_filter(&format, | |
1604 | avfilter_get_by_name("aformat"), | ||
1605 | 1243 | name, args.str, NULL, graph); | |
1606 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1243 times.
|
1243 | if (ret < 0) |
1607 | ✗ | goto fail; | |
1608 | |||
1609 | 1243 | ret = avfilter_link(last_filter, pad_idx, format, 0); | |
1610 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1243 times.
|
1243 | if (ret < 0) |
1611 | ✗ | goto fail; | |
1612 | |||
1613 | 1243 | last_filter = format; | |
1614 | 1243 | pad_idx = 0; | |
1615 | } | ||
1616 | |||
1617 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1243 times.
|
1243 | if (ofilter->apad) |
1618 | ✗ | AUTO_INSERT_FILTER("-apad", "apad", ofilter->apad); | |
1619 | |||
1620 | 1243 | snprintf(name, sizeof(name), "trim for output %s", ofp->name); | |
1621 | 1243 | ret = insert_trim(ofp->trim_start_us, ofp->trim_duration_us, | |
1622 | &last_filter, &pad_idx, name); | ||
1623 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1243 times.
|
1243 | if (ret < 0) |
1624 | ✗ | goto fail; | |
1625 | |||
1626 |
1/2✓ Branch 1 taken 1243 times.
✗ Branch 2 not taken.
|
1243 | if ((ret = avfilter_link(last_filter, pad_idx, ofp->filter, 0)) < 0) |
1627 | ✗ | goto fail; | |
1628 | 1243 | fail: | |
1629 | 1243 | av_bprint_finalize(&args, NULL); | |
1630 | |||
1631 | 1243 | return ret; | |
1632 | } | ||
1633 | |||
1634 | 6475 | static int configure_output_filter(FilterGraph *fg, AVFilterGraph *graph, | |
1635 | OutputFilter *ofilter, AVFilterInOut *out) | ||
1636 | { | ||
1637 |
2/3✓ Branch 0 taken 5232 times.
✓ Branch 1 taken 1243 times.
✗ Branch 2 not taken.
|
6475 | switch (ofilter->type) { |
1638 | 5232 | case AVMEDIA_TYPE_VIDEO: return configure_output_video_filter(fg, graph, ofilter, out); | |
1639 | 1243 | case AVMEDIA_TYPE_AUDIO: return configure_output_audio_filter(fg, graph, ofilter, out); | |
1640 | ✗ | default: av_assert0(0); return 0; | |
1641 | } | ||
1642 | } | ||
1643 | |||
1644 | 4 | static void sub2video_prepare(InputFilterPriv *ifp) | |
1645 | { | ||
1646 | 4 | ifp->sub2video.last_pts = INT64_MIN; | |
1647 | 4 | ifp->sub2video.end_pts = INT64_MIN; | |
1648 | |||
1649 | /* sub2video structure has been (re-)initialized. | ||
1650 | Mark it as such so that the system will be | ||
1651 | initialized with the first received heartbeat. */ | ||
1652 | 4 | ifp->sub2video.initialize = 1; | |
1653 | 4 | } | |
1654 | |||
1655 | 5199 | static int configure_input_video_filter(FilterGraph *fg, AVFilterGraph *graph, | |
1656 | InputFilter *ifilter, AVFilterInOut *in) | ||
1657 | { | ||
1658 | 5199 | InputFilterPriv *ifp = ifp_from_ifilter(ifilter); | |
1659 | |||
1660 | AVFilterContext *last_filter; | ||
1661 | 5199 | const AVFilter *buffer_filt = avfilter_get_by_name("buffer"); | |
1662 | const AVPixFmtDescriptor *desc; | ||
1663 | 5199 | AVRational fr = ifp->opts.framerate; | |
1664 | AVRational sar; | ||
1665 | AVBPrint args; | ||
1666 | char name[255]; | ||
1667 | 5199 | int ret, pad_idx = 0; | |
1668 | 5199 | AVBufferSrcParameters *par = av_buffersrc_parameters_alloc(); | |
1669 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5199 times.
|
5199 | if (!par) |
1670 | ✗ | return AVERROR(ENOMEM); | |
1671 | |||
1672 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 5195 times.
|
5199 | if (ifp->type_src == AVMEDIA_TYPE_SUBTITLE) |
1673 | 4 | sub2video_prepare(ifp); | |
1674 | |||
1675 | 5199 | sar = ifp->sample_aspect_ratio; | |
1676 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 5195 times.
|
5199 | if(!sar.den) |
1677 | 4 | sar = (AVRational){0,1}; | |
1678 | 5199 | av_bprint_init(&args, 0, AV_BPRINT_SIZE_AUTOMATIC); | |
1679 | 5199 | av_bprintf(&args, | |
1680 | "video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:" | ||
1681 | "pixel_aspect=%d/%d:colorspace=%d:range=%d", | ||
1682 | ifp->width, ifp->height, ifp->format, | ||
1683 | ifp->time_base.num, ifp->time_base.den, sar.num, sar.den, | ||
1684 | 5199 | ifp->color_space, ifp->color_range); | |
1685 |
3/4✓ Branch 0 taken 5194 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 5194 times.
✗ Branch 3 not taken.
|
5199 | if (fr.num && fr.den) |
1686 | 5194 | av_bprintf(&args, ":frame_rate=%d/%d", fr.num, fr.den); | |
1687 | 5199 | snprintf(name, sizeof(name), "graph %d input from stream %s", fg->index, | |
1688 | ifp->opts.name); | ||
1689 | |||
1690 | |||
1691 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5199 times.
|
5199 | if ((ret = avfilter_graph_create_filter(&ifp->filter, buffer_filt, name, |
1692 | 5199 | args.str, NULL, graph)) < 0) | |
1693 | ✗ | goto fail; | |
1694 | 5199 | par->hw_frames_ctx = ifp->hw_frames_ctx; | |
1695 | 5199 | ret = av_buffersrc_parameters_set(ifp->filter, par); | |
1696 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5199 times.
|
5199 | if (ret < 0) |
1697 | ✗ | goto fail; | |
1698 | 5199 | av_freep(&par); | |
1699 | 5199 | last_filter = ifp->filter; | |
1700 | |||
1701 | 5199 | desc = av_pix_fmt_desc_get(ifp->format); | |
1702 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5199 times.
|
5199 | av_assert0(desc); |
1703 | |||
1704 | // TODO: insert hwaccel enabled filters like transpose_vaapi into the graph | ||
1705 | 5199 | ifp->displaymatrix_applied = 0; | |
1706 |
2/2✓ Branch 0 taken 5198 times.
✓ Branch 1 taken 1 times.
|
5199 | if ((ifp->opts.flags & IFILTER_FLAG_AUTOROTATE) && |
1707 |
1/2✓ Branch 0 taken 5198 times.
✗ Branch 1 not taken.
|
5198 | !(desc->flags & AV_PIX_FMT_FLAG_HWACCEL)) { |
1708 | 5198 | int32_t *displaymatrix = ifp->displaymatrix; | |
1709 | double theta; | ||
1710 | |||
1711 | 5198 | theta = get_rotation(displaymatrix); | |
1712 | |||
1713 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 5197 times.
|
5198 | if (fabs(theta - 90) < 1.0) { |
1714 | 1 | ret = insert_filter(&last_filter, &pad_idx, "transpose", | |
1715 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | displaymatrix[3] > 0 ? "cclock_flip" : "clock"); |
1716 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5197 times.
|
5197 | } else if (fabs(theta - 180) < 1.0) { |
1717 | ✗ | if (displaymatrix[0] < 0) { | |
1718 | ✗ | ret = insert_filter(&last_filter, &pad_idx, "hflip", NULL); | |
1719 | ✗ | if (ret < 0) | |
1720 | ✗ | return ret; | |
1721 | } | ||
1722 | ✗ | if (displaymatrix[4] < 0) { | |
1723 | ✗ | ret = insert_filter(&last_filter, &pad_idx, "vflip", NULL); | |
1724 | } | ||
1725 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5197 times.
|
5197 | } else if (fabs(theta - 270) < 1.0) { |
1726 | ✗ | ret = insert_filter(&last_filter, &pad_idx, "transpose", | |
1727 | ✗ | displaymatrix[3] < 0 ? "clock_flip" : "cclock"); | |
1728 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5197 times.
|
5197 | } else if (fabs(theta) > 1.0) { |
1729 | char rotate_buf[64]; | ||
1730 | ✗ | snprintf(rotate_buf, sizeof(rotate_buf), "%f*PI/180", theta); | |
1731 | ✗ | ret = insert_filter(&last_filter, &pad_idx, "rotate", rotate_buf); | |
1732 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5197 times.
|
5197 | } else if (fabs(theta) < 1.0) { |
1733 | ✗ | if (displaymatrix && displaymatrix[4] < 0) { | |
1734 | ✗ | ret = insert_filter(&last_filter, &pad_idx, "vflip", NULL); | |
1735 | } | ||
1736 | } | ||
1737 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5198 times.
|
5198 | if (ret < 0) |
1738 | ✗ | return ret; | |
1739 | |||
1740 | 5198 | ifp->displaymatrix_applied = 1; | |
1741 | } | ||
1742 | |||
1743 | 5199 | snprintf(name, sizeof(name), "trim_in_%s", ifp->opts.name); | |
1744 | 5199 | ret = insert_trim(ifp->opts.trim_start_us, ifp->opts.trim_end_us, | |
1745 | &last_filter, &pad_idx, name); | ||
1746 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5199 times.
|
5199 | if (ret < 0) |
1747 | ✗ | return ret; | |
1748 | |||
1749 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 5199 times.
|
5199 | if ((ret = avfilter_link(last_filter, 0, in->filter_ctx, in->pad_idx)) < 0) |
1750 | ✗ | return ret; | |
1751 | 5199 | return 0; | |
1752 | ✗ | fail: | |
1753 | ✗ | av_freep(&par); | |
1754 | |||
1755 | ✗ | return ret; | |
1756 | } | ||
1757 | |||
1758 | 1241 | static int configure_input_audio_filter(FilterGraph *fg, AVFilterGraph *graph, | |
1759 | InputFilter *ifilter, AVFilterInOut *in) | ||
1760 | { | ||
1761 | 1241 | InputFilterPriv *ifp = ifp_from_ifilter(ifilter); | |
1762 | AVFilterContext *last_filter; | ||
1763 | 1241 | const AVFilter *abuffer_filt = avfilter_get_by_name("abuffer"); | |
1764 | AVBPrint args; | ||
1765 | char name[255]; | ||
1766 | 1241 | int ret, pad_idx = 0; | |
1767 | |||
1768 | 1241 | av_bprint_init(&args, 0, AV_BPRINT_SIZE_AUTOMATIC); | |
1769 | 1241 | av_bprintf(&args, "time_base=%d/%d:sample_rate=%d:sample_fmt=%s", | |
1770 | ifp->time_base.num, ifp->time_base.den, | ||
1771 | ifp->sample_rate, | ||
1772 | 1241 | av_get_sample_fmt_name(ifp->format)); | |
1773 |
1/2✓ Branch 1 taken 1241 times.
✗ Branch 2 not taken.
|
1241 | if (av_channel_layout_check(&ifp->ch_layout) && |
1774 |
2/2✓ Branch 0 taken 1228 times.
✓ Branch 1 taken 13 times.
|
1241 | ifp->ch_layout.order != AV_CHANNEL_ORDER_UNSPEC) { |
1775 | 1228 | av_bprintf(&args, ":channel_layout="); | |
1776 | 1228 | av_channel_layout_describe_bprint(&ifp->ch_layout, &args); | |
1777 | } else | ||
1778 | 13 | av_bprintf(&args, ":channels=%d", ifp->ch_layout.nb_channels); | |
1779 | 1241 | snprintf(name, sizeof(name), "graph_%d_in_%s", fg->index, ifp->opts.name); | |
1780 | |||
1781 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1241 times.
|
1241 | if ((ret = avfilter_graph_create_filter(&ifp->filter, abuffer_filt, |
1782 | 1241 | name, args.str, NULL, | |
1783 | graph)) < 0) | ||
1784 | ✗ | return ret; | |
1785 | 1241 | last_filter = ifp->filter; | |
1786 | |||
1787 | 1241 | snprintf(name, sizeof(name), "trim for input stream %s", ifp->opts.name); | |
1788 | 1241 | ret = insert_trim(ifp->opts.trim_start_us, ifp->opts.trim_end_us, | |
1789 | &last_filter, &pad_idx, name); | ||
1790 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1241 times.
|
1241 | if (ret < 0) |
1791 | ✗ | return ret; | |
1792 | |||
1793 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1241 times.
|
1241 | if ((ret = avfilter_link(last_filter, 0, in->filter_ctx, in->pad_idx)) < 0) |
1794 | ✗ | return ret; | |
1795 | |||
1796 | 1241 | return 0; | |
1797 | } | ||
1798 | |||
1799 | 6440 | static int configure_input_filter(FilterGraph *fg, AVFilterGraph *graph, | |
1800 | InputFilter *ifilter, AVFilterInOut *in) | ||
1801 | { | ||
1802 |
2/3✓ Branch 1 taken 5199 times.
✓ Branch 2 taken 1241 times.
✗ Branch 3 not taken.
|
6440 | switch (ifp_from_ifilter(ifilter)->type) { |
1803 | 5199 | case AVMEDIA_TYPE_VIDEO: return configure_input_video_filter(fg, graph, ifilter, in); | |
1804 | 1241 | case AVMEDIA_TYPE_AUDIO: return configure_input_audio_filter(fg, graph, ifilter, in); | |
1805 | ✗ | default: av_assert0(0); return 0; | |
1806 | } | ||
1807 | } | ||
1808 | |||
1809 | 6425 | static void cleanup_filtergraph(FilterGraph *fg, FilterGraphThread *fgt) | |
1810 | { | ||
1811 |
2/2✓ Branch 0 taken 6475 times.
✓ Branch 1 taken 6425 times.
|
12900 | for (int i = 0; i < fg->nb_outputs; i++) |
1812 | 6475 | ofp_from_ofilter(fg->outputs[i])->filter = NULL; | |
1813 |
2/2✓ Branch 0 taken 6440 times.
✓ Branch 1 taken 6425 times.
|
12865 | for (int i = 0; i < fg->nb_inputs; i++) |
1814 | 6440 | ifp_from_ifilter(fg->inputs[i])->filter = NULL; | |
1815 | 6425 | avfilter_graph_free(&fgt->graph); | |
1816 | 6425 | } | |
1817 | |||
1818 | 7611 | static int filter_is_buffersrc(const AVFilterContext *f) | |
1819 | { | ||
1820 |
2/2✓ Branch 0 taken 2915 times.
✓ Branch 1 taken 4696 times.
|
10526 | return f->nb_inputs == 0 && |
1821 |
2/2✓ Branch 0 taken 665 times.
✓ Branch 1 taken 2250 times.
|
2915 | (!strcmp(f->filter->name, "buffer") || |
1822 |
2/2✓ Branch 0 taken 608 times.
✓ Branch 1 taken 57 times.
|
665 | !strcmp(f->filter->name, "abuffer")); |
1823 | } | ||
1824 | |||
1825 | 6425 | static int graph_is_meta(AVFilterGraph *graph) | |
1826 | { | ||
1827 |
2/2✓ Branch 0 taken 15593 times.
✓ Branch 1 taken 1672 times.
|
17265 | for (unsigned i = 0; i < graph->nb_filters; i++) { |
1828 | 15593 | const AVFilterContext *f = graph->filters[i]; | |
1829 | |||
1830 | /* in addition to filters flagged as meta, also | ||
1831 | * disregard sinks and buffersources (but not other sources, | ||
1832 | * since they introduce data we are not aware of) | ||
1833 | */ | ||
1834 |
4/4✓ Branch 0 taken 10472 times.
✓ Branch 1 taken 5121 times.
✓ Branch 2 taken 4753 times.
✓ Branch 3 taken 2858 times.
|
23204 | if (!((f->filter->flags & AVFILTER_FLAG_METADATA_ONLY) || |
1835 |
2/2✓ Branch 0 taken 7611 times.
✓ Branch 1 taken 2861 times.
|
10472 | f->nb_outputs == 0 || |
1836 | 7611 | filter_is_buffersrc(f))) | |
1837 | 4753 | return 0; | |
1838 | } | ||
1839 | 1672 | return 1; | |
1840 | } | ||
1841 | |||
1842 | static int sub2video_frame(InputFilter *ifilter, AVFrame *frame, int buffer); | ||
1843 | |||
1844 | 6425 | static int configure_filtergraph(FilterGraph *fg, FilterGraphThread *fgt) | |
1845 | { | ||
1846 | 6425 | FilterGraphPriv *fgp = fgp_from_fg(fg); | |
1847 | AVBufferRef *hw_device; | ||
1848 | AVFilterInOut *inputs, *outputs, *cur; | ||
1849 | 6425 | int ret, i, simple = filtergraph_is_simple(fg); | |
1850 | 6425 | int have_input_eof = 0; | |
1851 | 6425 | const char *graph_desc = fgp->graph_desc; | |
1852 | |||
1853 | 6425 | cleanup_filtergraph(fg, fgt); | |
1854 | 6425 | fgt->graph = avfilter_graph_alloc(); | |
1855 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6425 times.
|
6425 | if (!fgt->graph) |
1856 | ✗ | return AVERROR(ENOMEM); | |
1857 | |||
1858 |
2/2✓ Branch 0 taken 6308 times.
✓ Branch 1 taken 117 times.
|
6425 | if (simple) { |
1859 | 6308 | OutputFilterPriv *ofp = ofp_from_ofilter(fg->outputs[0]); | |
1860 | |||
1861 |
2/2✓ Branch 0 taken 359 times.
✓ Branch 1 taken 5949 times.
|
6308 | if (filter_nbthreads) { |
1862 | 359 | ret = av_opt_set(fgt->graph, "threads", filter_nbthreads, 0); | |
1863 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 359 times.
|
359 | if (ret < 0) |
1864 | ✗ | goto fail; | |
1865 |
2/2✓ Branch 0 taken 3573 times.
✓ Branch 1 taken 2376 times.
|
5949 | } else if (fgp->nb_threads) { |
1866 | 3573 | ret = av_opt_set(fgt->graph, "threads", fgp->nb_threads, 0); | |
1867 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3573 times.
|
3573 | if (ret < 0) |
1868 | ✗ | return ret; | |
1869 | } | ||
1870 | |||
1871 |
2/2✓ Branch 1 taken 3904 times.
✓ Branch 2 taken 2404 times.
|
6308 | if (av_dict_count(ofp->sws_opts)) { |
1872 | 3904 | ret = av_dict_get_string(ofp->sws_opts, | |
1873 | 3904 | &fgt->graph->scale_sws_opts, | |
1874 | '=', ':'); | ||
1875 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3904 times.
|
3904 | if (ret < 0) |
1876 | ✗ | goto fail; | |
1877 | } | ||
1878 | |||
1879 |
2/2✓ Branch 1 taken 59 times.
✓ Branch 2 taken 6249 times.
|
6308 | if (av_dict_count(ofp->swr_opts)) { |
1880 | char *args; | ||
1881 | 59 | ret = av_dict_get_string(ofp->swr_opts, &args, '=', ':'); | |
1882 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 59 times.
|
59 | if (ret < 0) |
1883 | ✗ | goto fail; | |
1884 | 59 | av_opt_set(fgt->graph, "aresample_swr_opts", args, 0); | |
1885 | 59 | av_free(args); | |
1886 | } | ||
1887 | } else { | ||
1888 | 117 | fgt->graph->nb_threads = filter_complex_nbthreads; | |
1889 | } | ||
1890 | |||
1891 | 6425 | hw_device = hw_device_for_filter(); | |
1892 | |||
1893 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 6425 times.
|
6425 | if ((ret = graph_parse(fgt->graph, graph_desc, &inputs, &outputs, hw_device)) < 0) |
1894 | ✗ | goto fail; | |
1895 | |||
1896 |
2/2✓ Branch 0 taken 6440 times.
✓ Branch 1 taken 6425 times.
|
12865 | for (cur = inputs, i = 0; cur; cur = cur->next, i++) |
1897 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 6440 times.
|
6440 | if ((ret = configure_input_filter(fg, fgt->graph, fg->inputs[i], cur)) < 0) { |
1898 | ✗ | avfilter_inout_free(&inputs); | |
1899 | ✗ | avfilter_inout_free(&outputs); | |
1900 | ✗ | goto fail; | |
1901 | } | ||
1902 | 6425 | avfilter_inout_free(&inputs); | |
1903 | |||
1904 |
2/2✓ Branch 0 taken 6475 times.
✓ Branch 1 taken 6425 times.
|
12900 | for (cur = outputs, i = 0; cur; cur = cur->next, i++) { |
1905 | 6475 | ret = configure_output_filter(fg, fgt->graph, fg->outputs[i], cur); | |
1906 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6475 times.
|
6475 | if (ret < 0) { |
1907 | ✗ | avfilter_inout_free(&outputs); | |
1908 | ✗ | goto fail; | |
1909 | } | ||
1910 | } | ||
1911 | 6425 | avfilter_inout_free(&outputs); | |
1912 | |||
1913 |
2/2✓ Branch 0 taken 4659 times.
✓ Branch 1 taken 1766 times.
|
6425 | if (fgp->disable_conversions) |
1914 | 4659 | avfilter_graph_set_auto_convert(fgt->graph, AVFILTER_AUTO_CONVERT_NONE); | |
1915 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 6425 times.
|
6425 | if ((ret = avfilter_graph_config(fgt->graph, NULL)) < 0) |
1916 | ✗ | goto fail; | |
1917 | |||
1918 | 6425 | fgp->is_meta = graph_is_meta(fgt->graph); | |
1919 | |||
1920 | /* limit the lists of allowed formats to the ones selected, to | ||
1921 | * make sure they stay the same if the filtergraph is reconfigured later */ | ||
1922 |
2/2✓ Branch 0 taken 6475 times.
✓ Branch 1 taken 6425 times.
|
12900 | for (int i = 0; i < fg->nb_outputs; i++) { |
1923 | 6475 | OutputFilter *ofilter = fg->outputs[i]; | |
1924 | 6475 | OutputFilterPriv *ofp = ofp_from_ofilter(ofilter); | |
1925 | 6475 | AVFilterContext *sink = ofp->filter; | |
1926 | |||
1927 | 6475 | ofp->format = av_buffersink_get_format(sink); | |
1928 | |||
1929 | 6475 | ofp->width = av_buffersink_get_w(sink); | |
1930 | 6475 | ofp->height = av_buffersink_get_h(sink); | |
1931 | |||
1932 | // If the timing parameters are not locked yet, get the tentative values | ||
1933 | // here but don't lock them. They will only be used if no output frames | ||
1934 | // are ever produced. | ||
1935 |
2/2✓ Branch 0 taken 6434 times.
✓ Branch 1 taken 41 times.
|
6475 | if (!ofp->tb_out_locked) { |
1936 | 6434 | AVRational fr = av_buffersink_get_frame_rate(sink); | |
1937 |
3/4✓ Branch 0 taken 6413 times.
✓ Branch 1 taken 21 times.
✓ Branch 2 taken 6413 times.
✗ Branch 3 not taken.
|
6434 | if (ofp->fps.framerate.num <= 0 && ofp->fps.framerate.den <= 0 && |
1938 |
4/4✓ Branch 0 taken 5169 times.
✓ Branch 1 taken 1244 times.
✓ Branch 2 taken 5164 times.
✓ Branch 3 taken 5 times.
|
6413 | fr.num > 0 && fr.den > 0) |
1939 | 5164 | ofp->fps.framerate = fr; | |
1940 | 6434 | ofp->tb_out = av_buffersink_get_time_base(sink); | |
1941 | } | ||
1942 | 6475 | ofp->sample_aspect_ratio = av_buffersink_get_sample_aspect_ratio(sink); | |
1943 | |||
1944 | 6475 | ofp->sample_rate = av_buffersink_get_sample_rate(sink); | |
1945 | 6475 | av_channel_layout_uninit(&ofp->ch_layout); | |
1946 | 6475 | ret = av_buffersink_get_ch_layout(sink, &ofp->ch_layout); | |
1947 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6475 times.
|
6475 | if (ret < 0) |
1948 | ✗ | goto fail; | |
1949 | } | ||
1950 | |||
1951 |
2/2✓ Branch 0 taken 6440 times.
✓ Branch 1 taken 6425 times.
|
12865 | for (int i = 0; i < fg->nb_inputs; i++) { |
1952 | 6440 | InputFilterPriv *ifp = ifp_from_ifilter(fg->inputs[i]); | |
1953 | AVFrame *tmp; | ||
1954 |
2/2✓ Branch 1 taken 237 times.
✓ Branch 2 taken 6440 times.
|
6677 | while (av_fifo_read(ifp->frame_queue, &tmp, 1) >= 0) { |
1955 |
2/2✓ Branch 0 taken 38 times.
✓ Branch 1 taken 199 times.
|
237 | if (ifp->type_src == AVMEDIA_TYPE_SUBTITLE) { |
1956 | 38 | sub2video_frame(&ifp->ifilter, tmp, !fgt->graph); | |
1957 | } else { | ||
1958 | 199 | ret = av_buffersrc_add_frame(ifp->filter, tmp); | |
1959 | } | ||
1960 | 237 | av_frame_free(&tmp); | |
1961 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 237 times.
|
237 | if (ret < 0) |
1962 | ✗ | goto fail; | |
1963 | } | ||
1964 | } | ||
1965 | |||
1966 | /* send the EOFs for the finished inputs */ | ||
1967 |
2/2✓ Branch 0 taken 6440 times.
✓ Branch 1 taken 6425 times.
|
12865 | for (int i = 0; i < fg->nb_inputs; i++) { |
1968 | 6440 | InputFilterPriv *ifp = ifp_from_ifilter(fg->inputs[i]); | |
1969 |
2/2✓ Branch 0 taken 7 times.
✓ Branch 1 taken 6433 times.
|
6440 | if (fgt->eof_in[i]) { |
1970 | 7 | ret = av_buffersrc_add_frame(ifp->filter, NULL); | |
1971 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
|
7 | if (ret < 0) |
1972 | ✗ | goto fail; | |
1973 | 7 | have_input_eof = 1; | |
1974 | } | ||
1975 | } | ||
1976 | |||
1977 |
2/2✓ Branch 0 taken 7 times.
✓ Branch 1 taken 6418 times.
|
6425 | if (have_input_eof) { |
1978 | // make sure the EOF propagates to the end of the graph | ||
1979 | 7 | ret = avfilter_graph_request_oldest(fgt->graph); | |
1980 |
4/6✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 3 times.
|
7 | if (ret < 0 && ret != AVERROR(EAGAIN) && ret != AVERROR_EOF) |
1981 | ✗ | goto fail; | |
1982 | } | ||
1983 | |||
1984 | 6425 | return 0; | |
1985 | ✗ | fail: | |
1986 | ✗ | cleanup_filtergraph(fg, fgt); | |
1987 | ✗ | return ret; | |
1988 | } | ||
1989 | |||
1990 | 6433 | static int ifilter_parameters_from_frame(InputFilter *ifilter, const AVFrame *frame) | |
1991 | { | ||
1992 | 6433 | InputFilterPriv *ifp = ifp_from_ifilter(ifilter); | |
1993 | AVFrameSideData *sd; | ||
1994 | int ret; | ||
1995 | |||
1996 | 6433 | ret = av_buffer_replace(&ifp->hw_frames_ctx, frame->hw_frames_ctx); | |
1997 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6433 times.
|
6433 | if (ret < 0) |
1998 | ✗ | return ret; | |
1999 | |||
2000 |
2/2✓ Branch 0 taken 1238 times.
✓ Branch 1 taken 5195 times.
|
11603 | ifp->time_base = (ifp->type == AVMEDIA_TYPE_AUDIO) ? (AVRational){ 1, frame->sample_rate } : |
2001 |
2/2✓ Branch 0 taken 25 times.
✓ Branch 1 taken 5170 times.
|
5195 | (ifp->opts.flags & IFILTER_FLAG_CFR) ? av_inv_q(ifp->opts.framerate) : |
2002 | frame->time_base; | ||
2003 | |||
2004 | 6433 | ifp->format = frame->format; | |
2005 | |||
2006 | 6433 | ifp->width = frame->width; | |
2007 | 6433 | ifp->height = frame->height; | |
2008 | 6433 | ifp->sample_aspect_ratio = frame->sample_aspect_ratio; | |
2009 | 6433 | ifp->color_space = frame->colorspace; | |
2010 | 6433 | ifp->color_range = frame->color_range; | |
2011 | |||
2012 | 6433 | ifp->sample_rate = frame->sample_rate; | |
2013 | 6433 | ret = av_channel_layout_copy(&ifp->ch_layout, &frame->ch_layout); | |
2014 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6433 times.
|
6433 | if (ret < 0) |
2015 | ✗ | return ret; | |
2016 | |||
2017 | 6433 | sd = av_frame_get_side_data(frame, AV_FRAME_DATA_DISPLAYMATRIX); | |
2018 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 6432 times.
|
6433 | if (sd) |
2019 | 1 | memcpy(ifp->displaymatrix, sd->data, sizeof(ifp->displaymatrix)); | |
2020 | 6433 | ifp->displaymatrix_present = !!sd; | |
2021 | |||
2022 | 6433 | return 0; | |
2023 | } | ||
2024 | |||
2025 | 32039 | int filtergraph_is_simple(const FilterGraph *fg) | |
2026 | { | ||
2027 | 32039 | const FilterGraphPriv *fgp = cfgp_from_cfg(fg); | |
2028 | 32039 | return fgp->is_simple; | |
2029 | } | ||
2030 | |||
2031 | ✗ | static void send_command(FilterGraph *fg, AVFilterGraph *graph, | |
2032 | double time, const char *target, | ||
2033 | const char *command, const char *arg, int all_filters) | ||
2034 | { | ||
2035 | int ret; | ||
2036 | |||
2037 | ✗ | if (!graph) | |
2038 | ✗ | return; | |
2039 | |||
2040 | ✗ | if (time < 0) { | |
2041 | char response[4096]; | ||
2042 | ✗ | ret = avfilter_graph_send_command(graph, target, command, arg, | |
2043 | response, sizeof(response), | ||
2044 | all_filters ? 0 : AVFILTER_CMD_FLAG_ONE); | ||
2045 | ✗ | fprintf(stderr, "Command reply for stream %d: ret:%d res:\n%s", | |
2046 | fg->index, ret, response); | ||
2047 | ✗ | } else if (!all_filters) { | |
2048 | ✗ | fprintf(stderr, "Queuing commands only on filters supporting the specific command is unsupported\n"); | |
2049 | } else { | ||
2050 | ✗ | ret = avfilter_graph_queue_command(graph, target, command, arg, 0, time); | |
2051 | ✗ | if (ret < 0) | |
2052 | ✗ | fprintf(stderr, "Queuing command failed with error %s\n", av_err2str(ret)); | |
2053 | } | ||
2054 | } | ||
2055 | |||
2056 | 353186 | static int choose_input(const FilterGraph *fg, const FilterGraphThread *fgt) | |
2057 | { | ||
2058 | 353186 | int nb_requests, nb_requests_max = -1; | |
2059 | 353186 | int best_input = -1; | |
2060 | |||
2061 |
2/2✓ Branch 0 taken 364385 times.
✓ Branch 1 taken 353186 times.
|
717571 | for (int i = 0; i < fg->nb_inputs; i++) { |
2062 | 364385 | InputFilter *ifilter = fg->inputs[i]; | |
2063 | 364385 | InputFilterPriv *ifp = ifp_from_ifilter(ifilter); | |
2064 | |||
2065 |
2/2✓ Branch 0 taken 1227 times.
✓ Branch 1 taken 363158 times.
|
364385 | if (fgt->eof_in[i]) |
2066 | 1227 | continue; | |
2067 | |||
2068 | 363158 | nb_requests = av_buffersrc_get_nb_failed_requests(ifp->filter); | |
2069 |
2/2✓ Branch 0 taken 355127 times.
✓ Branch 1 taken 8031 times.
|
363158 | if (nb_requests > nb_requests_max) { |
2070 | 355127 | nb_requests_max = nb_requests; | |
2071 | 355127 | best_input = i; | |
2072 | } | ||
2073 | } | ||
2074 | |||
2075 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 353186 times.
|
353186 | av_assert0(best_input >= 0); |
2076 | |||
2077 | 353186 | return best_input; | |
2078 | } | ||
2079 | |||
2080 | 6431 | static int choose_out_timebase(OutputFilterPriv *ofp, AVFrame *frame) | |
2081 | { | ||
2082 | 6431 | OutputFilter *ofilter = &ofp->ofilter; | |
2083 | 6431 | FPSConvContext *fps = &ofp->fps; | |
2084 | 6431 | AVRational tb = (AVRational){ 0, 0 }; | |
2085 | AVRational fr; | ||
2086 | const FrameData *fd; | ||
2087 | |||
2088 | 6431 | fd = frame_data_c(frame); | |
2089 | |||
2090 | // apply -enc_time_base | ||
2091 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 6430 times.
|
6431 | if (ofp->enc_timebase.num == ENC_TIME_BASE_DEMUX && |
2092 |
2/4✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
|
1 | (fd->dec.tb.num <= 0 || fd->dec.tb.den <= 0)) { |
2093 | ✗ | av_log(ofp, AV_LOG_ERROR, | |
2094 | "Demuxing timebase not available - cannot use it for encoding\n"); | ||
2095 | ✗ | return AVERROR(EINVAL); | |
2096 | } | ||
2097 | |||
2098 |
2/4✓ Branch 0 taken 6430 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
6431 | switch (ofp->enc_timebase.num) { |
2099 | 6430 | case 0: break; | |
2100 | 1 | case ENC_TIME_BASE_DEMUX: tb = fd->dec.tb; break; | |
2101 | ✗ | case ENC_TIME_BASE_FILTER: tb = frame->time_base; break; | |
2102 | ✗ | default: tb = ofp->enc_timebase; break; | |
2103 | } | ||
2104 | |||
2105 |
2/2✓ Branch 0 taken 1239 times.
✓ Branch 1 taken 5192 times.
|
6431 | if (ofilter->type == AVMEDIA_TYPE_AUDIO) { |
2106 |
1/2✓ Branch 0 taken 1239 times.
✗ Branch 1 not taken.
|
1239 | tb = tb.num ? tb : (AVRational){ 1, frame->sample_rate }; |
2107 | 1239 | goto finish; | |
2108 | } | ||
2109 | |||
2110 | 5192 | fr = fps->framerate; | |
2111 |
2/2✓ Branch 0 taken 7 times.
✓ Branch 1 taken 5185 times.
|
5192 | if (!fr.num) { |
2112 | 7 | AVRational fr_sink = av_buffersink_get_frame_rate(ofp->filter); | |
2113 |
3/4✓ Branch 0 taken 5 times.
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
|
7 | if (fr_sink.num > 0 && fr_sink.den > 0) |
2114 | ✗ | fr = fr_sink; | |
2115 | } | ||
2116 | |||
2117 |
4/4✓ Branch 0 taken 5140 times.
✓ Branch 1 taken 52 times.
✓ Branch 2 taken 442 times.
✓ Branch 3 taken 4698 times.
|
5192 | if (fps->vsync_method == VSYNC_CFR || fps->vsync_method == VSYNC_VSCFR) { |
2118 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 494 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
494 | if (!fr.num && !fps->framerate_max.num) { |
2119 | ✗ | fr = (AVRational){25, 1}; | |
2120 | ✗ | av_log(ofp, AV_LOG_WARNING, | |
2121 | "No information " | ||
2122 | "about the input framerate is available. Falling " | ||
2123 | "back to a default value of 25fps. Use the -r option " | ||
2124 | "if you want a different framerate.\n"); | ||
2125 | } | ||
2126 | |||
2127 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 494 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
494 | if (fps->framerate_max.num && |
2128 | ✗ | (av_q2d(fr) > av_q2d(fps->framerate_max) || | |
2129 | ✗ | !fr.den)) | |
2130 | ✗ | fr = fps->framerate_max; | |
2131 | } | ||
2132 | |||
2133 |
2/2✓ Branch 0 taken 5185 times.
✓ Branch 1 taken 7 times.
|
5192 | if (fr.num > 0) { |
2134 |
2/2✓ Branch 0 taken 54 times.
✓ Branch 1 taken 5131 times.
|
5185 | if (fps->framerate_supported) { |
2135 | 54 | int idx = av_find_nearest_q_idx(fr, fps->framerate_supported); | |
2136 | 54 | fr = fps->framerate_supported[idx]; | |
2137 | } | ||
2138 |
2/2✓ Branch 0 taken 60 times.
✓ Branch 1 taken 5125 times.
|
5185 | if (fps->framerate_clip) { |
2139 | 60 | av_reduce(&fr.num, &fr.den, | |
2140 | 60 | fr.num, fr.den, fps->framerate_clip); | |
2141 | } | ||
2142 | } | ||
2143 | |||
2144 |
3/4✓ Branch 0 taken 1 times.
✓ Branch 1 taken 5191 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
|
5192 | if (!(tb.num > 0 && tb.den > 0)) |
2145 | 5191 | tb = av_inv_q(fr); | |
2146 |
3/4✓ Branch 0 taken 5185 times.
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 5185 times.
|
5192 | if (!(tb.num > 0 && tb.den > 0)) |
2147 | 7 | tb = frame->time_base; | |
2148 | |||
2149 | 5192 | fps->framerate = fr; | |
2150 | 6431 | finish: | |
2151 | 6431 | ofp->tb_out = tb; | |
2152 | 6431 | ofp->tb_out_locked = 1; | |
2153 | |||
2154 | 6431 | return 0; | |
2155 | } | ||
2156 | |||
2157 | 108344 | static double adjust_frame_pts_to_encoder_tb(AVFrame *frame, AVRational tb_dst, | |
2158 | int64_t start_time) | ||
2159 | { | ||
2160 | 108344 | double float_pts = AV_NOPTS_VALUE; // this is identical to frame.pts but with higher precision | |
2161 | |||
2162 | 108344 | AVRational tb = tb_dst; | |
2163 | 108344 | AVRational filter_tb = frame->time_base; | |
2164 | 108344 | const int extra_bits = av_clip(29 - av_log2(tb.den), 0, 16); | |
2165 | |||
2166 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 108344 times.
|
108344 | if (frame->pts == AV_NOPTS_VALUE) |
2167 | ✗ | goto early_exit; | |
2168 | |||
2169 | 108344 | tb.den <<= extra_bits; | |
2170 | 108344 | float_pts = av_rescale_q(frame->pts, filter_tb, tb) - | |
2171 | 108344 | av_rescale_q(start_time, AV_TIME_BASE_Q, tb); | |
2172 | 108344 | float_pts /= 1 << extra_bits; | |
2173 | // when float_pts is not exactly an integer, | ||
2174 | // avoid exact midpoints to reduce the chance of rounding differences, this | ||
2175 | // can be removed in case the fps code is changed to work with integers | ||
2176 |
2/2✓ Branch 0 taken 6056 times.
✓ Branch 1 taken 102288 times.
|
108344 | if (float_pts != llrint(float_pts)) |
2177 |
1/2✓ Branch 0 taken 6056 times.
✗ Branch 1 not taken.
|
6056 | float_pts += FFSIGN(float_pts) * 1.0 / (1<<17); |
2178 | |||
2179 | 108344 | frame->pts = av_rescale_q(frame->pts, filter_tb, tb_dst) - | |
2180 | 108344 | av_rescale_q(start_time, AV_TIME_BASE_Q, tb_dst); | |
2181 | 108344 | frame->time_base = tb_dst; | |
2182 | |||
2183 | 108344 | early_exit: | |
2184 | |||
2185 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 108344 times.
|
108344 | if (debug_ts) { |
2186 | ✗ | av_log(NULL, AV_LOG_INFO, "filter -> pts:%s pts_time:%s exact:%f time_base:%d/%d\n", | |
2187 | ✗ | frame ? av_ts2str(frame->pts) : "NULL", | |
2188 | ✗ | av_ts2timestr(frame->pts, &tb_dst), | |
2189 | float_pts, tb_dst.num, tb_dst.den); | ||
2190 | } | ||
2191 | |||
2192 | 108344 | return float_pts; | |
2193 | } | ||
2194 | |||
2195 | /* Convert frame timestamps to the encoder timebase and decide how many times | ||
2196 | * should this (and possibly previous) frame be repeated in order to conform to | ||
2197 | * desired target framerate (if any). | ||
2198 | */ | ||
2199 | 110913 | static void video_sync_process(OutputFilterPriv *ofp, AVFrame *frame, | |
2200 | int64_t *nb_frames, int64_t *nb_frames_prev) | ||
2201 | { | ||
2202 | 110913 | OutputFilter *ofilter = &ofp->ofilter; | |
2203 | 110913 | FPSConvContext *fps = &ofp->fps; | |
2204 | double delta0, delta, sync_ipts, duration; | ||
2205 | |||
2206 |
2/2✓ Branch 0 taken 2569 times.
✓ Branch 1 taken 108344 times.
|
110913 | if (!frame) { |
2207 | 2569 | *nb_frames_prev = *nb_frames = mid_pred(fps->frames_prev_hist[0], | |
2208 | 2569 | fps->frames_prev_hist[1], | |
2209 | 2569 | fps->frames_prev_hist[2]); | |
2210 | |||
2211 |
4/4✓ Branch 0 taken 2568 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 2565 times.
|
2569 | if (!*nb_frames && fps->last_dropped) { |
2212 | 3 | atomic_fetch_add(&ofilter->nb_frames_drop, 1); | |
2213 | 3 | fps->last_dropped++; | |
2214 | } | ||
2215 | |||
2216 | 2569 | goto finish; | |
2217 | } | ||
2218 | |||
2219 | 108344 | duration = frame->duration * av_q2d(frame->time_base) / av_q2d(ofp->tb_out); | |
2220 | |||
2221 | 108344 | sync_ipts = adjust_frame_pts_to_encoder_tb(frame, ofp->tb_out, ofp->ts_offset); | |
2222 | /* delta0 is the "drift" between the input frame and | ||
2223 | * where it would fall in the output. */ | ||
2224 | 108344 | delta0 = sync_ipts - ofp->next_pts; | |
2225 | 108344 | delta = delta0 + duration; | |
2226 | |||
2227 | // tracks the number of times the PREVIOUS frame should be duplicated, | ||
2228 | // mostly for variable framerate (VFR) | ||
2229 | 108344 | *nb_frames_prev = 0; | |
2230 | /* by default, we output a single frame */ | ||
2231 | 108344 | *nb_frames = 1; | |
2232 | |||
2233 |
4/4✓ Branch 0 taken 5029 times.
✓ Branch 1 taken 103315 times.
✓ Branch 2 taken 3844 times.
✓ Branch 3 taken 1185 times.
|
108344 | if (delta0 < 0 && |
2234 | 3844 | delta > 0 && | |
2235 |
1/2✓ Branch 0 taken 3844 times.
✗ Branch 1 not taken.
|
3844 | fps->vsync_method != VSYNC_PASSTHROUGH |
2236 | #if FFMPEG_OPT_VSYNC_DROP | ||
2237 |
1/2✓ Branch 0 taken 3844 times.
✗ Branch 1 not taken.
|
3844 | && fps->vsync_method != VSYNC_DROP |
2238 | #endif | ||
2239 | ) { | ||
2240 |
2/2✓ Branch 0 taken 45 times.
✓ Branch 1 taken 3799 times.
|
3844 | if (delta0 < -0.6) { |
2241 | 45 | av_log(ofp, AV_LOG_VERBOSE, "Past duration %f too large\n", -delta0); | |
2242 | } else | ||
2243 | 3799 | av_log(ofp, AV_LOG_DEBUG, "Clipping frame in rate conversion by %f\n", -delta0); | |
2244 | 3844 | sync_ipts = ofp->next_pts; | |
2245 | 3844 | duration += delta0; | |
2246 | 3844 | delta0 = 0; | |
2247 | } | ||
2248 | |||
2249 |
4/5✓ Branch 0 taken 10236 times.
✓ Branch 1 taken 1470 times.
✓ Branch 2 taken 75222 times.
✓ Branch 3 taken 21416 times.
✗ Branch 4 not taken.
|
108344 | switch (fps->vsync_method) { |
2250 | 10236 | case VSYNC_VSCFR: | |
2251 |
3/4✓ Branch 0 taken 442 times.
✓ Branch 1 taken 9794 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 442 times.
|
10236 | if (fps->frame_number == 0 && delta0 >= 0.5) { |
2252 | ✗ | av_log(ofp, AV_LOG_DEBUG, "Not duplicating %d initial frames\n", (int)lrintf(delta0)); | |
2253 | ✗ | delta = duration; | |
2254 | ✗ | delta0 = 0; | |
2255 | ✗ | ofp->next_pts = llrint(sync_ipts); | |
2256 | } | ||
2257 | case VSYNC_CFR: | ||
2258 | // FIXME set to 0.5 after we fix some dts/pts bugs like in avidec.c | ||
2259 |
1/6✗ Branch 0 not taken.
✓ Branch 1 taken 11706 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
11706 | if (frame_drop_threshold && delta < frame_drop_threshold && fps->frame_number) { |
2260 | ✗ | *nb_frames = 0; | |
2261 |
2/2✓ Branch 0 taken 375 times.
✓ Branch 1 taken 11331 times.
|
11706 | } else if (delta < -1.1) |
2262 | 375 | *nb_frames = 0; | |
2263 |
2/2✓ Branch 0 taken 727 times.
✓ Branch 1 taken 10604 times.
|
11331 | else if (delta > 1.1) { |
2264 | 727 | *nb_frames = llrintf(delta); | |
2265 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 725 times.
|
727 | if (delta0 > 1.1) |
2266 | 2 | *nb_frames_prev = llrintf(delta0 - 0.6); | |
2267 | } | ||
2268 | 11706 | frame->duration = 1; | |
2269 | 11706 | break; | |
2270 | 75222 | case VSYNC_VFR: | |
2271 |
2/2✓ Branch 0 taken 100 times.
✓ Branch 1 taken 75122 times.
|
75222 | if (delta <= -0.6) |
2272 | 100 | *nb_frames = 0; | |
2273 |
2/2✓ Branch 0 taken 58069 times.
✓ Branch 1 taken 17053 times.
|
75122 | else if (delta > 0.6) |
2274 | 58069 | ofp->next_pts = llrint(sync_ipts); | |
2275 | 75222 | frame->duration = llrint(duration); | |
2276 | 75222 | break; | |
2277 | #if FFMPEG_OPT_VSYNC_DROP | ||
2278 | 21416 | case VSYNC_DROP: | |
2279 | #endif | ||
2280 | case VSYNC_PASSTHROUGH: | ||
2281 | 21416 | ofp->next_pts = llrint(sync_ipts); | |
2282 | 21416 | frame->duration = llrint(duration); | |
2283 | 21416 | break; | |
2284 | ✗ | default: | |
2285 | ✗ | av_assert0(0); | |
2286 | } | ||
2287 | |||
2288 | 110913 | finish: | |
2289 | 110913 | memmove(fps->frames_prev_hist + 1, | |
2290 | 110913 | fps->frames_prev_hist, | |
2291 | sizeof(fps->frames_prev_hist[0]) * (FF_ARRAY_ELEMS(fps->frames_prev_hist) - 1)); | ||
2292 | 110913 | fps->frames_prev_hist[0] = *nb_frames_prev; | |
2293 | |||
2294 |
4/4✓ Branch 0 taken 110910 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 475 times.
✓ Branch 3 taken 110435 times.
|
110913 | if (*nb_frames_prev == 0 && fps->last_dropped) { |
2295 | 475 | atomic_fetch_add(&ofilter->nb_frames_drop, 1); | |
2296 | 475 | av_log(ofp, AV_LOG_VERBOSE, | |
2297 | "*** dropping frame %"PRId64" at ts %"PRId64"\n", | ||
2298 | 475 | fps->frame_number, fps->last_frame->pts); | |
2299 | } | ||
2300 |
5/6✓ Branch 0 taken 3 times.
✓ Branch 1 taken 110910 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 269 times.
✓ Branch 5 taken 110644 times.
|
110913 | if (*nb_frames > (*nb_frames_prev && fps->last_dropped) + (*nb_frames > *nb_frames_prev)) { |
2301 | uint64_t nb_frames_dup; | ||
2302 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 269 times.
|
269 | if (*nb_frames > dts_error_threshold * 30) { |
2303 | ✗ | av_log(ofp, AV_LOG_ERROR, "%"PRId64" frame duplication too large, skipping\n", *nb_frames - 1); | |
2304 | ✗ | atomic_fetch_add(&ofilter->nb_frames_drop, 1); | |
2305 | ✗ | *nb_frames = 0; | |
2306 | ✗ | return; | |
2307 | } | ||
2308 |
3/4✓ Branch 0 taken 3 times.
✓ Branch 1 taken 266 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
|
269 | nb_frames_dup = atomic_fetch_add(&ofilter->nb_frames_dup, |
2309 | *nb_frames - (*nb_frames_prev && fps->last_dropped) - (*nb_frames > *nb_frames_prev)); | ||
2310 | 269 | av_log(ofp, AV_LOG_VERBOSE, "*** %"PRId64" dup!\n", *nb_frames - 1); | |
2311 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 269 times.
|
269 | if (nb_frames_dup > fps->dup_warning) { |
2312 | ✗ | av_log(ofp, AV_LOG_WARNING, "More than %"PRIu64" frames duplicated\n", fps->dup_warning); | |
2313 | ✗ | fps->dup_warning *= 10; | |
2314 | } | ||
2315 | } | ||
2316 | |||
2317 |
4/4✓ Branch 0 taken 3044 times.
✓ Branch 1 taken 107869 times.
✓ Branch 2 taken 475 times.
✓ Branch 3 taken 2569 times.
|
110913 | fps->last_dropped = *nb_frames == *nb_frames_prev && frame; |
2318 |
4/4✓ Branch 0 taken 475 times.
✓ Branch 1 taken 110438 times.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 468 times.
|
110913 | fps->dropped_keyframe |= fps->last_dropped && (frame->flags & AV_FRAME_FLAG_KEY); |
2319 | } | ||
2320 | |||
2321 | 3781 | static int close_output(OutputFilterPriv *ofp, FilterGraphThread *fgt) | |
2322 | { | ||
2323 | 3781 | FilterGraphPriv *fgp = fgp_from_fg(ofp->ofilter.graph); | |
2324 | int ret; | ||
2325 | |||
2326 | // we are finished and no frames were ever seen at this output, | ||
2327 | // at least initialize the encoder with a dummy frame | ||
2328 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3778 times.
|
3781 | if (!fgt->got_frame) { |
2329 | 3 | AVFrame *frame = fgt->frame; | |
2330 | FrameData *fd; | ||
2331 | |||
2332 | 3 | frame->time_base = ofp->tb_out; | |
2333 | 3 | frame->format = ofp->format; | |
2334 | |||
2335 | 3 | frame->width = ofp->width; | |
2336 | 3 | frame->height = ofp->height; | |
2337 | 3 | frame->sample_aspect_ratio = ofp->sample_aspect_ratio; | |
2338 | |||
2339 | 3 | frame->sample_rate = ofp->sample_rate; | |
2340 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | if (ofp->ch_layout.nb_channels) { |
2341 | 3 | ret = av_channel_layout_copy(&frame->ch_layout, &ofp->ch_layout); | |
2342 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | if (ret < 0) |
2343 | ✗ | return ret; | |
2344 | } | ||
2345 | |||
2346 | 3 | fd = frame_data(frame); | |
2347 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | if (!fd) |
2348 | ✗ | return AVERROR(ENOMEM); | |
2349 | |||
2350 | 3 | fd->frame_rate_filter = ofp->fps.framerate; | |
2351 | |||
2352 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | av_assert0(!frame->buf[0]); |
2353 | |||
2354 | 3 | av_log(ofp, AV_LOG_WARNING, | |
2355 | "No filtered frames for output stream, trying to " | ||
2356 | "initialize anyway.\n"); | ||
2357 | |||
2358 | 3 | ret = sch_filter_send(fgp->sch, fgp->sch_idx, ofp->index, frame); | |
2359 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | if (ret < 0) { |
2360 | ✗ | av_frame_unref(frame); | |
2361 | ✗ | return ret; | |
2362 | } | ||
2363 | } | ||
2364 | |||
2365 | 3781 | fgt->eof_out[ofp->index] = 1; | |
2366 | |||
2367 | 3781 | ret = sch_filter_send(fgp->sch, fgp->sch_idx, ofp->index, NULL); | |
2368 |
2/2✓ Branch 0 taken 3655 times.
✓ Branch 1 taken 126 times.
|
3781 | return (ret == AVERROR_EOF) ? 0 : ret; |
2369 | } | ||
2370 | |||
2371 | 360927 | static int fg_output_frame(OutputFilterPriv *ofp, FilterGraphThread *fgt, | |
2372 | AVFrame *frame) | ||
2373 | { | ||
2374 | 360927 | FilterGraphPriv *fgp = fgp_from_fg(ofp->ofilter.graph); | |
2375 | 360927 | AVFrame *frame_prev = ofp->fps.last_frame; | |
2376 | 360927 | enum AVMediaType type = ofp->ofilter.type; | |
2377 | |||
2378 | 360927 | int64_t nb_frames = !!frame, nb_frames_prev = 0; | |
2379 | |||
2380 |
5/6✓ Branch 0 taken 110913 times.
✓ Branch 1 taken 250014 times.
✓ Branch 2 taken 2569 times.
✓ Branch 3 taken 108344 times.
✓ Branch 4 taken 2569 times.
✗ Branch 5 not taken.
|
360927 | if (type == AVMEDIA_TYPE_VIDEO && (frame || fgt->got_frame)) |
2381 | 110913 | video_sync_process(ofp, frame, &nb_frames, &nb_frames_prev); | |
2382 | |||
2383 |
2/2✓ Branch 0 taken 357102 times.
✓ Branch 1 taken 358274 times.
|
715376 | for (int64_t i = 0; i < nb_frames; i++) { |
2384 | AVFrame *frame_out; | ||
2385 | int ret; | ||
2386 | |||
2387 |
2/2✓ Branch 0 taken 108300 times.
✓ Branch 1 taken 248802 times.
|
357102 | if (type == AVMEDIA_TYPE_VIDEO) { |
2388 |
1/2✓ Branch 0 taken 69 times.
✗ Branch 1 not taken.
|
69 | AVFrame *frame_in = (i < nb_frames_prev && frame_prev->buf[0]) ? |
2389 |
2/2✓ Branch 0 taken 69 times.
✓ Branch 1 taken 108231 times.
|
108369 | frame_prev : frame; |
2390 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 108300 times.
|
108300 | if (!frame_in) |
2391 | ✗ | break; | |
2392 | |||
2393 | 108300 | frame_out = fgp->frame_enc; | |
2394 | 108300 | ret = av_frame_ref(frame_out, frame_in); | |
2395 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 108300 times.
|
108300 | if (ret < 0) |
2396 | ✗ | return ret; | |
2397 | |||
2398 | 108300 | frame_out->pts = ofp->next_pts; | |
2399 | |||
2400 |
2/2✓ Branch 0 taken 7 times.
✓ Branch 1 taken 108293 times.
|
108300 | if (ofp->fps.dropped_keyframe) { |
2401 | 7 | frame_out->flags |= AV_FRAME_FLAG_KEY; | |
2402 | 7 | ofp->fps.dropped_keyframe = 0; | |
2403 | } | ||
2404 | } else { | ||
2405 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 248802 times.
|
248802 | frame->pts = (frame->pts == AV_NOPTS_VALUE) ? ofp->next_pts : |
2406 | 248802 | av_rescale_q(frame->pts, frame->time_base, ofp->tb_out) - | |
2407 | 248802 | av_rescale_q(ofp->ts_offset, AV_TIME_BASE_Q, ofp->tb_out); | |
2408 | |||
2409 | 248802 | frame->time_base = ofp->tb_out; | |
2410 | 248802 | frame->duration = av_rescale_q(frame->nb_samples, | |
2411 | 248802 | (AVRational){ 1, frame->sample_rate }, | |
2412 | ofp->tb_out); | ||
2413 | |||
2414 | 248802 | ofp->next_pts = frame->pts + frame->duration; | |
2415 | |||
2416 | 248802 | frame_out = frame; | |
2417 | } | ||
2418 | |||
2419 | // send the frame to consumers | ||
2420 | 357102 | ret = sch_filter_send(fgp->sch, fgp->sch_idx, ofp->index, frame_out); | |
2421 |
2/2✓ Branch 0 taken 2653 times.
✓ Branch 1 taken 354449 times.
|
357102 | if (ret < 0) { |
2422 | 2653 | av_frame_unref(frame_out); | |
2423 | |||
2424 |
1/2✓ Branch 0 taken 2653 times.
✗ Branch 1 not taken.
|
2653 | if (!fgt->eof_out[ofp->index]) { |
2425 | 2653 | fgt->eof_out[ofp->index] = 1; | |
2426 | 2653 | fgp->nb_outputs_done++; | |
2427 | } | ||
2428 | |||
2429 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2653 times.
|
2653 | return ret == AVERROR_EOF ? 0 : ret; |
2430 | } | ||
2431 | |||
2432 |
2/2✓ Branch 0 taken 105677 times.
✓ Branch 1 taken 248772 times.
|
354449 | if (type == AVMEDIA_TYPE_VIDEO) { |
2433 | 105677 | ofp->fps.frame_number++; | |
2434 | 105677 | ofp->next_pts++; | |
2435 | |||
2436 |
3/4✓ Branch 0 taken 105246 times.
✓ Branch 1 taken 431 times.
✓ Branch 2 taken 105246 times.
✗ Branch 3 not taken.
|
105677 | if (i == nb_frames_prev && frame) |
2437 | 105246 | frame->flags &= ~AV_FRAME_FLAG_KEY; | |
2438 | } | ||
2439 | |||
2440 | 354449 | fgt->got_frame = 1; | |
2441 | } | ||
2442 | |||
2443 |
4/4✓ Branch 0 taken 354493 times.
✓ Branch 1 taken 3781 times.
✓ Branch 2 taken 105721 times.
✓ Branch 3 taken 248772 times.
|
358274 | if (frame && frame_prev) { |
2444 | 105721 | av_frame_unref(frame_prev); | |
2445 | 105721 | av_frame_move_ref(frame_prev, frame); | |
2446 | } | ||
2447 | |||
2448 |
2/2✓ Branch 0 taken 3781 times.
✓ Branch 1 taken 354493 times.
|
358274 | if (!frame) |
2449 | 3781 | return close_output(ofp, fgt); | |
2450 | |||
2451 | 354493 | return 0; | |
2452 | } | ||
2453 | |||
2454 | 717844 | static int fg_output_step(OutputFilterPriv *ofp, FilterGraphThread *fgt, | |
2455 | AVFrame *frame) | ||
2456 | { | ||
2457 | 717844 | FilterGraphPriv *fgp = fgp_from_fg(ofp->ofilter.graph); | |
2458 | 717844 | AVFilterContext *filter = ofp->filter; | |
2459 | FrameData *fd; | ||
2460 | int ret; | ||
2461 | |||
2462 | 717844 | ret = av_buffersink_get_frame_flags(filter, frame, | |
2463 | AV_BUFFERSINK_FLAG_NO_REQUEST); | ||
2464 |
4/4✓ Branch 0 taken 392 times.
✓ Branch 1 taken 717452 times.
✓ Branch 2 taken 15 times.
✓ Branch 3 taken 377 times.
|
717844 | if (ret == AVERROR_EOF && !fgt->eof_out[ofp->index]) { |
2465 | 15 | ret = fg_output_frame(ofp, fgt, NULL); | |
2466 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
|
15 | return (ret < 0) ? ret : 1; |
2467 |
4/4✓ Branch 0 taken 357525 times.
✓ Branch 1 taken 360304 times.
✓ Branch 2 taken 377 times.
✓ Branch 3 taken 357148 times.
|
717829 | } else if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { |
2468 | 360681 | return 1; | |
2469 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 357148 times.
|
357148 | } else if (ret < 0) { |
2470 | ✗ | av_log(ofp, AV_LOG_WARNING, | |
2471 | "Error in retrieving a frame from the filtergraph: %s\n", | ||
2472 | ✗ | av_err2str(ret)); | |
2473 | ✗ | return ret; | |
2474 | } | ||
2475 | |||
2476 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 357146 times.
|
357148 | if (fgt->eof_out[ofp->index]) { |
2477 | 2 | av_frame_unref(frame); | |
2478 | 2 | return 0; | |
2479 | } | ||
2480 | |||
2481 | 357146 | frame->time_base = av_buffersink_get_time_base(filter); | |
2482 | |||
2483 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 357146 times.
|
357146 | if (debug_ts) |
2484 | ✗ | av_log(ofp, AV_LOG_INFO, "filter_raw -> pts:%s pts_time:%s time_base:%d/%d\n", | |
2485 | ✗ | av_ts2str(frame->pts), av_ts2timestr(frame->pts, &frame->time_base), | |
2486 | frame->time_base.num, frame->time_base.den); | ||
2487 | |||
2488 | // Choose the output timebase the first time we get a frame. | ||
2489 |
2/2✓ Branch 0 taken 6431 times.
✓ Branch 1 taken 350715 times.
|
357146 | if (!ofp->tb_out_locked) { |
2490 | 6431 | ret = choose_out_timebase(ofp, frame); | |
2491 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6431 times.
|
6431 | if (ret < 0) { |
2492 | ✗ | av_log(ofp, AV_LOG_ERROR, "Could not choose an output time base\n"); | |
2493 | ✗ | av_frame_unref(frame); | |
2494 | ✗ | return ret; | |
2495 | } | ||
2496 | } | ||
2497 | |||
2498 | 357146 | fd = frame_data(frame); | |
2499 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 357146 times.
|
357146 | if (!fd) { |
2500 | ✗ | av_frame_unref(frame); | |
2501 | ✗ | return AVERROR(ENOMEM); | |
2502 | } | ||
2503 | |||
2504 | 357146 | fd->wallclock[LATENCY_PROBE_FILTER_POST] = av_gettime_relative(); | |
2505 | |||
2506 | // only use bits_per_raw_sample passed through from the decoder | ||
2507 | // if the filtergraph did not touch the frame data | ||
2508 |
2/2✓ Branch 0 taken 249722 times.
✓ Branch 1 taken 107424 times.
|
357146 | if (!fgp->is_meta) |
2509 | 249722 | fd->bits_per_raw_sample = 0; | |
2510 | |||
2511 |
2/2✓ Branch 0 taken 108344 times.
✓ Branch 1 taken 248802 times.
|
357146 | if (ofp->ofilter.type == AVMEDIA_TYPE_VIDEO) { |
2512 |
2/2✓ Branch 0 taken 1962 times.
✓ Branch 1 taken 106382 times.
|
108344 | if (!frame->duration) { |
2513 | 1962 | AVRational fr = av_buffersink_get_frame_rate(filter); | |
2514 |
4/4✓ Branch 0 taken 1869 times.
✓ Branch 1 taken 93 times.
✓ Branch 2 taken 1769 times.
✓ Branch 3 taken 100 times.
|
1962 | if (fr.num > 0 && fr.den > 0) |
2515 | 1769 | frame->duration = av_rescale_q(1, av_inv_q(fr), frame->time_base); | |
2516 | } | ||
2517 | |||
2518 | 108344 | fd->frame_rate_filter = ofp->fps.framerate; | |
2519 | } | ||
2520 | |||
2521 | 357146 | ret = fg_output_frame(ofp, fgt, frame); | |
2522 | 357146 | av_frame_unref(frame); | |
2523 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 357146 times.
|
357146 | if (ret < 0) |
2524 | ✗ | return ret; | |
2525 | |||
2526 | 357146 | return 0; | |
2527 | } | ||
2528 | |||
2529 | /* retrieve all frames available at filtergraph outputs | ||
2530 | * and send them to consumers */ | ||
2531 | 361418 | static int read_frames(FilterGraph *fg, FilterGraphThread *fgt, | |
2532 | AVFrame *frame) | ||
2533 | { | ||
2534 | 361418 | FilterGraphPriv *fgp = fgp_from_fg(fg); | |
2535 | 361418 | int did_step = 0; | |
2536 | |||
2537 | // graph not configured, just select the input to request | ||
2538 |
2/2✓ Branch 0 taken 241 times.
✓ Branch 1 taken 361177 times.
|
361418 | if (!fgt->graph) { |
2539 |
1/2✓ Branch 0 taken 535 times.
✗ Branch 1 not taken.
|
535 | for (int i = 0; i < fg->nb_inputs; i++) { |
2540 | 535 | InputFilterPriv *ifp = ifp_from_ifilter(fg->inputs[i]); | |
2541 |
3/4✓ Branch 0 taken 241 times.
✓ Branch 1 taken 294 times.
✓ Branch 2 taken 241 times.
✗ Branch 3 not taken.
|
535 | if (ifp->format < 0 && !fgt->eof_in[i]) { |
2542 | 241 | fgt->next_in = i; | |
2543 | 241 | return 0; | |
2544 | } | ||
2545 | } | ||
2546 | |||
2547 | // This state - graph is not configured, but all inputs are either | ||
2548 | // initialized or EOF - should be unreachable because sending EOF to a | ||
2549 | // filter without even a fallback format should fail | ||
2550 | ✗ | av_assert0(0); | |
2551 | return AVERROR_BUG; | ||
2552 | } | ||
2553 | |||
2554 |
2/2✓ Branch 0 taken 714616 times.
✓ Branch 1 taken 2653 times.
|
717269 | while (fgp->nb_outputs_done < fg->nb_outputs) { |
2555 | int ret; | ||
2556 | |||
2557 | 714616 | ret = avfilter_graph_request_oldest(fgt->graph); | |
2558 |
2/2✓ Branch 0 taken 353186 times.
✓ Branch 1 taken 361430 times.
|
714616 | if (ret == AVERROR(EAGAIN)) { |
2559 | 353186 | fgt->next_in = choose_input(fg, fgt); | |
2560 | 353186 | break; | |
2561 |
2/2✓ Branch 0 taken 3731 times.
✓ Branch 1 taken 357699 times.
|
361430 | } else if (ret < 0) { |
2562 |
1/2✓ Branch 0 taken 3731 times.
✗ Branch 1 not taken.
|
3731 | if (ret == AVERROR_EOF) |
2563 | 3731 | av_log(fg, AV_LOG_VERBOSE, "Filtergraph returned EOF, finishing\n"); | |
2564 | else | ||
2565 | ✗ | av_log(fg, AV_LOG_ERROR, | |
2566 | "Error requesting a frame from the filtergraph: %s\n", | ||
2567 | ✗ | av_err2str(ret)); | |
2568 | 3731 | return ret; | |
2569 | } | ||
2570 | 357699 | fgt->next_in = fg->nb_inputs; | |
2571 | |||
2572 | // return after one iteration, so that scheduler can rate-control us | ||
2573 |
4/4✓ Branch 0 taken 3620 times.
✓ Branch 1 taken 354079 times.
✓ Branch 2 taken 1607 times.
✓ Branch 3 taken 2013 times.
|
357699 | if (did_step && fgp->have_sources) |
2574 | 1607 | return 0; | |
2575 | |||
2576 | /* Reap all buffers present in the buffer sinks */ | ||
2577 |
2/2✓ Branch 0 taken 360696 times.
✓ Branch 1 taken 356092 times.
|
716788 | for (int i = 0; i < fg->nb_outputs; i++) { |
2578 | 360696 | OutputFilterPriv *ofp = ofp_from_ofilter(fg->outputs[i]); | |
2579 | |||
2580 | 360696 | ret = 0; | |
2581 |
2/2✓ Branch 0 taken 717844 times.
✓ Branch 1 taken 360696 times.
|
1078540 | while (!ret) { |
2582 | 717844 | ret = fg_output_step(ofp, fgt, frame); | |
2583 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 717844 times.
|
717844 | if (ret < 0) |
2584 | ✗ | return ret; | |
2585 | } | ||
2586 | } | ||
2587 | 356092 | did_step = 1; | |
2588 | } | ||
2589 | |||
2590 |
2/2✓ Branch 0 taken 2653 times.
✓ Branch 1 taken 353186 times.
|
355839 | return (fgp->nb_outputs_done == fg->nb_outputs) ? AVERROR_EOF : 0; |
2591 | } | ||
2592 | |||
2593 | 948 | static void sub2video_heartbeat(InputFilter *ifilter, int64_t pts, AVRational tb) | |
2594 | { | ||
2595 | 948 | InputFilterPriv *ifp = ifp_from_ifilter(ifilter); | |
2596 | int64_t pts2; | ||
2597 | |||
2598 | /* subtitles seem to be usually muxed ahead of other streams; | ||
2599 | if not, subtracting a larger time here is necessary */ | ||
2600 | 948 | pts2 = av_rescale_q(pts, tb, ifp->time_base) - 1; | |
2601 | |||
2602 | /* do not send the heartbeat frame if the subtitle is already ahead */ | ||
2603 |
2/2✓ Branch 0 taken 769 times.
✓ Branch 1 taken 179 times.
|
948 | if (pts2 <= ifp->sub2video.last_pts) |
2604 | 769 | return; | |
2605 | |||
2606 |
3/4✓ Branch 0 taken 91 times.
✓ Branch 1 taken 88 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 91 times.
|
179 | if (pts2 >= ifp->sub2video.end_pts || ifp->sub2video.initialize) |
2607 | /* if we have hit the end of the current displayed subpicture, | ||
2608 | or if we need to initialize the system, update the | ||
2609 | overlayed subpicture and its start/end times */ | ||
2610 | 88 | sub2video_update(ifp, pts2 + 1, NULL); | |
2611 | else | ||
2612 | 91 | sub2video_push_ref(ifp, pts2); | |
2613 | } | ||
2614 | |||
2615 | 1078 | static int sub2video_frame(InputFilter *ifilter, AVFrame *frame, int buffer) | |
2616 | { | ||
2617 | 1078 | InputFilterPriv *ifp = ifp_from_ifilter(ifilter); | |
2618 | int ret; | ||
2619 | |||
2620 |
2/2✓ Branch 0 taken 38 times.
✓ Branch 1 taken 1040 times.
|
1078 | if (buffer) { |
2621 | AVFrame *tmp; | ||
2622 | |||
2623 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 38 times.
|
38 | if (!frame) |
2624 | ✗ | return 0; | |
2625 | |||
2626 | 38 | tmp = av_frame_alloc(); | |
2627 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 38 times.
|
38 | if (!tmp) |
2628 | ✗ | return AVERROR(ENOMEM); | |
2629 | |||
2630 | 38 | av_frame_move_ref(tmp, frame); | |
2631 | |||
2632 | 38 | ret = av_fifo_write(ifp->frame_queue, &tmp, 1); | |
2633 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 38 times.
|
38 | if (ret < 0) { |
2634 | ✗ | av_frame_free(&tmp); | |
2635 | ✗ | return ret; | |
2636 | } | ||
2637 | |||
2638 | 38 | return 0; | |
2639 | } | ||
2640 | |||
2641 | // heartbeat frame | ||
2642 |
4/4✓ Branch 0 taken 1036 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 948 times.
✓ Branch 3 taken 88 times.
|
1040 | if (frame && !frame->buf[0]) { |
2643 | 948 | sub2video_heartbeat(ifilter, frame->pts, frame->time_base); | |
2644 | 948 | return 0; | |
2645 | } | ||
2646 | |||
2647 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 88 times.
|
92 | if (!frame) { |
2648 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | if (ifp->sub2video.end_pts < INT64_MAX) |
2649 | 4 | sub2video_update(ifp, INT64_MAX, NULL); | |
2650 | |||
2651 | 4 | return av_buffersrc_add_frame(ifp->filter, NULL); | |
2652 | } | ||
2653 | |||
2654 |
1/2✓ Branch 0 taken 88 times.
✗ Branch 1 not taken.
|
88 | ifp->width = frame->width ? frame->width : ifp->width; |
2655 |
1/2✓ Branch 0 taken 88 times.
✗ Branch 1 not taken.
|
88 | ifp->height = frame->height ? frame->height : ifp->height; |
2656 | |||
2657 | 88 | sub2video_update(ifp, INT64_MIN, (const AVSubtitle*)frame->buf[0]->data); | |
2658 | |||
2659 | 88 | return 0; | |
2660 | } | ||
2661 | |||
2662 | 3192 | static int send_eof(FilterGraphThread *fgt, InputFilter *ifilter, | |
2663 | int64_t pts, AVRational tb) | ||
2664 | { | ||
2665 | 3192 | InputFilterPriv *ifp = ifp_from_ifilter(ifilter); | |
2666 | int ret; | ||
2667 | |||
2668 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3192 times.
|
3192 | if (fgt->eof_in[ifp->index]) |
2669 | ✗ | return 0; | |
2670 | |||
2671 | 3192 | fgt->eof_in[ifp->index] = 1; | |
2672 | |||
2673 |
2/2✓ Branch 0 taken 3185 times.
✓ Branch 1 taken 7 times.
|
3192 | if (ifp->filter) { |
2674 | 3185 | pts = av_rescale_q_rnd(pts, tb, ifp->time_base, | |
2675 | AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX); | ||
2676 | |||
2677 | 3185 | ret = av_buffersrc_close(ifp->filter, pts, AV_BUFFERSRC_FLAG_PUSH); | |
2678 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3185 times.
|
3185 | if (ret < 0) |
2679 | ✗ | return ret; | |
2680 | } else { | ||
2681 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 4 times.
|
7 | if (ifp->format < 0) { |
2682 | // the filtergraph was never configured, use the fallback parameters | ||
2683 | 3 | ifp->format = ifp->opts.fallback->format; | |
2684 | 3 | ifp->sample_rate = ifp->opts.fallback->sample_rate; | |
2685 | 3 | ifp->width = ifp->opts.fallback->width; | |
2686 | 3 | ifp->height = ifp->opts.fallback->height; | |
2687 | 3 | ifp->sample_aspect_ratio = ifp->opts.fallback->sample_aspect_ratio; | |
2688 | 3 | ifp->color_space = ifp->opts.fallback->colorspace; | |
2689 | 3 | ifp->color_range = ifp->opts.fallback->color_range; | |
2690 | 3 | ifp->time_base = ifp->opts.fallback->time_base; | |
2691 | |||
2692 | 3 | ret = av_channel_layout_copy(&ifp->ch_layout, | |
2693 | 3 | &ifp->opts.fallback->ch_layout); | |
2694 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | if (ret < 0) |
2695 | ✗ | return ret; | |
2696 | |||
2697 |
1/2✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
|
3 | if (ifilter_has_all_input_formats(ifilter->graph)) { |
2698 | 3 | ret = configure_filtergraph(ifilter->graph, fgt); | |
2699 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | if (ret < 0) { |
2700 | ✗ | av_log(NULL, AV_LOG_ERROR, "Error initializing filters!\n"); | |
2701 | ✗ | return ret; | |
2702 | } | ||
2703 | } | ||
2704 | } | ||
2705 | |||
2706 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
|
7 | if (ifp->format < 0) { |
2707 | ✗ | av_log(NULL, AV_LOG_ERROR, | |
2708 | "Cannot determine format of input %s after EOF\n", | ||
2709 | ifp->opts.name); | ||
2710 | ✗ | return AVERROR_INVALIDDATA; | |
2711 | } | ||
2712 | } | ||
2713 | |||
2714 | 3192 | return 0; | |
2715 | } | ||
2716 | |||
2717 | enum ReinitReason { | ||
2718 | VIDEO_CHANGED = (1 << 0), | ||
2719 | AUDIO_CHANGED = (1 << 1), | ||
2720 | MATRIX_CHANGED = (1 << 2), | ||
2721 | HWACCEL_CHANGED = (1 << 3) | ||
2722 | }; | ||
2723 | |||
2724 | 121 | static const char *unknown_if_null(const char *str) | |
2725 | { | ||
2726 |
1/2✓ Branch 0 taken 121 times.
✗ Branch 1 not taken.
|
121 | return str ? str : "unknown"; |
2727 | } | ||
2728 | |||
2729 | 355484 | static int send_frame(FilterGraph *fg, FilterGraphThread *fgt, | |
2730 | InputFilter *ifilter, AVFrame *frame) | ||
2731 | { | ||
2732 | 355484 | InputFilterPriv *ifp = ifp_from_ifilter(ifilter); | |
2733 | FrameData *fd; | ||
2734 | AVFrameSideData *sd; | ||
2735 | 355484 | int need_reinit = 0, ret; | |
2736 | |||
2737 | /* determine if the parameters for this input changed */ | ||
2738 |
2/3✓ Branch 0 taken 248091 times.
✓ Branch 1 taken 107393 times.
✗ Branch 2 not taken.
|
355484 | switch (ifp->type) { |
2739 | 248091 | case AVMEDIA_TYPE_AUDIO: | |
2740 |
2/2✓ Branch 0 taken 246854 times.
✓ Branch 1 taken 1237 times.
|
248091 | if (ifp->format != frame->format || |
2741 |
3/4✓ Branch 0 taken 246854 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 246853 times.
|
493708 | ifp->sample_rate != frame->sample_rate || |
2742 | 246854 | av_channel_layout_compare(&ifp->ch_layout, &frame->ch_layout)) | |
2743 | 1238 | need_reinit |= AUDIO_CHANGED; | |
2744 | 248091 | break; | |
2745 | 107393 | case AVMEDIA_TYPE_VIDEO: | |
2746 |
2/2✓ Branch 0 taken 102226 times.
✓ Branch 1 taken 5167 times.
|
107393 | if (ifp->format != frame->format || |
2747 |
2/2✓ Branch 0 taken 102203 times.
✓ Branch 1 taken 23 times.
|
102226 | ifp->width != frame->width || |
2748 |
2/2✓ Branch 0 taken 102198 times.
✓ Branch 1 taken 5 times.
|
102203 | ifp->height != frame->height || |
2749 |
1/2✓ Branch 0 taken 102198 times.
✗ Branch 1 not taken.
|
102198 | ifp->color_space != frame->colorspace || |
2750 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 102198 times.
|
102198 | ifp->color_range != frame->color_range) |
2751 | 5195 | need_reinit |= VIDEO_CHANGED; | |
2752 | 107393 | break; | |
2753 | } | ||
2754 | |||
2755 |
2/2✓ Branch 1 taken 105 times.
✓ Branch 2 taken 355379 times.
|
355484 | if (sd = av_frame_get_side_data(frame, AV_FRAME_DATA_DISPLAYMATRIX)) { |
2756 |
2/2✓ Branch 0 taken 104 times.
✓ Branch 1 taken 1 times.
|
105 | if (!ifp->displaymatrix_present || |
2757 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 104 times.
|
104 | memcmp(sd->data, ifp->displaymatrix, sizeof(ifp->displaymatrix))) |
2758 | 1 | need_reinit |= MATRIX_CHANGED; | |
2759 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 355379 times.
|
355379 | } else if (ifp->displaymatrix_present) |
2760 | ✗ | need_reinit |= MATRIX_CHANGED; | |
2761 | |||
2762 |
4/4✓ Branch 0 taken 50 times.
✓ Branch 1 taken 355434 times.
✓ Branch 2 taken 49 times.
✓ Branch 3 taken 1 times.
|
355484 | if (!(ifp->opts.flags & IFILTER_FLAG_REINIT) && fgt->graph) |
2763 | 49 | need_reinit = 0; | |
2764 | |||
2765 |
1/2✓ Branch 0 taken 355484 times.
✗ Branch 1 not taken.
|
355484 | if (!!ifp->hw_frames_ctx != !!frame->hw_frames_ctx || |
2766 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 355484 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
355484 | (ifp->hw_frames_ctx && ifp->hw_frames_ctx->data != frame->hw_frames_ctx->data)) |
2767 | ✗ | need_reinit |= HWACCEL_CHANGED; | |
2768 | |||
2769 |
2/2✓ Branch 0 taken 6433 times.
✓ Branch 1 taken 349051 times.
|
355484 | if (need_reinit) { |
2770 | 6433 | ret = ifilter_parameters_from_frame(ifilter, frame); | |
2771 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6433 times.
|
6433 | if (ret < 0) |
2772 | ✗ | return ret; | |
2773 | } | ||
2774 | |||
2775 | /* (re)init the graph if possible, otherwise buffer the frame and return */ | ||
2776 |
4/4✓ Branch 0 taken 349051 times.
✓ Branch 1 taken 6433 times.
✓ Branch 2 taken 131 times.
✓ Branch 3 taken 348920 times.
|
355484 | if (need_reinit || !fgt->graph) { |
2777 | 6564 | AVFrame *tmp = av_frame_alloc(); | |
2778 | |||
2779 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6564 times.
|
6564 | if (!tmp) |
2780 | 199 | return AVERROR(ENOMEM); | |
2781 | |||
2782 |
2/2✓ Branch 1 taken 199 times.
✓ Branch 2 taken 6365 times.
|
6564 | if (!ifilter_has_all_input_formats(fg)) { |
2783 | 199 | av_frame_move_ref(tmp, frame); | |
2784 | |||
2785 | 199 | ret = av_fifo_write(ifp->frame_queue, &tmp, 1); | |
2786 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 199 times.
|
199 | if (ret < 0) |
2787 | ✗ | av_frame_free(&tmp); | |
2788 | |||
2789 | 199 | return ret; | |
2790 | } | ||
2791 | |||
2792 |
2/2✓ Branch 0 taken 41 times.
✓ Branch 1 taken 6324 times.
|
6365 | ret = fgt->graph ? read_frames(fg, fgt, tmp) : 0; |
2793 | 6365 | av_frame_free(&tmp); | |
2794 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6365 times.
|
6365 | if (ret < 0) |
2795 | ✗ | return ret; | |
2796 | |||
2797 |
2/2✓ Branch 0 taken 41 times.
✓ Branch 1 taken 6324 times.
|
6365 | if (fgt->graph) { |
2798 | AVBPrint reason; | ||
2799 | 41 | av_bprint_init(&reason, 0, AV_BPRINT_SIZE_AUTOMATIC); | |
2800 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 40 times.
|
41 | if (need_reinit & AUDIO_CHANGED) { |
2801 | 1 | const char *sample_format_name = av_get_sample_fmt_name(frame->format); | |
2802 | 1 | av_bprintf(&reason, "audio parameters changed to %d Hz, ", frame->sample_rate); | |
2803 | 1 | av_channel_layout_describe_bprint(&frame->ch_layout, &reason); | |
2804 | 1 | av_bprintf(&reason, ", %s, ", unknown_if_null(sample_format_name)); | |
2805 | } | ||
2806 |
2/2✓ Branch 0 taken 40 times.
✓ Branch 1 taken 1 times.
|
41 | if (need_reinit & VIDEO_CHANGED) { |
2807 | 40 | const char *pixel_format_name = av_get_pix_fmt_name(frame->format); | |
2808 | 40 | const char *color_space_name = av_color_space_name(frame->colorspace); | |
2809 | 40 | const char *color_range_name = av_color_range_name(frame->color_range); | |
2810 | 40 | av_bprintf(&reason, "video parameters changed to %s(%s, %s), %dx%d, ", | |
2811 | unknown_if_null(pixel_format_name), unknown_if_null(color_range_name), | ||
2812 | unknown_if_null(color_space_name), frame->width, frame->height); | ||
2813 | } | ||
2814 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 41 times.
|
41 | if (need_reinit & MATRIX_CHANGED) |
2815 | ✗ | av_bprintf(&reason, "display matrix changed, "); | |
2816 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 41 times.
|
41 | if (need_reinit & HWACCEL_CHANGED) |
2817 | ✗ | av_bprintf(&reason, "hwaccel changed, "); | |
2818 |
1/2✓ Branch 0 taken 41 times.
✗ Branch 1 not taken.
|
41 | if (reason.len > 1) |
2819 | 41 | reason.str[reason.len - 2] = '\0'; // remove last comma | |
2820 |
1/2✓ Branch 0 taken 41 times.
✗ Branch 1 not taken.
|
41 | av_log(fg, AV_LOG_INFO, "Reconfiguring filter graph%s%s\n", reason.len ? " because " : "", reason.str); |
2821 | } | ||
2822 | |||
2823 | 6365 | ret = configure_filtergraph(fg, fgt); | |
2824 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6365 times.
|
6365 | if (ret < 0) { |
2825 | ✗ | av_log(fg, AV_LOG_ERROR, "Error reinitializing filters!\n"); | |
2826 | ✗ | return ret; | |
2827 | } | ||
2828 | } | ||
2829 | |||
2830 | 355285 | frame->pts = av_rescale_q(frame->pts, frame->time_base, ifp->time_base); | |
2831 | 355285 | frame->duration = av_rescale_q(frame->duration, frame->time_base, ifp->time_base); | |
2832 | 355285 | frame->time_base = ifp->time_base; | |
2833 | |||
2834 |
2/2✓ Branch 0 taken 107254 times.
✓ Branch 1 taken 248031 times.
|
355285 | if (ifp->displaymatrix_applied) |
2835 | 107254 | av_frame_remove_side_data(frame, AV_FRAME_DATA_DISPLAYMATRIX); | |
2836 | |||
2837 | 355285 | fd = frame_data(frame); | |
2838 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 355285 times.
|
355285 | if (!fd) |
2839 | ✗ | return AVERROR(ENOMEM); | |
2840 | 355285 | fd->wallclock[LATENCY_PROBE_FILTER_PRE] = av_gettime_relative(); | |
2841 | |||
2842 | 355285 | ret = av_buffersrc_add_frame_flags(ifp->filter, frame, | |
2843 | AV_BUFFERSRC_FLAG_PUSH); | ||
2844 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 355284 times.
|
355285 | if (ret < 0) { |
2845 | 1 | av_frame_unref(frame); | |
2846 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (ret != AVERROR_EOF) |
2847 | ✗ | av_log(fg, AV_LOG_ERROR, "Error while filtering: %s\n", av_err2str(ret)); | |
2848 | 1 | return ret; | |
2849 | } | ||
2850 | |||
2851 | 355284 | return 0; | |
2852 | } | ||
2853 | |||
2854 | 6384 | static void fg_thread_set_name(const FilterGraph *fg) | |
2855 | { | ||
2856 | char name[16]; | ||
2857 |
2/2✓ Branch 1 taken 6267 times.
✓ Branch 2 taken 117 times.
|
6384 | if (filtergraph_is_simple(fg)) { |
2858 | 6267 | OutputFilterPriv *ofp = ofp_from_ofilter(fg->outputs[0]); | |
2859 | 12534 | snprintf(name, sizeof(name), "%cf%s", | |
2860 | 6267 | av_get_media_type_string(ofp->ofilter.type)[0], | |
2861 | ofp->name); | ||
2862 | } else { | ||
2863 | 117 | snprintf(name, sizeof(name), "fc%d", fg->index); | |
2864 | } | ||
2865 | |||
2866 | 6384 | ff_thread_setname(name); | |
2867 | 6384 | } | |
2868 | |||
2869 | 6384 | static void fg_thread_uninit(FilterGraphThread *fgt) | |
2870 | { | ||
2871 |
1/2✓ Branch 0 taken 6384 times.
✗ Branch 1 not taken.
|
6384 | if (fgt->frame_queue_out) { |
2872 | AVFrame *frame; | ||
2873 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 6384 times.
|
6384 | while (av_fifo_read(fgt->frame_queue_out, &frame, 1) >= 0) |
2874 | ✗ | av_frame_free(&frame); | |
2875 | 6384 | av_fifo_freep2(&fgt->frame_queue_out); | |
2876 | } | ||
2877 | |||
2878 | 6384 | av_frame_free(&fgt->frame); | |
2879 | 6384 | av_freep(&fgt->eof_in); | |
2880 | 6384 | av_freep(&fgt->eof_out); | |
2881 | |||
2882 | 6384 | avfilter_graph_free(&fgt->graph); | |
2883 | |||
2884 | 6384 | memset(fgt, 0, sizeof(*fgt)); | |
2885 | 6384 | } | |
2886 | |||
2887 | 6384 | static int fg_thread_init(FilterGraphThread *fgt, const FilterGraph *fg) | |
2888 | { | ||
2889 | 6384 | memset(fgt, 0, sizeof(*fgt)); | |
2890 | |||
2891 | 6384 | fgt->frame = av_frame_alloc(); | |
2892 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6384 times.
|
6384 | if (!fgt->frame) |
2893 | ✗ | goto fail; | |
2894 | |||
2895 | 6384 | fgt->eof_in = av_calloc(fg->nb_inputs, sizeof(*fgt->eof_in)); | |
2896 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6384 times.
|
6384 | if (!fgt->eof_in) |
2897 | ✗ | goto fail; | |
2898 | |||
2899 | 6384 | fgt->eof_out = av_calloc(fg->nb_outputs, sizeof(*fgt->eof_out)); | |
2900 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6384 times.
|
6384 | if (!fgt->eof_out) |
2901 | ✗ | goto fail; | |
2902 | |||
2903 | 6384 | fgt->frame_queue_out = av_fifo_alloc2(1, sizeof(AVFrame*), AV_FIFO_FLAG_AUTO_GROW); | |
2904 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6384 times.
|
6384 | if (!fgt->frame_queue_out) |
2905 | ✗ | goto fail; | |
2906 | |||
2907 | 6384 | return 0; | |
2908 | |||
2909 | ✗ | fail: | |
2910 | ✗ | fg_thread_uninit(fgt); | |
2911 | ✗ | return AVERROR(ENOMEM); | |
2912 | } | ||
2913 | |||
2914 | 6384 | static int filter_thread(void *arg) | |
2915 | { | ||
2916 | 6384 | FilterGraphPriv *fgp = arg; | |
2917 | 6384 | FilterGraph *fg = &fgp->fg; | |
2918 | |||
2919 | FilterGraphThread fgt; | ||
2920 | 6384 | int ret = 0, input_status = 0; | |
2921 | |||
2922 | 6384 | ret = fg_thread_init(&fgt, fg); | |
2923 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6384 times.
|
6384 | if (ret < 0) |
2924 | ✗ | goto finish; | |
2925 | |||
2926 | 6384 | fg_thread_set_name(fg); | |
2927 | |||
2928 | // if we have all input parameters the graph can now be configured | ||
2929 |
2/2✓ Branch 1 taken 6327 times.
✓ Branch 2 taken 57 times.
|
6384 | if (ifilter_has_all_input_formats(fg)) { |
2930 | 57 | ret = configure_filtergraph(fg, &fgt); | |
2931 |
1/2✓ Branch 0 taken 57 times.
✗ Branch 1 not taken.
|
57 | if (ret < 0) { |
2932 | ✗ | av_log(fg, AV_LOG_ERROR, "Error configuring filter graph: %s\n", | |
2933 | ✗ | av_err2str(ret)); | |
2934 | ✗ | goto finish; | |
2935 | } | ||
2936 | } | ||
2937 | |||
2938 | 354994 | while (1) { | |
2939 | InputFilter *ifilter; | ||
2940 | InputFilterPriv *ifp; | ||
2941 | enum FrameOpaque o; | ||
2942 | 361378 | unsigned input_idx = fgt.next_in; | |
2943 | |||
2944 | 361378 | input_status = sch_filter_receive(fgp->sch, fgp->sch_idx, | |
2945 | 361378 | &input_idx, fgt.frame); | |
2946 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 361378 times.
|
361378 | if (input_status == AVERROR_EOF) { |
2947 | ✗ | av_log(fg, AV_LOG_VERBOSE, "Filtering thread received EOF\n"); | |
2948 | ✗ | break; | |
2949 |
2/2✓ Branch 0 taken 1662 times.
✓ Branch 1 taken 359716 times.
|
361378 | } else if (input_status == AVERROR(EAGAIN)) { |
2950 | // should only happen when we didn't request any input | ||
2951 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1662 times.
|
1662 | av_assert0(input_idx == fg->nb_inputs); |
2952 | 1662 | goto read_frames; | |
2953 | } | ||
2954 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 359716 times.
|
359716 | av_assert0(input_status >= 0); |
2955 | |||
2956 | 359716 | o = (intptr_t)fgt.frame->opaque; | |
2957 | |||
2958 | 359716 | o = (intptr_t)fgt.frame->opaque; | |
2959 | |||
2960 | // message on the control stream | ||
2961 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 359716 times.
|
359716 | if (input_idx == fg->nb_inputs) { |
2962 | FilterCommand *fc; | ||
2963 | |||
2964 | ✗ | av_assert0(o == FRAME_OPAQUE_SEND_COMMAND && fgt.frame->buf[0]); | |
2965 | |||
2966 | ✗ | fc = (FilterCommand*)fgt.frame->buf[0]->data; | |
2967 | ✗ | send_command(fg, fgt.graph, fc->time, fc->target, fc->command, fc->arg, | |
2968 | fc->all_filters); | ||
2969 | ✗ | av_frame_unref(fgt.frame); | |
2970 | 1 | continue; | |
2971 | } | ||
2972 | |||
2973 | // we received an input frame or EOF | ||
2974 | 359716 | ifilter = fg->inputs[input_idx]; | |
2975 | 359716 | ifp = ifp_from_ifilter(ifilter); | |
2976 | |||
2977 |
2/2✓ Branch 0 taken 1040 times.
✓ Branch 1 taken 358676 times.
|
359716 | if (ifp->type_src == AVMEDIA_TYPE_SUBTITLE) { |
2978 |
3/4✓ Branch 0 taken 1040 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 948 times.
✓ Branch 3 taken 92 times.
|
1040 | int hb_frame = input_status >= 0 && o == FRAME_OPAQUE_SUB_HEARTBEAT; |
2979 |
2/2✓ Branch 0 taken 948 times.
✓ Branch 1 taken 4 times.
|
1040 | ret = sub2video_frame(ifilter, (fgt.frame->buf[0] || hb_frame) ? fgt.frame : NULL, |
2980 |
2/2✓ Branch 0 taken 952 times.
✓ Branch 1 taken 88 times.
|
1040 | !fgt.graph); |
2981 |
2/2✓ Branch 0 taken 355484 times.
✓ Branch 1 taken 3192 times.
|
358676 | } else if (fgt.frame->buf[0]) { |
2982 | 355484 | ret = send_frame(fg, &fgt, ifilter, fgt.frame); | |
2983 | } else { | ||
2984 | av_assert1(o == FRAME_OPAQUE_EOF); | ||
2985 | 3192 | ret = send_eof(&fgt, ifilter, fgt.frame->pts, fgt.frame->time_base); | |
2986 | } | ||
2987 | 359716 | av_frame_unref(fgt.frame); | |
2988 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 359715 times.
|
359716 | if (ret == AVERROR_EOF) { |
2989 | 1 | av_log(fg, AV_LOG_VERBOSE, "Input %u no longer accepts new data\n", | |
2990 | input_idx); | ||
2991 | 1 | sch_filter_receive_finish(fgp->sch, fgp->sch_idx, input_idx); | |
2992 | 1 | continue; | |
2993 | } | ||
2994 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 359715 times.
|
359715 | if (ret < 0) |
2995 | ✗ | goto finish; | |
2996 | |||
2997 | 359715 | read_frames: | |
2998 | // retrieve all newly avalable frames | ||
2999 | 361377 | ret = read_frames(fg, &fgt, fgt.frame); | |
3000 |
2/2✓ Branch 0 taken 6384 times.
✓ Branch 1 taken 354993 times.
|
361377 | if (ret == AVERROR_EOF) { |
3001 | 6384 | av_log(fg, AV_LOG_VERBOSE, "All consumers returned EOF\n"); | |
3002 | 6384 | break; | |
3003 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 354993 times.
|
354993 | } else if (ret < 0) { |
3004 | ✗ | av_log(fg, AV_LOG_ERROR, "Error sending frames to consumers: %s\n", | |
3005 | ✗ | av_err2str(ret)); | |
3006 | ✗ | goto finish; | |
3007 | } | ||
3008 | } | ||
3009 | |||
3010 |
2/2✓ Branch 0 taken 6434 times.
✓ Branch 1 taken 6384 times.
|
12818 | for (unsigned i = 0; i < fg->nb_outputs; i++) { |
3011 | 6434 | OutputFilterPriv *ofp = ofp_from_ofilter(fg->outputs[i]); | |
3012 | |||
3013 |
3/4✓ Branch 0 taken 3766 times.
✓ Branch 1 taken 2668 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3766 times.
|
6434 | if (fgt.eof_out[i] || !fgt.graph) |
3014 | 2668 | continue; | |
3015 | |||
3016 | 3766 | ret = fg_output_frame(ofp, &fgt, NULL); | |
3017 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3766 times.
|
3766 | if (ret < 0) |
3018 | ✗ | goto finish; | |
3019 | } | ||
3020 | |||
3021 | 6384 | finish: | |
3022 | // EOF is normal termination | ||
3023 |
2/2✓ Branch 0 taken 2658 times.
✓ Branch 1 taken 3726 times.
|
6384 | if (ret == AVERROR_EOF) |
3024 | 2658 | ret = 0; | |
3025 | |||
3026 | 6384 | fg_thread_uninit(&fgt); | |
3027 | |||
3028 | 6384 | return ret; | |
3029 | } | ||
3030 | |||
3031 | ✗ | void fg_send_command(FilterGraph *fg, double time, const char *target, | |
3032 | const char *command, const char *arg, int all_filters) | ||
3033 | { | ||
3034 | ✗ | FilterGraphPriv *fgp = fgp_from_fg(fg); | |
3035 | AVBufferRef *buf; | ||
3036 | FilterCommand *fc; | ||
3037 | |||
3038 | ✗ | fc = av_mallocz(sizeof(*fc)); | |
3039 | ✗ | if (!fc) | |
3040 | ✗ | return; | |
3041 | |||
3042 | ✗ | buf = av_buffer_create((uint8_t*)fc, sizeof(*fc), filter_command_free, NULL, 0); | |
3043 | ✗ | if (!buf) { | |
3044 | ✗ | av_freep(&fc); | |
3045 | ✗ | return; | |
3046 | } | ||
3047 | |||
3048 | ✗ | fc->target = av_strdup(target); | |
3049 | ✗ | fc->command = av_strdup(command); | |
3050 | ✗ | fc->arg = av_strdup(arg); | |
3051 | ✗ | if (!fc->target || !fc->command || !fc->arg) { | |
3052 | ✗ | av_buffer_unref(&buf); | |
3053 | ✗ | return; | |
3054 | } | ||
3055 | |||
3056 | ✗ | fc->time = time; | |
3057 | ✗ | fc->all_filters = all_filters; | |
3058 | |||
3059 | ✗ | fgp->frame->buf[0] = buf; | |
3060 | ✗ | fgp->frame->opaque = (void*)(intptr_t)FRAME_OPAQUE_SEND_COMMAND; | |
3061 | |||
3062 | ✗ | sch_filter_command(fgp->sch, fgp->sch_idx, fgp->frame); | |
3063 | } | ||
3064 |