やること
- webRTCをAndroid用にビルドして libwebrtc.aar (library的な?) を作る
- Android Studioに入れて使ってみる。ローカルのカメラを拾って表示。
ググるとちょいちょい情報はありますが、変更があったりするので、2017/04/13 現在のものを整理。
実際に繋げるのは次回
webRTC for android vol2
成果物
環境
- OS X El Capitan (version 10.11.6)
- AndroidStudio 2.3.1
- Nexus 5X Android6.0.1
参考
libwebrtc.aar を作る
基本的にこちら
How to build webrtc library for Android in OSX host
macではできないらしい。ので、Vagrant で Ubuntu 環境入れてそこで作る
やってみる
僕の環境ではそのままやるとエラーが出たので、調整が必要です
Vagrant の設定を作ってVagrantに入る
参考サイトのようにVagrantfile を作る
# -*- mode: ruby -*-
# vi: set ft=ruby :
# All Vagrant configuration is done below. The "2" in Vagrant.configure
# configures the configuration version (we support older styles for
# backwards compatibility). Please don't change it unless you know what
# you're doing.
Vagrant.configure(2) do |config|
# The most common configuration options are documented and commented below.
# For a complete reference, please see the online documentation at
# https://docs.vagrantup.com.
# Every Vagrant development environment requires a box. You can search for
# boxes at https://atlas.hashicorp.com/search.
config.vm.box = "hashicorp/precise64"
config.ssh.forward_agent = TRUE
config.vm.provider "virtualbox" do |vb|
vb.memory = 4096
vb.cpus = 2
end
config.vm.network "private_network", ip: "192.168.50.5"
config.vm.synced_folder ".", "/vagrant", type: :nfs
# Enable provisioning with a shell script. Additional provisioners such as
# Puppet, Chef, Ansible, Salt, and Docker are also available. Please see the
# documentation for more information about their specific syntax and use.
config.vm.provision "shell", inline: <<-SHELL
sudo apt-get update
sudo apt-get -y install wget git gnupg flex bison gperf build-essential zip curl subversion pkg-config libglib2.0-dev libgtk2.0-dev libxtst-dev libxss-dev libpci-dev libdbus-1-dev libgconf2-dev libgnome-keyring-dev libnss3-dev
# Download the latest script to install the android dependencies for ubuntu
curl -o install-build-deps-android.sh https://src.chromium.org/svn/trunk/src/build/install-build-deps-android.sh
# Use bash (not dash which is default) to run the script
sudo /bin/bash ./install-build-deps-android.sh
# Delete the file we just downloaded... not needed anymore
rm install-build-deps-android.sh
SHELL
end
up する
vagrant up
Bringing machine 'default' up with 'virtualbox' provider...
==> default: Importing base box 'hashicorp/precise64'...
- 略 -
==> default: 250 0 --:--:-- --:--:-- --:--:-- 460
==> default: ./install-build-deps-android.sh: line 1: syntax error near unexpected tokennewline' ==> default: ./install-build-deps-android.sh: line 1:
'
https://src.chromium.org/svn/trunk/src/build/install-build-deps-android.sh
が存在しないので、エラーが出ますがそのままいきます。
vagrant ssh
depot_tools
Googleの開発ツール的なやつ
git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git
export PATH=`pwd`/depot_tools:"$PATH"
ソースコードのダウンロード
フォルダ作って移動
mkdir webrtc-checkout
cd webrtc-checkout
fetch --nohooks webrtc_android
Running: gclient root
- 略 (※けっこう時間かかる) -
Running: git config diff.ignoreSubmodules all
gclient sync
________ running '/usr/bin/python src/cleanup_links.py' in '/home/vagrant/webrtc-checkout'
略
Do you accept the license for version 10.2.0 of the Google Play services client library? [y/n]
5> Downloading src/resources/audio_processing/agc/agc_no_circular_buffer.dat...
Hook 'download_from_google_storage --directory --recursive --num_threads=10 --no_auth --quiet --bucket chromium-webrtc-resources src/resources' took 598.61 secs
コミットを確認してみる
cd src/
git log
commit 64349c7e08c7ccf7acd298393fd2662cf7b25139
Author: buildbot buildbot@webrtc.org
Date: Sat Apr 15 18:08:59 2017 -0700
ブランチ見る
git branch
* (no branch)
master
とりあえずブランチ切る
git checkout -b nakadoribooks-build
git status
Not currently on any branch.
Untracked files:
(use "git add ..." to include in what will be committed)
resources/ConferenceMotion_1280_720_50.yuv
とりあえずコミットしとく
git add -A
git commit -m “develop”
もどって
cd ../
再度 'glient sync'
src/build/android/play_services/update.py download
gclient sync
________ running '/usr/bin/python src/cleanup_links.py' in '/home/vagrant/webrtc-checkout'
Syncing projects: 100% (42/42), done.
- 略 -
________ running 'download_from_google_storage --directory --recursive --num_threads=10 --no_auth --quiet --bucket chromium-webrtc-resources src/resources' in '/home/vagrant/webrtc-checkout'
cd src
ビルド
いけーーー
tools-webrtc/android/build_aar.py
INFO:root:Building: armeabi-v7a
/home/vagrant/webrtc-checkout/src/buildtools/linux64/gn: /usr/lib/x86_64-linux-gnu/libstdc++.so.6: version `GLIBCXX_3.4.18' not found (required by /home/vagrant/webrtc-checkout/src/buildtools/linux64/gn)
あかん、GLIBCXX_3.4.18 not found
GLIBCXX_ 問題
sudo strings /usr/lib/x86_64-linux-gnu/libstdc++.so.6 | grep GLIBCXX
GLIBCXX_3.4
GLIBCXX_3.4.1
GLIBCXX_3.4.2
GLIBCXX_3.4.3
GLIBCXX_3.4.4
GLIBCXX_3.4.5
GLIBCXX_3.4.6
GLIBCXX_3.4.7
GLIBCXX_3.4.8
GLIBCXX_3.4.9
GLIBCXX_3.4.10
GLIBCXX_3.4.11
GLIBCXX_3.4.12
GLIBCXX_3.4.13
GLIBCXX_3.4.14
GLIBCXX_3.4.15
GLIBCXX_3.4.16
GLIBCXX_DEBUG_MESSAGE_LENGTH
16までしかない。
ググってみると
https://askubuntu.com/questions/575505/glibcxx-3-4-20-not-found-how-to-fix-this-error
sudo apt-get install libstdc++6
Reading package lists... Done
Building dependency tree
- 略 -
gpg: imported: 1 (RSA: 1)
OK
sudo add-apt-repository ppa:ubuntu-toolchain-r/test
sudo apt-get update
Ign http://us.archive.ubuntu.com precise InRelease
- 略 -
Reading package lists... Done
sudo apt-get upgrade
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following packages have been kept back:
cpp-4.6 g++-4.6 gcc-4.6 gcc-4.6-base libgcc1 libgomp1 libquadmath0 libstdc++6 libstdc++6-4.6-dev
0 upgraded, 0 newly installed, 0 to remove and 9 not upgraded.
sudo apt-get dist-upgrade
Reading package lists... Done
Building dependency tree
略
Processing triggers for libc-bin ...
ldconfig deferred processing now taking place
sudo strings /usr/lib/x86_64-linux-gnu/libstdc++.so.6 | grep GLIBCXX
GLIBCXX_3.4
GLIBCXX_3.4.1
GLIBCXX_3.4.2
GLIBCXX_3.4.3
GLIBCXX_3.4.4
GLIBCXX_3.4.5
GLIBCXX_3.4.6
GLIBCXX_3.4.7
GLIBCXX_3.4.8
GLIBCXX_3.4.9
GLIBCXX_3.4.10
GLIBCXX_3.4.11
GLIBCXX_3.4.12
GLIBCXX_3.4.13
GLIBCXX_3.4.14
GLIBCXX_3.4.15
GLIBCXX_3.4.16
GLIBCXX_3.4.17
GLIBCXX_3.4.18
GLIBCXX_3.4.19
GLIBCXX_3.4.20
GLIBCXX_3.4.21
GLIBCXX_3.4.22
GLIBCXX_DEBUG_MESSAGE_LENGTH
入った!
再度。
tools-webrtc/android/build_aar.py
— 略 -
third_party/android_tools/sdk/tools/lint: line 68: exec: java: not found
— 略 -
java 問題
sudo apt-get uninstall openjdk-7-jdk
java -version
java version "1.6.0_41"
sudo update-alternatives --config java
0 /usr/lib/jvm/java-6-openjdk-amd64/jre/bin/java 1061 auto mode
1 /usr/lib/jvm/java-6-openjdk-amd64/jre/bin/java 1061 manual mode
2 /usr/lib/jvm/java-7-openjdk-amd64/jre/bin/java 1051 manual mode
Press enter to keep the current choice[※], or type selection number: 2
java -version
java version "1.7.0_121"
OpenJDK Runtime Environment (IcedTea 2.6.8) (7u121-2.6.8-1ubuntu0.12.04.3)
OpenJDK 64-Bit Server VM (build 24.121-b00, mixed mode)
入った。
これでいけるはず!
再度
tools-webrtc/android/build_aar.py
INFO:root:Building: armeabi-v7a
Done. Made 2757 targets from 172 files in 2925ms
ninja: Entering directory /tmp/tmp06LS69/armeabi-v7a
- 略 -
[2228/2228] SOLINK ./libjingle_peerconnection_so.so
— 略 —
INFO:root:Building: arm64-v8a
Done. Made 2751 targets from 172 files in 2456ms
ninja: Entering directory /tmp/tmp06LS69/arm64-v8a
— 略 -
[2150/2150] SOLINK ./libjingle_peerconnection_so.so
— 略 -
INFO:root:Building: x86
Done. Made 2779 targets from 173 files in 2858ms
ninja: Entering directory /tmp/tmp06LS69/x86
— 略 -
[2379/2379] SOLINK ./libjingle_peerconnection_so.so
— 略 -
INFO:root:Building: x86_64
Done. Made 2779 targets from 173 files in 2517ms
ninja: Entering directory /tmp/tmp06LS69/x86_64
— 略 -
[2374/2374] SOLINK ./libjingle_peerconnection_so.so
INFO:root:Collecting common files.
INFO:root:Collecting: armeabi-v7a
INFO:root:Collecting: arm64-v8a
INFO:root:Collecting: x86
INFO:root:Collecting: x86_64
できた!
ls -l
ーrw-rw-r-- 1 vagrant vagrant 29M Apr 16 06:53 libwebrtc.aar
macと共有してるフォルダにコピー
cp libwebrtc.aar /vagrant/
vagrant から出て確認。
exit
ls -hl
29M 4 16 15:56 libwebrtc.aar
AndroidStudio に libwebrtc.aar を入れる
参考
AppRTCDemo
- libsフォルダに libwebrtc.aar をコピー
- build.gradle (Module:app) に追記
libsフォルダに libwebrtc.aar をコピー
ここね
build.gradle (Module:app) に追記
// 略
dependencies {
// 略
compile(name:'libwebrtc', ext:'aar')
// 略
}
repositories{
flatDir{
dirs 'libs'
}
}
// 略
使ってみる
実装
アプリケーション
package com.nakadoribooks.webrtcexample;
import android.Manifest;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity {
private static final int REQUEST_CODE_CAMERA_PERMISSION = 1;
private WebRTC webRTC;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// checkPermission → onRequestPermissionsResult → setupWebRTC
checkPermission();
}
private void checkPermission(){
String[] permissioins = new String[]{ Manifest.permission.CAMERA};
ActivityCompat.requestPermissions(this, permissioins, REQUEST_CODE_CAMERA_PERMISSION);
}
@Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
if (requestCode != REQUEST_CODE_CAMERA_PERMISSION)
return;
webRTC = new WebRTC(this);
webRTC.startCapture();
}
}
WebRTC
package com.nakadoribooks.webrtcexample;
import android.app.Activity;
import android.content.Context;
import android.util.DisplayMetrics;
import android.view.WindowManager;
import org.webrtc.Camera2Enumerator;
import org.webrtc.CameraEnumerator;
import org.webrtc.EglBase;
import org.webrtc.MediaStream;
import org.webrtc.PeerConnectionFactory;
import org.webrtc.RendererCommon;
import org.webrtc.SurfaceViewRenderer;
import org.webrtc.VideoCapturer;
import org.webrtc.VideoRenderer;
import org.webrtc.VideoSource;
import org.webrtc.VideoTrack;
/**
* Created by kawase on 2017/04/13.
*/
public class WebRTC {
private PeerConnectionFactory factory;
private VideoCapturer videoCapturer;
private EglBase.Context renderEGLContext;
private Activity activity;
WebRTC(Activity activity){
this.activity = activity;
// rendereContext
EglBase eglBase = EglBase.create();
renderEGLContext = eglBase.getEglBaseContext();
// initialize Factory
PeerConnectionFactory.initializeAndroidGlobals(activity.getApplicationContext(), true);
PeerConnectionFactory.Options options = new PeerConnectionFactory.Options();
factory = new PeerConnectionFactory(options);
factory.setVideoHwAccelerationOptions(renderEGLContext, renderEGLContext);
// setupLocalStream
setupLocalStream();
}
// interface -----------------
public void startCapture(){
_startCapture();
}
// implements -------------
private void setupLocalStream() {
SurfaceViewRenderer localRenderer = setupRenderer();
MediaStream localStream = factory.createLocalMediaStream("android_local_stream");
videoCapturer = createCameraCapturer(new Camera2Enumerator(activity));
VideoSource localVideoSource = factory.createVideoSource(videoCapturer);
VideoTrack localVideoTrack = factory.createVideoTrack("android_local_videotrack", localVideoSource);
localStream.addTrack(localVideoTrack);
VideoRenderer videoRender = new VideoRenderer(localRenderer);
localVideoTrack.addRenderer(videoRender);
}
private void _startCapture(){
DisplayMetrics displayMetrics = new DisplayMetrics();
WindowManager windowManager =
(WindowManager) activity.getApplication().getSystemService(Context.WINDOW_SERVICE);
windowManager.getDefaultDisplay().getRealMetrics(displayMetrics);
int videoWidth = displayMetrics.widthPixels;
int videoHeight = displayMetrics.heightPixels;
videoCapturer.startCapture(videoWidth, videoHeight, 30);
}
private SurfaceViewRenderer setupRenderer(){
SurfaceViewRenderer localRenderer = (SurfaceViewRenderer) activity.findViewById(R.id.local_render_view);
localRenderer.init(renderEGLContext, null);
localRenderer.setScalingType(RendererCommon.ScalingType.SCALE_ASPECT_FILL);
localRenderer.setZOrderMediaOverlay(true);
localRenderer.setEnableHardwareScaler(true);
return localRenderer;
}
private VideoCapturer createCameraCapturer(CameraEnumerator enumerator) {
return createBackCameraCapturer(enumerator);
}
private VideoCapturer createBackCameraCapturer(CameraEnumerator enumerator) {
final String[] deviceNames = enumerator.getDeviceNames();
for (String deviceName : deviceNames) {
if (!enumerator.isFrontFacing(deviceName)) {
VideoCapturer videoCapturer = enumerator.createCapturer(deviceName, null);
if (videoCapturer != null) {
return videoCapturer;
}
}
}
return null;
}
}
設定 / レイアウト
gradle
apply plugin: 'com.android.application'
android {
compileSdkVersion 24
buildToolsVersion "25.0.2"
defaultConfig {
applicationId "com.nakadoribooks.webrtcexample"
minSdkVersion 21
targetSdkVersion 24
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
packagingOptions {
exclude 'META-INF/io.netty.versions.properties'
exclude 'META-INF/INDEX.LIST'
exclude 'META-INF/LICENSE'
exclude 'META-INF/NOTICE'
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile(name:'libwebrtc', ext:'aar')
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
compile 'com.android.support:appcompat-v7:24.2.1'
compile 'com.android.support.constraint:constraint-layout:1.0.2'
testCompile 'junit:junit:4.12'
compile 'io.reactivex:rxandroid:0.24.0'
}
repositories{
flatDir{
dirs 'libs'
}
}
Layout
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.nakadoribooks.webrtcexample.MainActivity">
<org.webrtc.SurfaceViewRenderer
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/local_render_view"
/>
</android.support.constraint.ConstraintLayout>
以上。