¿Por qué las DLL de los filtros frei0r C++ no se cargan en ffmpeg pero los filtros C sí?

¿Por qué las DLL de los filtros frei0r C++ no se cargan en ffmpeg pero los filtros C sí?

Estoy intentando realizar una compilación cruzada de ffmpeg con soporte frei0r para Windows 10. En Linux (Ubuntu 18.04) todo va perfectamente. En Windows (Mingw-w64 7.3.0 en Ubuntu), la compilación está bien. Sin embargo, cuando se ejecuta en Windows con esta línea de comando:

ffmpeg -i http://lb.streaming.sk/fashiontv/stream/playlist.m3u8 -vf frei0r=pixeliz0r -loglevel debug -f mpegts pipe:play | ffplay -loglevel quiet -i pipe:play

Obtengo el comportamiento correcto, pero con

ffmpeg -i http://lb.streaming.sk/fashiontv/stream/playlist.m3u8 -vf frei0r=vignette -loglevel debug -f mpegts pipe:play | ffplay -loglevel quiet -i pipe:play

Recibo un error que indica que no se encontró la DLL.

[Parsed_frei0r_0 @ 000000000347ef00] Could not find module 'vignette'.
[AVFilterGraph @ 00000000029074c0] Error initializing filter 'frei0r' with args 'vignette'
Error reinitializing filters!
Failed to inject frame into filter network: Invalid argument
Error while processing the decoded data for stream #0:1
[AVIOContext @ 00000000028d8f40] Statistics: 0 seeks, 0 writeouts
[AVIOContext @ 00000000028c5480] Statistics: 133422 bytes read, 0 seeks
[AVIOContext @ 00000000028d1b00] Statistics: 0 bytes read, 0 seeks
[AVIOContext @ 00000000006ccd80] Statistics: 201 bytes read, 0 seeks
[AVIOContext @ 00000000028a8100] Statistics: 137 bytes read, 0 seeks

El mismo comportamiento es consistente en Windows, todos los complementos de C funcionan mientras que no se encuentra ninguno de los complementos dll de C++. En la versión de Linux, todos funcionan sin problemas.

Esta es mi configuración de compilación para ffmpeg:

./configure --arch=x86_64 --target-os=mingw32 --cross-prefix=x86_64-w64-mingw32- --disable-doc --enable-nonfree --enable-gpl --enable-version3 --enable-static --disable-shared --enable-frei0r --extra-cflags='-I../frei0r/include -I/usr/local/include -I/usr/share/mingw-w64/include' --extra-ldflags="-static -static-libstdc++ -static-libgcc" --extra-libs='-lstdc++ /usr/local/lib/libdl.dll.a'

Intenté localizar el problema y descubrí que, por alguna razón, el filtro ffmpeg vf_frei0r no puede abrir esos archivos DLL. Más exactamente, dlopen devuelve un controlador nulo después de la llamada con la ruta/nombre del dll. Nuevamente, solo para los de C++.

Sospecho que podría ser algo relacionado con la alteración de nombres en C++, pero por lo que veo, frei0r hpp exporta todas las funciones de C llamadas por dlopen como externas.

¿Alguna pista o idea sobre este tema? Gracias.

Respuesta1

Respondiendo a mi propia pregunta.

Después de mirar los archivos binarios generados, descubrí que, por alguna razón, el compilador mingw32-w64 g++ ignora el "C externo" que rodea la inclusión frei0r.h. Debido a esto, los símbolos exportados tienen sus nombres alterados según lo dicta el compilador de C++ y no se encuentran cuando se invocan desde el código C desde ffmpeg .

Actualizar: Después de investigar más, aprendí que incluso el compilador de C decora los nombres de los símbolos, y una forma de evitarlo es mediante el uso de archivos .def (para Visual Studio) donde definir los nombres exportados de sus funciones.

información relacionada