映像の送受信と描画

映像を送受信する

カメラの映像を取得する

カメラの映像を取得するキャプチャー (org.webrtc.CameraVideoCapturer) は jp.shiguredo.sora.sdk.camera.CameraCapturerFactory のコンパニオンオブジェクトの create() を呼ぶと取得できます。

create() の定義は次の通りです:

fun create(context: android.content.Context,
           fixedResolution: Boolean = false,
           frontFacingFirst: Boolean = true) : org.webrtc.CameraVideoCapturer?
  • context: アプリケーションコンテキスト。 Activity オブジェクトを渡します。

  • fixedResolution: true であれば解像度の維持を優先します。 false であればフレームレートの維持を優先します。デフォルトは false です。

  • frontFacingFirst: true であれば前面カメラを優先します。 false であれば背面カメラを優先します。デフォルトは true です。

使用例:

class MainActivity : AppCompatActivity() {

  fun start() {
    capturer = CameraCapturerFactory.create(this)
    ...
  }

}

サーバーに接続して映像を送受信する

SoraMediaOption で接続の設定を行い、 SoraMediaChannel を使ってサーバーに接続します。 SoraMediaOption の主な設定内容を次に示します。 デフォルトの設定はいずれも無効です。

  • enableVideoUpstream(): 映像を送信します。引数にキャプチャーと OpenGL ES コンテキストを与えます。

  • enableVideoDownstream(): 映像を受信します。引数に OpenGL ES コンテキストを与えます。

  • enableAudioUpstream(): 音声を送信します。

  • enableAudioDownstream(): 音声を受信します。

  • videoCodec: 映像コーデックを指定します。デフォルトは VP9 です。

  • videoBitrate: 映像ビットレートを指定します。

  • audioCodec: 音声コーデックを指定します。デフォルトは OPUS です。

  • audioBitrate: 音声ビットレートを指定します。

  • enableMultistream(): マルチストリームを有効にします。

  • enableSimulcast(): サイマルキャストを有効にします。

例:

val option = SoraMediaOption().apply {
  enableVideoUpstream(capturer, egl.eglBaseContext)
  enableAudioUpstream()
  ...
}

// 接続して映像を送受信する
val mediaChannel = SoraMediaChannel(
              context           = this,
              signalingEndpoint = BuildConfig.SIGNALING_ENDPOINT,
              channelId         = BuildConfig.CHANNEL_ID,
              mediaOption       = option,
              listener          = channelListener)
mediaChannel!!.connect()

映像を描画する

Sora Android SDK は基本的に libwebrtc の API を隠蔽していますが、映像の描画には直接 libwebrtc の API を使う必要があります。

UI コンポーネント

映像を描画する UI コンポーネントは org.webrtc.SurfaceViewRenderer です。 SurfaceViewRendererandroid.view.SurfaceView のサブクラスであり、 OpenGL ES を利用して映像を描画します。

レイアウト

SurfaceViewRenderer は一般的なレイアウトと同様に XML ファイルでレイアウトを定義できます。

次に例を示します:

<LinearLayout
    android:id="@+id/renderers"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:padding="20dp">

    <org.webrtc.SurfaceViewRenderer
        android:id="@+id/localRenderer"
        android:layout_width="match_parent"
        android:layout_height="300dp"/>

    <org.webrtc.SurfaceViewRenderer
        android:id="@+id/remoteRenderer"
        android:layout_width="match_parent"
        android:layout_height="300dp" />
</LinearLayout>

初期化と終了処理

SurfaceViewRenderer で映像を描画する際は、明示的な初期化と終了処理を行う必要があります。 映像の描画を行う前に init() を呼び出して初期化し、 SurfaceViewRenderer を使い終えたら release() を呼び出して終了処理を行います。 終了処理を忘れるとリソースがリークする原因になります。

init() は OpenGL ES の API である android.opengl.EGLContext を引数に取ります。 EGLContextorg.webrtc.EglBase のプロパティであり、他にも様々な箇所で使います。

EglBase は OpenGL ES のレンダリングコンテキストを保持するオブジェクトです。 こちらも使い終えたら release() で終了処理を行う必要があります。

一般的には、アクティビティの生成時に EglBase の生成と SurfaceViewRenderer の初期化を行い、アクティビティの終了時に両方の終了処理を行うとよいでしょう。 次に例を示します:

class MyActivity : AppCompatActivity() {

  private val egl:EglBase? = null;

  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    egl = EglBase.create()
    // その他の初期化
  }

  // UIの組み立てが終わった直後にこのメソッドを呼ぶようにする
  fun initRenderers() {
    // localRenderer, remoteRenderer は XML ファイルで定義済み
    localRenderer.init(egl.eglContext, null)
    remoteRenderer.init(egl.eglContext, null)
  }

  // このメソッドを最後に必ず呼ぶようにする
  fun releaseRenderers() {
    localRenderer.release()
    remoteRenderer.release()
    egl.release()
  }
}

動画の左右を反転する

setMirror() を呼ぶと動画の左右を反転させることができます。

例:

localRenderer.setMirror(true)

キャプチャーの操作

キャプチャーを開始する

映像のキャプチャーを開始するには startCapture() を呼びます。

キャプチャーを停止する

キャプチャーを停止するには stopCapture() を呼びます。

キャプチャーのフォーマットを変更する

changeCaptureFormat() を使うと、キャプチャーした映像のサイズとフレームレートを変更できます。