Giter Site home page Giter Site logo

cordova-rtc / cordova-plugin-iosrtc Goto Github PK

View Code? Open in Web Editor NEW
687.0 55.0 339.0 312.71 MB

Cordova iOS plugin exposing the WebRTC W3C API

License: MIT License

JavaScript 23.01% Objective-C 47.31% Swift 27.91% C 0.53% Makefile 0.02% Python 1.22%
cordova ios cordova-ios webrtc cordova-plugin-iosrtc webrtc-api libwebrtc webrtc-w3c

cordova-plugin-iosrtc's Introduction

cordova-rtc-logo

cordova-plugin-iosrtc

npm version Build Status

NPM

Cordova iOS plugin exposing the ̶f̶u̶l̶l̶ WebRTC W3C JavaScript APIs.

  • Community Forum for questions and discussions about cordova-plugin-iosrtc.
  • Bug Tracker for reporting issues and requesting new features (please don't use the bug tracker for questions or problems, use the mailing list instead).
  • NPM package.

Yet another WebRTC SDK for iOS?

Absolutely not. This plugin exposes the WebRTC W3C API for Cordova iOS apps (you know there is no WebRTC in iOS, right?), which means no need to learn "yet another WebRTC API" and no need to use a specific service/product/provider.

Who?

This plugin was initially developed at eFace2Face, and later maintained by the community, specially by Saúl Ibarra Corretgé (The OpenSource Warrior Who Does Not Burn).

Requirements

In order to make this Cordova plugin run into a iOS application some requirements must be satisfied in both development computer and target devices:

  • Xcode >= 13.2.1 (13C100)
  • iOS >= 14.3 (run on lower versions at your own risk, don't report issues)
  • swift-version => 4.2
  • cordova >= 11.0.0
  • cordova-ios >= 6.2.0

Third-Party Supported Library

  • WebRTC W3C v1.0.0
  • WebRTC.framework => M87
  • Janus => 0.7.4
  • JSSip => 3.1.2
  • Sip.js => 0.15.6
  • OpenEasyrtc => 2.0.3
  • openvidu => 2.11.0
  • Ionic => v8
  • Jitsi ~ 3229
  • Apizee => 2.6.11
  • Twillio => 2.4.0

Installation

Within your Cordova project:

$ cordova plugin add cordova-plugin-iosrtc

(or add it into a <plugin> entry in the config.xml of your app).

Building

  • Last Tested WebRTC.framework version: M87 on cordova-plugin-iosrtc version 8.0.0+
  • Building: Guidelines for building a Cordova iOS application including the cordova-plugin-iosrtc plugin.
  • Building libwebrtc: Guidelines for building Google's libwebrtc with modifications needed by the cordova-plugin-iosrtc plugin (just in case you want to use a different version of libwebrtc or apply your own changes to it).

Sample Application

The cordova-plugin-iosrtc-sample include mutiple example for using cordova-plugin-iosrtc with JsSip, Janus, EasyRTC, and basic WebSocket Signaling. It's is used to test cordova-plugin-iosrtc new release and reproduce reported issues.

Usage

The plugin exposes the cordova.plugins.iosrtc JavaScript namespace which contains all the WebRTC classes and functions.

/* global RTCPeerConnection */


//
// Container for this sample
//

var appContainer = document.body;
appContainer.innerHTML = "";

//
// Sample getUserMedia
//

//
var localStream, localVideoEl;
function TestGetUserMedia() {
  localVideoEl = document.createElement('video');
  localVideoEl.style.height = "50vh";
  localVideoEl.setAttribute('autoplay', 'autoplay');
  localVideoEl.setAttribute('playsinline', 'playsinline');
  appContainer.appendChild(localVideoEl);

  return navigator.mediaDevices.getUserMedia({
    video: true,
    audio: true
    // Note: Use navigator.mediaDevices.enumerateDevices() Promise to get deviceIds
    /*
    video: {
      // Test Back Camera
      //deviceId: 'com.apple.avfoundation.avcapturedevice.built-in_video:0'
      //sourceId: 'com.apple.avfoundation.avcapturedevice.built-in_video:0'
      deviceId: {
        exact: 'com.apple.avfoundation.avcapturedevice.built-in_video:0'
      }
      // Test FrameRate
      frameRate:{ min: 15.0, max: 30.0 } // Note: Back camera may only support max 30 fps
    },
    audio: {
      deviceId: {
        exact: 'Built-In Microphone'
      }
    }*/
  }).then(function (stream) {

    console.log('getUserMedia.stream', stream);
    console.log('getUserMedia.stream.getTracks', stream.getTracks());

    // Note: Expose for debug
    localStream = stream;

    // Attach local stream to video element
    localVideoEl.srcObject = localStream;

    return localStream;

  }).catch(function (err) {
    console.log('getUserMedia.error', err, err.stack);
  });
}

//
// Sample RTCPeerConnection
//

var pc1, pc2;

var peerConnectionConfig = {
    offerToReceiveVideo: true,
    offerToReceiveAudio: true,
    //iceTransportPolicy: 'relay',
    sdpSemantics: 'unified-plan',
    //sdpSemantics: 'plan-b',
    bundlePolicy: 'max-compat',
    rtcpMuxPolicy: 'negotiate',
    iceServers: [
      {
         urls: ["stun:stun.stunprotocol.org"]
      }
    ]
};

// This plugin handle 'addstream' and 'track' event for MediaStream creation.
var useTrackEvent = Object.getOwnPropertyDescriptors(RTCPeerConnection.prototype).ontrack;

var peerVideoEl, peerStream;
function TestRTCPeerConnection(localStream) {

  pc1 = new RTCPeerConnection(peerConnectionConfig);
  pc2 = new RTCPeerConnection(peerConnectionConfig);

  if (useTrackEvent) {

    // Add local stream tracks to RTCPeerConnection
    var localPeerStream = new MediaStream();
    localStream.getTracks().forEach(function (track) {
      console.log('pc1.addTrack', track, localPeerStream);
      pc1.addTrack(track, localPeerStream);
    });

  // Note: Deprecated but supported
  } else {
     pc1.addStream(localStream);

     // Note: Deprecated Test removeStream
     // pc1.removeStream(pc1.getLocalStreams()[0]);<
  }

  // Basic RTCPeerConnection Local WebRTC Signaling follow.
  function onAddIceCandidate(pc, can) {
    console.log('addIceCandidate', pc, can);
    return can && pc.addIceCandidate(can).catch(function (err) {
      console.log('addIceCandidateError', err);
    });
  }

  pc1.addEventListener('icecandidate', function (e) {
    onAddIceCandidate(pc2, e.candidate);
  });

  pc2.addEventListener('icecandidate', function (e) {
    onAddIceCandidate(pc1, e.candidate);
  });

  function setPeerVideoStream(stream) {

    // Create peer video element
    peerVideoEl = document.createElement('video');
    peerVideoEl.style.height = "50vh";
    peerVideoEl.setAttribute('autoplay', 'autoplay');
    peerVideoEl.setAttribute('playsinline', 'playsinline');
    appContainer.appendChild(peerVideoEl);

    // Note: Expose for debug
    peerStream = stream;

    // Attach peer stream to video element
    peerVideoEl.srcObject = peerStream;
  }

  if (useTrackEvent) {
    var newPeerStream;
    pc2.addEventListener('track', function(e) {
      console.log('pc2.track', e);
      newPeerStream = e.streams[0] || newPeerStream || new MediaStream();
      setPeerVideoStream(newPeerStream);
      newPeerStream.addTrack(e.track);
    });

  // Note: Deprecated but supported
  } else {
    pc2.addEventListener('addstream', function(e) {
      console.log('pc2.addStream', e);
      setPeerVideoStream(e.stream);
    });
  }

  pc1.addEventListener('iceconnectionstatechange', function (e) {
    console.log('pc1.iceConnectionState', e, pc1.iceConnectionState);

    if (pc1.iceConnectionState === 'completed') {
      console.log('pc1.getSenders', pc1.getSenders());
      console.log('pc2.getReceivers', pc2.getReceivers());
    }
  });

  pc1.addEventListener('icegatheringstatechange', function (e) {
    console.log('pc1.iceGatheringStateChange', e);
  });

  pc1.addEventListener('negotiationneeded', function (e) {
    console.log('pc1.negotiatioNeeded', e);

    return pc1.createOffer().then(function (d) {
      var desc = {
        type: d.type,
        sdp: d.sdp
      };
      console.log('pc1.setLocalDescription', desc);
      return pc1.setLocalDescription(desc);
    }).then(function () {
      var desc = {
        type: pc1.localDescription.type,
        sdp: pc1.localDescription.sdp
      };
      console.log('pc2.setLocalDescription', desc);
      return pc2.setRemoteDescription(desc);
    }).then(function () {
      console.log('pc2.createAnswer');
      return pc2.createAnswer();
    }).then(function (d) {
      var desc = {
        type: d.type,
        sdp: d.sdp
      };
      console.log('pc2.setLocalDescription', desc);
      return pc2.setLocalDescription(d);
    }).then(function () {
      var desc = {
        type: pc2.localDescription.type,
        sdp: pc2.localDescription.sdp
      };
      console.log('pc1.setRemoteDescription', desc);
      return pc1.setRemoteDescription(desc);
    }).catch(function (err) {
      console.log('pc1.createOffer.error', err);
    });
  });
}

function TestRTCPeerConnectionLocal() {

  // Note: This allow this sample to run on any Browser
  var cordova = window.cordova;
  if (cordova && cordova.plugins && cordova.plugins.iosrtc) {

    // Expose WebRTC and GetUserMedia SHIM as Globals (Optional)
    // Alternatively WebRTC API will be inside cordova.plugins.iosrtc namespace
    cordova.plugins.iosrtc.registerGlobals();

    // Enable iosrtc debug (Optional)
    cordova.plugins.iosrtc.debug.enable('*', true);
  }

  // Run sample
  TestGetUserMedia().then(function (localStream) {
    TestRTCPeerConnection(localStream);
  });
}

if (document.readyState === "complete" || document.readyState === "loaded") {
  TestRTCPeerConnectionLocal();
} else {
  window.addEventListener("DOMContentLoaded", TestRTCPeerConnectionLocal);
}

// See ./extra/renderer-and-libwebrtc-tests.js for more samples usage.

In case you'd like to expose the API in the global namespace like regular browsers you can do the following:

// Just for Cordova apps.
document.addEventListener('deviceready', function () {
  // Just for iOS devices.
  if (window.device.platform === 'iOS') {
    cordova.plugins.iosrtc.registerGlobals();

    // load adapter.js
    var adapterVersion = 'latest';
    var script = document.createElement("script");
    script.type = "text/javascript";
    script.src = "https://webrtc.github.io/adapter/adapter-" + adapterVersion + ".js";
    script.async = false;
    document.getElementsByTagName("head")[0].appendChild(script);
  }
});

And that's all. Now you have window.RTCPeerConnection, navigator.getUserMedia, etc.

FAQ

See the FAQ.

Documentation

Read the full documentation in the docs folder.

Who Uses It

People and companies using cordova-plugin-iosrtc.

If you are using the plugin we would love to hear back from you!

Known Issues

iOS Safari and crash on WebSocket events

Don't call plugin methods within WebSocket events (onopen, onmessage, etc). There is an issue in iOS Safari (see issue #12). Instead run a setTimeout() within the WebSocket event if you need to call plugin methods on it.

Or better yet, include the provided ios-websocket-hack.js in your app and load into your index.html as follows:

<script src="cordova.js"></script>
<script src="ios-websocket-hack.min.js"></script>

HTML5 video API

There is no real media source attached to the <video> element so some HTML5 video events and properties are artificially emitted/set by the plugin on behalf of the video element.

Methods such as play(), pause() are not implemented. In order to pause a video just set enabled = false on the associated MediaStreamTrack.

iOS >= 13.3.1 Device support

To run on Devices with iOS >= 13.3.1, you need a valid Apple Developer account to sign the WebRTC dynamic frameworks for more info see https://stackoverflow.com/a/60090629/8691951

Changelog

See CHANGELOG.md.

Authors

Maintainer

If you like this project you can support me.

Buy Me A Coffee

License

MIT :)

cordova-plugin-iosrtc's People

Contributors

akilude avatar albanonm avatar andrewvmail avatar axel-calmid avatar cah-kyle-dunn avatar calebboyd avatar csantosm avatar dependabot[bot] avatar derwaldgeist avatar dgreif avatar dunnky avatar gprost avatar hthetiot avatar ibc avatar jerry2013 avatar jesusprubio avatar jitinl avatar mark-veenstra avatar mccob avatar menelike avatar mosatch avatar murillo128 avatar onaips avatar onerinas avatar rsatom avatar saghul avatar samgabriel avatar sejh avatar slavchev avatar yangjingyu avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

cordova-plugin-iosrtc's Issues

AppGyver integration

Hi all!

I'm trying to use this plugin in a AppGyver build, but it failed because the required cordova version, they use 3.5.0 version:

Adding plugin from: https://github.com/eface2face/cordova-plugin-iosrtc
Plugin doesn't support this project's cordova-ios version. cordova-ios: 3.5.0, failed version requirement: >=3.8.0

This plugin really need this requirement?

Thanks!

Blank video from second call onwards.

When trying to make a call from iPhone to Web . First call works perfectly.
From second call onwards , it shows a blank video on the iPhone but the audio works and Video on Web works too.
We are using "onaddstream" function of "window.RTCPeerConnection" to display the video in

Can it be problem of "onaddstream" , as it is not implemented in this plugin?

Adding events for videoView

I'm trying to implement a click even on the videoView to get additional functionality in my Cordova plugin. I tried a couple of things to register the setOnTouchListener to the view, but nothing worked so far. How do I include the view in my plugin and register the listener?

Thanks!

Build error on Xcode (swift)

Hi,
I tried to install the plugin but I have a lot of error (160 exactly) when I build with Xcode (6.3) but it works with 'cordova build'. Apparently, it is because of swift which don't find identifiers.
Error example :
In PluginMediaStream.swift:5:22: Use of undeclared type 'RTCMediaStream'

Swift file wouldn't find associate header ?

expose MediaStream (and webkitMediaStream) in registerGlobals

It would be handy to have these methods exposed for feature detection. Specifically some libraries polyfill these with an implementation of getVideoTracks() and getAudioTracks() for backwards compatibility. Having them exposed is important so that the feature detection properly doesn't attempt to polyfill.

Implement based on(add|remove)track via NotifierObserver

The c++ code provies a NotifierOberserver::onChanged even whenever there is a change on the stream. This code seems to be triggered from both local/remote AddTrack and RemoveTrack methods.

So it should be possible to listen to that event in swift/js and retrieve the current state+tracks of the stream and compare to previous stored ones.

If the NotifierObserver is not exposed on the ObjectiveC code, we should propose a patch to the libwertc lib to include it.

Video freezes on pause

If the home button is pressed, the local video stream will freeze. Remote (incoming) video still shows and audio appears to continue working.

Is the plugin for Android ready?

I have googling for plugin of webrtc.
And I found this plugin, and I'm really glad to see this, and thanks for developer of this.
I have the plugin for Android, but I have not found it.
So where I can see it?

Build Error

Hi,

I came with the lots of following error after following your guides in the building section.

'RTCSignalingState' does not have a member named 'value',

Am I facing some strange situations? Thank in advance.

FYI, I am using EL Capitan 2 and Xcode 7 Beta but installing on a iOS 8.3 machine.

Crash due to garbage collector

Sometimes when the app is loaded and an JavaScript RTCPeerConnection is created the app crashes (note that the NSLog of the PluginRTCPeerConnection constructor is not shown, maybe because it never reaches it...):

2015-06-01 15:29:17.810 cordovaIosrtcDemo[2298:602476] DiskCookieStorage changing policy from 2 to 0, cookie file: file:///private/var/mobile/Containers/Data/Application/3588C109-5F97-4E5F-83EA-36165871ACC3/Library/Cookies/Cookies.binarycookies
2015-06-01 15:29:18.083 cordovaIosrtcDemo[2298:602476] Apache Cordova native platform version 3.8.0 is starting.
2015-06-01 15:29:18.083 cordovaIosrtcDemo[2298:602476] Multi-tasking -> Device: YES, App: YES
2015-06-01 15:29:18.088 cordovaIosrtcDemo[2298:602476] Unlimited access to network resources
2015-06-01 15:29:18.277 cordovaIosrtcDemo[2298:602476] iosrtcPlugin#init()
2015-06-01 15:29:18.325 cordovaIosrtcDemo[2298:602476] PluginGetUserMedia#init()
2015-06-01 15:29:18.326 cordovaIosrtcDemo[2298:602476] [CDVTimer][iosrtcplugin] 55.085003ms
2015-06-01 15:29:18.326 cordovaIosrtcDemo[2298:602476] [CDVTimer][TotalPluginStartup] 55.342019ms
2015-06-01 15:29:18.967 cordovaIosrtcDemo[2298:602476] Resetting plugins due to page load.
2015-06-01 15:29:19.432 cordovaIosrtcDemo[2298:602476] Finished load of: file:///private/var/mobile/Containers/Bundle/Application/90A5F156-4893-490C-B608-A7D3715F379D/cordovaIosrtcDemo.app/www/index.html
Process 2298 stopped
* thread #8: tid = 0x931b5, 0x21e410e8 CoreFoundation`CFRelease + 1268, name = 'WebThread', stop reason = EXC_BREAKPOINT (code=EXC_ARM_BREAKPOINT, subcode=0xdefe)
    frame #0: 0x21e410e8 CoreFoundation`CFRelease + 1268
CoreFoundation`CFRelease:
->  0x21e410e8 <+1268>: trap
    0x21e410ea <+1270>: trap

CoreFoundation`_CFAllocatorDeallocateGC:
    0x21e410ec <+0>:    push   {r4, r7, lr}
    0x21e410ee <+2>:    mov    r4, r1

Video lag

I am running video between iOS and browser and I am experiencing a significant lag in the video. I am running the project locally so it should be really quick. My suspicion is that the video streaming from iOS to the browser is high resolution with extremely high frame rate. My video window is about 200x200px so I don't need a very high resolution. Is it possible that the video lag is caused by the video resolution/frame rate? How can I change the resolution of the video coming from iOS?

Make private properties more private

I ran into this issue when trying to load Twilio on the iPad.

Referring to these properties specifically:
https://github.com/eface2face/cordova-plugin-iosrtc/blob/master/js/MediaStream.js#L66-L70

Twilio has a method that looks like this:

PeerConnection.prototype.attachAudio = function(callback) {
        if (this.stream) {
            var audioTracks = this.stream.audioTracks || this.stream.getAudioTracks();
            audioTracks[0].enabled = true;
        }
        if (callback && typeof callback == "function") {
            callback();
        }
}

As you can see it errors when accessing the [0].enabled property of this.stream.audioTracks

I've filed an issue in Twilio to prefer spec.. But it would probably be good for the module hide its private state better anyway.

Also.. Thank you for a great plugin!

Video Not Showing

So everything compiles on my cordova app great, no errors nothing. When I run in debug mode in XCode, I can see everything running. However my video does not show up.

      var pc = new cordova.plugins.iosrtc.RTCPeerConnection({
        iceServers: [
          {
            url: '',
            username: '',
            credential: ''
          }
        ]
      });

      navigator.getUserMedia(
        {
          video: true,
          audio: true
        },
        function(stream) {
          pc.addStream(stream);
          video.src = vendorURL.createObjectURL(stream);
          video.play();
        },
        function(err) {
          console.log("An error occured! " + err);
        }
      )

Am I missing something? I have a

Move app hook into plugin hook

About the hook that adds the header file to xcode project.
Is there anything that prevents you to make it a plugin hook instead? This way we would not have to put it into the config.xml of parent project.

No 'replay' candidates are being generated. Is TURN supported?

I'm having routing issues across different internet connections. Using TURN seems like a possible solution but no 'replay' candidates appear to be generated on the iOS side.

candidate: "candidate:2848196663 1 udp 1685987071 82.132.230.244 30200 typ srflx raddr 10.144.44.44 rport 62017 generation 0"
sdpMLineIndex: 0
sdpMid: "audio"
candidate: "candidate:2848196663 1 udp 1685987071 82.132.230.244 30200 typ srflx raddr 10.144.44.44 rport 62017 generation 0"
sdpMLineIndex: 1
sdpMid: "video"
candidate: "candidate:3298782126 1 udp 1686052607 82.34.23.22 57259 typ srflx raddr 192.168.0.7 rport 57259 generation 0"
sdpMLineIndex: 1
sdpMid: "video"
candidate: "candidate:3298782126 1 udp 1686052607 82.34.23.22 62749 typ srflx raddr 192.168.0.7 rport 62749 generation 0"
sdpMLineIndex: 0
sdpMid: "audio"
candidate: "candidate:3298782126 2 udp 1686052606 82.34.23.22 53172 typ srflx raddr 192.168.0.7 rport 53172 generation 0"
sdpMLineIndex: 0
sdpMid: "audio"
candidate: "candidate:3298782126 2 udp 1686052606 82.34.23.22 50628 typ srflx raddr 192.168.0.7 rport 50628 generation 0"
sdpMLineIndex: 1
sdpMid: "video"
sdpMid: "video", 
sdpMLineIndex: 1, 
candidate: "candidate:290950419 2 tcp 1518214910 10.144.44.44 49853 typ host tcptype passive generation 0"
sdpMid: "video", 
sdpMLineIndex: 1, 
candidate: "candidate:591599755 2 tcp 1518280446 192.168.0.7 49852 typ host tcptype passive generation 0"
sdpMid: "video", 
sdpMLineIndex: 1, 
candidate: "candidate:290950419 1 tcp 1518214911 10.144.44.44 49851 typ host tcptype passive generation 0"

I have my IceServers configured a so:

new RTCPeerConnection({ 
    iceServers: [ 
        { 
          url: "stun:global.stun.twilio.com:3478?transport=udp" 
        },
        { 
          credential: "pQ7MSm98aoZvsHca+hE9IMUUTF8zGDFdHxaLUoHQAv8=",
          url: "turn:global.turn.twilio.com:3478?transport=udp",
          username: "340bd1298bd2a7f1cd5d2f3e1e3b8f405c4297fcb7ad7a810bed416f90017fb3"
        }
    ]
});

Android with the exact same credentials is successful.

(ps. Do you have an IRC channel setup?)

z-index of video

any idea when will be available to control the z-index of the video ? to add overlayers, controls, etc...

data channel close logs an error

When killing a PC that has a data channel:

2015-08-24 15:54:49.956 charmed[713:227024] iosrtc:RTCPeerConnection close() +10s
nnection_close()
2015-08-24 15:54:49.956 charmed[713:227024] iosrtc:RTCDataChannel close() +0ms
2015-08-24 15:54:49.956 charmed[713:227024] iosrtcPlugin#RTCPeerConnection_RTCDataChannel_close()
CPeerConnection_RTCDataChannel_close() | ERROR: pluginRTCPeerConnection with pcId=21737 does not exist
2015-08-24 15:54:49.972 charmed[713:227141] PluginRTCPeerConnection | oniceconnectionstatechange [iceConnectionState:closed]
2015-08-24 15:54:49.972 charmed[713:227141] PluginRTCPeerConnection | onsignalingstatechange [signalingState:closed]

Implement video.src media stream attachment via MutationObserver

<html>
    <head>
        <style>
            #v {
                width: 100px;
                height: 50px;
                background-color: green;
                z-index: 6;
            }
        </style>
<script>
//Observe of changes of the video element
var videoObserver = new MutationObserver(function(mutations) {
    //For each mutation
    mutations.forEach(function(mutation) {
        //Get video element
        var video = mutation.target;
        //Get BLOB from src
        var xhr = new XMLHttpRequest();
        xhr.open('GET', video.src, true);
        xhr.responseType = 'blob';
        xhr.onload = function () {
            var reader = new FileReader();
            reader.addEventListener("loadend", function() {
                console.log("MediaStream id: " + reader.result);
            });
            reader.readAsText(this.response);
        };
        xhr.send();
    });  
 });

//Observes dom additions/deletion in document node and childrens
var observer = new MutationObserver(function(mutations) {
    //For each mutation
    mutations.forEach(function(mutation) {
        //Check if there has been addition or deletions of nodes
        if (mutation.type==='childList') {
            //Check added nodes
            for (var i=0; i<mutation.addedNodes.length; i++) {
                if (mutation.addedNodes[i].nodeName==='VIDEO') {
                    console.log('added video element');
                    //Add src observer 
                    videoObserver.observe(mutation.addedNodes[i],{
                        childList: false,       // Set to true if additions and removals of the target node's child elements (including text nodes) are to be observed.
                        attributes: true,       // Set to true if mutations to target's attributes are to be observed.
                        characterData: false,       // Set to true if mutations to target's data are to be observed.
                        subtree: false,         // Set to true if mutations to not just target, but also target's descendants are to be observed.
                        attributeOldValue:false,    // Set to true if attributes is set to true and target's attribute value before the mutation needs to be recorded.
                        characterDataOldValue:false,    // Set to true if characterData is set to true and target's data before the mutation needs to be recorded.
                        attributeFilter: ['src']    //Set to an array of attribute local names (without namespace) if not all attribute mutations need to be observed.  
                    });
                }
            }
            //Check removed nodes
            for (var i=0; i<mutation.removedNodes.length; i++) {
                if (mutation.removedNodes[i].nodeName==='video') {
                    console.log('removed video element');
                }
            }
        }
    });
});

observer.observe(document,{
    childList: true,        // Set to true if additions and removals of the target node's child elements (including text nodes) are to be observed.
    attributes: false,      // Set to true if mutations to target's attributes are to be observed.
    characterData: false,       // Set to true if mutations to target's data are to be observed.
    subtree: true,          // Set to true if mutations to not just target, but also target's descendants are to be observed.
    attributeOldValue:false,    // Set to true if attributes is set to true and target's attribute value before the mutation needs to be recorded.
    characterDataOldValue:false,    // Set to true if characterData is set to true and target's data before the mutation needs to be recorded.
    //attributeFilter       // Set to an array of attribute local names (without namespace) if not all attribute mutations need to be observed. 
});

        </script>
    </head>
    <body>
        <video id="v" style="z-index:1;"></video>
    </body>
</html>

<script>
    var id = '123456';
    //Create Blob with id as data
    var stream = new Blob([id], {type : 'application/octet-stream'});

    //Get url from blob
    v.src = URL.createObjectURL(stream);
</script>   

Dark video moving device from face up to vertical position

Usign iosRTC on iPad mini 2 (iOS 8.4) I can make call with windows native peer.
But I have a problem during a video call. Every time i move the device from face up portrait to portrait but in vertical position (no rotation portrait/landscape) the local video fadeout and It is like the streaming restart because on remote peer I see black video for about 1 second. Sometime when the video appear newly It remains dark.

Relay candidate

Hi,

I just get the host candidate in SDP from iOSRTC but not relay candidate.
We must require relay candidate for our application. What could be the cause of this and how to get relay candidate?

Issue generating the answer on the browser

Hi, I currently have everything setup and working between browsers. I'm not using video nor audio, just DataChannel. When trying to connect with an ios cordova app using the plugin (which is awesome by the way!) I can't get setRemoteDescription to work. This is the error I get:

Failed to set remote offer sdp: Session error code: ERROR_CONTENT. Session error description: Failed to set data send codecs..

Am I only the only one this is issue?
Thank you for the time,
Gabriel

Update video properties when the MediaStream is closed

Currently the properties of the video (videoWidth, readyState...) are not reverted to the native values until the .src attribute of the video is changed (which may never happen). Same for its MediaStreamRenderer which is not closed until that moment.

Improve that.

Feature of this plugin

Hello,

We plan to create a new application on iOS (iPhone and iPad) and we want to know if we can use this plugin to make calls through our phone system (asterisk & WebRTC). Is there a function that accept sip credentials?

Thanks.

video elements fire 'error' event even when successfully assigning to video.src

Can we find a way to intercept and swallow the 'error' event that the

repro:

videoElement.addEventListener('error', function(event) {
  if (event.target.error.code === window.MediaError.MEDIA_ERR_SRC_NOT_SUPPORTED) {
    console.error(':(');
  }
});
videoElement.addEventListneer('loadedmetadata' function() {
  console.log('success!');
});
videoElement.src = URL.createObjectURL(stream);

The output will be:

:(
success!

I only expect:

success!

Make the libWebRTC.a thinner

The current libWebRTC static library is compiled for all the architectured (included the i386 of the OSX iPhone simulator). We should provide a smaller one in the plugin just for real iOS devices.

iOS video dimensions and positions incorrect

iOS is not displaying the video output well, or at least according to my css markup, even after running cordova.plugins.iosrtc.refreshVideos();. Android previews as expected.

HTML:

 <video class="remote" id="remote" autoplay></video>
 <video class="preview" id="video" autoplay></video>

CSS:

video.preview{
    position:absolute;
    bottom:16px;
    right:16px;
    height:100px;
}
video.remote{
    position:absolute;
    height:100%;
    border-radius:3px;
    box-shadow:0 0 3px #888;
}

What I see on iPhone 5 is a small video object towards the bottom of the screen.

telling when a stream is loaded

with the browser, we render the stream to a video element (just a document.createElement('video') in memory) and wait for it to start playing.

with iosrtc, the video never starts playing since it isn't in the DOM.

what's the best way to determine when a video stream from iosrtc is ready to show?

Issues with `plugman publish`

I cannot make plugman publish work again... It seems that the Cordova registry is currently a mess due to the migration to NPM registry, not sure which version of the plugman package to install, etc etc. I get "auth" errors. Tried everything.

So, version 1.2.9 is not yet in the Cordova registry.

Failed to bind EAGLDrawable: <CAEAGLLayer: 0x127bdf030> to GL_RENDERBUFFER 1

Should I be worried about this issue?

Here is some more log context...

2015-08-13 14:01:37.059 MyApp[3755:1802834] iosrtc:videoElementsHandler new video element added +3ms
2015-08-13 14:01:37.059 MyApp[3755:1802834] iosrtc:videoElementsHandler observeVideo() | [class:"", src:blob:file:///9a0110fb-f23d-4540-8c2f-f42bd990550e] +0ms
2015-08-13 14:01:37.059 MyApp[3755:1802834] iosrtc:videoElementsHandler new video element added +7ms
2015-08-13 14:01:37.061 MyApp[3755:1802834] iosrtc:MediaStreamTrack onEvent() | [type:statechange, data:{"type":"statechange","readyState":"initializing","enabled":false}] +13ms
2015-08-13 14:01:37.062 MyApp[3755:1802921] PluginMediaStreamTrack#setEnabled() [value:false]
2015-08-13 14:01:37.063 MyApp[3755:1802960] PluginMediaStreamTrack | state changed [state:initializing, enabled:false]
2015-08-13 14:01:37.064 MyApp[3755:1802834] iosrtc:MediaStreamTrack onEvent() | [type:statechange, data:{"type":"statechange","readyState":"initializing","enabled":false}] +3ms
2015-08-13 14:01:37.155 MyApp[3755:1802834] iosrtc:MediaStreamRenderer new() | [element:"[object HTMLVideoElement]"] +70ms
2015-08-13 14:01:37.155 MyApp[3755:1802834] iosrtcPlugin#new_MediaStreamRenderer()
2015-08-13 14:01:37.155 MyApp[3755:1802834] PluginMediaStreamRenderer#init()
2015-08-13 14:01:37.310 MyApp[3755:1802834] PluginMediaStreamRenderer#run()
2015-08-13 14:01:37.311 MyApp[3755:1802834] THREAD WARNING: ['iosrtcPlugin'] took '155.472900' ms. Plugin should use a background thread.
2015-08-13 14:01:37.312 MyApp[3755:1802834] Failed to bind EAGLDrawable: <CAEAGLLayer: 0x127bdf030> to GL_RENDERBUFFER 1
2015-08-13 14:01:37.312 MyApp[3755:1802834] Failed to make complete framebuffer object 8cd6
2015-08-13 14:01:37.314 MyApp[3755:1802834] iosrtc:MediaStreamRenderer refresh() +4ms
2015-08-13 14:01:37.314 MyApp[3755:1802834] iosrtc:MediaStreamRenderer refresh() | no video track yet +3ms
2015-08-13 14:01:37.314 MyApp[3755:1802834] iosrtc:MediaStreamRenderer refresh() | [data:{"elementLeft":-42.65625,"elementTop":307,"elementWidth":165,"elementHeight":124,"videoViewWidth":165,"videoViewHeight":124,"visible":true,"opacity":1,"zIndex":0,"mirrored":false,"objectFit":"cover","clip":true,"borderRadius":0}] +1ms

<video> element sizing behavior: support for 'object-fit' and 'overflow' styles

Right now the MediaStreamRenderer will always render video by scaling it down so that the entire frame fits within the <video> element (preserving aspect ratio and centering) and fills the rest of the area with black pixels. This is equivalent to the standards when the <video> has the default styles applied (specifically object-fit: contain).

I'm interested in support for the object-fit: cover style. This behavior is different in that the video frame is scaled up to as large as it needs to grow in order to draw in all the pixels inside the video element (preserving aspect ratio and centering). There are no black pixels.

With that style alone, it actually draws video outside of the bounds of the video element. I believe a common use case is to pair this with overflow: hidden on some parent in the DOM tree so that the video frame is "cropped" to the bounds of a certain size. I understand that implementing this in the MediaStreamRenderer would mean you would have to observe every parent of the video element up the DOM tree and that would probably be too slow. I want to suggest that we only aim to implement the correct overflow: hidden behavior for its direct parent.

Implement videoWidth & videoHeight <video> properties

This hack may work:

  • When the video src is a MediaStream:
Object.defineProperty(video, 'videoWidth', {
  configurable:true,  // Needed for later removal.
  get: function () { return XXXX; }
});
  • When the video src is not a MediaStream:
delete video.videoWidth

Build error

Hi,

I have an error when i build my cordova project with this plugin (without the plugin, no problem) :

Ld build/emulator/Assistance.app/Assistance normal i386
    cd /Users/cwi/Desktop/app-assistance-git/***/platforms/ios
    export IPHONEOS_DEPLOYMENT_TARGET=8.3
    export PATH="/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/usr/bin:/Applications/Xcode.app/Contents/Developer/usr/bin:/Users/cwi/webrtcios/depot_tools:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/Users/cwi/adt-bundle/sdk/platform-tools:/Users/cwi/adt-bundle/sdk/tools"
    /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang -arch i386 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator8.3.sdk -L/Users/cwi/Desktop/app-assistance-git/***/platforms/ios/build/emulator -L/Users/cwi/Desktop/app-assistance-git/***/platforms/ios/Assistance/Plugins/com.eface2face.iosrtc -F/Users/cwi/Desktop/app-assistance-git/***/platforms/ios/build/emulator -filelist /Users/cwi/Desktop/app-assistance-git/***/platforms/ios/build/Assistance.build/Debug-iphonesimulator/Assistance.build/Objects-normal/i386/Assistance.LinkFileList -Xlinker -objc_abi_version -Xlinker 2 -weak_framework CoreFoundation -weak_framework UIKit -weak_framework AVFoundation -weak_framework CoreMedia -weak-lSystem -ObjC -fobjc-arc -fobjc-link-runtime -Xlinker -no_implicit_dylibs -mios-simulator-version-min=8.3 -framework VideoToolbox -framework AudioToolbox -licucore -lz -framework AssetsLibrary /Users/cwi/Desktop/app-assistance-git/***/platforms/ios/build/emulator/libCordova.a -framework CoreGraphics -framework MobileCoreServices -weak_framework ImageIO -framework CoreLocation -weak_framework SystemConfiguration -framework CoreTelephony -lWebRTC-LATEST-Universal-Release -lc++ -lstdc++ -Xlinker -dependency_info -Xlinker /Users/cwi/Desktop/app-assistance-git/***/platforms/ios/build/Assistance.build/Debug-iphonesimulator/Assistance.build/Objects-normal/i386/Assistance_dependency_info.dat -o /Users/cwi/Desktop/app-assistance-git/***/platforms/ios/build/emulator/Assistance.app/Assistance
Undefined symbols for architecture i386:
  "_CVPixelBufferGetBaseAddressOfPlane", referenced from:
      webrtc::AVFoundationVideoCapturer::CaptureSampleBuffer(opaqueCMSampleBuffer*) in libWebRTC-LATEST-Universal-Release.a(libjingle_peerconnection_objc.avfoundationvideocapturer.o)
      -[RTCVideoCaptureIosObjC captureOutput:didOutputSampleBuffer:fromConnection:] in libWebRTC-LATEST-Universal-Release.a(video_capture_module_internal_impl.rtc_video_capture_ios_objc.o)
  "_CVPixelBufferGetBytesPerRowOfPlane", referenced from:
      webrtc::AVFoundationVideoCapturer::CaptureSampleBuffer(opaqueCMSampleBuffer*) in libWebRTC-LATEST-Universal-Release.a(libjingle_peerconnection_objc.avfoundationvideocapturer.o)
      -[RTCVideoCaptureIosObjC captureOutput:didOutputSampleBuffer:fromConnection:] in libWebRTC-LATEST-Universal-Release.a(video_capture_module_internal_impl.rtc_video_capture_ios_objc.o)
  "_CVPixelBufferGetHeight", referenced from:
      -[RTCVideoCaptureIosObjC captureOutput:didOutputSampleBuffer:fromConnection:] in libWebRTC-LATEST-Universal-Release.a(video_capture_module_internal_impl.rtc_video_capture_ios_objc.o)
  "_CVPixelBufferGetHeightOfPlane", referenced from:
      webrtc::AVFoundationVideoCapturer::CaptureSampleBuffer(opaqueCMSampleBuffer*) in libWebRTC-LATEST-Universal-Release.a(libjingle_peerconnection_objc.avfoundationvideocapturer.o)
      -[RTCVideoCaptureIosObjC captureOutput:didOutputSampleBuffer:fromConnection:] in libWebRTC-LATEST-Universal-Release.a(video_capture_module_internal_impl.rtc_video_capture_ios_objc.o)
  "_CVPixelBufferGetWidth", referenced from:
      -[RTCVideoCaptureIosObjC captureOutput:didOutputSampleBuffer:fromConnection:] in libWebRTC-LATEST-Universal-Release.a(video_capture_module_internal_impl.rtc_video_capture_ios_objc.o)
  "_CVPixelBufferGetWidthOfPlane", referenced from:
      webrtc::AVFoundationVideoCapturer::CaptureSampleBuffer(opaqueCMSampleBuffer*) in libWebRTC-LATEST-Universal-Release.a(libjingle_peerconnection_objc.avfoundationvideocapturer.o)
  "_CVPixelBufferLockBaseAddress", referenced from:
      webrtc::AVFoundationVideoCapturer::CaptureSampleBuffer(opaqueCMSampleBuffer*) in libWebRTC-LATEST-Universal-Release.a(libjingle_peerconnection_objc.avfoundationvideocapturer.o)
      -[RTCVideoCaptureIosObjC captureOutput:didOutputSampleBuffer:fromConnection:] in libWebRTC-LATEST-Universal-Release.a(video_capture_module_internal_impl.rtc_video_capture_ios_objc.o)
  "_CVPixelBufferUnlockBaseAddress", referenced from:
      webrtc::AVFoundationVideoCapturer::CaptureSampleBuffer(opaqueCMSampleBuffer*) in libWebRTC-LATEST-Universal-Release.a(libjingle_peerconnection_objc.avfoundationvideocapturer.o)
      -[RTCVideoCaptureIosObjC captureOutput:didOutputSampleBuffer:fromConnection:] in libWebRTC-LATEST-Universal-Release.a(video_capture_module_internal_impl.rtc_video_capture_ios_objc.o)
  "_OBJC_CLASS_$_CADisplayLink", referenced from:
      objc-class-ref in libWebRTC-LATEST-Universal-Release.a(libjingle_peerconnection_objc.RTCEAGLVideoView.o)
  "_OBJC_CLASS_$_CAEAGLLayer", referenced from:
      objc-class-ref in libWebRTC-LATEST-Universal-Release.a(video_render_module_internal_impl.video_render_ios_view.o)
  "_OBJC_CLASS_$_EAGLContext", referenced from:
      objc-class-ref in libWebRTC-LATEST-Universal-Release.a(libjingle_peerconnection_objc.RTCOpenGLVideoRenderer.o)
      objc-class-ref in libWebRTC-LATEST-Universal-Release.a(libjingle_peerconnection_objc.RTCEAGLVideoView.o)
      objc-class-ref in libWebRTC-LATEST-Universal-Release.a(video_render_module_internal_impl.video_render_ios_view.o)
  "_OBJC_CLASS_$_GLKView", referenced from:
      objc-class-ref in libWebRTC-LATEST-Universal-Release.a(libjingle_peerconnection_objc.RTCEAGLVideoView.o)
  "_glActiveTexture", referenced from:
      -[RTCOpenGLVideoRenderer setupTextures] in libWebRTC-LATEST-Universal-Release.a(libjingle_peerconnection_objc.RTCOpenGLVideoRenderer.o)
      -[RTCOpenGLVideoRenderer updateTextureSizesForFrame:] in libWebRTC-LATEST-Universal-Release.a(libjingle_peerconnection_objc.RTCOpenGLVideoRenderer.o)
      -[RTCOpenGLVideoRenderer uploadPlane:sampler:offset:width:height:stride:] in libWebRTC-LATEST-Universal-Release.a(libjingle_peerconnection_objc.RTCOpenGLVideoRenderer.o)
      webrtc::OpenGles20::UpdateTextures(webrtc::I420VideoFrame const&) in libWebRTC-LATEST-Universal-Release.a(video_render_module_internal_impl.open_gles20.o)
      InitializeTexture(int, int, int, int) in libWebRTC-LATEST-Universal-Release.a(video_render_module_internal_impl.open_gles20.o)
  "_glAttachShader", referenced from:
      CreateProgram(unsigned int, unsigned int) in libWebRTC-LATEST-Universal-Release.a(libjingle_peerconnection_objc.RTCOpenGLVideoRenderer.o)
      webrtc::OpenGles20::CreateProgram(char const*, char const*) in libWebRTC-LATEST-Universal-Release.a(video_render_module_internal_impl.open_gles20.o)
  "_glBindBuffer", referenced from:
      -[RTCOpenGLVideoRenderer drawFrame:] in libWebRTC-LATEST-Universal-Release.a(libjingle_peerconnection_objc.RTCOpenGLVideoRenderer.o)
      -[RTCOpenGLVideoRenderer setupVertices] in libWebRTC-LATEST-Universal-Release.a(libjingle_peerconnection_objc.RTCOpenGLVideoRenderer.o)
  "_glBindFramebuffer", referenced from:
      -[VideoRenderIosView createContext] in libWebRTC-LATEST-Universal-Release.a(video_render_module_internal_impl.video_render_ios_view.o)
  "_glBindRenderbuffer", referenced from:
      -[VideoRenderIosView createContext] in libWebRTC-LATEST-Universal-Release.a(video_render_module_internal_impl.video_render_ios_view.o)
  "_glBindTexture", referenced from:
      -[RTCOpenGLVideoRenderer setupTextures] in libWebRTC-LATEST-Universal-Release.a(libjingle_peerconnection_objc.RTCOpenGLVideoRenderer.o)
      webrtc::OpenGles20::UpdateTextures(webrtc::I420VideoFrame const&) in libWebRTC-LATEST-Universal-Release.a(video_render_module_internal_impl.open_gles20.o)
      InitializeTexture(int, int, int, int) in libWebRTC-LATEST-Universal-Release.a(video_render_module_internal_impl.open_gles20.o)
  "_glBufferData", referenced from:
      -[RTCOpenGLVideoRenderer setupVertices] in libWebRTC-LATEST-Universal-Release.a(libjingle_peerconnection_objc.RTCOpenGLVideoRenderer.o)
  "_glCheckFramebufferStatus", referenced from:
      -[VideoRenderIosView createContext] in libWebRTC-LATEST-Universal-Release.a(video_render_module_internal_impl.video_render_ios_view.o)
  "_glClear", referenced from:
      -[RTCOpenGLVideoRenderer drawFrame:] in libWebRTC-LATEST-Universal-Release.a(libjingle_peerconnection_objc.RTCOpenGLVideoRenderer.o)
  "_glCompileShader", referenced from:
      CreateShader(unsigned int, char const*) in libWebRTC-LATEST-Universal-Release.a(libjingle_peerconnection_objc.RTCOpenGLVideoRenderer.o)
      webrtc::OpenGles20::LoadShader(unsigned int, char const*) in libWebRTC-LATEST-Universal-Release.a(video_render_module_internal_impl.open_gles20.o)
  "_glCreateProgram", referenced from:
      CreateProgram(unsigned int, unsigned int) in libWebRTC-LATEST-Universal-Release.a(libjingle_peerconnection_objc.RTCOpenGLVideoRenderer.o)
      webrtc::OpenGles20::CreateProgram(char const*, char const*) in libWebRTC-LATEST-Universal-Release.a(video_render_module_internal_impl.open_gles20.o)
  "_glCreateShader", referenced from:
      CreateShader(unsigned int, char const*) in libWebRTC-LATEST-Universal-Release.a(libjingle_peerconnection_objc.RTCOpenGLVideoRenderer.o)
      webrtc::OpenGles20::LoadShader(unsigned int, char const*) in libWebRTC-LATEST-Universal-Release.a(video_render_module_internal_impl.open_gles20.o)
  "_glDeleteBuffers", referenced from:
      -[RTCOpenGLVideoRenderer teardownGL] in libWebRTC-LATEST-Universal-Release.a(libjingle_peerconnection_objc.RTCOpenGLVideoRenderer.o)
  "_glDeleteFramebuffers", referenced from:
      -[VideoRenderIosView dealloc] in libWebRTC-LATEST-Universal-Release.a(video_render_module_internal_impl.video_render_ios_view.o)
  "_glDeleteProgram", referenced from:
      CreateProgram(unsigned int, unsigned int) in libWebRTC-LATEST-Universal-Release.a(libjingle_peerconnection_objc.RTCOpenGLVideoRenderer.o)
      -[RTCOpenGLVideoRenderer teardownGL] in libWebRTC-LATEST-Universal-Release.a(libjingle_peerconnection_objc.RTCOpenGLVideoRenderer.o)
      webrtc::OpenGles20::~OpenGles20() in libWebRTC-LATEST-Universal-Release.a(video_render_module_internal_impl.open_gles20.o)
      webrtc::OpenGles20::CreateProgram(char const*, char const*) in libWebRTC-LATEST-Universal-Release.a(video_render_module_internal_impl.open_gles20.o)
  "_glDeleteRenderbuffers", referenced from:
      -[VideoRenderIosView dealloc] in libWebRTC-LATEST-Universal-Release.a(video_render_module_internal_impl.video_render_ios_view.o)
  "_glDeleteShader", referenced from:
      CreateShader(unsigned int, char const*) in libWebRTC-LATEST-Universal-Release.a(libjingle_peerconnection_objc.RTCOpenGLVideoRenderer.o)
      -[RTCOpenGLVideoRenderer setupProgram] in libWebRTC-LATEST-Universal-Release.a(libjingle_peerconnection_objc.RTCOpenGLVideoRenderer.o)
      webrtc::OpenGles20::CreateProgram(char const*, char const*) in libWebRTC-LATEST-Universal-Release.a(video_render_module_internal_impl.open_gles20.o)
      webrtc::OpenGles20::LoadShader(unsigned int, char const*) in libWebRTC-LATEST-Universal-Release.a(video_render_module_internal_impl.open_gles20.o)
  "_glDeleteTextures", referenced from:
      -[RTCOpenGLVideoRenderer teardownGL] in libWebRTC-LATEST-Universal-Release.a(libjingle_peerconnection_objc.RTCOpenGLVideoRenderer.o)
      webrtc::OpenGles20::~OpenGles20() in libWebRTC-LATEST-Universal-Release.a(video_render_module_internal_impl.open_gles20.o)
  "_glDisable", referenced from:
      +[RTCOpenGLVideoRenderer initialize] in libWebRTC-LATEST-Universal-Release.a(libjingle_peerconnection_objc.RTCOpenGLVideoRenderer.o)
  "_glDrawArrays", referenced from:
      -[RTCOpenGLVideoRenderer drawFrame:] in libWebRTC-LATEST-Universal-Release.a(libjingle_peerconnection_objc.RTCOpenGLVideoRenderer.o)
  "_glDrawElements", referenced from:
      webrtc::OpenGles20::Render(webrtc::I420VideoFrame const&) in libWebRTC-LATEST-Universal-Release.a(video_render_module_internal_impl.open_gles20.o)
  "_glEnableVertexAttribArray", referenced from:
      -[RTCOpenGLVideoRenderer setupVertices] in libWebRTC-LATEST-Universal-Release.a(libjingle_peerconnection_objc.RTCOpenGLVideoRenderer.o)
      webrtc::OpenGles20::Setup(int, int) in libWebRTC-LATEST-Universal-Release.a(video_render_module_internal_impl.open_gles20.o)
  "_glFramebufferRenderbuffer", referenced from:
      -[VideoRenderIosView createContext] in libWebRTC-LATEST-Universal-Release.a(video_render_module_internal_impl.video_render_ios_view.o)
  "_glGenBuffers", referenced from:
      -[RTCOpenGLVideoRenderer setupVertices] in libWebRTC-LATEST-Universal-Release.a(libjingle_peerconnection_objc.RTCOpenGLVideoRenderer.o)
  "_glGenFramebuffers", referenced from:
      -[VideoRenderIosView createContext] in libWebRTC-LATEST-Universal-Release.a(video_render_module_internal_impl.video_render_ios_view.o)
  "_glGenRenderbuffers", referenced from:
      -[VideoRenderIosView createContext] in libWebRTC-LATEST-Universal-Release.a(video_render_module_internal_impl.video_render_ios_view.o)
  "_glGenTextures", referenced from:
      -[RTCOpenGLVideoRenderer setupTextures] in libWebRTC-LATEST-Universal-Release.a(libjingle_peerconnection_objc.RTCOpenGLVideoRenderer.o)
      webrtc::OpenGles20::SetupTextures(webrtc::I420VideoFrame const&) in libWebRTC-LATEST-Universal-Release.a(video_render_module_internal_impl.open_gles20.o)
  "_glGetAttribLocation", referenced from:
      -[RTCOpenGLVideoRenderer setupProgram] in libWebRTC-LATEST-Universal-Release.a(libjingle_peerconnection_objc.RTCOpenGLVideoRenderer.o)
      webrtc::OpenGles20::Setup(int, int) in libWebRTC-LATEST-Universal-Release.a(video_render_module_internal_impl.open_gles20.o)
  "_glGetProgramInfoLog", referenced from:
      webrtc::OpenGles20::CreateProgram(char const*, char const*) in libWebRTC-LATEST-Universal-Release.a(video_render_module_internal_impl.open_gles20.o)
  "_glGetProgramiv", referenced from:
      CreateProgram(unsigned int, unsigned int) in libWebRTC-LATEST-Universal-Release.a(libjingle_peerconnection_objc.RTCOpenGLVideoRenderer.o)
      webrtc::OpenGles20::CreateProgram(char const*, char const*) in libWebRTC-LATEST-Universal-Release.a(video_render_module_internal_impl.open_gles20.o)
  "_glGetRenderbufferParameteriv", referenced from:
      -[VideoRenderIosView createContext] in libWebRTC-LATEST-Universal-Release.a(video_render_module_internal_impl.video_render_ios_view.o)
  "_glGetShaderInfoLog", referenced from:
      webrtc::OpenGles20::LoadShader(unsigned int, char const*) in libWebRTC-LATEST-Universal-Release.a(video_render_module_internal_impl.open_gles20.o)
  "_glGetShaderiv", referenced from:
      CreateShader(unsigned int, char const*) in libWebRTC-LATEST-Universal-Release.a(libjingle_peerconnection_objc.RTCOpenGLVideoRenderer.o)
      webrtc::OpenGles20::LoadShader(unsigned int, char const*) in libWebRTC-LATEST-Universal-Release.a(video_render_module_internal_impl.open_gles20.o)
  "_glGetUniformLocation", referenced from:
      -[RTCOpenGLVideoRenderer setupProgram] in libWebRTC-LATEST-Universal-Release.a(libjingle_peerconnection_objc.RTCOpenGLVideoRenderer.o)
      webrtc::OpenGles20::Setup(int, int) in libWebRTC-LATEST-Universal-Release.a(video_render_module_internal_impl.open_gles20.o)
  "_glLinkProgram", referenced from:
      CreateProgram(unsigned int, unsigned int) in libWebRTC-LATEST-Universal-Release.a(libjingle_peerconnection_objc.RTCOpenGLVideoRenderer.o)
      webrtc::OpenGles20::CreateProgram(char const*, char const*) in libWebRTC-LATEST-Universal-Release.a(video_render_module_internal_impl.open_gles20.o)
  "_glPixelStorei", referenced from:
      -[RTCOpenGLVideoRenderer setupGL] in libWebRTC-LATEST-Universal-Release.a(libjingle_peerconnection_objc.RTCOpenGLVideoRenderer.o)
      -[RTCOpenGLVideoRenderer uploadPlane:sampler:offset:width:height:stride:] in libWebRTC-LATEST-Universal-Release.a(libjingle_peerconnection_objc.RTCOpenGLVideoRenderer.o)
      InitializeTexture(int, int, int, int) in libWebRTC-LATEST-Universal-Release.a(video_render_module_internal_impl.open_gles20.o)
  "_glShaderSource", referenced from:
      CreateShader(unsigned int, char const*) in libWebRTC-LATEST-Universal-Release.a(libjingle_peerconnection_objc.RTCOpenGLVideoRenderer.o)
      webrtc::OpenGles20::LoadShader(unsigned int, char const*) in libWebRTC-LATEST-Universal-Release.a(video_render_module_internal_impl.open_gles20.o)
  "_glTexImage2D", referenced from:
      -[RTCOpenGLVideoRenderer updateTextureSizesForFrame:] in libWebRTC-LATEST-Universal-Release.a(libjingle_peerconnection_objc.RTCOpenGLVideoRenderer.o)
      -[RTCOpenGLVideoRenderer uploadPlane:sampler:offset:width:height:stride:] in libWebRTC-LATEST-Universal-Release.a(libjingle_peerconnection_objc.RTCOpenGLVideoRenderer.o)
      InitializeTexture(int, int, int, int) in libWebRTC-LATEST-Universal-Release.a(video_render_module_internal_impl.open_gles20.o)
  "_glTexParameterf", referenced from:
      InitializeTexture(int, int, int, int) in libWebRTC-LATEST-Universal-Release.a(video_render_module_internal_impl.open_gles20.o)
  "_glTexParameteri", referenced from:
      -[RTCOpenGLVideoRenderer setupTextures] in libWebRTC-LATEST-Universal-Release.a(libjingle_peerconnection_objc.RTCOpenGLVideoRenderer.o)
  "_glTexSubImage2D", referenced from:
      GlTexSubImage2D(int, int, int, unsigned char const*) in libWebRTC-LATEST-Universal-Release.a(video_render_module_internal_impl.open_gles20.o)
  "_glUniform1i", referenced from:
      -[RTCOpenGLVideoRenderer uploadPlane:sampler:offset:width:height:stride:] in libWebRTC-LATEST-Universal-Release.a(libjingle_peerconnection_objc.RTCOpenGLVideoRenderer.o)
      webrtc::OpenGles20::Setup(int, int) in libWebRTC-LATEST-Universal-Release.a(video_render_module_internal_impl.open_gles20.o)
  "_glUseProgram", referenced from:
      -[RTCOpenGLVideoRenderer setupGL] in libWebRTC-LATEST-Universal-Release.a(libjingle_peerconnection_objc.RTCOpenGLVideoRenderer.o)
      webrtc::OpenGles20::Setup(int, int) in libWebRTC-LATEST-Universal-Release.a(video_render_module_internal_impl.open_gles20.o)
  "_glVertexAttribPointer", referenced from:
      -[RTCOpenGLVideoRenderer setupVertices] in libWebRTC-LATEST-Universal-Release.a(libjingle_peerconnection_objc.RTCOpenGLVideoRenderer.o)
      webrtc::OpenGles20::Setup(int, int) in libWebRTC-LATEST-Universal-Release.a(video_render_module_internal_impl.open_gles20.o)
  "_glViewport", referenced from:
      -[VideoRenderIosView createContext] in libWebRTC-LATEST-Universal-Release.a(video_render_module_internal_impl.video_render_ios_view.o)
      webrtc::OpenGles20::Setup(int, int) in libWebRTC-LATEST-Universal-Release.a(video_render_module_internal_impl.open_gles20.o)
  "_kCVPixelBufferPixelFormatTypeKey", referenced from:
      -[RTCAVFoundationVideoCapturerInternal setupCaptureSession] in libWebRTC-LATEST-Universal-Release.a(libjingle_peerconnection_objc.avfoundationvideocapturer.o)
      -[RTCVideoCaptureIosObjC initWithOwner:captureId:] in libWebRTC-LATEST-Universal-Release.a(video_capture_module_internal_impl.rtc_video_capture_ios_objc.o)
      -[RTCAVFoundationVideoCapturerInternal setupCaptureSession] in libWebRTC-LATEST-Universal-Release.a(libjingle_peerconnection_objc.avfoundationvideocapturer.o)
      -[RTCVideoCaptureIosObjC initWithOwner:captureId:] in libWebRTC-LATEST-Universal-Release.a(video_capture_module_internal_impl.rtc_video_capture_ios_objc.o)
  "_kEAGLColorFormatRGBA8", referenced from:
      -[VideoRenderIosView createContext] in libWebRTC-LATEST-Universal-Release.a(video_render_module_internal_impl.video_render_ios_view.o)
  "_kEAGLDrawablePropertyColorFormat", referenced from:
      -[VideoRenderIosView createContext] in libWebRTC-LATEST-Universal-Release.a(video_render_module_internal_impl.video_render_ios_view.o)
  "_kEAGLDrawablePropertyRetainedBacking", referenced from:
      -[VideoRenderIosView createContext] in libWebRTC-LATEST-Universal-Release.a(video_render_module_internal_impl.video_render_ios_view.o)
ld: symbol(s) not found for architecture i386
clang: error: linker command failed with exit code 1 (use -v to see invocation)

** BUILD FAILED **


The following build commands failed:
    Ld build/emulator/Assistance.app/Assistance normal i386
(1 failure)

I tried everything without success...

iOS 9 Swift Compilation

I downloaded XCode 7 Beta to test building our app to an iOS 9 device, and iosrtc caused several Swift compilation errors, as the new XCode works using Swift 2.0. This also occurred after using the migration feature to upgrade the Swift code source.

You are a saint.

<3
I will do whatever it takes to contribute back for your efforts.
Looked at phonertc, realized it didn't implement the W3C standard of webrtc... seriously...

My only thing is compatibility with older android devices without webrtc in browser. Guess it would be a similar plugin needed for that stuff.

But other than that, this solves a lot! :)

Thank you so much.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.