WebRTC Android SDK & OpenGL ES 3.0

lyokato
6 min readJun 10, 2017

--

WebRTCのAndroid側のSDKは、現状OpenGL ES2.0前提になっている。

ES3.0は、Android4.3以降からのようなので、OSの普及率考えるとまあ妥当かもしれない。普通に動画を表示している分にはそんな害があるわけでもないし。

ではどんな時に困るかというと、VR連動などをしたいとき。

gvr-unity-sdkなどはES3.0前提になっている。Unityのビルド設定をES30にしなくてはならない。

WebRTCでリモートから取得したビデオフレームをUnity上のTextureに流し込みたい場合、Unity上の描画スレッドとWebRTCの描画スレッド間で、同じバージョンのEGL Contextを共有しなければならない。

そのためWebRTCのAndroid SDKのコードを以下のようにOpenGL ES3.0に対応させていく必要がある。

  1. eglCreateContextのバージョン変更

EglBase14.javaの中で以下のように2がハードコードされているのが分かる

int[] contextAttributes = {EGL14.EGL_CONTEXT_CLIENT_VERSION, 2, EGL14.EGL_NONE};

これを3に変えておく。

int[] contextAttributes = {EGL14.EGL_CONTEXT_CLIENT_VERSION, 3, EGL14.EGL_NONE};

EglBase10.javaにも同様の箇所があるので必要なら変えておく。ES3.0前提なのでEglBase14だけ対応しておけば十分かもしれない。

2. CONFIG配列の設定値の変更

EglBase.javaには

private static final int EGL_OPENGL_ES2_BIT = 4;

というように冒頭でES2用のビット値が与えられていて、この値を片っ端から各コンフィグに設定している。

例えばCONFIG_PLAINは以下のようになっている。

public static final int[] CONFIG_PLAIN = {
EGL10.EGL_RED_SIZE, 8,
EGL10.EGL_GREEN_SIZE, 8,
EGL10.EGL_BLUE_SIZE, 8,
EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, // ES2のビット値が設定されてる
EGL10.EGL_NONE
};

ES3のビット値は64 (0x0040) だ。なので以下のようにES3用の値を準備しておく。

private static final int EGL_OPENGL_ES2_BIT = 4;
private static final int EGL_OPENGL_ES3_BIT = 64;

これを使って、このファイル内の全てのコンフィグ設定を置き換えていく

public static final int[] CONFIG_PLAIN = {
EGL10.EGL_RED_SIZE, 8,
EGL10.EGL_GREEN_SIZE, 8,
EGL10.EGL_BLUE_SIZE, 8,
EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT, // ES3に変更
EGL10.EGL_NONE
};

3. Shaderのversion指定

OpenGL ESのバージョンを3.0にしてしまったので、デフォルトのshaderバージョンが変わってしまい、今まで使われていたshaderがそのままで使えない。とりあえず一番簡単な応急処置は#versionプリプロセッサで100を指定することだ。

例えばGlRectDrawer.javaでは、以下のように色々なshaderが定義されている。

private static final String VERTEX_SHADER_STRING =
"varying vec2 interp_tc;\n"
+ "attribute vec4 in_pos;\n"
+ "attribute vec4 in_tc;\n"
+ "\n"
+ "uniform mat4 texMatrix;\n"
+ "\n"
+ "void main() {\n"
+ " gl_Position = in_pos;\n"
+ " interp_tc = (texMatrix * in_tc).xy;\n"
+ "}\n";

これらの全ての先頭に、以下のようにversion指定をつけていけばよい

private static final String VERTEX_SHADER_STRING = 
"#version 100\n"
+ "varying vec2 interp_tc;\n"
+ "attribute vec4 in_pos;\n"
+ "attribute vec4 in_tc;\n"
+ "\n"
+ "uniform mat4 texMatrix;\n"
+ "\n"
+ "void main() {\n"
+ " gl_Position = in_pos;\n"
+ " interp_tc = (texMatrix * in_tc).xy;\n"
+ "}\n";

4. GLES20 -> GLES30 (Optional)

以下のようにGLES20クラスが使われているところがたくさんある

GLES20.glShaderSource(shader, source);
GLES20.glCompileShader(shader);

これを全てGLES30に置き換えていく

GLES30.glShaderSource(shader, source);
GLES30.glCompileShader(shader);

が、実はbackward compatibilityがあるとのことなので、置き換えなくても大丈夫だと言われている。自分は書き換えてしまっているが。

Pokemon Goのおかげで、Android4.3より前のサポートを外しやすい世界になってきていることもあり、自分の用途ではもうES3.0前提でもいいかな、と考えているので、これらの書き換えを行って使っていく所存。

--

--