Aufruf des FFmpeg-Filters aus dem Quellcode (C-API)

Ich versuche herauszufinden, wie man einen FFmpegFilter ( freezedetect) aus dem Quellcode von FFmpeg aufruft. Ich sehe, dass sich die Datei des Filters unter befindet libavfilter/vf_freezedetect.c, aber ich weiß nicht, wie ich diesen Filter im Quellcode verwenden soll. Wie kann ich das machen? Und was muss ich der Funktion übergeben?

Die High-Level-API meines FFmpeg-Befehls lautet wie folgt:

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

Und was ich brauchen würde, um die resultierenden Ausgaben direkt nach dem Aufruf einer Funktion mit ihren Eingabeargumenten zu erhalten:

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
Sind Sie bereits mit der C-Programmierung und den ffmpeg-APIs vertraut? Wenn nicht, schlage ich vor, dass Sie zuerst mit dem dranger.com-Tutorial zum Lesen und Analysieren beginnen. Wenn Sie damit einverstanden sind, können Sie diese Frage auf Stackoverflow stellen, und ich kann Ihnen beim Erstellen von Pads und Filtern helfen.
Ich bin mit C vertraut, aber nicht mit der FFmpeg-C-API. Es wäre hilfreich zu wissen, wie dieser Filter von der C-API aufgerufen wird.
Siehe auch doc/examplesim FFmpeg-Quellcode, wie z filtering_video.c.
Sicher. Ich hoffe, die folgende Antwort kann detailliert genug sein, um sie umzusetzen. Ich bin kein Super-C-Typ.
@llogan Ist die Filter-API sequentiell oder multithreaded? Ich meine, wenn Filter aufgerufen werden, werden sie sequentiell ausgeführt, nicht in einem separaten Thread?
@TinaJ Ich bin mir nicht sicher, aber Sie können die Ausgabe von anzeigen, ffmpeg -filtersum zu sehen, welche Filter Slice-Threading unterstützen.

Antworten (1)

Sie können einen Filter nicht einfach aufrufen, Sie müssen einen Filtergraphen instanziieren.

Zuerst müssen Sie ein bufferund buffersinküber erstellen:

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);

Sie können dann Ihren Filter über so etwas erstellen

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

Dann alles miteinander verknüpfen:

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

Schließlich können Sie Frames an den Filter senden über

av_buffersrc_write_frame(source, frame);

Und erhalten Sie das Ergebnis mit

 av_buffersink_get_frame(sink, frame);

Vergiss nicht, alles am Ende zu befreien

ähm sieht sehr vielversprechend aus! Und gleichzeitig nicht einfach. Danke!
Ja, Filter sind ziemlich kompliziert.
Ist die Filter-API sequentiell oder multithreaded? Ich meine, wenn Filter aufgerufen werden, werden sie sequentiell ausgeführt, nicht in einem separaten Thread?