How to integrate part of WebRTC as a static / dynamic library with the existing C++ code?
Asked Answered
W

3

4

From its official code site, I am able to download & install the WebRTC in Ubuntu. Now I intend to use its certain C++ APIs in our server for the purpose of creating P2P endpoints and encrypting / decrypting VoIP data. But there is no guideline on how to use the module as a static or dynamically linked library.

Question: How to link [preferably minimal] part of the WebRTC library in C++?
Note: I am using Qt platform.

Warmup answered 14/2, 2022 at 4:7 Comment(3)
Are you building an Andorid or IOS app using webrtc?Side
@Abdulahad, no currently we want to implement only the server part for Windows, Mac & Linux. I am not sure, if it's called Native APIs or something else. We may not want the full fledged features. We should be able to create endpoints on the server who can consume OFFER, ANSWER, CANDIDATEs etc. and decrypt / encrypt the VoIP data.Warmup
yes for that purpose you will need the WinRTC setup and you will need Windows to build that static librarySide
W
4

Linking against Google's implementation of WebRTC is not trivial task because:

  1. It has its own 'toolchain' with compiler and stdlib (for example, for Ubuntu it uses clang and libc++). And that might be incompatible with your executable on ABI level. Also if you are using libstdc++ (AFAIK Qt does that), then you cannot have both libs linked in one unit.
  2. WebRTC uses BoringSSL and if your application uses OpenSSL then it's similar issue to previous one with std lib: you have conflicting symbols.

Solution 1

One of the solutions for this problem is to wrap WebRTC in dynamic library in which all WebRTC symbols are hidden. This lib must contain your implementation for working with offers/answers/candidates etc. And make pure C interface that wraps this functionality. Since only this interface would be exported from the lib, you won't have symbol conflicts and ABI incompatibility. To create such dynamic library the easiest way I've found is to modify some BUILD.gn files, add my implementation to WebRTC codebase and build it with GN, i.e. within whole WebRTC lib.

These steps describe example of adding customizations to GN build system:

  • add directory to root src dir (i.e. where root BUILD.gn is located)
  • create file BUILD.gn inside the new dir
  • in the root BUILD.gn file find section rtc_static_library("webrtc") and to its deps section add the name of your new dir

This is a template for your BUILD.gn file:

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"
  ]
}

In result after successful build you'll get lib_name_of_your_dir.so file in out dir. In this lib all symbols are hidden by default rules in WebRTC build system, so you need to export yours: to do this mark your methods/classes with __attribute__((visibility("default")))

Solution 2

Another solution is to compile WebRTC without included compiler and std lib, and that might be tricky because it requires you to go deep into GN build settings. But this approach has an advantage: it allows to use C++ interface instead of pure C, because the lib would be ABI compatible.

P.S. To understand how to work with signaling and create peer to peer connection you can refer to this example: https://webrtc.googlesource.com/src/+/refs/heads/main/examples/peerconnection

Worthy answered 20/2, 2022 at 1:5 Comment(9)
add my implementation -- where can I find your implementation? Is there any source where someone has done this already? For your criteria-1, we can try using clang for Ubuntu, if that satisfies the static linking.Warmup
Unfortunately I'm not allowed to share that implementation, but I can provide steps how to add your code to GN build system (updated the answer). Using clang for Ubuntu - compiler is not a big problem, in general it's possible to link units that are built with different compilers. The main problem is that by default WebRTC static lib has built-in libc++ inside (i.e. static) and highly likely that your application has libstdc++ linked dynamically. So, you should either hide symbols and create C interface or build WebRTC using your toolchain.Worthy
If we can recognize the files which are useful for making p2p connections then may be with minimal files, we can build a server. Have you or anyone tried the solution 2?Warmup
I've tried that solution, but I also had to use steps for modifying GN build system from the first one. In result I've got a wrapper with C++ interface instead of C. That wrapper was required because WebRTC avoids using of forward declarations, so when you include some header file, it includes other headers and in turn they include more headers and so on. I suppose it's possible to add all dirs with headers to your CMake (or whatever else) includes, but I've chosen the approach with a wrapper which hides infernal WebRTC includes, consider it as PIMPL.Worthy
And I didn't quite understand your idea with minimal files: do you mean include several headers or extract several .cc files and compile only them instead of whole WebRTC lib?Worthy
Regarding the "minimal files" concept, you got it right. For protobuf, I have done it in past, where I skipped several files and directly included into my Qt project and compiled it. WebRTC being a huge library, I believe that at the server side for making peer connections and decrypting the VoIP data, not many files will be required.Warmup
I see, then consider to use some open source project like Janus: janus.conf.meetecho.com/audiobridgetest.html Because it seems to be a huge work to extract something from WebRTC sources.Worthy
What about using use_custom_libcxx=false gn argument?Stockroom
@Stockroom setting that option would be the first step in "Solution 2". But beyond that you'll have to setup GN for using your toolchain, i.e. provide paths to includes, libs and whatever else settings of your tools. And still you'll have to deal with symbols conflict BoringSSL/OpenSSL.Worthy
S
0

We have three platforms available for the webrtc.

1- WinRTC (used for making libraries for windows and Desktop apps)

2- Webrtc for Android app (Need Ubuntu for that)

3- Webrtc for IOS (Need MACOS for that)

For all of these platforms there are different mothods to setup the project. You are using the tutorial for using Webrtc for windows knows as winRTC.

In linux, You can only make the webrtc libs for the android app and the method is provided in this link.

https://github.com/mail2chromium/Compile_WebRTC_Library_For_Android

********************* Integration ******************

For integrating webrtc library in android app, You have to apply a flag named

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

in your App level build.gradle So, now you will be able to call the Java function of webRTC like createPeerConnection or closePeerConnection directly.

Side answered 17/2, 2022 at 11:12 Comment(2)
The official code is build-able for all the major platforms. The primary question is how to link it as a library into the existing code to be able to use it as a server. See this another bounty question as well.Warmup
Actually I intend to use WebRTC in the server side with Windows, Mac, Linux. I am able to compile the code as per the steps, but unable to integrate in any of them as don't know what to integrate! The client sides like Android & iOS may not be of much use for now. Thanks for your updated answer anyways.Warmup
D
0

First You need to build libwebrtc.a static library from official code site. After running ninja -C out/Default you will get libwebrtc.a in <your webrtc source dir>/webrtc-checkout/src/out/Default/obj/libwebrtc.a.

Then in your CMakeLists.txt add following include directories :

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} is the absolute path to your /webrtc-checkout/src directory.

After adding include dirctories add link library like this:

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

Done!

I am also using googles webrtc source code in my project and I am am able to compile and start webrtc debug build with no issues. See here.

Dutch answered 1/3, 2023 at 9:55 Comment(1)
Have you tried to use SSL connection for signaling? Interesting how you deal with symbols conflict between OpenSSL for websocketpp and BoringSSL from WebRTC.Worthy

© 2022 - 2024 — McMap. All rights reserved.