This directory contains an example Unity native plugin for Windows OS and Android.

The APIs use Platform Invoke (P/Invoke) technology as required by Unity native plugin.
This plugin dll can also be used by Windows C# applications other than Unity.

For detailed build instruction on Android, see ANDROID_INSTRUCTION

An example of wrapping native plugin into a C# managed class in Unity is given as following:

using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;

namespace SimplePeerConnectionM {
  // A class for ice candidate.
  public class IceCandidate {
    public IceCandidate(string candidate, int sdpMlineIndex, string sdpMid) {
      mCandidate = candidate;
      mSdpMlineIndex = sdpMlineIndex;
      mSdpMid = sdpMid;
    }
    string mCandidate;
    int mSdpMlineIndex;
    string mSdpMid;

    public string Candidate {
      get { return mCandidate; }
      set { mCandidate = value; }
    }

    public int SdpMlineIndex {
      get { return mSdpMlineIndex; }
      set { mSdpMlineIndex = value; }
    }

    public string SdpMid {
      get { return mSdpMid; }
      set { mSdpMid = value; }
    }
  }

  // A managed wrapper up class for the native c style peer connection APIs.
  public class PeerConnectionM {
    private const string dllPath = "webrtc_unity_plugin";

    //create a peerconnection with turn servers
    [DllImport(dllPath, CallingConvention = CallingConvention.Cdecl)]
    private static extern int CreatePeerConnection(string[] turnUrls, int noOfUrls,
        string username, string credential);

    [DllImport(dllPath, CallingConvention = CallingConvention.Cdecl)]
    private static extern bool ClosePeerConnection(int peerConnectionId);

    [DllImport(dllPath, CallingConvention = CallingConvention.Cdecl)]
    private static extern bool AddStream(int peerConnectionId, bool audioOnly);

    [DllImport(dllPath, CallingConvention = CallingConvention.Cdecl)]
    private static extern bool AddDataChannel(int peerConnectionId);

    [DllImport(dllPath, CallingConvention = CallingConvention.Cdecl)]
    private static extern bool CreateOffer(int peerConnectionId);

    [DllImport(dllPath, CallingConvention = CallingConvention.Cdecl)]
    private static extern bool CreateAnswer(int peerConnectionId);

    [DllImport(dllPath, CallingConvention = CallingConvention.Cdecl)]
    private static extern bool SendDataViaDataChannel(int peerConnectionId, string data);

    [DllImport(dllPath, CallingConvention = CallingConvention.Cdecl)]
    private static extern bool SetAudioControl(int peerConnectionId, bool isMute, bool isRecord);

    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
    private delegate void LocalDataChannelReadyInternalDelegate();
    public delegate void LocalDataChannelReadyDelegate(int id);
    [DllImport(dllPath, CallingConvention = CallingConvention.Cdecl)]
    private static extern bool RegisterOnLocalDataChannelReady(
        int peerConnectionId, LocalDataChannelReadyInternalDelegate callback);

    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
    private delegate void DataFromDataChannelReadyInternalDelegate(string s);
    public delegate void DataFromDataChannelReadyDelegate(int id, string s);
    [DllImport(dllPath, CallingConvention = CallingConvention.Cdecl)]
    private static extern bool RegisterOnDataFromDataChannelReady(
        int peerConnectionId, DataFromDataChannelReadyInternalDelegate callback);

    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
    private delegate void FailureMessageInternalDelegate(string msg);
    public delegate void FailureMessageDelegate(int id, string msg);
    [DllImport(dllPath, CallingConvention = CallingConvention.Cdecl)]
    private static extern bool RegisterOnFailure(int peerConnectionId,
        FailureMessageInternalDelegate callback);

    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
    private delegate void AudioBusReadyInternalDelegate(IntPtr data, int bitsPerSample,
        int sampleRate, int numberOfChannels, int numberOfFrames);
    public delegate void AudioBusReadyDelegate(int id, IntPtr data, int bitsPerSample,
        int sampleRate, int numberOfChannels, int numberOfFrames);
    [DllImport(dllPath, CallingConvention = CallingConvention.Cdecl)]
    private static extern bool RegisterOnAudioBusReady(int peerConnectionId,
        AudioBusReadyInternalDelegate callback);

    // Video callbacks.
    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
    private delegate void I420FrameReadyInternalDelegate(
        IntPtr dataY, IntPtr dataU, IntPtr dataV,
        int strideY, int strideU, int strideV,
        uint width, uint height);
    public delegate void I420FrameReadyDelegate(int id,
        IntPtr dataY, IntPtr dataU, IntPtr dataV,
        int strideY, int strideU, int strideV,
        uint width, uint height);
    [DllImport(dllPath, CallingConvention = CallingConvention.Cdecl)]
    private static extern bool RegisterOnLocalI420FrameReady(int peerConnectionId,
        I420FrameReadyInternalDelegate callback);
    [DllImport(dllPath, CallingConvention = CallingConvention.Cdecl)]
    private static extern bool RegisterOnRemoteI420FrameReady(int peerConnectionId,
        I420FrameReadyInternalDelegate callback);

    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
    private delegate void LocalSdpReadytoSendInternalDelegate(string type, string sdp);
    public delegate void LocalSdpReadytoSendDelegate(int id, string type, string sdp);
    [DllImport(dllPath, CallingConvention = CallingConvention.Cdecl)]
    private static extern bool RegisterOnLocalSdpReadytoSend(int peerConnectionId,
        LocalSdpReadytoSendInternalDelegate callback);

    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
    private delegate void IceCandiateReadytoSendInternalDelegate(
        string candidate, int sdpMlineIndex, string sdpMid);
    public delegate void IceCandiateReadytoSendDelegate(
        int id, string candidate, int sdpMlineIndex, string sdpMid);
    [DllImport(dllPath, CallingConvention = CallingConvention.Cdecl)]
    private static extern bool RegisterOnIceCandiateReadytoSend(
        int peerConnectionId, IceCandiateReadytoSendInternalDelegate callback);

    [DllImport(dllPath, CallingConvention = CallingConvention.Cdecl)]
    private static extern bool SetRemoteDescription(int peerConnectionId, string type, string sdp);

    [DllImport(dllPath, CallingConvention = CallingConvention.Cdecl)]
    private static extern bool AddIceCandidate(int peerConnectionId, string sdp,
      int sdpMlineindex, string sdpMid);

    public PeerConnectionM(List<string> turnUrls, string username, string credential) {
      string[] urls = turnUrls != null ? turnUrls.ToArray() : null;
      int length = turnUrls != null ? turnUrls.Count : 0;
      mPeerConnectionId = CreatePeerConnection(urls, length, username, credential);
      RegisterCallbacks();
    }

    public void ClosePeerConnection() {
      ClosePeerConnection(mPeerConnectionId);
      mPeerConnectionId = -1;
    }

    // Return -1 if Peerconnection is not available.
    public int GetUniqueId() {
      return mPeerConnectionId;
    }

    public void AddStream(bool audioOnly) {
      AddStream(mPeerConnectionId, audioOnly);
    }

    public void AddDataChannel() {
      AddDataChannel(mPeerConnectionId);
    }

    public void CreateOffer() {
      CreateOffer(mPeerConnectionId);
    }

    public void CreateAnswer() {
      CreateAnswer(mPeerConnectionId);
    }

    public void SendDataViaDataChannel(string data) {
      SendDataViaDataChannel(mPeerConnectionId, data);
    }

    public void SetAudioControl(bool isMute, bool isRecord) {
      SetAudioControl(mPeerConnectionId, isMute, isRecord);
    }

    public void SetRemoteDescription(string type, string sdp) {
      SetRemoteDescription(mPeerConnectionId, type, sdp);
    }

    public void AddIceCandidate(string candidate, int sdpMlineindex, string sdpMid) {
      AddIceCandidate(mPeerConnectionId, candidate, sdpMlineindex, sdpMid);
    }

    private void RegisterCallbacks() {
      localDataChannelReadyDelegate = new LocalDataChannelReadyInternalDelegate(
          RaiseLocalDataChannelReady);
      RegisterOnLocalDataChannelReady(mPeerConnectionId, localDataChannelReadyDelegate);

      dataFromDataChannelReadyDelegate = new DataFromDataChannelReadyInternalDelegate(
          RaiseDataFromDataChannelReady);
      RegisterOnDataFromDataChannelReady(mPeerConnectionId, dataFromDataChannelReadyDelegate);

      failureMessageDelegate = new FailureMessageInternalDelegate(RaiseFailureMessage);
      RegisterOnFailure(mPeerConnectionId, failureMessageDelegate);

      audioBusReadyDelegate = new AudioBusReadyInternalDelegate(RaiseAudioBusReady);
      RegisterOnAudioBusReady(mPeerConnectionId, audioBusReadyDelegate);

      localI420FrameReadyDelegate = new I420FrameReadyInternalDelegate(
        RaiseLocalVideoFrameReady);
      RegisterOnLocalI420FrameReady(mPeerConnectionId, localI420FrameReadyDelegate);

      remoteI420FrameReadyDelegate = new I420FrameReadyInternalDelegate(
        RaiseRemoteVideoFrameReady);
      RegisterOnRemoteI420FrameReady(mPeerConnectionId, remoteI420FrameReadyDelegate);

      localSdpReadytoSendDelegate = new LocalSdpReadytoSendInternalDelegate(
        RaiseLocalSdpReadytoSend);
      RegisterOnLocalSdpReadytoSend(mPeerConnectionId, localSdpReadytoSendDelegate);

      iceCandiateReadytoSendDelegate =
          new IceCandiateReadytoSendInternalDelegate(RaiseIceCandiateReadytoSend);
      RegisterOnIceCandiateReadytoSend(
          mPeerConnectionId, iceCandiateReadytoSendDelegate);
    }

    private void RaiseLocalDataChannelReady() {
      if (OnLocalDataChannelReady != null)
        OnLocalDataChannelReady(mPeerConnectionId);
    }

    private void RaiseDataFromDataChannelReady(string data) {
      if (OnDataFromDataChannelReady != null)
        OnDataFromDataChannelReady(mPeerConnectionId, data);
    }

    private void RaiseFailureMessage(string msg) {
      if (OnFailureMessage != null)
        OnFailureMessage(mPeerConnectionId, msg);
    }

    private void RaiseAudioBusReady(IntPtr data, int bitsPerSample,
      int sampleRate, int numberOfChannels, int numberOfFrames) {
      if (OnAudioBusReady != null)
        OnAudioBusReady(mPeerConnectionId, data, bitsPerSample, sampleRate,
            numberOfChannels, numberOfFrames);
    }

    private void RaiseLocalVideoFrameReady(
        IntPtr dataY, IntPtr dataU, IntPtr dataV,
        int strideY, int strideU, int strideV,
        uint width, uint height) {
      if (OnLocalVideoFrameReady != null)
        OnLocalVideoFrameReady(mPeerConnectionId, dataY, dataU, dataV, strideY, strideU, strideV,
          width, height);
    }

    private void RaiseRemoteVideoFrameReady(
       IntPtr dataY, IntPtr dataU, IntPtr dataV,
       int strideY, int strideU, int strideV,
       uint width, uint height) {
      if (OnRemoteVideoFrameReady != null)
        OnRemoteVideoFrameReady(mPeerConnectionId, dataY, dataU, dataV, strideY, strideU, strideV,
          width, height);
    }


    private void RaiseLocalSdpReadytoSend(string type, string sdp) {
      if (OnLocalSdpReadytoSend != null)
        OnLocalSdpReadytoSend(mPeerConnectionId, type, sdp);
    }

    private void RaiseIceCandiateReadytoSend(string candidate, int sdpMlineIndex, string sdpMid) {
      if (OnIceCandiateReadytoSend != null)
        OnIceCandiateReadytoSend(mPeerConnectionId, candidate, sdpMlineIndex, sdpMid);
    }

    public void AddQueuedIceCandidate(List<IceCandidate> iceCandidateQueue) {
      if (iceCandidateQueue != null) {
        foreach (IceCandidate ic in iceCandidateQueue) {
          AddIceCandidate(mPeerConnectionId, ic.Candidate, ic.SdpMlineIndex, ic.SdpMid);
        }
      }
    }

    private LocalDataChannelReadyInternalDelegate localDataChannelReadyDelegate = null;
    public event LocalDataChannelReadyDelegate OnLocalDataChannelReady;

    private DataFromDataChannelReadyInternalDelegate dataFromDataChannelReadyDelegate = null;
    public event DataFromDataChannelReadyDelegate OnDataFromDataChannelReady;

    private FailureMessageInternalDelegate failureMessageDelegate = null;
    public event FailureMessageDelegate OnFailureMessage;

    private AudioBusReadyInternalDelegate audioBusReadyDelegate = null;
    public event AudioBusReadyDelegate OnAudioBusReady;

    private I420FrameReadyInternalDelegate localI420FrameReadyDelegate = null;
    public event I420FrameReadyDelegate OnLocalVideoFrameReady;

    private I420FrameReadyInternalDelegate remoteI420FrameReadyDelegate = null;
    public event I420FrameReadyDelegate OnRemoteVideoFrameReady;

    private LocalSdpReadytoSendInternalDelegate localSdpReadytoSendDelegate = null;
    public event LocalSdpReadytoSendDelegate OnLocalSdpReadytoSend;

    private IceCandiateReadytoSendInternalDelegate iceCandiateReadytoSendDelegate = null;
    public event IceCandiateReadytoSendDelegate OnIceCandiateReadytoSend;

    private int mPeerConnectionId = -1;
  }
}
