プログラムの素

スマートフォンアプリ開発に携わっているペーペープログラマのブログです

【iOS】【Android】動画をOpenGL ESで描画する方法

iOSAndroidで動画をOpenGL ESで描画したかったのでその方法を調査しました。

iOSの場合

iOSiOS Dev Centerにこれを実現するためのサンプルコードが提供されていました。

Real-time Video Processing Using AVPlayerItemVideoOutput

ミソはAVPlayerItemVideoOutputというクラスです。

このクラスを使用すれば任意の時間のCVPixelBufferRefというバッファデータが取得できます。
このバッファデータが任意の時間における動画の画像情報となります。

このCVPixelBufferRefのオブジェクトから、CVOpenGLESTextureCacheCreateTextureFromImage()関数でCVOpenGLESTextureRefオブジェクトを取得し、これをCVOpenGLESTextureGetTarget()関数の引数に指定する事によって、OpenGLにおけるテクスチャIDが取得できます。

取得したテクスチャIDでテクスチャをバインドさせる事により、動画から取得した画像データが使用できます。

ちなみに、サンプルコードではAVPlayerItemVideoOutputからYUV420形式で画像データを取得しており、フラグメントシェーダーでは2枚のテクスチャ(Y情報とUV情報のテクスチャ)からRGBへと変換して描画していました。

ちなみに余談ですが、OpenGL ESでなくMetalでも動画を描画する事が可能みたいです。

MetalVideoCapture

Androidの場合

AndroidではGitHubにアップされていた以下のサンプルコードを参考にさせていただきました。

crossle/MediaPlayerSurface · GitHub

また実装してから気づいたのですが、以下のサイトのページがすごいまとまっていました。

SurfaceTextureでMediaPlayerやカメラ映像をOpenGLテクスチャとして使う場合の注意点 - eaglesakuraの技術ブログ

AndroidではMediaPlayerSurfaceTextureの組み合わせで実現が可能でした。

このSurfaceTextureというクラスですが、OpenGL ESのテクスチャとして動画のデータを取得できるみたいです。

注意点としては、OpenGL ESのExtension機能が使用されている点です。
テクスチャターゲットにはGL_TEXTURE_2Dの代わりにGL_TEXTURE_EXTERNAL_OESを使用しなければなりません。

またフラグメントシェーダーでは先頭行に#extension GL_OES_EGL_image_external : requireを記述して、サンプラーのタイプをsamplerExternalOESで指定する必要があります。

詳細は上記のサンプルコードやサイトを参考にしてみてください。