blob: 82a466ac0e2613db087720c005ad1471bfb02d1c [file] [log] [blame]
gyzhouad7cad82017-05-11 16:10:03 -07001This directory contains an example Unity native plugin for Windows OS.
2The APIs use Platform Invoke (P/Invoke) technology as required by Unity native plugin.
3This plugin dll can also be used by Windows C# applications other than Unity.
4
5An example of wrapping native plugin into a C# managed class in Unity is given as following:
6
7using System;
gyzhoub38f3862017-07-25 16:04:31 -07008using System.Collections.Generic;
gyzhouad7cad82017-05-11 16:10:03 -07009using System.Runtime.InteropServices;
10
11namespace SimplePeerConnectionM {
gyzhoub38f3862017-07-25 16:04:31 -070012 // A class for ice candidate.
13 public class IceCandidate {
14 public IceCandidate(string candidate, int sdpMlineIndex, string sdpMid) {
15 mCandidate = candidate;
16 mSdpMlineIndex = sdpMlineIndex;
17 mSdpMid = sdpMid;
18 }
19 string mCandidate;
20 int mSdpMlineIndex;
21 string mSdpMid;
22
23 public string Candidate {
24 get { return mCandidate; }
25 set { mCandidate = value; }
26 }
27
28 public int SdpMlineIndex {
29 get { return mSdpMlineIndex; }
30 set { mSdpMlineIndex = value; }
31 }
32
33 public string SdpMid {
34 get { return mSdpMid; }
35 set { mSdpMid = value; }
36 }
37 }
38
39 // A managed wrapper up class for the native c style peer connection APIs.
gyzhouad7cad82017-05-11 16:10:03 -070040 public class PeerConnectionM {
gyzhoub38f3862017-07-25 16:04:31 -070041 private const string dllPath = "webrtc_unity_plugin";
gyzhouad7cad82017-05-11 16:10:03 -070042
gyzhoub38f3862017-07-25 16:04:31 -070043 //create a peerconnection with turn servers
44 [DllImport(dllPath, CallingConvention = CallingConvention.Cdecl)]
45 private static extern int CreatePeerConnection(string[] turnUrls, int noOfUrls,
46 string username, string credential);
gyzhouad7cad82017-05-11 16:10:03 -070047
gyzhoub38f3862017-07-25 16:04:31 -070048 [DllImport(dllPath, CallingConvention = CallingConvention.Cdecl)]
49 private static extern bool ClosePeerConnection(int peerConnectionId);
gyzhouad7cad82017-05-11 16:10:03 -070050
gyzhoub38f3862017-07-25 16:04:31 -070051 [DllImport(dllPath, CallingConvention = CallingConvention.Cdecl)]
52 private static extern bool AddStream(int peerConnectionId, bool audioOnly);
gyzhouad7cad82017-05-11 16:10:03 -070053
gyzhoub38f3862017-07-25 16:04:31 -070054 [DllImport(dllPath, CallingConvention = CallingConvention.Cdecl)]
55 private static extern bool AddDataChannel(int peerConnectionId);
gyzhouad7cad82017-05-11 16:10:03 -070056
gyzhoub38f3862017-07-25 16:04:31 -070057 [DllImport(dllPath, CallingConvention = CallingConvention.Cdecl)]
58 private static extern bool CreateOffer(int peerConnectionId);
gyzhouad7cad82017-05-11 16:10:03 -070059
gyzhoub38f3862017-07-25 16:04:31 -070060 [DllImport(dllPath, CallingConvention = CallingConvention.Cdecl)]
61 private static extern bool CreateAnswer(int peerConnectionId);
gyzhouad7cad82017-05-11 16:10:03 -070062
gyzhoub38f3862017-07-25 16:04:31 -070063 [DllImport(dllPath, CallingConvention = CallingConvention.Cdecl)]
64 private static extern bool SendDataViaDataChannel(int peerConnectionId, string data);
gyzhouad7cad82017-05-11 16:10:03 -070065
gyzhoub38f3862017-07-25 16:04:31 -070066 [DllImport(dllPath, CallingConvention = CallingConvention.Cdecl)]
67 private static extern bool SetAudioControl(int peerConnectionId, bool isMute, bool isRecord);
gyzhouad7cad82017-05-11 16:10:03 -070068
69 [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
70 private delegate void LocalDataChannelReadyInternalDelegate();
71 public delegate void LocalDataChannelReadyDelegate(int id);
gyzhoub38f3862017-07-25 16:04:31 -070072 [DllImport(dllPath, CallingConvention = CallingConvention.Cdecl)]
73 private static extern bool RegisterOnLocalDataChannelReady(
74 int peerConnectionId, LocalDataChannelReadyInternalDelegate callback);
gyzhouad7cad82017-05-11 16:10:03 -070075
76 [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
77 private delegate void DataFromDataChannelReadyInternalDelegate(string s);
78 public delegate void DataFromDataChannelReadyDelegate(int id, string s);
gyzhoub38f3862017-07-25 16:04:31 -070079 [DllImport(dllPath, CallingConvention = CallingConvention.Cdecl)]
80 private static extern bool RegisterOnDataFromDataChannelReady(
81 int peerConnectionId, DataFromDataChannelReadyInternalDelegate callback);
gyzhouad7cad82017-05-11 16:10:03 -070082
83 [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
84 private delegate void FailureMessageInternalDelegate(string msg);
85 public delegate void FailureMessageDelegate(int id, string msg);
gyzhoub38f3862017-07-25 16:04:31 -070086 [DllImport(dllPath, CallingConvention = CallingConvention.Cdecl)]
87 private static extern bool RegisterOnFailure(int peerConnectionId,
88 FailureMessageInternalDelegate callback);
gyzhouad7cad82017-05-11 16:10:03 -070089
90 [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
gyzhoub38f3862017-07-25 16:04:31 -070091 private delegate void AudioBusReadyInternalDelegate(IntPtr data, int bitsPerSample,
92 int sampleRate, int numberOfChannels, int numberOfFrames);
93 public delegate void AudioBusReadyDelegate(int id, IntPtr data, int bitsPerSample,
94 int sampleRate, int numberOfChannels, int numberOfFrames);
95 [DllImport(dllPath, CallingConvention = CallingConvention.Cdecl)]
96 private static extern bool RegisterOnAudioBusReady(int peerConnectionId,
97 AudioBusReadyInternalDelegate callback);
98
99 // Video callbacks.
100 [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
101 private delegate void I420FrameReadyInternalDelegate(
102 IntPtr dataY, IntPtr dataU, IntPtr dataV,
103 int strideY, int strideU, int strideV,
104 uint width, uint height);
105 public delegate void I420FrameReadyDelegate(int id,
106 IntPtr dataY, IntPtr dataU, IntPtr dataV,
107 int strideY, int strideU, int strideV,
108 uint width, uint height);
109 [DllImport(dllPath, CallingConvention = CallingConvention.Cdecl)]
110 private static extern bool RegisterOnLocalI420FrameReady(int peerConnectionId,
111 I420FrameReadyInternalDelegate callback);
112 [DllImport(dllPath, CallingConvention = CallingConvention.Cdecl)]
113 private static extern bool RegisterOnRemoteI420FrameReady(int peerConnectionId,
114 I420FrameReadyInternalDelegate callback);
gyzhouad7cad82017-05-11 16:10:03 -0700115
116 [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
gyzhoub38f3862017-07-25 16:04:31 -0700117 private delegate void LocalSdpReadytoSendInternalDelegate(string type, string sdp);
118 public delegate void LocalSdpReadytoSendDelegate(int id, string type, string sdp);
119 [DllImport(dllPath, CallingConvention = CallingConvention.Cdecl)]
120 private static extern bool RegisterOnLocalSdpReadytoSend(int peerConnectionId,
121 LocalSdpReadytoSendInternalDelegate callback);
gyzhouad7cad82017-05-11 16:10:03 -0700122
123 [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
gyzhoub38f3862017-07-25 16:04:31 -0700124 private delegate void IceCandiateReadytoSendInternalDelegate(
125 string candidate, int sdpMlineIndex, string sdpMid);
126 public delegate void IceCandiateReadytoSendDelegate(
127 int id, string candidate, int sdpMlineIndex, string sdpMid);
128 [DllImport(dllPath, CallingConvention = CallingConvention.Cdecl)]
129 private static extern bool RegisterOnIceCandiateReadytoSend(
130 int peerConnectionId, IceCandiateReadytoSendInternalDelegate callback);
gyzhouad7cad82017-05-11 16:10:03 -0700131
gyzhoub38f3862017-07-25 16:04:31 -0700132 [DllImport(dllPath, CallingConvention = CallingConvention.Cdecl)]
133 private static extern bool SetRemoteDescription(int peerConnectionId, string type, string sdp);
gyzhouad7cad82017-05-11 16:10:03 -0700134
gyzhoub38f3862017-07-25 16:04:31 -0700135 [DllImport(dllPath, CallingConvention = CallingConvention.Cdecl)]
136 private static extern bool AddIceCandidate(int peerConnectionId, string sdp,
137 int sdpMlineindex, string sdpMid);
gyzhouad7cad82017-05-11 16:10:03 -0700138
gyzhoub38f3862017-07-25 16:04:31 -0700139 public PeerConnectionM(List<string> turnUrls, string username, string credential) {
140 string[] urls = turnUrls != null ? turnUrls.ToArray() : null;
141 int length = turnUrls != null ? turnUrls.Count : 0;
142 mPeerConnectionId = CreatePeerConnection(urls, length, username, credential);
gyzhouad7cad82017-05-11 16:10:03 -0700143 RegisterCallbacks();
144 }
145
gyzhoub38f3862017-07-25 16:04:31 -0700146 public void ClosePeerConnection() {
147 ClosePeerConnection(mPeerConnectionId);
148 mPeerConnectionId = -1;
gyzhouad7cad82017-05-11 16:10:03 -0700149 }
150
151 // Return -1 if Peerconnection is not available.
152 public int GetUniqueId() {
gyzhoub38f3862017-07-25 16:04:31 -0700153 return mPeerConnectionId;
gyzhouad7cad82017-05-11 16:10:03 -0700154 }
155
gyzhoub38f3862017-07-25 16:04:31 -0700156 public void AddStream(bool audioOnly) {
157 AddStream(mPeerConnectionId, audioOnly);
gyzhouad7cad82017-05-11 16:10:03 -0700158 }
159
gyzhoub38f3862017-07-25 16:04:31 -0700160 public void AddDataChannel() {
161 AddDataChannel(mPeerConnectionId);
gyzhouad7cad82017-05-11 16:10:03 -0700162 }
163
gyzhoub38f3862017-07-25 16:04:31 -0700164 public void CreateOffer() {
165 CreateOffer(mPeerConnectionId);
gyzhouad7cad82017-05-11 16:10:03 -0700166 }
167
gyzhoub38f3862017-07-25 16:04:31 -0700168 public void CreateAnswer() {
169 CreateAnswer(mPeerConnectionId);
gyzhouad7cad82017-05-11 16:10:03 -0700170 }
171
gyzhoub38f3862017-07-25 16:04:31 -0700172 public void SendDataViaDataChannel(string data) {
173 SendDataViaDataChannel(mPeerConnectionId, data);
gyzhouad7cad82017-05-11 16:10:03 -0700174 }
175
gyzhoub38f3862017-07-25 16:04:31 -0700176 public void SetAudioControl(bool isMute, bool isRecord) {
177 SetAudioControl(mPeerConnectionId, isMute, isRecord);
gyzhouad7cad82017-05-11 16:10:03 -0700178 }
179
gyzhoub38f3862017-07-25 16:04:31 -0700180 public void SetRemoteDescription(string type, string sdp) {
181 SetRemoteDescription(mPeerConnectionId, type, sdp);
gyzhouad7cad82017-05-11 16:10:03 -0700182 }
183
gyzhoub38f3862017-07-25 16:04:31 -0700184 public void AddIceCandidate(string candidate, int sdpMlineindex, string sdpMid) {
185 AddIceCandidate(mPeerConnectionId, candidate, sdpMlineindex, sdpMid);
186 }
187
188 private void RegisterCallbacks() {
189 localDataChannelReadyDelegate = new LocalDataChannelReadyInternalDelegate(
190 RaiseLocalDataChannelReady);
191 RegisterOnLocalDataChannelReady(mPeerConnectionId, localDataChannelReadyDelegate);
192
193 dataFromDataChannelReadyDelegate = new DataFromDataChannelReadyInternalDelegate(
194 RaiseDataFromDataChannelReady);
195 RegisterOnDataFromDataChannelReady(mPeerConnectionId, dataFromDataChannelReadyDelegate);
196
197 failureMessageDelegate = new FailureMessageInternalDelegate(RaiseFailureMessage);
198 RegisterOnFailure(mPeerConnectionId, failureMessageDelegate);
199
200 audioBusReadyDelegate = new AudioBusReadyInternalDelegate(RaiseAudioBusReady);
201 RegisterOnAudioBusReady(mPeerConnectionId, audioBusReadyDelegate);
202
203 localI420FrameReadyDelegate = new I420FrameReadyInternalDelegate(
204 RaiseLocalVideoFrameReady);
205 RegisterOnLocalI420FrameReady(mPeerConnectionId, localI420FrameReadyDelegate);
206
207 remoteI420FrameReadyDelegate = new I420FrameReadyInternalDelegate(
208 RaiseRemoteVideoFrameReady);
209 RegisterOnRemoteI420FrameReady(mPeerConnectionId, remoteI420FrameReadyDelegate);
210
211 localSdpReadytoSendDelegate = new LocalSdpReadytoSendInternalDelegate(
212 RaiseLocalSdpReadytoSend);
213 RegisterOnLocalSdpReadytoSend(mPeerConnectionId, localSdpReadytoSendDelegate);
214
215 iceCandiateReadytoSendDelegate =
216 new IceCandiateReadytoSendInternalDelegate(RaiseIceCandiateReadytoSend);
217 RegisterOnIceCandiateReadytoSend(
218 mPeerConnectionId, iceCandiateReadytoSendDelegate);
gyzhouad7cad82017-05-11 16:10:03 -0700219 }
220
221 private void RaiseLocalDataChannelReady() {
222 if (OnLocalDataChannelReady != null)
gyzhoub38f3862017-07-25 16:04:31 -0700223 OnLocalDataChannelReady(mPeerConnectionId);
gyzhouad7cad82017-05-11 16:10:03 -0700224 }
225
226 private void RaiseDataFromDataChannelReady(string data) {
227 if (OnDataFromDataChannelReady != null)
gyzhoub38f3862017-07-25 16:04:31 -0700228 OnDataFromDataChannelReady(mPeerConnectionId, data);
gyzhouad7cad82017-05-11 16:10:03 -0700229 }
230
231 private void RaiseFailureMessage(string msg) {
232 if (OnFailureMessage != null)
gyzhoub38f3862017-07-25 16:04:31 -0700233 OnFailureMessage(mPeerConnectionId, msg);
gyzhouad7cad82017-05-11 16:10:03 -0700234 }
235
gyzhoub38f3862017-07-25 16:04:31 -0700236 private void RaiseAudioBusReady(IntPtr data, int bitsPerSample,
237 int sampleRate, int numberOfChannels, int numberOfFrames) {
gyzhouad7cad82017-05-11 16:10:03 -0700238 if (OnAudioBusReady != null)
gyzhoub38f3862017-07-25 16:04:31 -0700239 OnAudioBusReady(mPeerConnectionId, data, bitsPerSample, sampleRate,
240 numberOfChannels, numberOfFrames);
gyzhouad7cad82017-05-11 16:10:03 -0700241 }
242
gyzhoub38f3862017-07-25 16:04:31 -0700243 private void RaiseLocalVideoFrameReady(
244 IntPtr dataY, IntPtr dataU, IntPtr dataV,
245 int strideY, int strideU, int strideV,
246 uint width, uint height) {
247 if (OnLocalVideoFrameReady != null)
248 OnLocalVideoFrameReady(mPeerConnectionId, dataY, dataU, dataV, strideY, strideU, strideV,
249 width, height);
250 }
251
252 private void RaiseRemoteVideoFrameReady(
253 IntPtr dataY, IntPtr dataU, IntPtr dataV,
254 int strideY, int strideU, int strideV,
255 uint width, uint height) {
256 if (OnRemoteVideoFrameReady != null)
257 OnRemoteVideoFrameReady(mPeerConnectionId, dataY, dataU, dataV, strideY, strideU, strideV,
258 width, height);
259 }
260
261
262 private void RaiseLocalSdpReadytoSend(string type, string sdp) {
gyzhouad7cad82017-05-11 16:10:03 -0700263 if (OnLocalSdpReadytoSend != null)
gyzhoub38f3862017-07-25 16:04:31 -0700264 OnLocalSdpReadytoSend(mPeerConnectionId, type, sdp);
gyzhouad7cad82017-05-11 16:10:03 -0700265 }
266
gyzhoub38f3862017-07-25 16:04:31 -0700267 private void RaiseIceCandiateReadytoSend(string candidate, int sdpMlineIndex, string sdpMid) {
gyzhouad7cad82017-05-11 16:10:03 -0700268 if (OnIceCandiateReadytoSend != null)
gyzhoub38f3862017-07-25 16:04:31 -0700269 OnIceCandiateReadytoSend(mPeerConnectionId, candidate, sdpMlineIndex, sdpMid);
gyzhouad7cad82017-05-11 16:10:03 -0700270 }
271
gyzhoub38f3862017-07-25 16:04:31 -0700272 public void AddQueuedIceCandidate(List<IceCandidate> iceCandidateQueue) {
273 if (iceCandidateQueue != null) {
274 foreach (IceCandidate ic in iceCandidateQueue) {
275 AddIceCandidate(mPeerConnectionId, ic.Candidate, ic.SdpMlineIndex, ic.SdpMid);
276 }
277 }
278 }
279
280 private LocalDataChannelReadyInternalDelegate localDataChannelReadyDelegate = null;
gyzhouad7cad82017-05-11 16:10:03 -0700281 public event LocalDataChannelReadyDelegate OnLocalDataChannelReady;
282
gyzhoub38f3862017-07-25 16:04:31 -0700283 private DataFromDataChannelReadyInternalDelegate dataFromDataChannelReadyDelegate = null;
gyzhouad7cad82017-05-11 16:10:03 -0700284 public event DataFromDataChannelReadyDelegate OnDataFromDataChannelReady;
285
gyzhoub38f3862017-07-25 16:04:31 -0700286 private FailureMessageInternalDelegate failureMessageDelegate = null;
gyzhouad7cad82017-05-11 16:10:03 -0700287 public event FailureMessageDelegate OnFailureMessage;
288
gyzhoub38f3862017-07-25 16:04:31 -0700289 private AudioBusReadyInternalDelegate audioBusReadyDelegate = null;
gyzhouad7cad82017-05-11 16:10:03 -0700290 public event AudioBusReadyDelegate OnAudioBusReady;
291
gyzhoub38f3862017-07-25 16:04:31 -0700292 private I420FrameReadyInternalDelegate localI420FrameReadyDelegate = null;
293 public event I420FrameReadyDelegate OnLocalVideoFrameReady;
294
295 private I420FrameReadyInternalDelegate remoteI420FrameReadyDelegate = null;
296 public event I420FrameReadyDelegate OnRemoteVideoFrameReady;
297
298 private LocalSdpReadytoSendInternalDelegate localSdpReadytoSendDelegate = null;
gyzhouad7cad82017-05-11 16:10:03 -0700299 public event LocalSdpReadytoSendDelegate OnLocalSdpReadytoSend;
300
gyzhoub38f3862017-07-25 16:04:31 -0700301 private IceCandiateReadytoSendInternalDelegate iceCandiateReadytoSendDelegate = null;
gyzhouad7cad82017-05-11 16:10:03 -0700302 public event IceCandiateReadytoSendDelegate OnIceCandiateReadytoSend;
303
gyzhoub38f3862017-07-25 16:04:31 -0700304 private int mPeerConnectionId = -1;
gyzhouad7cad82017-05-11 16:10:03 -0700305 }
306}