Llame al filtro FFmpeg desde el código fuente (C API)

Estoy tratando de averiguar cómo llamar a un FFmpegfiltro ( freezedetect) desde el código fuente de FFmpeg. Veo que el archivo del filtro está debajo libavfilter/vf_freezedetect.c, pero no sé cómo usar ese filtro dentro del código fuente. ¿Cómo puedo hacer eso? ¿Y qué necesito para pasar a la función?

La API de alto nivel de mi comando FFmpeg es esta:

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

Y lo que necesitaría para obtener los resultados resultantes directamente después de llamar a una función dados sus argumentos de entrada:

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
Solo por un poco de contexto, ¿ya está familiarizado con la programación en C y las API de ffmpeg? Si no, le sugiero que comience con el tutorial de dranger.com sobre lectura y análisis primero. Si se siente cómodo con eso, puede hacer esta pregunta en stackoverflow y puedo ayudarlo a crear pads y filtros.
Estoy familiarizado con C, pero no con la API de FFmpeg C. Sería útil saber cómo llamar a este filtro desde la API de C.
Consulte también doc/examplesen el código fuente de FFmpeg, como filtering_video.c.
Seguro. Espero que la respuesta a continuación pueda ser lo suficientemente detallada como para implementarla. No soy un tipo súper C.
@llogan ¿La API de filtro es secuencial o multiproceso? Quiero decir, al llamar a los filtros, ¿se ejecutan secuencialmente, no en un hilo separado?
@TinaJ No estoy seguro, pero puede ver el resultado ffmpeg -filterspara ver qué filtros admiten el subproceso de corte.

Respuestas (1)

No puede simplemente llamar a un filtro, debe crear una instancia de un gráfico de filtro.

Primero necesitas crear un buffery buffersinkvía:

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

A continuación, puede crear su filtro a través de algo como esto

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

Luego vincúlalo todo:

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

Finalmente, puede enviar marcos al filtro a través de

av_buffersrc_write_frame(source, frame);

Y obtener el resultado con

 av_buffersink_get_frame(sink, frame);

No olvides liberarlo todo al final.

umm se ve muy prometedor! Y al mismo tiempo no es fácil. ¡Gracias!
Sí, los filtros son bastante complicados.
¿La API de filtro es secuencial o multiproceso? Quiero decir, al llamar a los filtros, ¿se ejecutan secuencialmente, no en un hilo separado?