LoginSignup
12
13

More than 5 years have passed since last update.

[webRTC for android vol1] android用のライブラリをビルド

Last updated at Posted at 2017-04-14

やること

  • 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 を作る

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 token newline'
==> default: ./install-build-deps-android.sh: line 1:
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">'

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 をコピー

スクリーンショット 2017-04-14 23.55.35.png

ここね

build.gradle (Module:app) に追記

build.gradle
// 略

dependencies {
    // 略
    compile(name:'libwebrtc', ext:'aar')
    // 略
}

repositories{
    flatDir{
        dirs 'libs'
    }
}

// 略

使ってみる

実装

アプリケーション

MainActivity.java
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

WebRTC.java
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

build.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

activity_main.xml
<?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>

以上。

12
13
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
13