这个问题我解决了,WebRTC 多少有点坑的,先说个结论:
如果我们这样写:
#include "third_party/ffmpeg/libavcodec/avcodec.h"
#include "third_party/ffmpeg/libavformat/avformat.h"
#include "third_party/ffmpeg/libswscale/swscale.h"
它在编译时是直接使用 C++ 来编译的,因此链接库它是带参数的;其实从我上面给出的图也能看出来... 我上面的提示都是 :
ld.lld: error: undefined symbol: avcodec_free_context(AVCodecContext**)
>>> referenced by MP4VideoDecoder.cc:23 (../../examples/MyFECExp/MP4VideoDecoder.cc:23)
>>> obj/examples/MyFECExp/MP4VideoDecoder.o:(webrtc::videoplayermodule::MP4VideoDecoder::~MP4VideoDecoder())
给出的 symbol 都是 avcodec_free_context(AVCodecContext**) 这样子的,然后,非常感谢超哥提示,WebRTC 是不会用操作系统的链接库的,而是会用自己的链接库!我们看看它的编译指令:
"vpython3" "../../build/toolchain/gcc_link_wrapper.py" --output="./MyFECExp"
-- ../../third_party/llvm-build/Release+Asserts/bin/clang++ -Werror -fuse-ld=lld -Wl,--fatal-warnings
-Wl,--build-id=fast -fPIC -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now -Wl,--color-diagnostics
-Wl,--undefined-version -Wl,--no-call-graph-profile-sort -m64 -no-canonical-prefixes -Wl,--gdb-index
-Wl,-z,defs -Wl,--as-needed -nostdlib++ --sysroot=../../build/linux/debian_bullseye_amd64-sysroot
-rdynamic -pie -Wl,--disable-new-dtags -o "./MyFECExp" -Wl,--start-group @"./MyFECExp.rsp"
-Wl,--end-group -lX11 -lXcomposite -lXext -lXrender ../../third_party/llvm-build/
Release+Asserts/lib/clang/20/lib/x86_64-unknown-linux-gnu/libclang_rt.builtins.a -ldl -lpthread
-lrt -lgmodule-2.0 -lgthread-2.0 -lgtk-3 -lgdk-3 -lpangocairo-1.0 -lpango-1.0 -lharfbuzz
-latk-1.0 -lcairo-gobject -lcairo -lgdk_pixbuf-2.0 -lgio-2.0 -lgobject-2.0 -lglib-2.0 -lm
-lz -Wl,--start-group -Wl,--end-group
其中有一句话:
--sysroot=../../build/linux/debian_bullseye_amd64-sysroot
这其实就是告诉了操作系统:我优先在这个目录下找链接库!这里还在 linux 目录下的 debian...amd64 目录下,显然这是 WebRTC 为了做一些多平台的迁移支持,所以使用 ninja 编译时没有用本地的链接库,而是直接用自己提供的库。然后我们去这个目录下的库看看,在我这里具体用的目录如下:
WebRTC/src/build/linux/debian_bullseye_amd64-sysroot/usr/lib/x86_64-linux-gnu
这里就是一个大坑了,首先它没有 swscale 这个库,这就是为什么我上面 libs 加了也白加;其次我这个目录下 libavformat.so 这个文件还是损坏的,它好像下载下来就是损坏的,如果大家用的是超哥推荐的 4096 版本的话需要检查一下...
其次,它自带的是 C 语言的库呀... 我们用 nm 看一下就可以看出来:
OK问题找到,我的做法比较暴力:
找到 WebRTC/third_party 对应版本的 ffmpeg (4096 使用的是 7.0),然后编译一下把新的 .so 文件丢到上面那个库文件夹里面。然后 #include 的时候这样写:
extern "C" {
#include "third_party/ffmpeg/libavcodec/avcodec.h"
#include "third_party/ffmpeg/libavformat/avformat.h"
#include "third_party/ffmpeg/libswscale/swscale.h"
}
也就是让它用 C 的方式来 LINK ,别带参数!
其实吧,这个问题我一年前想把 ffmpeg 塞到 ns3 里面做实验的时候就遇到过,但人总是不长记性的;我之前用的是一种更暴力的做法,直接改了 ffmpeg 的 MakeFile 文件,然后编译了一个 C++ 版本的 .so 文件塞到 ns3 的 lib 里面去了... 我记得这种方法也很简单,只需要改 MakeFile 几个符号就行了....