webrtc on native app

19
1 WebRTC on Native App Newphoria Corporation Development Division Yoshitake Hatada

Upload: webrtcconferencejapan

Post on 13-Feb-2017

629 views

Category:

Technology


7 download

TRANSCRIPT

1

WebRTC on Native App

Newphoria CorporationDevelopment DivisionYoshitake Hatada

2

本セッションでは… .

WebRTC プラットフォーム SkyWay SDK 開発時にご協力した際の知見、四方山をお話しさせていただきます。

3

プラットフォーム SDK 故の難しさ

各 OS { iOS | Android } から同様に使える必要がある。→ 抽象度の均一化→ 性能差の解消(端末ごとのベストエフォート)→ 機能的には全方位対応

個別のアプリケーションを開発するよりも、ちょっと 結構厄介。

libjingle Platform 層

4

プラットフォーム SDK レイヤ構造

App 層SDK 層

libjingle Platform 層libjingle Core 層 OS 固有層

OS 層

libjingle Platform 層

5

libjingle – Google Talk Voice and P2P Interoperability Libiraty

• C/C++ • STL (but がっつりテンプレートではないのでちょっと安心 )• 2GB++• Camel と Snake が混在 ( かなり改善されたがそれでも… )• 通信プロトコルは XMPP の拡張• 基本 UDP のみ (Pseudo TCP もあるでよ )

libjingle Platform 層

6

プラットフォーム SDK レイヤ構造

App 層SDK 層

libjingle Platform 層libjingle Core 層 OS 固有層

OS 層

(WebSocket/XHR Stream によるシグナリングサーバとの通信、 MessagePack 仕様によるデータコネクション通信は libjingle とは 別実装 )

特定のプラットフォーム向けにビルドすることでWebRTC Native APIs の共通 API を利用を実現する層libjingle Platform 層

7

libjingle Platform for iOS (Objective-C)

RTCAVFoundationVideoSource.h RTCI420Frame.hRTCMediaStream.h RTCPeerConnectionDelegate.hRTCStatsReport.hRTCAudioSource.h RTCICECandidate.hRTCMediaStreamTrack.h RTCPeerConnectionFactory.hRTCTypes.hRTCAudioTrack.h RTCICEServer.hRTCNSGLVideoView.h RTCPeerConnectionInterface.hRTCVideoCapturer.h RTCDataChannel.hRTCLogging.h RTCOpenGLVideoRenderer.hRTCSessionDescription.h RTCVideoRenderer.hRTCEAGLVideoView.h RTCMediaConstraints.hRTCPair.h RTCSessionDescriptionDelegate.hRTCVideoSource.h RTCFileLogger.hRTCMediaSource.h RTCPeerConnection.hRTCStatsDelegate.h RTCVideoTrack.h

8

libjingle Platform for Android (org.webrtc)

org.webrtc.AudioSourceorg.webrtc.AudioTrackorg.webrtc.CameraEnumerationAndroidorg.webrtc.DataChannelorg.webrtc.EglBaseorg.webrtc.Loggingorg.webrtc.MediaConstraintsorg.webrtc.MediaStreamorg.webrtc.PeerConnectionorg.webrtc.PeerConnectionFactoryorg.webrtc.RendererCommonorg.webrtc.SurfaceViewRendererorg.webrtc.VideoCapturerAndroidorg.webrtc.VideoRendererorg.webrtc.VideoSourceorg.webrtc.VideoTrackorg.webrtc.voiceengine.WebRtcAudioManager : :

libjingle Platform 層

9

プラットフォーム SDK レイヤ構造

App 層SDK 層

libjingle Platform 層libjingle Core 層 OS 固有層

OS 層

(WebSocket/XHR Stream によるシグナリングサーバとの通信、 MessagePack 仕様によるデータコネクション通信は libjingle とは 別実装 )

特定のプラットフォーム向けにビルドすることでWebRTC Native APIs の共通 API を利用を実現する層

WebRTC で利用する各機能を実現している層

libjingle Platform 層

10

libjingle Core 層

WebRTC で利用する各機能を実現しているそれぞれの機能層。

f.e.)• ビデオコーデック (VP8 、 VP9 、 H.264…)• オーディオコーデック (iSAC 、 opus 、 G722 、 iLIBC 、 PCMU 、 PCMA 、 CN 、 red 、 telephone-event…)• RTP/RTCP• STUN• TURN• SDP ICE

※ ここで用意されているビデオコーデック、オーディオコーデックは Software Codec です。

libjingle Platform 層

11

プラットフォーム SDK レイヤ構造

App 層SDK 層

libjingle Platform 層libjingle Core 層 OS 固有層

OS 層

(WebSocket/XHR Stream によるシグナリングサーバとの通信、 MessagePack 仕様によるデータコネクション通信は libjingle とは 別実装 )

特定のプラットフォーム向けにビルドすることでWebRTC Native APIs の共通 API を利用を実現する層

WebRTC で利用する各機能を実現している層

libjingle Platform 層

各 OS 固有機能の層Camera 、 MIC 、映像描画、音声再生、ハードウェアコーデック (Video Codec 、 DSP Extension…)

12

ローカルからの OFFER までの大まかな流れ

1. PeerConnection を作成するための Factory オブジェクトの初期化2. PeerConnectionFactory オブジェクトの生成3. ローカルメディアストリームの生成 (Video, Audio)4. PeerConnection オブジェクトを生成5. PeerConnection オブジェクトに OFFER をリクエスト6. OFFER の準備ができると SDP が生成されるので、 OFFER 相手にシグナリングサーバ経由で送信。7. 生成された ICE CANDIDATE を OFFER 相手にシグナリングサーバ経由で送信8. 受信した相手側の ANSWER を PeerConnection の RemoteDescription として設定9. 受信した相手側の ICE CANDIDATE を PeerConnection に追加10. 映像と音声の通信開始

13

Java // PeerConnection や MediaStream を生成するための Factory を生成{

Context context = getApplicationContext();boolean useAudio = true;boolean useVideo = true;boolean useHWCodec = true;PeerConnectionFactory.initializeAndroidGlobals(context, useAudio, useVideo, useHWCodec);

PeerConnectionFactory.Options option = new PeerConnectionFactory.Options();PeerConnectionFactory factory = new PeerConnectionFactory(option);

}

// ローカルのメディアストリームを生成{

MediaStream stream = factory.createLocalMediaStream("ARDAMS");

// カメラから映像トラックを生成String nameOfCamera = CameraEnumerationAndroid.getNameOfFrontFacingDevice();VideoCapturerAndroid capture = VideoCapturerAndroid.create(nameOfCamera, this, null);

MediaConstraints videoMediaConstraints = new MediaConstraints();mediaConstraints.mandatory.add(new MediaConstraints.KeyValuePair("maxWidth", "640"));mediaConstraints.mandatory.add(new MediaConstraints.KeyValuePair("maxHeight", "480"));

VideoSource videoSource = factory.createVideoSource(capture, videoMediaConstraints);

VideoTrack videoTrack = factory.createVideoTrack("ARDAMSv0", vidSrc);

stream.addVideoTrack(videoTrack);

// マイクから音声トラックを生成MediaConstraints audioMediaConstraints = new MediaConstraints();AudioSource audioSource = factory.createAudioSource(audioMediaConstraints);

AudioTrack audioTrack = factory.createAudioTrack("ARDAMSa0", audioSource);

stream.addAudioTrack(audioTrack);}

14

Java // PeerConnection オブジェクトの生成{

LinkedList<PeerConnection.IceServer> servers = new LinkedList<>();PeerConnection.RTCConfiguration configuration = new PeerConnection.RTCConfiguration(servers);

MediaConstraints mediaConstraints = new MediaConstraints();mediaConstraints.mandatory.add(new MediaConstraints.KeyValuePair("OfferToReceiveAudio", "true"));mediaConstraints.mandatory.add(new MediaConstraints.KeyValuePair("OfferToReceiveVideo", "true"));PeerConnection peerConnection = factory.createPeerConnection(configuration, mediaConstraints, observer);

// PeerConnection にメディアストリームを追加peerConnection.addStream(stream);

}

// OFFER リクエスト{

MediaConstraints mediaConstraints = new MediaConstraints();...peerConnection.createOffer(SdpObserver, mediaConstraints);

}

// ローカルセッションディスクリプション生成時のオーバーライドメソッド{

@Overridepublic void onCreateSuccess(SessionDescription sessionDescription){

peerConnection.setLocalDescription(this, sessionDescription);// このあと、シグナリングサーバに OFFER / ANSWER メッセージを送る

}}

// リモートからのメッセージでリモートセッションディスクリプションを設定{

// 受信したデータから SDP 部分を抽出String sdp = ( 抽出処理 )SessionDescription desc = new SessionDescription(type, sdp);peerConnection.setRemoteDescription(this, desc);

}

15

Objective-C // PeerConnection や MediaStream を生成するための Factory を生成{

[RTCPeerConnectionFactory initializeSSL];RTCPeerConnectionFactory factory = [[RTCPeerConnectionFactory alloc] init];

}

// ローカルのメディアストリームを生成{

RTCMediaStream* stream = [factory mediaStreamWithLabel:@"ARDAMS"];// カメラから映像トラックを生成RTCMediaConstraints* videoConstraints = [[RTCMediaConstraints alloc] initWithMandatoryConstraints:aryMandatory optionalConstraints:nil];RTCAVFoundationVideoSource* sourceVideo = [[RTCAVFoundationVideoSource alloc] initWithFactory:factory constraints:videoConstraints];RTCVideoTrack* videoTrack = [factory videoTrackWithID:@"ARDAMSv0" source:sourceVideo];[stream addVideoTrack:videoTrack];

// マイクから音声トラックを生成RTCAudioTrack* audioTrack = [factory audioTrackWithID:@"ARDAMSa0"];[stream addAudioTrack:audioTrack];

}

// PeerConnection オブジェクトの生成{

RTCConfiguration* config = [[RTCConfiguration alloc] init];[config setIceTransportsType:kRTCIceTransportsTypeAll];[config setBundlePolicy:kRTCBundlePolicyBalanced];[config setRtcpMuxPolicy:kRTCRtcpMuxPolicyNegotiate];[config setTcpCandidatePolicy:kRTCTcpCandidatePolicyEnabled];[config setIceServers:arServers];[config setAudioJitterBufferMaxPackets:50];[config setIceConnectionReceivingTimeout:-1];

RTCPair* pairVideoValue = [[RTCPair alloc] initWithKey:@"OfferToReceiveVideo" value:@"true"];RTCPair* pairAudioValue = [[RTCPair alloc] initWithKey:@"OfferToReceiveAudio" value:@"true"];NSArray* arrayConstraints = @[ pairVideoValue, pairAudioValue ];

RTCMediaConstraints* constraints = [[RTCMediaConstraints alloc] initWithMandatoryConstraints:arrayConstraints optionalConstraints:nil];PeerConnection peerConnection = [factory peerConnectionWithConfiguration:config constraints:constraints delegate:Observer];

// PeerConnection にメディアストリームを追加[peerConnection addStream:stream];

}

16

Objective-C // Offer リクエスト{

NSArray* arrayConstraints = @[ ... ];RTCMediaConstraints* constraints = [[RTCMediaConstraints alloc] initWithMandatoryConstraints:arrayConstraints optionalConstraints:nil];

[peerConnection createOfferWithDelegate:Observer constraints:constraints];}

// ローカルセッションディスクリプション生成時の Delegate / RTCSessionDescriptionDelegate{

- (void)peerConnection:(RTCPeerConnection *)peerConnection didCreateSessionDescription:(RTCSessionDescription *)sdp error:(NSError *)error{

NSString* type = [sdp.type lowercaseString];NSString* desc = [sdp description];

RTCSessionDescription* sd = [[RTCSessionDescription alloc] initWithType:type sdp:desc];[peerConnection setLocalDescriptionWithDelegate:self sessionDescription:sd];

// このあと、シグナリングサーバに OFFER / ANSWER メッセージを送る}

}

// リモートからのメッセージでリモートセッションディスクリプションを設定{

// 受信したデータから TYPE 部分を抽出NSString* type = ( 抽出処理 )

// 受信したデータから SDP 部分を抽出NSString* desc = ( 抽出処理 )

// Set remote descriptionRTCSessionDescription* sd = [[RTCSessionDescription alloc] initWithType:type sdp:desc];[self.peerConnection setRemoteDescriptionWithDelegate:self sessionDescription:sd];

}

17

libjingle あるある

Libjingle 自体は C/C++ だが、追加で Android 、 iOS 、 Windows 用の API が追加されている。Python,ninja によってそれぞれのプラットフォーム向けのネイティブライブラリが作成できる。

{Android | iOS | Windows} { 実機 | シミュレータ } {32bit | 64bit }{Chip A| Chip B |Chinp C}

とっちらかる一括ビルドスクリプト ( https://github.com/pristineio/webrtc-build-scripts )

libjingle 開発活動が活発1 日で master ブランチのコミットが数十進むことも珍しくない。もろもろの事情 (OS 依存性の問題 ) や新機能の追加、バグフィックスなどでコードの移動が多発。→API が変わったり、無くなったり、新しく追加されたり…

ライブラリ作成のスクリプト構造も追随して変えなければ…一括ビルドスクリプトが追いつかない

やっぱり、とっちらかる

18

iOS / Android• iOS8.0 から H.264 だとハードウェア支援が受けられる!• WebRTC では V8 デフォルト。 CPU 負荷高い! (libjingle/iOS でもデフォルトでは H.264 は使用できない )• ビルド時に記述追加で H.264 を有効化して対応。• bitcode はオプションとして存在しているが、動的に生成される .py に記述• → どこにどう書いてあるか、ふたを開けなきゃわからない• 新しいソースに切り替わるたびに手動で修正。

• とっちらかる• Android では V8 のハードウェア支援の有無は Android OS API で検知可能。

libjingle API でもハードウェア支援を行うオプションが提供。

• ハードウェア支援を行うと特定の機種でエラー発生。

• 結果、とっちらかる• Android でも H.264 を使用できる !• 使用コーデックが VP8…• iOS とはプロファイルが違うらしい… .

• iOS デバイス同士、 Android デバイス同士ならば H.264 でハードウェア支援をうけて楽々。• iOS デバイスと Android デバイスだと VP8 になってしまう…

• やっぱり、とっちらかる

19

まとめ• libjingle の開発はとてもアグレッシブ。• アグレッシブすぎて若干無政府状態、もう少し秩序を

• 世紀末救世主 急募。