Por que as DLLs dos filtros frei0r C++ não estão sendo carregadas no ffmpeg, mas os filtros C sim

Por que as DLLs dos filtros frei0r C++ não estão sendo carregadas no ffmpeg, mas os filtros C sim

Estou tentando compilar o ffmpeg com suporte frei0r para Windows 10. No Linux (Ubuntu 18.04) tudo corre perfeitamente. No Windows (Mingw-w64 7.3.0 no Ubuntu), a construção está correta. No entanto, ao executar no Windows com esta linha 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

Eu tenho o comportamento certo, mas com

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

Recebo um erro informando que a dll não foi encontrada.

[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

O mesmo comportamento é consistente no Windows, todos os plug-ins C funcionam enquanto nenhum dos plug-ins dll C++ é encontrado. Na versão Linux todos funcionam sem problemas.

Esta é minha configuração de compilação 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'

Tentei rastrear o problema e descobri que por algum motivo o filtro ffmpeg vf_frei0r não consegue abrir essas dlls. Mais exatamente, o dlopen retorna um manipulador nulo após a chamada com o caminho/nome da dll. Novamente, apenas para C++.

Suspeito que possa ser algo relacionado à confusão de nomes em C++, mas pelo que vejo frei0r hpp exporta todas as funções C chamadas por dlopen como externas.

Alguma dica, ideia sobre esse assunto? Obrigado.

Responder1

Respondendo à minha própria pergunta.

Depois de examinar os binários gerados, descobri que, por algum motivo, o compilador mingw32-w64 g++ está ignorando o "C externo" que envolve o include frei0r.h. Por causa disso, os símbolos exportados têm seus nomes distorcidos conforme determina o compilador c++ e não são encontrados quando invocados a partir do código C de ffmpeg .

Atualizar: Depois de mais pesquisas, aprendi que até o compilador C faz decoração de nomes de símbolos, e uma maneira de evitar isso é usando arquivos .def (para visual studio) onde definir os nomes exportados de suas funções.

informação relacionada