BlogKLabは、多くのスマートフォン向けゲームを開発・提供しています。スマートフォン向けゲームの開発と運用は、Webソーシャルゲームと比べて格段に複雑で、またコンシューマゲーム開発とも異なったノウハウが求められる領域もあります。このブログでは、KLabのゲーム開発・運用の中で培われた様々な技術や挑戦とそのノウハウについて、広く紹介していきます。2016/07/01YUVをちゃんと理解してからRGBにコンバートしましょうねしばらく前に、Windows上でTextureMovie機能の実装をしました。TextureMovieというのは動画形式のファイルからフレームを取得し、デコードした結果をOpenGLやDirectX用のテクスチャへ焼きこんでこれらのレンダリングシステムを使って描画するものです。ここで出たデコードを処理するのはデコーダーで、つまり、何かしらの形式の色情報をRGB(A)に変換するものです。世の中には既成のデコーダーが幾つかありますが、いろいろ事情があって自作という選択肢に至りました。Windowsのことですから、MSが提供している低レベルAPIで何とかなるのかもしれないと考えました。そこで、ほぼRGBとCMYKしか知らない私がいろいろ調べていきました。テクスチャという流れです。(MFT)についていろいろ調べました。悪戦苦闘の末、やっと「YUV」でのデータ出力までたどり着きました(MFTに関してはサンプルや資料が極めて少ないため、結構試行錯誤の連続で.mp4からYUVバッファーの出力までできました。それは別の回に改めて紹介することとし、ここでは割愛します)。いま振り返ると、そこで現れた見知らぬ「YUV」という単語が実に意味深いです。「YUVって何ぞや、RGBの従兄弟なの?」と思いながら、Wikipediaを開きました。YUVやYCbCrやYPbPrとは、輝度信号Yと、2つの色差信号を使って表現される色空間。Wikipedia先生がこう答えてくれました。わからないため、さらにGoogle先生へ答えを求めました。鈍感である」というわけで,色度を抑え、輝度により広い帯域やビット数を割くことにより、少ない損失で効率の良い伝送や圧縮を実現するフォーマット.デジタル画像の圧縮CODECにおけるフォーマットという観点でまとめる.つまり、人間の目をうまく欺いて、データの容量を削減するための圧縮フォーマットと考えればいいでしょう。エンコード(圧縮をかける)したから、デコード(圧縮を解除する)と呼ばれた処理なんだとふっと思いながら、YUVからRGBに変換する方法を探し始めました。ところが、YUVというのは一つの形式ではなく、幾つかの形式の総称だということに気づきました。MSDNから各形式についてこんな説明があります(以下、図を引用します)。見ただけでは最初に文字も図も今ひとつ分からなかったので、読み飛ばして分かるところまで先に進みました。そのページの後半にとても重要な計算式が書いてあります(同ページより引用)。これを手に入れたら、あとはYUVの構造さえ分かれば、変換が可能になります。次に、代表的なフォーマット毎に詳しい説明があります(同ページより引用)。PixelAYUVこのフォーマットは輝度毎に色差信号をサンプリングし、アルファ情報もついています。最高クォリティの画質です。PixelYUY2UYVYこのフォーマットはY0とY1が同じUV(U0、V0)を使っています。YUY2とUYVYの差はY、U、Vの並び順だけです。Pixel※以下のメモリイメージ図はビデオフレームの横幅がY配列の列数と等しく、ビデオフレームの縦幅はY行列の行数と同じです(実際にメモリ上は一次配列扱い。IMC1IMC3このフォーマットは四つのYが同じUVを使います。特徴的な構造として、メモリ上配列でYの値を全部格納してから、Uの配列、Vの配列を置いていることが挙げられます。UとVの配列はYと同じ幅(行と列の比率、ここはややこしい)なので、ややメモリ利用効率が悪そうです。IMC1とIMC3のメモリ構造はほぼ一緒です。唯一異なるのはUの配列とVの配列どちらを先に並べるかです。Pixelこれらのフォーマットは全部四つのYが同じUVを使用しています。違いはメモリ上でのデータ格納方法だけです。IMC2、IMC4(IMC2)この形式の特徴はYの値を全部格納してからUとVの値を交替に格納することです。一行の半分はUの値、残り半分はVの値になります。メモリをより効率的に利用できます。IMC2とIMC4の違いはU配列とV配列どちらが先に置かれるかです。IMC2はNV12以外で最も使われる形式だと書いてあります(つまり、NV12は最も使われているということで、これは扱いやすさゆえでしょう)。YV12正直なところ最初にこの図を見て、IMC1とは何か違うのが分かりませんでした。その後に分かりやすい説明を見つけました(下図は英語版Wikipediaより引用)。YUV420はYV12の別名です。簡単にいうと、メモリ上でみた場合にY、U、Vの配列が全部繋がっています。NV12同じく、分かりやすい説明が見つかりました(同上)。NV12のメモリ構造を見ると、最も頻繁に使われる理由が分かります。UVがセットで来るため、ループでとてもまわしやすい構造です。Yが四つに対し、UVセット一つを使うので、とても自然なプログラムが書けます。ここまで全部読んだら、一番最初の〇と×の図もちゃんと理解できるようになりました。UVということでした。これで.mp4からテクスチャへの色変換の基礎知識が全部揃いました。計算式とメモリ上のデータ取得部分をプログラムへ組み込み、またMFTで試行錯誤して完成にこぎつけました。