[webRTC for ios vol1] iOS用のframeworkのビルド

webRTCをiosようにビルドしてwebRTC.framework を作る。
ググるとちょいちょい情報はありますが、変更があったりするので、2017/04/02 現在のものを整理。

実際につなげてみる Vol2 はこちら
http://qiita.com/nakadoribooks/items/9f1b1cbe32f2fc6dec70

## 成果物

https://github.com/nakadoribooks/webrtc-ios/releases/tag/v0.0.1

<img src="https://j.gifs.com/r0WMvK.gif" />

## 参考

- http://www.utali.io/entry/2016/09/07/142102
- http://mike-neko.github.io/blog/webrtc-build/


# webRTC.framework を作る

適当なフォルダを作って移動

```sh:
mkdir webrtc-build
cd webrtc-build
```

## Install depot_tools

http://dev.chromium.org/developers/how-tos/install-depot-tools

```sh:
git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git
export PATH=`pwd`/depot_tools:"$PATH"
```

## WebRTCのソースコードをダウンロード

https://webrtc.org/native-code/ios/

```sh:
fetch --nohooks webrtc_ios
gclient sync
```

src ディレクトリができるので、移動してコミットを確認

```sh:
cd src
git log

--
commit 76d9c9c3826f3c3622d3e8869fa54f7b39e70427
Author: stefan <stefan@webrtc.org>
Date:   Sat Apr 1 06:51:09 2017 -0700
```

てことで
76d9c9c3826f3c3622d3e8869fa54f7b39e70427 
これでやります

とりあえずブランチを切っとく

```sh:
git checkout -b nakadoribooks-build
```

## gn gen する

build の設定てきなやつ？

とりあえず64用と32用の二つ。
シュミレーター用も必要であれば target_cpuを変えてやる

>target_os:
To build for iOS this should be set as target_os="ios" in your gn args. The default is whatever OS you are running the script on, so this can be omitted when generating build files for macOS.
target_cpu:
For builds targeting iOS devices, this should be set to either "arm" or "arm64", depending on the architecture of the device. For builds to run in the simulator, this should be set to "x64".
is_debug:
Debug builds are the default. When building for release, specify false.
https://webrtc.org/native-code/ios/

```sh:
gn gen out/ios_64 --args='target_os="ios" target_cpu="arm64" is_debug=false ios_enable_code_signing=false'
gn gen out/ios_32 --args='target_os="ios" target_cpu="arm" is_debug=false ios_enable_code_signing=false'
```

## ninja する

build

```sh:
ninja -C out/ios_64 AppRTCMobile
ninja -C out/ios_32 AppRTCMobile
```

## 64用と32用をくっつける

フォルダを作る

```sh:
mkdir out/ios
```

コピーする

```sh:
cp -R out/ios_64/WebRTC.framework/ out/ios/WebRTC.framework
```

がっちゃんこする

```sh:
lipo -create out/ios_64/WebRTC.framework/WebRTC out/ios_32/WebRTC.framework/WebRTC -output out/ios/WebRTC.framework/WebRTC
```

なぜか "RTCVideoCapturer.h" だけ入ってないのでコピーする

```sh:
cp webrtc/sdk/objc/Framework/Headers/WebRTC/RTCVideoCapturer.h out/ios/WebRTC.framework/Headers/
```

できました。
out/ios/WebRTC.framework
こいつです。

# xcodeのプロジェクトに入れて使ってみる

## プロジェクトに追加

↑ でつくった WebRTC.framework をxcodeにドラッグアンドドロップして
"Embed Binaries"に追加

![スクリーンショット 2017-04-02 14.43.38.png](https://qiita-image-store.s3.amazonaws.com/0/159266/75f798cc-aaed-4726-adb6-ae7d513351c8.png)

## 設定の追加

### Enable bitcode を NO

![スクリーンショット 2017-04-02 14.44.24.png](https://qiita-image-store.s3.amazonaws.com/0/159266/e5838251-e123-b4e1-0821-6a1ea33e5d8f.png)

### Info.plist に Privacy - Camera Usage Description を追加

![スクリーンショット 2017-04-02 14.46.04.png](https://qiita-image-store.s3.amazonaws.com/0/159266/d2b5d5e5-d95d-2b5f-4240-f1e303b0cb5d.png)

## コードを書く

### webRTC の部分

```swift:WebRTC.swift
import UIKit

class WebRTC: NSObject {

    private let factory = RTCPeerConnectionFactory()
    private var localRenderView = RTCEAGLVideoView()
    private var localStream:RTCMediaStream?
    private let _localView = UIView(frame:CGRect(x:20, y:40, width:140, height:200))
    
    static let sharedInstance = WebRTC()
    
    private override init() {
        super.init()
    }
    
    // MARK: public
    
    func localView()->UIView{
        return _localView
    }
    
    func setup(){
        print("setup")
        
        setupLocalStream()
    }
    
    // MARK: private
    
    private func setupLocalStream(){
        
        let streamId = WebRTCUtil.idWithPrefix(prefix: "stream")
        localStream = factory.mediaStream(withStreamId: streamId)
        setupLocalVideoTrack()
    }
    
    private func setupLocalVideoTrack(){
        localRenderView.frame.size = _localView.frame.size
        _localView.addSubview(localRenderView)
        
        let localVideoSource = factory.avFoundationVideoSource(with: WebRTCUtil.mediaStreamConstraints())
        let localVideoTrack = factory.videoTrack(with: localVideoSource, trackId: WebRTCUtil.idWithPrefix(prefix: "video"))
        
        localVideoTrack.add(localRenderView)
        
        localStream?.addVideoTrack(localVideoTrack)
    }
    
}
```

```swift:WebRTCUtil.swift
import UIKit

class WebRTCUtil: NSObject {

    static func idWithPrefix(prefix:String)->String{
        return "\(prefix)_\(randomStringWithLength(len: 20))"
    }
    
    static func randomStringWithLength (len : Int) -> NSString {
        let letters : NSString = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
        let randomString : NSMutableString = NSMutableString(capacity: len)
        
        for _ in 0..<len {
            let length = UInt32 (letters.length)
            let rand = arc4random_uniform(length)
            randomString.appendFormat("%C", letters.character(at: Int(rand)))
        }
        
        return randomString
    }
    
    static func mediaStreamConstraints()->RTCMediaConstraints{
        return RTCMediaConstraints(mandatoryConstraints: nil, optionalConstraints: nil)
    }
}
```

### 画面

```swift:ViewController.swift

import UIKit

class ViewController: UIViewController {

    private let webRTC = WebRTC.sharedInstance
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        webRTC.setup()
        view.addSubview(webRTC.localView())
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

}

```

以上。