👌

③[Android][Kotlin][C++][JNI][OpenGL]動画再生を板ポリ上で実行するサンプルコードを作ってみた。

に公開

第1回 VuforiaでARの初めの一歩
第2回 Vuforiaのサンプルコード(Image Targetのみ)を動かしてみた。
第3回 動画再生を板ポリ上で実行するサンプルコードを作ってみた。
第4回 Vuforiaで動画再生ARを実装してみた。
第5回 Vuforia11.4.4の公式サンプルコードを動かしてみた。
お薦めしません: 第6回 VuforiaのVuMarkを動かしてみた。
お薦めしません: 第7回 Vuforiaで独自VuMarkを作ってみた。←挑戦中 ←無理ゲーすぎた
第8回 Vuforia(Image Target)を独自マーカーで動かしてみた。
第9回 Vuforia(Image Target)を独自マーカーの複数検出させてみた。


板ポリに動画再生って、Androidはライブラリを準備してくれてた。さすがっす。

第3回目 動画再生を板ポリ上で実行するサンプルコードを作ってみた。

Abstruct

  • 板ポリに動画再生のサンプルコードを作ってみた。
  • ポイント説明

※Vuforiaには3Dモデルを認識するModel Targetと、画像を認識するImage Targetってのがあって、この記事はImage Targetの話になります。

背景

こないだVuforiaのの公式サンプルコードが動かなくって、修正版をコミットしたんだけど、動画再生のの公式サンプルがないんよねー。昔はあったと思うのだけど。なので、まずは板ポリ上に動画再生するコードを作ってみた。ExoPlayerって便利なライブラリが助かった。さすがAndroid。おかげで難易度がかなり下がった感じ。動画再生ARへ一歩近づいた。
githubの場所はここ↓
https://github.com/aaaa1597/AndKot-VideoPlaybackPlanePolySampleG

準備

  • android端末(シミュレータでも可)
  • 開発用PC(Android Studioのインストールは済ませておく。)
  • android端末をつないで、デバッグができる様にしておく。

ビルドする。

上記のgithubからソースコードをDL→Android Studioでビルドする。
動くはずだから。

ポイント説明

おおまかな処理の流れ

  1. ExoPlayerで動画を再生。出力先はSurfece。
  2. Surface → SurfaceTextureがOpenGLのテクスチャに転送。
  3. GLSurfaceView.Renderで板ポリに描画。

1. ExoPlayerで動画を再生。出力先はSurface。

まず、ExoPlayerを生成して初期化処理する。該当ソースは下記。

ExoPlayerを生成して初期化処理
    private fun initExoPlayer(context: Context) {
        exoPlayer = ExoPlayer.Builder(context).build().apply {
            val surface = Surface(surfaceTexture)
            setVideoSurface(surface)

            /* res/raw にある動画ファイルを指定 */
            val uri = "android.resource://${context.packageName}/${R.raw.vuforiasizzlereel}"
            Log.d("aaaaa", "uri=$uri")
            val mediaItem = MediaItem.fromUri(uri)
            setMediaItem(mediaItem)

            repeatMode = Player.REPEAT_MODE_ONE /* ループ再生 */
            playWhenReady = true /* すぐに再生開始 */

            addListener(object : Player.Listener {
                override fun onVideoSizeChanged(videoSize: VideoSize) {
                    /* C++側に動画サイズを伝える */
                    nativeSetVideoSize(videoSize.width, videoSize.height)
                }
            })

            prepare()
        }
    }

で、ExoPlayerを再生。

ExoPlayerを再生
    override fun onResume() {
        super.onResume()
        exoPlayer?.play()
    }

2. Surface → SurfaceTextureがOpenGLのテクスチャに転送。

テクスチャに転送する設定をするとあとはいい感じにライブラリ側でやってくれる。

テクスチャに転送する設定
            override fun onSurfaceCreated(gl: GL10, config: EGLConfig) {
                val textureId = nativeOnSurfaceCreated()
                if (textureId < 0)
                    throw RuntimeException("Failed to create native texture")
                surfaceTexture = SurfaceTexture(textureId)
                surfaceTexture?.setOnFrameAvailableListener(object : SurfaceTexture.OnFrameAvailableListener {
                    override fun onFrameAvailable(surfaceTexture: SurfaceTexture?) {
                        synchronized(this) {
                            isFrameAvailable = true
                            _binding.viwGlsurface.requestRender()
                        }
                    }
                })
                CoroutineScope(Dispatchers.Main).launch {
                    initExoPlayer(this@MainActivity)
                }
            }

3. GLSurfaceView.Renderで板ポリに描画。

SurfaceTextureのupdateTexImage()を実行して、C++側関数 nativeOnDrawFrame()を呼出すと描画される。

板ポリに描画
            override fun onDrawFrame(gl: GL10) {
                synchronized(this) {
                    if (isFrameAvailable) {
                        surfaceTexture?.updateTexImage()
                        isFrameAvailable = false
                    }
                }
                nativeOnDrawFrame()
            }

出来た!!
これでVuforiaの動画再生サンプル作りに移れる。

                              「誰かの役に立つと思って」

Discussion