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 IceCandidateReadytoSendInternalDelegate(
        string candidate, int sdpMlineIndex, string sdpMid);
    public delegate void IceCandidateReadytoSendDelegate(
        int id, string candidate, int sdpMlineIndex, string sdpMid);
    [DllImport(dllPath, CallingConvention = CallingConvention.Cdecl)]
    private static extern bool RegisterOnIceCandidateReadytoSend(
        int peerConnectionId, IceCandidateReadytoSendInternalDelegate 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);

      iceCandidateReadytoSendDelegate =
          new IceCandidateReadytoSendInternalDelegate(RaiseIceCandidateReadytoSend);
      RegisterOnIceCandidateReadytoSend(
          mPeerConnectionId, iceCandidateReadytoSendDelegate);
    }

    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 RaiseIceCandidateReadytoSend(string candidate, int sdpMlineIndex, string sdpMid) {
      if (OnIceCandidateReadytoSend != null)
        OnIceCandidateReadytoSend(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 IceCandidateReadytoSendInternalDelegate iceCandidateReadytoSendDelegate = null;
    public event IceCandidateReadytoSendDelegate OnIceCandidateReadytoSend;

    private int mPeerConnectionId = -1;
  }
}
