WebRTC in iOS 2015 05


ios, webrtc

WebRTC in iOS 2015 05


Daniel Shin - May 03, 2015

Some parts of this post are no longer up-to-date. Please refer to updated post here for update.

This post will cover some of the things that I’ve learned while building iOS app powered by WebRTC.

Although app is still in progress, I wanted to still document some of the stuff that requires more attention.

If you are looking to get a general view about WebRTC in iOS, try this post from ninjanetic first.

I’m only going to cover some gotchas that tripped me up.

And WebRTC is definitely on the top of my list due to its complexity, introduced by not only its innate nature of it but also the lack of documentation and community.

Note that I’m not referring to WebRTC used by Web browsers since browser implementation is both well documented and has great community around it.

Also note that me referring to WebRTC is inherently incorrect since WebRTC is, as you can refer by its name, simply an implementation for web browser. The real engine that supports such implementation is called Libjingle, which started much earlier than WebRTC ever got standardized. It actually powers Google Hangout (previously known as Google Voice).

Term Libjingle should be used in all other native implementations, including iOS, Android, and any other non-browser implementation.

Compile

  1. You should already know that from iPhone5 onwards, arm64 architecture has been introduced. You need to account for both armv7 and arm64 when you compile libjingle source. You need separate archive file for both architecture, namely, for example, libWebRTC-armv7.a and libWebRTC-arm64.a

Or you could simply use lipo command to merge these two archive files. If properly minified, size should be around ~50MB when merged.

There is a big gotcha here. XCode simulator support neither of the above architectures since it runs on desktop not an actual mobile device. You will need to use ia32 architecture.

BUT ia32 is, as you can tell from its name, 32bit architecture, which is what armv7 is. This means that You cannot run 64bit iPhone simulator with libjingle. You just can’t. This may change in the future but for now it is. It took me long hours of frustration to figure this out.

Libjinlge simply doesn’t have simulator equivalent of 64 bit architecture. So if you are testing libjingle in simulator, be sure to only use 32 bit devices.

  1. Apple will reject any app binary without support for 64bit. This changed at around February, 2015. So be sure to include at least 64bit architecture of libWebRTC file.

  2. Here is the script I made to build for all three of ia32(Simulator), armv7(< iPhone5), arm64(iPhone5 <) architectures for libjingle.

#!/bin/bash

export GYP_CROSSCOMPILE=1
export GYP_GENERATORS=ninja

# NOTE:
# it seems like simulator version of libjingle only supports 32 bit(ia32), which means we can only test upto iPhone5 in simulator# armv7 will only work with 'device' version of armv7 (upto iPhone5)
# arm64 will only work with 'device' version of arm64 (iPhone5S onwards)

function build_iossim() {
  echo "-- building for iOS Simulator"

  export GYP_DEFINES="OS=ios target_arch=ia32"
  export GYP_GENERATOR_FLAGS="output_dir=out_sim"

  pushd src/
  webrtc/build/gyp_webrtc
  ninja -C out_sim/Release-iphonesimulator iossim AppRTCDemo
  libtool -static -o out_sim/Release-iphonesimulator/libWebRTC-sim.a out_sim/Release-iphonesimulator/*.a
  strip -S -x -o out_sim/Release-iphonesimulator/libWebRTC-sim-min.a -r out_sim/Release-iphonesimulator/libWebRTC-sim.a
  popd
}

function build_iosarmv7() {
  echo "-- building for iOS Device armv7"

  export GYP_DEFINES="OS=ios target_arch=armv7"
  export GYP_GENERATOR_FLAGS="output_dir=out_armv7"

  pushd src/
  webrtc/build/gyp_webrtc
  ninja -C out_armv7/Release-iphoneos AppRTCDemo
  libtool -static -o out_armv7/Release-iphoneos/libWebRTC-armv7.a out_armv7/Release-iphoneos/*.a
  strip -S -x -o out_armv7/Release-iphoneos/libWebRTC-armv7-min.a -r out_armv7/Release-iphoneos/libWebRTC-armv7.a
  popd
}

function build_iosarm64() {
  echo "-- building for iOS Device arm64"

  export GYP_DEFINES="OS=ios target_arch=arm64 target_subarch=arm64"
  export GYP_GENERATOR_FLAGS="output_dir=out_arm64"

  pushd src/
  webrtc/build/gyp_webrtc
  ninja -C out_arm64/Release-iphoneos AppRTCDemo
  libtool -static -o out_arm64/Release-iphoneos/libWebRTC-arm64.a out_arm64/Release-iphoneos/*.a
  strip -S -x -o out_arm64/Release-iphoneos/libWebRTC-arm64-min.a -r out_arm64/Release-iphoneos/libWebRTC-arm64.a
  popd
}

$@  

This assumes that you are running this after fulfilling all the requirements from WebRTC official webpage.

Eg. If you want to build for arm64 device only, then run

./build_ios.sh build_iosarm64

This will create archive file in out_arm64/Release-iphoneos/libWebRTC-arm64.a
From here, you can either include this file in XCode, or build for another architecture and merge it using lipo command.

Implementation

  1. If you are using Swift to implement Libjingle, be sure to subclass NSObject for whichever class that implements RTCPeerConnectionDelegate or RTCSessionDescriptionDelegate. These protocols require NSObject as base class since the code was written in Objective-C.

  2. Be very comfortable with Delegation Design Pattern. Libjingle requires lots of different classes talking to each other simultaneously.

Eg. RTCPeerConnectionDelegate <-> RTCSessionDescriptionDelegate <-> $(CustomSignalingChannelDelegate) <-> $(UIDelegate) <-> $(CustomSDPChannelDelegate) etc…

To keep yourself sane and also for future maintenance, embrace delegation pattern fully.

I will add more and more things as I go along since I’m still learning a lot here.

I also have simplified swift version of apprtc for iOS that doesn’t use apprtc server by google but comes with node.js server in it that uses socket.io to exchange SDP. I thought apprtc example by google was using too much abstraction due to lack of server implementation detailed. I will open source this once I’m done with my project too.