Skip to content

Commit c8ee4cb

Browse files
authored
Merge pull request #1 from HackWebRTC/windows
add windows support
2 parents 4635e66 + 9887869 commit c8ee4cb

File tree

39 files changed

+1667
-82
lines changed

39 files changed

+1667
-82
lines changed

.github/workflows/ci.yaml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ jobs:
2929
- cmd: "./scripts/build_mac_demo.sh"
3030
os: macos-latest
3131
dep: "brew update && brew install cocoapods xcodegen"
32+
- 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"
33+
os: windows-latest
3234
runs-on: ${{ matrix.os }}
3335
permissions:
3436
pull-requests: write
@@ -50,6 +52,11 @@ jobs:
5052
with:
5153
url: "https://github.com/HackWebRTC/kmp-webrtc/releases/latest/download/libs.zip"
5254
target: ./
55+
- name: Setup MSBuild
56+
if: ${{ matrix.os == 'windows-latest' }}
57+
uses: microsoft/setup-msbuild@v2
58+
with:
59+
msbuild-architecture: x64
5360
- if: ${{ matrix.dep }}
5461
run: ${{ matrix.dep }}
5562
- name: Extract libs

README.md

Lines changed: 60 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,12 @@ KMP wrapper for WebRTC.
88

99
| Platform | 🛠Builds🛠 + 🔬Tests🔬 |
1010
| :----------------: | :------------------: |
11-
| `JVM` 17 | 🔮 |
12-
| `JS` (Chrome) | 🔮 |
13-
| `WasmJS` (Chrome) | 🔮 |
1411
| `Android` | 🚀 |
1512
| `iOS` | 🚀 |
16-
| `macOS` | 🔮 |
17-
| `Windows X64` | 🔮 |
13+
| `macOS` | 🚀 |
14+
| `Windows X64` | 🚀 |
15+
| `JS` (Chrome) | 🔮 |
16+
| `WasmJS` (Chrome) | 🔮 |
1817
| `Linux X64` | 🔮 |
1918

2019
## Dependency
@@ -41,6 +40,15 @@ kotlin {
4140

4241
## Env Setup
4342

43+
Download and extract the `libs` dir:
44+
45+
```bash
46+
wget https://github.com/HackWebRTC/kmp-webrtc/releases/latest/download/libs.zip
47+
unzip -o libs.zip
48+
```
49+
50+
### macOS
51+
4452
You need to install [RVM](https://rvm.io/) to manage your ruby version, and install gems. You need to use homebrew to install the following tools:
4553

4654
```bash
@@ -51,6 +59,10 @@ brew install cocoapods xcodegen
5159

5260
You may need to restart your system so that Android Studio could use the correct ruby.
5361

62+
### Windows
63+
64+
Follow [this guide](https://chromium.googlesource.com/chromium/src/+/master/docs/windows_build_instructions.md) to install Visual Studio 2022 and necessary tools.
65+
5466
## Example
5567

5668
### Android
@@ -71,31 +83,66 @@ Open the project (the repo root dir) in Android studio, and run the example.andr
7183
# open example/macApp/macApp.xcworkspace in Xcode, and run it.
7284
```
7385

86+
### Windows
87+
88+
```bash
89+
.\scripts\setup_windows.bat
90+
# open example\winApp\winApp.sln in Visual Studio 2022, and run it.
91+
```
92+
7493
## Build WebRTC
7594

95+
[hack_webrtc_43659 branch of HackWebRTC/webrtc](https://github.com/HackWebRTC/webrtc/tree/hack_webrtc_43659), which is based on m133.
96+
97+
File structure for macOS:
98+
99+
```
100+
- webrtc_apple
101+
- src
102+
- kmp-webrtc
103+
```
104+
105+
File structure for Windows:
106+
107+
```
108+
- webrtc_windows
109+
- src
110+
- kmp-webrtc
111+
```
112+
76113
### Android
77114

115+
CPP code need to be built on Linux.
116+
78117
```bash
79118
# on Linux
80119
./sdk/build_android_libs.sh <output path> --skip-build-ffmpeg
81120

82121
# on macOS, copy prebuilt_libs into sdk/android_gradle/webrtc/
83122
# then build aar like this:
84-
pushd ../webrtc_repo/webrtc_ios/src/sdk/android_gradle/ && \
123+
pushd ../webrtc_apple/src/sdk/android_gradle/ && \
85124
./gradlew :webrtc:assembleRelease && \
86125
cp webrtc/build/outputs/aar/webrtc-release.aar \
87-
../../../../../kmp-webrtc/libs/android/webrtc.aar && \
126+
../../../../kmp-webrtc/libs/android/webrtc.aar && \
88127
popd
89128
```
90129

91130
### Apple
92131

93132
```bash
94-
pushd ../webrtc_repo/webrtc_ios/src/ && \
95-
./sdk/build_apple_framework.sh ../../../kmp-webrtc/libs --skip-build-ffmpeg && \
133+
pushd ../webrtc_apple/src/ && \
134+
./sdk/build_apple_framework.sh ../../kmp-webrtc/libs --skip-build-ffmpeg && \
96135
popd
97136
```
98137

138+
### Windows
139+
140+
In `x64 Native Tools Command Prompt for VS 2022`:
141+
142+
```bash
143+
.\sdk\build_windows_libs.bat ..\..\kmp-webrtc
144+
```
145+
99146
### Upload libs zip
100147

101148
```bash
@@ -112,3 +159,7 @@ Maven central portal credentials and signing configs are set in `~/.gradle/gradl
112159
```
113160

114161
Login to https://central.sonatype.com/publishing/deployments, and release them manually.
162+
163+
## Other projects
164+
165+
- [shepeliev/webrtc-kmp](https://github.com/shepeliev/webrtc-kmp)

example/androidApp/src/main/java/com/piasy/kmp/webrtc/android/CallActivity.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -279,8 +279,8 @@ private void startLoopback() {
279279
getLifecycle(), eglBase, options, true, null, null, null
280280
);
281281
PeerConnectionClientFactory.Config config = new PeerConnectionClientFactory.Config(
282-
PeerConnectionClientFactory.Config.VIDEO_CAPTURE_IMPL_SYSTEM_CAMERA,
283-
videoWidth, videoHeight, videoFps, PeerConnectionClientFactory.Config.CAMERA_FACE_FRONT,
282+
PeerConnectionClientFactory.VIDEO_CAPTURE_IMPL_SYSTEM_CAMERA,
283+
videoWidth, videoHeight, videoFps, PeerConnectionClientFactory.CAMERA_FACE_FRONT,
284284
privateConfig
285285
);
286286
pcClientFactory = createPeerConnectionClientFactory(config, new Function2<Integer, String, Unit>() {

example/common/cpp/libKmpWebrtc.cpp

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
#include "libKmpWebrtc.h"
2+
3+
#include <cstring>
4+
5+
#if defined(WEBRTC_WIN)
6+
#include "kmp_webrtc_api.h"
7+
#elif defined(WEBRTC_LINUX)
8+
#include "libkmp_webrtc_api.h"
9+
#else
10+
#error "Unknown target"
11+
#endif
12+
13+
#include "lib_pc_client.h"
14+
15+
#if defined(WEBRTC_WIN)
16+
#define KT_SYMBOL(sym) sym
17+
#elif defined(WEBRTC_LINUX)
18+
#define KT_SYMBOL(sym) lib##sym
19+
#else
20+
#error "Unknown target"
21+
#endif
22+
23+
#define KFunc(NAME) g_lib->kotlin.root.com.piasy.kmp.webrtc.##NAME
24+
#define KType(NAME) kmp_webrtc_kref_com_piasy_kmp_webrtc_##NAME
25+
26+
static KT_SYMBOL(kmp_webrtc_ExportedSymbols)* g_lib = nullptr;
27+
28+
int InitializeWebRTC(const char* field_trials, int debug_log) {
29+
if (!g_lib) {
30+
g_lib = KT_SYMBOL(kmp_webrtc_symbols)();
31+
}
32+
return KFunc(initializeWebRTC)(kmp_webrtc_kref_kotlin_Any(), field_trials, debug_log);
33+
}
34+
35+
struct PCClientFactoryConfig* DefaultPCClientFactoryConfig() {
36+
PCClientFactoryConfig* config = new PCClientFactoryConfig();
37+
config->video_capture_impl = kKmpWebRTCCaptureSystemCamera;
38+
config->video_capture_width = 1280;
39+
config->video_capture_height = 720;
40+
config->video_capture_fps = 30;
41+
config->private_config.hwnd = nullptr;
42+
return config;
43+
}
44+
45+
void PCClientFactoryConfigDestroy(struct PCClientFactoryConfig** config) {
46+
delete (*config);
47+
*config = nullptr;
48+
}
49+
50+
struct PcClientFactoryHolder {
51+
KType(PeerConnectionClientFactory) factory;
52+
};
53+
54+
void* CreatePCClientFactory(struct PCClientFactoryConfig* config, PCClientFactoryErrorHandler handler, void* opaque) {
55+
KType(PeerConnectionClientFactory_PrivateConfig) private_config = KFunc(PeerConnectionClientFactory.PrivateConfig.PrivateConfig)();
56+
KType(PeerConnectionClientFactory_Config) k_config = KFunc(PeerConnectionClientFactory.Config.Config)(
57+
(int) config->video_capture_impl, config->video_capture_width, config->video_capture_height,
58+
config->video_capture_fps, 0, private_config);
59+
KType(WinPrivateConfig) win_private_config = KFunc(WinPrivateConfig.WinPrivateConfig)(config->private_config.hwnd, config->private_config.disable_encryption);
60+
KType(PeerConnectionClientFactory_Config) k_config_with_pri = KFunc(utils.createPcClientFactoryConfig)(k_config, win_private_config);
61+
62+
kmp_webrtc_kref_kotlin_Function2 error_handler = KFunc(utils.createErrorHandler)(handler, opaque);
63+
64+
PcClientFactoryHolder* holder = new PcClientFactoryHolder();
65+
holder->factory = KFunc(createPeerConnectionClientFactory)(k_config_with_pri, error_handler);
66+
return holder;
67+
}
68+
69+
void DestroyPCClientFactory(void** pc_client_factory) {
70+
PcClientFactoryHolder* holder = reinterpret_cast<PcClientFactoryHolder*>(*pc_client_factory);
71+
KFunc(PeerConnectionClientFactory.destroyPeerConnectionFactory)(holder->factory);
72+
delete (*pc_client_factory);
73+
*pc_client_factory = nullptr;
74+
}
75+
76+
void CreateLocalTracks(void* pc_client_factory) {
77+
PcClientFactoryHolder* holder = reinterpret_cast<PcClientFactoryHolder*>(pc_client_factory);
78+
KFunc(PeerConnectionClientFactory.createLocalTracks)(holder->factory);
79+
}
80+
81+
void StartVideoCapture(void* pc_client_factory) {
82+
PcClientFactoryHolder* holder = reinterpret_cast<PcClientFactoryHolder*>(pc_client_factory);
83+
KFunc(PeerConnectionClientFactory.startVideoCapture)(holder->factory);
84+
}
85+
86+
void StopVideoCapture(void* pc_client_factory) {
87+
PcClientFactoryHolder* holder = reinterpret_cast<PcClientFactoryHolder*>(pc_client_factory);
88+
KFunc(PeerConnectionClientFactory.stopVideoCapture)(holder->factory);
89+
}
90+
91+
struct PcClientHolder {
92+
KType(PeerConnectionClient) client;
93+
};
94+
95+
void* CreatePeerConnectionClient(void* pc_client_factory, const char* peer_uid, KmpWebRTCDir dir, int has_video,
96+
int video_max_bitrate_kbps, int video_max_frame_rate, PCClientCallback* callback, void* opaque) {
97+
PcClientFactoryHolder* factory_holder = reinterpret_cast<PcClientFactoryHolder*>(pc_client_factory);
98+
KType(PeerConnectionClientCallback) pc_client_callback = KFunc(utils.createPcClientCallback)(callback, opaque);
99+
100+
PcClientHolder* holder = new PcClientHolder();
101+
holder->client = KFunc(PeerConnectionClientFactory.createPeerConnectionClient)(factory_holder->factory, peer_uid, (int)dir,
102+
has_video, video_max_bitrate_kbps, video_max_frame_rate, pc_client_callback);
103+
return holder;
104+
}
105+
106+
void ClosePeerConnectionClient(void** pc_client) {
107+
PcClientHolder* holder = reinterpret_cast<PcClientHolder*>(*pc_client);
108+
KFunc(PeerConnectionClient.close)(holder->client);
109+
delete (*pc_client);
110+
*pc_client = nullptr;
111+
}
112+
113+
void CreatePeerConnection(void* pc_client) {
114+
PcClientHolder* holder = reinterpret_cast<PcClientHolder*>(pc_client);
115+
kmp_webrtc_kref_kotlin_collections_List ice_servers = KFunc(utils.emptyIceServers)();
116+
KFunc(PeerConnectionClient.createPeerConnection)(holder->client, ice_servers);
117+
}
118+
119+
void CreateOffer(void* pc_client) {
120+
PcClientHolder* holder = reinterpret_cast<PcClientHolder*>(pc_client);
121+
KFunc(PeerConnectionClient.createOffer)(holder->client);
122+
}
123+
124+
void SetRemoteDescription(void* pc_client, KmpWebRTCSdpType type, const char* sdp) {
125+
KType(data_SessionDescription) answer = KFunc(data.SessionDescription.SessionDescription)((int) type, sdp);
126+
PcClientHolder* holder = reinterpret_cast<PcClientHolder*>(pc_client);
127+
KFunc(PeerConnectionClient.setRemoteDescription)(holder->client, answer);
128+
}
129+
130+
void AddIceCandidate(void* pc_client, const char* sdp_mid, int m_line_index, const char* sdp) {
131+
KType(data_IceCandidate) candidate = KFunc(data.IceCandidate.IceCandidate)(sdp_mid, m_line_index, sdp);
132+
PcClientHolder* holder = reinterpret_cast<PcClientHolder*>(pc_client);
133+
KFunc(PeerConnectionClient.addIceCandidate)(holder->client, candidate);
134+
}
135+
136+
void GetStats(void* pc_client) {
137+
PcClientHolder* holder = reinterpret_cast<PcClientHolder*>(pc_client);
138+
KFunc(PeerConnectionClient.getStats)(holder->client);
139+
}
140+
141+
#if defined(WEBRTC_WIN)
142+
void AddRemoteTrackRenderer(void* pc_client, void* renderer) {
143+
PcClientHolder* holder = reinterpret_cast<PcClientHolder*>(pc_client);
144+
KFunc(utils.addRemoteTrackRenderer)(holder->client, renderer);
145+
}
146+
#endif
147+
148+
void LogInfo(const char* log) {
149+
KFunc(utils.logInfo)(log);
150+
}

0 commit comments

Comments
 (0)