为什么 frei0r C++ 过滤器 DLL 无法在 ffmpeg 中加载,但 C 过滤器可以加载

为什么 frei0r C++ 过滤器 DLL 无法在 ffmpeg 中加载,但 C 过滤器可以加载

我正在尝试交叉编译支持 frei0r 的 Windows 10 ffmpeg。在 Linux(Ubuntu 18.04)上一切顺利。在 Windows(Ubuntu 上的 Mingw-w64 7.3.0)上,构建正常。但是,在 Windows 上使用以下命令行运行时:

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

我得到了正确的行为,但是

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

我收到错误:未找到 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

在 Windows 上,同样的行为是一致的,所有 C 插件都可以工作,但找不到任何 C++ dll 插件。在 Linux 版本上,它们都可以正常工作。

这是我为 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'

我尝试追踪问题,发现出于某种原因,ffmpeg 过滤器 vf_frei0r 无法打开这些 dll。更确切地说,dlopen 在调用 dll 的路径/名称后返回一个空处理程序。同样,仅适用于 C++ 版本。

我怀疑这可能与 C++ 中的名称修改有关,但据我所知,frei0r hpp 将 dlopen 调用的所有 C 函数导出为外部函数。

关于这个问题有什么提示或想法吗?谢谢。

答案1

回答我自己的问题。

查看生成的二进制文件后,我发现出于某种原因,mingw32-w64 g++ 编译器忽略了围绕 frei0r.h 包含的“外部 C”。因此,导出的符号的名称会按照 c++ 编译器的要求发生混乱,并且在从 ffmpeg 的 C 代码调用时找不到

更新:经过进一步挖掘,我了解到即使是 C 编译器也会进行符号名称修饰,而防止这种情况的一种方法是使用 .def 文件(用于 Visual Studio)来定义函数的导出名称。

相关内容