如何将WebRTC的部分作为静态/动态库与现有的C++代码集成?

4
官方代码网站可以下载并在Ubuntu上安装WebRTC。现在我打算在我们的服务器上使用其特定的C++ API,以创建P2P端点并加密/解密VoIP数据。但是没有指南说明如何将模块作为静态或动态链接库使用。
问题:如何在C++中链接WebRTC库的[最小化]部分?注意:我正在使用Qt平台。

你正在使用webrtc构建Android或IOS应用程序吗? - Abdul ahad
@Abdulahad,目前我们只想实现Windows、Mac和Linux的服务器端部分。我不确定它是否称为本地API或其他什么东西。我们可能不需要全部功能。我们应该能够在服务器上创建端点,这些端点可以消耗OFFER、ANSWER、CANDIDATE等,并解密/加密VoIP数据。 - iammilind
是的,为此您需要WinRTC设置,并且需要Windows来构建该静态库。 - Abdul ahad
3个回答

4

链接到Google的WebRTC实现不是一个简单的任务,因为:

  1. 它有自己的“toolchain”(例如对于Ubuntu,它使用clang和libc++),这可能与您的可执行文件在ABI级别上不兼容。而且,如果您正在使用libstdc++(据我所知,Qt使用它),那么无法将两个库链接在一个单位中。
  2. WebRTC使用BoringSSL,如果您的应用程序使用OpenSSL,则与前一个标准库相似:您会遇到冲突的符号。

解决方案1

解决此问题的一种方法是将WebRTC包装在动态库中,其中所有WebRTC符号都被隐藏。此库必须包含您的实现以使用offers/answers/candidates等进行工作。并创建纯C接口来包装此功能。由于只有此接口将从库中导出,因此您不会遇到符号冲突和ABI不兼容性。 要创建这样的动态库,我发现最简单的方法是修改一些BUILD.gn文件,将我的实现添加到WebRTC代码库中,并在GN中构建它,即在整个WebRTC库内部构建它。

以下是添加自定义内容到GN构建系统的示例步骤:

  • 将目录添加到根src目录(即位于根BUILD.gn所在的位置)
  • 创建新目录中的BUILD.gn文件
  • 在根BUILD.gn文件中查找rtc_static_library(“webrtc”)部分,并将其deps部分添加到您的新目录名称中

这是BUILD.gn文件的模板:

rtc_shared_library("name_of_your_dir") {
  deps = [
    "../api:create_peerconnection_factory",
    "../api:libjingle_peerconnection_api",
    "../api:media_stream_interface",
    "../api/audio_codecs:builtin_audio_decoder_factory",
    "../api/audio_codecs:builtin_audio_encoder_factory",
    "../api/video_codecs:builtin_video_decoder_factory",
    "../api/video:video_frame",
    "../media:rtc_audio_video",
    "../media:rtc_internal_video_codecs",
    "../media:rtc_media",
    "../media:rtc_media_base",
    "../modules/audio_device",
    "../pc:peerconnection",
    "../rtc_base",   ]

  # Add your source files here
  sources = [
    # "name_of_your_dir/header.h",
    # "name_of_your_dir/impl.cc"
  ]
}

编译成功后,您将在out目录中获得lib_name_of_your_dir.so文件。在WebRTC构建系统的默认规则下,该库中的所有符号均被隐藏,因此您需要导出自己的符号:为此,请使用__attribute__((visibility("default")))标记您的方法/类。

解决方案2

另一种解决方案是不包含编译器和标准库来编译WebRTC,这可能有些棘手,因为它要求您深入了解GN构建设置。但是,这种方法有一个优点:它允许使用C++接口而不是纯C,因为库将是ABI兼容的。

P.S. 要了解如何处理信令并创建点对点连接,您可以参考此示例:https://webrtc.googlesource.com/src/+/refs/heads/main/examples/peerconnection


添加我的实现 -- 你的实现在哪里?有没有某个地方已经有人做过这个了?对于你的第一标准,我们可以尝试在Ubuntu上使用clang进行静态链接,看是否满足要求。 - iammilind
很遗憾,我不能分享那个实现,但我可以提供如何将您的代码添加到GN构建系统的步骤(已更新答案)。 在Ubuntu上使用clang - 编译器不是一个大问题,通常可以链接使用不同编译器构建的单元。主要问题是默认情况下WebRTC静态库内置了libc++(即静态),很可能您的应用程序动态链接了libstdc++。因此,您应该隐藏符号并创建C接口或使用您的工具链构建WebRTC。 - Artem Suprunov
如果我们能够识别出用于建立P2P连接的有用文件,那么也许只需要极少量的文件,我们就可以构建一个服务器。你或者其他人尝试过解决方案2吗? - iammilind
我尝试过那个解决方案,但我还必须使用修改GN构建系统的步骤。结果,我得到了一个带有C++接口的包装器,而不是C。这个包装器是必需的,因为WebRTC避免使用前向声明,所以当你包含某个头文件时,它会包含其他头文件,依此类推。我想你可以将所有包含头文件的目录添加到你的CMake(或其他任何)包含中,但我选择了一个隐藏可怕的WebRTC包含的包装器方法,将其视为PIMPL。 - Artem Suprunov
我明白了,那么考虑使用一些开源项目,比如Janus:https://janus.conf.meetecho.com/audiobridgetest.html。因为从WebRTC源代码中提取某些东西似乎是一项巨大的工作。 - Artem Suprunov
显示剩余4条评论

0

我们有三个可用于webrtc的平台。

1- WinRTC(用于制作Windows和桌面应用程序的库)

2- Android应用程序的Webrtc(需要Ubuntu)

3- IOS的Webrtc(需要MACOS)

对于所有这些平台,都有不同的设置项目的方法。 您正在使用用于Windows的Webrtc教程,称为winRTC。

在Linux中,您只能为Android应用程序制作webrtc libs,并且该方法在此链接中提供。

https://github.com/mail2chromium/Compile_WebRTC_Library_For_Android

********************* 集成 ******************

如果要在 Android 应用程序中集成 WebRTC 库,您需要应用一个名为的标志。

implementation(name: 'library_Name', ext: 'Extension like .aar,.so,.a')

在您的应用级别的 build.gradle 文件中,现在您可以直接调用 webRTC 的 Java 函数,例如 createPeerConnectionclosePeerConnection

官方代码可在所有主要平台上构建。主要问题是如何将其链接为库到现有代码中,以便将其用作服务器。还可以参考此悬赏问题 - iammilind
实际上,我打算在Windows、Mac和Linux的服务器端使用WebRTC。我能够按照步骤编译代码,但由于不知道如何集成,所以无法将其集成到任何一个平台中!客户端,如Android和iOS,现在可能没有太大用处。无论如何,感谢您的更新回答。 - iammilind

0

首先,您需要从官方代码网站构建libwebrtc.a静态库。运行ninja -C out/Default后,您将在<your webrtc source dir>/webrtc-checkout/src/out/Default/obj/libwebrtc.a中获得libwebrtc.a。

然后,在您的CMakeLists.txt中添加以下包含目录:

target_include_directories(WebRTC SYSTEM PRIVATE ${WEBRTC_SRC})
target_include_directories(WebRTC SYSTEM PRIVATE ${WEBRTC_SRC}/buildtools/third_party/libc++/trunk/include)
target_include_directories(WebRTC SYSTEM PRIVATE ${WEBRTC_SRC}/third_party/perfetto/buildtools/libcxx_config)
target_include_directories(WebRTC SYSTEM PRIVATE ${WEBRTC_SRC}/third_party/abseil-cpp/)
target_include_directories(WebRTC SYSTEM PRIVATE ${WEBRTC_SRC}/third_party/jsoncpp/source/include/)

${WEBRTC_SRC} 是您的 /webrtc-checkout/src 目录的绝对路径。

在添加包含目录后,像这样添加链接库:

target_link_libraries(WebRTC
        PRIVATE
        ${WEBRTC_SRC}/out/Debug/obj/libwebrtc.a
        )

完成了!

我在我的项目中也使用了谷歌的webrtc源代码,并且能够编译和启动webrtc调试版本,没有任何问题。点击这里


你尝试过使用SSL连接进行信令传输吗?有趣的是,你如何处理websocketpp的OpenSSL和WebRTC的BoringSSL之间的符号冲突。 - Artem Suprunov

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接