Вызов фильтра FFmpeg из исходного кода (C API)

Я пытаюсь выяснить, как вызвать FFmpegфильтр ( freezedetect) из исходного кода FFmpeg. Я вижу, что файл фильтра находится под libavfilter/vf_freezedetect.c, но я не знаю, как использовать этот фильтр в исходном коде. Как мне это сделать? А что мне нужно передать в функцию?

API высокого уровня моей команды FFmpeg таков:

ffmpeg -i freeze.mp4 -vf "freezedetect=n=-60dB:d=2" -map 0:v:0 -f null -

И что мне нужно, чтобы получить результирующие результаты непосредственно после вызова функции с учетом ее входных аргументов:

lavfi.freezedetect.freeze_start: 5.005
lavfi.freezedetect.freeze_duration: 2.03537
lavfi.freezedetect.freeze_end: 7.04037
lavfi.freezedetect.freeze_start: 13.0464
lavfi.freezedetect.freeze_duration: 3.03637
lavfi.freezedetect.freeze_end: 16.0827
Просто для некоторого контекста: вы уже знакомы с программированием на C и API ffmpeg? Если нет, я предлагаю вам начать с учебника dranger.com по чтению и синтаксическому анализу. Если вас это устраивает, вы можете задать этот вопрос в stackoverflow, и я могу помочь с созданием прокладок и фильтров.
Я знаком с C, но не FFmpeg C API. Знание того, как вызывать этот фильтр из C API, может помочь.
Также см doc/examples. исходный код FFmpeg, например filtering_video.c.
Конечно. Я надеюсь, что ответ ниже может быть достаточно подробным для реализации. Я не супер C парень.
@llogan Является ли API фильтра последовательным или многопоточным? Я имею в виду, при вызове фильтров они выполняются последовательно, а не в отдельном потоке?
@TinaJ Я не уверен, но вы можете просмотреть вывод, ffmpeg -filtersчтобы увидеть, какие фильтры поддерживают многопоточность слайсов.

Ответы (1)

Вы не можете просто вызвать фильтр, вы должны создать экземпляр графа фильтра.

Сначала вам нужно создать bufferи buffersinkчерез:

AVFilterContext* source = 0;
AVFilterContext* sink = 0;
AVFilterGraph *graph = avfilter_graph_alloc()
avfilter_graph_create_filter(&source, avfilter_get_by_name("buffer"), nullptr, args, nullptr, graph);


AVBufferSinkParams* buffersink_params = av_buffersink_params_alloc();
buffersink_params->pixel_fmts = /*Your pixel format HERE*/;

avfilter_graph_create_filter(&sink, avfilter_get_by_name("buffersink"), nullptr, nullptr, buffersink_params, graph);

Затем вы можете создать свой фильтр с помощью чего-то вроде этого

snprintf(args, sizeof(args), "n=-60dB:d=2");
avfilter_graph_create_filter(&freezedetect, avfilter_get_by_name("freezedetect"), nullptr, args, nullptr, graph);

Затем соедините все вместе:

avfilter_link(source, 0, freezedetect, 0);
avfilter_link(freezedetect, 0, sink, 0);
avfilter_graph_config(graph, 0);

Наконец, вы можете отправлять кадры в фильтр через

av_buffersrc_write_frame(source, frame);

И получить результат с

 av_buffersink_get_frame(sink, frame);

Не забудьте освободить все это в конце

ммм выглядит очень многообещающе! И в то же время не простой. Спасибо!
Да, фильтры довольно сложные.
Является ли API фильтра последовательным или многопоточным? Я имею в виду, при вызове фильтров они выполняются последовательно, а не в отдельном потоке?