カメラやビデオ動画をGPUで画像処理しよう! Adobe AIRのVideoTexture機能の使い方

Adobe AIRには、3D空間にビデオを表示できるVideoTexture機能が備わっています。VideoTexture機能ではビデオ動画をFlashのStage3Dのテクスチャーとして扱えるため、ビデオ動画のStage3Dコンテンツとの共存、および複雑な画像処理が可能になり、コンテンツ表現の幅がさらに広がります。本記事ではVideoTextureを使ってサンプルを作成したので紹介します。まずはサンプルの様子を録画したビデオをご覧ください。

コンテンツを再生するとパソコンが搭載しているカメラの動画をStage3Dのテクスチャーとして画面に表示し、GPU上で画像処理をします。画面右上のコンボボックスを選択すると以下の処理をカメラ動画に対して行います。

  • normal: カメラからの動画をそのまま表示します
  • monochrome: カメラからの動画をモノクロに画像処理して表示します
  • neg: カメラからの動画をネガ(反転)に画像処理して表示します
  • sepia: カメラからの動画をセピア色に画像処理して表示します

本記事のサンプルはGitHubのリポジトリにソースコードとインストーラーを用意していますので、お手元で試したい場合はリポジトリを参考ください。なお、VideoTextureの利用には最新版のAIR SDKが必要となります。

Flash Player/Adobe AIRにおけるビデオの扱いについて

昔のFlash Player/Adobe AIRにおいて、ビデオはVideoオブジェクトで制御していました。従来のVideoオブジェクトでは再生・表示処理はCPUの役割のためCPU使用率が高くなります。そのため、ビデオに対し高フレームレートでリアルタイムに画像処理をするのは現実的ではありませんでした。

2011年リリースのFlash Player 10.2でハードウェアアクセラレーションが有効なStageVideo機能が追加されましたが、ビデオのフレームごとの表示データにアクセスすることができないため、複雑な画像処理を行うことができません。また、StageVideoレイヤーに対してStage3Dレイヤーは透過することができず、StageVideoを表示させたい時は上のレイヤーにあるStage3Dを非表示にするほかありませんでした。

2015年リリースのAdobe AIR 17で追加されたVideoTextureクラスは上記2種類のビデオ再生機能の弱点を克服したビデオ再生方法といえるでしょう。

VideoTextureの使用方法

VideoTextureクラスはビデオファイルを再生するNetStreamオブジェクトと、パソコンのカメラ画像を再生するCameraオブジェクトの2種類の再生表示に対応しています。今回のサンプルで使用したようにCameraオブジェクトをテクスチャーとして扱うには、下記のように記述します。

// Context3Dインスタンスを通してVideoTextureインスタンスを作成します。
var videoTexture:VideoTexture = context3D.createVideoTexture();

// あらかじめ取得したCameraインスタンスをVideoTextureインスタンスにアタッチします。
videoTexture.attachCamera(camera);

// VideoTextureインスタンスがパソコンのカメラとリンクしてStage3DのTextureとして有効になるまで待つため、RENDER_STATEイベントハンドラを設定します。
videoTexture.addEventListener(VideoTextureEvent.RENDER_STATE, videoTexture_renderStateHandler);

NetStreamオブジェクトを再生する場合は、attachCamera()メソッドをattachNetstream()メソッドに読み替えてください。

VideoTextureオブジェクトに渡したCameraオブジェクトの再生準備が整うと、RENDER_STATEイベントが送出されます。以降はStage3DのTextureオブジェクトと同様に扱うことができるため、通常のレンダリング手順にしたがってテクスチャーをポリゴンに貼り付けるなどして使用します。

画像処理の方法

今回のサンプルでは、カメラ動画を再生するVideoTextureに対して簡単な画像処理を行いました。例として、モノクロ化(白黒化)処理を説明します。実際にビデオ表示の各ピクセルに対して画像処理を行っている処理(フラグメントシェーダー)だけ表示すると、下記のようなコードになります。
※コードは「AGAL(エーギャル)」というFlash Stage3Dのシェーダー言語で記述してます。

// [AGAL]
// 変数ft0にバーテックスシェーダーから送られてきたUV座標情報をコピーします。
mov ft0 v0;

// UV座標を格納したft0に応じてVideoTextureを貼り付けます。
tex ft0, ft0, fs0<2d,clamp,linear>;

// 貼り付けたVideoTextureのR(赤)カラー成分とG(緑)カラー成分を加算した値を変数ft1.xに代入します。
add ft1.x, ft0.x, ft0.y;

// 上記の値にB(青)カラー成分を加算します。
add ft1.x, ft1.x, ft0.z;

// 上記2行で計算したRGB合計値を平均するためfc0.xとして予めGPUに送信しておいた値「3」で除算します。
div ft1.x, ft1.x, fc0.x;

// 変数ft0に上記で計算したRGBカラーの平均値(モノクロカラー)を代入します。
mov ft0.xyz, ft1.x;

// 変数ft0に格納されている画像処理済みカラーをディスプレイに出力します。
mov oc, ft0;

処理の内容はVideoTextureオブジェクトの各ピクセルに対してRGBカラーの平均値を出力するだけですが、見てわかるとおり非常に煩雑なコードになっています。Stage3Dでシェーダー言語として使われているAGALはアセンブリ言語なので、プロセッサに実際に行わせる処理1命令につき1行のコードを記述しなくてはなりません。これらのコードはGPUで並列に処理されるためCPUでの処理に比べ非常に高速で、うまく使うことができればCPUでは負荷のために断念せざるを得なかった表現も可能になるでしょう。

Adobe AIR以外のVideoTextureについて

VideoTexture機能は、残念ながら現在のところ利用できるのはAdobe AIRのみで、Flash Playerには対応していません。Adobe Labsにあるβ版のFlash Playerでは以前から対応されてますが、執筆時点では正式リリースには至っていません。2016年4月に発表されたFlash Runtimeのロードマップ(About Flash Runtime 2016)ではUpcoming Priorities(次期機能)として挙げられているので、近々対応するかもしれません。

またFlash Playerと同じく、webでGPUを使用した技術であるWebGLにもActionScript 3.0のVideoTextureクラスと同じ機能があり、HTML5のvideo要素をテクスチャーとして使用できます。WebGLの人気ライブラリの1つ「Three.js」でも対応している機能なので、Webで使用したい場合にはWebGLを検討してみるのもいいかもしれません。

最後に

今回ご紹介したVideoTextureStage3Dで従来表現できなかった(あるいは処理速度等の面で妥協していた)動画表現が可能になり、さらに表現の幅を広げることができる機能です。自分でシェーダーの処理を行おうと思うとそれなりに大変ですが、StarlingAway3DといったStage3DフレームワークでVideoTextureが対応されれば手軽に恩恵を得ることもできるようになるかと思います。今後の各フレームワークの動きにも期待しましょう。

川勝 研太郎

インタラクティブディベロッパー。ゲーム技術、GPUとその周辺技術について日々勉強中。自宅周辺の移動手段は自転車。

この担当の記事一覧