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