Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 14 additions & 12 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,20 +19,22 @@ jobs:
fail-fast: false
matrix:
include:
- cmd: "./gradlew :kmp-webrtc:testDebugUnitTest"
os: macos-latest
- cmd: "./gradlew :example:androidApp:assembleDebug"
os: macos-latest
- cmd: "./scripts/build_ios_demo.sh"
os: macos-latest
- os: macos-latest
cmd: "./gradlew :kmp-webrtc:testDebugUnitTest"
- os: macos-latest
cmd: "./gradlew :example:androidApp:assembleDebug"
- os: macos-latest
dep: "brew update && brew install cocoapods xcodegen"
- cmd: "./scripts/build_mac_demo.sh"
os: macos-latest
cmd: "./scripts/build_ios_demo.sh"
- os: macos-latest
dep: "brew update && brew install cocoapods xcodegen"
- cmd: ".\\scripts\\setup_windows.bat \"C:\\Program Files\\Microsoft Visual Studio\\2022\\Enterprise\\VC\\Tools\\MSVC\\14.43.34808\\bin\\Hostx64\\x64\\lib.exe\" && cd example\\winApp && msbuild winApp.vcxproj /t:Build /p:Configuration=Release /p:Platform=x64"
os: windows-latest
- cmd: "./gradlew :example:webApp:jsBrowserDistribution"
os: macos-latest
cmd: "./scripts/build_mac_demo.sh"
- os: windows-latest
cmd: ".\\scripts\\setup_windows.bat \"C:\\Program Files\\Microsoft Visual Studio\\2022\\Enterprise\\VC\\Tools\\MSVC\\14.43.34808\\bin\\Hostx64\\x64\\lib.exe\" && cd example\\winApp && msbuild winApp.vcxproj /t:Build /p:Configuration=Release /p:Platform=x64"
- os: macos-latest
cmd: "./gradlew :example:webApp:jsBrowserDistribution"
- os: ubuntu-latest
cmd: "./scripts/build_linux_demo.sh"
runs-on: ${{ matrix.os }}
permissions:
pull-requests: write
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ captures
.cxx
local.properties

*.mp4
*.mkv

xcuserdata
**.podspec
**.xcodeproj
Expand Down
25 changes: 24 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ KMP wrapper for WebRTC.
| `macOS` | 🚀 |
| `Windows X64` | 🚀 |
| `JS` (Chrome) | 🚀 |
| `Linux X64` | 🔮 |
| `Linux X64` | 🚀 |

## Dependency

Expand Down Expand Up @@ -89,6 +89,13 @@ Open the project (the repo root dir) in Android studio, and run the example.andr
# open example\winApp\winApp.sln in Visual Studio 2022, and run it.
```

### Linux

```bash
./scripts/build_linux_demo.sh
./example/linuxApp/build/loopback <path to video file>
```

### JS

```bash
Expand All @@ -115,6 +122,14 @@ File structure for Windows:
- kmp-webrtc
```

File structure for Linux:

```
- webrtc_android
- src
- kmp-webrtc
```

### Android

CPP code need to be built on Linux.
Expand Down Expand Up @@ -148,6 +163,14 @@ In `x64 Native Tools Command Prompt for VS 2022`:
.\sdk\build_windows_libs.bat ..\..\kmp-webrtc
```

### Linux

```bash
pushd ../webrtc_android/src/ && \
./sdk/build_linux_libs.sh ../../kmp-webrtc/libs --skip-build-ffmpeg && \
popd
```

### Upload libs zip

```bash
Expand Down
45 changes: 34 additions & 11 deletions example/common/cpp/libKmpWebrtc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,16 @@
#error "Unknown target"
#endif

#define KFunc(NAME) g_lib->kotlin.root.com.piasy.kmp.webrtc.##NAME
#define KType(NAME) kmp_webrtc_kref_com_piasy_kmp_webrtc_##NAME
#define KFunc(NAME) g_lib->kotlin.root.com.piasy.kmp.webrtc.NAME
#define KType(NAME) KT_SYMBOL(kmp_webrtc_kref_com_piasy_kmp_webrtc_##NAME)

static KT_SYMBOL(kmp_webrtc_ExportedSymbols)* g_lib = nullptr;

int InitializeWebRTC(const char* field_trials, int debug_log) {
if (!g_lib) {
g_lib = KT_SYMBOL(kmp_webrtc_symbols)();
}
return KFunc(initializeWebRTC)(kmp_webrtc_kref_kotlin_Any(), field_trials, debug_log);
return KFunc(initializeWebRTC)(KT_SYMBOL(kmp_webrtc_kref_kotlin_Any)(), field_trials, debug_log);
}

struct PCClientFactoryConfig* DefaultPCClientFactoryConfig() {
Expand All @@ -39,6 +39,11 @@ struct PCClientFactoryConfig* DefaultPCClientFactoryConfig() {
config->video_capture_height = 720;
config->video_capture_fps = 30;
config->private_config.hwnd = nullptr;
config->private_config.disable_encryption = 0;
config->private_config.dummy_audio_device = 0;
config->private_config.transit_video = 0;
config->private_config.capture_file_path = "";
config->private_config.capture_dump_path = "";
return config;
}

Expand All @@ -52,14 +57,18 @@ struct PcClientFactoryHolder {
};

void* CreatePCClientFactory(struct PCClientFactoryConfig* config, PCClientFactoryErrorHandler handler, void* opaque) {
KType(PeerConnectionClientFactory_PrivateConfig) private_config = KFunc(PeerConnectionClientFactory.PrivateConfig.PrivateConfig)();
KType(PeerConnectionClientFactory_PrivateConfig) pconfig = KFunc(PeerConnectionClientFactory.PrivateConfig.PrivateConfig)();
KType(PeerConnectionClientFactory_Config) k_config = KFunc(PeerConnectionClientFactory.Config.Config)(
(int) config->video_capture_impl, config->video_capture_width, config->video_capture_height,
config->video_capture_fps, 0, private_config);
KType(WinPrivateConfig) win_private_config = KFunc(WinPrivateConfig.WinPrivateConfig)(config->private_config.hwnd, config->private_config.disable_encryption);
KType(PeerConnectionClientFactory_Config) k_config_with_pri = KFunc(utils.createPcClientFactoryConfig)(k_config, win_private_config);
config->video_capture_fps, 0, pconfig);
#if defined(WEBRTC_WIN)
KType(WinPrivateConfig) private_config = KFunc(WinPrivateConfig.WinPrivateConfig)(config->private_config.hwnd, config->private_config.disable_encryption);
#else
KType(LinuxPrivateConfig) private_config = KFunc(LinuxPrivateConfig.LinuxPrivateConfig)(config->private_config.hwnd, config->private_config.disable_encryption, config->private_config.dummy_audio_device, config->private_config.transit_video, config->private_config.capture_file_path, config->private_config.capture_dump_path);
#endif
KType(PeerConnectionClientFactory_Config) k_config_with_pri = KFunc(utils.createPcClientFactoryConfig)(k_config, private_config);

kmp_webrtc_kref_kotlin_Function2 error_handler = KFunc(utils.createErrorHandler)(handler, opaque);
KT_SYMBOL(kmp_webrtc_kref_kotlin_Function2) error_handler = KFunc(utils.createErrorHandler)((void*) handler, opaque);

PcClientFactoryHolder* holder = new PcClientFactoryHolder();
holder->factory = KFunc(createPeerConnectionClientFactory)(k_config_with_pri, error_handler);
Expand All @@ -69,7 +78,7 @@ void* CreatePCClientFactory(struct PCClientFactoryConfig* config, PCClientFactor
void DestroyPCClientFactory(void** pc_client_factory) {
PcClientFactoryHolder* holder = reinterpret_cast<PcClientFactoryHolder*>(*pc_client_factory);
KFunc(PeerConnectionClientFactory.destroyPeerConnectionFactory)(holder->factory);
delete (*pc_client_factory);
delete (holder);
*pc_client_factory = nullptr;
}

Expand Down Expand Up @@ -106,13 +115,13 @@ void* CreatePeerConnectionClient(void* pc_client_factory, const char* peer_uid,
void ClosePeerConnectionClient(void** pc_client) {
PcClientHolder* holder = reinterpret_cast<PcClientHolder*>(*pc_client);
KFunc(PeerConnectionClient.close)(holder->client);
delete (*pc_client);
delete (holder);
*pc_client = nullptr;
}

void CreatePeerConnection(void* pc_client) {
PcClientHolder* holder = reinterpret_cast<PcClientHolder*>(pc_client);
kmp_webrtc_kref_kotlin_collections_List ice_servers = KFunc(utils.emptyIceServers)();
KT_SYMBOL(kmp_webrtc_kref_kotlin_collections_List) ice_servers = KFunc(utils.emptyIceServers)();
KFunc(PeerConnectionClient.createPeerConnection)(holder->client, ice_servers);
}

Expand All @@ -138,6 +147,16 @@ void GetStats(void* pc_client) {
KFunc(PeerConnectionClient.getStats)(holder->client);
}

int StartRecorder(void* pc_client, int dir, const char* path) {
PcClientHolder* holder = reinterpret_cast<PcClientHolder*>(pc_client);
return KFunc(PeerConnectionClient.startRecorder)(holder->client, dir, path);
}

int StopRecorder(void* pc_client, int dir) {
PcClientHolder* holder = reinterpret_cast<PcClientHolder*>(pc_client);
return KFunc(PeerConnectionClient.stopRecorder)(holder->client, dir);
}

#if defined(WEBRTC_WIN)
void AddRemoteTrackRenderer(void* pc_client, void* renderer) {
PcClientHolder* holder = reinterpret_cast<PcClientHolder*>(pc_client);
Expand All @@ -148,3 +167,7 @@ void AddRemoteTrackRenderer(void* pc_client, void* renderer) {
void LogInfo(const char* log) {
KFunc(utils.logInfo)(log);
}

const char* PreferSdp(const char* sdp, int codec) {
return KFunc(utils.preferCodec)(sdp, codec);
}
32 changes: 25 additions & 7 deletions example/common/cpp/libKmpWebrtc.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,29 @@
extern "C" {
#endif

enum KmpWebRTCCaptureImpl {
kKmpWebRTCCaptureSystemCamera = 1,
kKmpWebRTCCaptureScreen = 2,
kKmpWebRTCCaptureFile = 3,
kKmpWebRTCCaptureApp = 4,
};

enum KmpWebRTCDir {
kKmpWebRTCDirSendRecv = 0,
kKmpWebRTCDirSendOnly = 1,
kKmpWebRTCDirRecvOnly = 2,
kKmpWebRTCDirInactive = 3,
};

enum KmpWebRTCVideoCodec {
kKmpWebRTCVideoCodecVP8 = 1,
kKmpWebRTCVideoCodecVP9 = 2,
kKmpWebRTCVideoCodecH264Baseline = 3,
kKmpWebRTCVideoCodecH264HighProfile = 4,
kKmpWebRTCVideoCodecH265 = 5,
kKmpWebRTCVideoCodecAV1 = 6,
};

enum KmpWebRTCCaptureImpl {
kKmpWebRTCCaptureSystemCamera = 1,
kKmpWebRTCCaptureScreen = 2,
kKmpWebRTCCaptureFile = 3,
kKmpWebRTCCaptureApp = 4,
};

enum KmpWebRTCSdpType {
kKmpWebRTCSdpOffer = 1,
kKmpWebRTCSdpPrAnswer = 2,
Expand All @@ -50,6 +59,10 @@ enum KmpWebRTCError {
struct PCClientFactoryPrivateConfig {
void* hwnd;
int disable_encryption;
int dummy_audio_device;
int transit_video;
const char* capture_file_path;
const char* capture_dump_path;
};

struct PCClientFactoryConfig {
Expand Down Expand Up @@ -84,12 +97,17 @@ KMP_WEBRTC_API void SetRemoteDescription(void* pc_client, KmpWebRTCSdpType type,
KMP_WEBRTC_API void AddIceCandidate(void* pc_client, const char* sdp_mid, int m_line_index, const char* sdp);
KMP_WEBRTC_API void GetStats(void* pc_client);

KMP_WEBRTC_API int StartRecorder(void* pc_client, int dir, const char* path);
KMP_WEBRTC_API int StopRecorder(void* pc_client, int dir);

#if defined(WEBRTC_WIN)
KMP_WEBRTC_API void AddRemoteTrackRenderer(void* pc_client, void* renderer);
#endif

KMP_WEBRTC_API void LogInfo(const char* log);

KMP_WEBRTC_API const char* PreferSdp(const char* sdp, int codec);

#if __cplusplus
}
#endif
68 changes: 68 additions & 0 deletions example/linuxApp/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
cmake_minimum_required(VERSION 3.10)
project(linuxApp)

set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)

include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../libs/linux/x64)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../../libs/windows_linux/include)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../common/cpp)

add_definitions(-DWEBRTC_LINUX=1)

file(GLOB deps
${CMAKE_CURRENT_SOURCE_DIR}/../../libs/linux/x64/libkmp_webrtc.so
${CMAKE_CURRENT_SOURCE_DIR}/../../libs/linux/x64/liblinux_pc_client.so
)

set(BUILD_QT_DEMO FALSE)
if (BUILD_QT_DEMO)
find_package(Qt5 REQUIRED COMPONENTS Widgets)

include_directories(${Qt5Widgets_INCLUDE_DIRS})

set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOUIC ON)

add_executable(${PROJECT_NAME}
main.cpp
main_window.cpp
main_window.h
loopback.cpp
${CMAKE_CURRENT_SOURCE_DIR}/../common/cpp/libKmpWebrtc.cpp
)

target_link_libraries(${PROJECT_NAME}
${Qt5Widgets_LIBRARIES}
${deps}
)
endif()


add_executable(loopback
console_app.cpp
loopback.cpp
${CMAKE_CURRENT_SOURCE_DIR}/../common/cpp/libKmpWebrtc.cpp
)

target_link_libraries(loopback
${deps}
)

set(BUILD_FFMPEG_TEST FALSE)
if (BUILD_FFMPEG_TEST)
set(FFMPEG_INCLUDE_DIR /home/linker/src/FFmpeg/build/include)
set(FFMPEG_LIB_DIR /home/linker/src/FFmpeg/build/lib)
include_directories(${FFMPEG_INCLUDE_DIR})

add_executable(ffmpeg_test
ffmpeg_test.cpp
)

target_link_libraries(ffmpeg_test
${FFMPEG_LIB_DIR}/libavcodec.so
${FFMPEG_LIB_DIR}/libavformat.so
${FFMPEG_LIB_DIR}/libavutil.so
)
endif ()
27 changes: 27 additions & 0 deletions example/linuxApp/console_app.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#include "loopback.h"

#include <atomic>
#include <signal.h>
#include <stdio.h>
#include <unistd.h>

std::atomic<bool> running(true);

void signal_handler(int sig) {
running = false;
}

int main(int argc, char *argv[]) {
if (argc != 2) {
printf("Usage: loopback <input video file path>\n");
return -1;
}

signal(SIGINT, signal_handler);
startLoopback(argv[1]);
while (running) {
sleep(100);
}
stopLoopback();
return 0;
}
Loading
Loading