BlackmagicDesign DeckLink StudioでのリアルタイムHD映像取り込みのレイテンシー

そろそろ始まる年末までのラッシュに向けて、こつこつと準備中。


レイテンシーの検証をするのに、モニターを2枚/ないしはカメラのプレビューとモニターとを並べてiPhoneのカメラで撮影、そのフレームカウントを比較する、という力技。



Blackmagic Design、Decklink Studioを使ってのリアルタイムフルHDの映像の取り込みに取り組んでる。oFで受けるのにarturoc氏の
https://github.com/arturoc/ofxBlackmagicGrabber
を使えば、簡単に取り込めるのだけど、そのままだとレイテンシーが1秒前後あって、リアルタイム性を重要視する場合は実用にならない。BMDの配布してるSDKについてくるサンプルだとレイテンシー1フレームくらいなので、なにか方法があるはず、と探る。

結論としては、取り込んだ映像はそのままだとYUVで、それをRGBへと変換する部分があってそこの処理が重い模様(Xeon 2.8G使ってても3フレーム分くらい)。あとその変換のためにダブルバッファーになってて、それがさらにレイテンシーを酷くしている。BMDのサンプルではCocoa上のPreviewに直接データを送っててどう処理してるのか良くわからない。ただ表示できてんだからなにか方法があるはず。っていうか、YUV形式のままテクスチャに張り込む方法が必ずあるはず。

で、見つけたのがこの記事
http://stackoverflow.com/questions/1080545/how-to-display-a-raw-yuv-frame-in-a-cocoa-opengl-program
GL_YCBCR_422_APPLEのテクスチャ。少しはまったのは、oFで使う場合にofTextureのallocateで形式をGL_YCBCR_422_APPLEに指定するのではなくGL_RGBを指定するということ。allocateする時に指定するのはInternalFormatなので、GL_RGB。loadDataする時に渡すのがGL_YCBCR_422_APPLE。あと忘れちゃいけないのが、allocateした後に、ofTextureのtexData、そのpixelTypeにGL_UNSIGNED_SHORT_8_8_APPLEを指定すること。
とか書いてたら上の記事とちょっと内容が違うな。俺、これ、どこで見つけたんだろ。

とりあえず、arturoc氏のofxBlackmagicGrabber、フレームデータを受けたときのCallback、VideoInputFrameArrivedメソッドの中のyuv2rgbを呼び出している部分やらダブルバッファーのスワップなんかをしている部分をコメントアウトして、単にIDeckLinkVideoInputFramesのインスタンスからunsigned charの配列にフレームのデータをYUVのままコピー、testAppのupdate内で、tex.loadDataするのに最後の引数でGL_YCBCR_422_APPLEを指定すればOK。
あとはfboやらshaderやらreadbackするなり好きにすれば良い。