Unity+DeckLinkのHDMI出力の不思議


はじめに

Blackmagic製品を使っていると
「何か色違わない?」
って聞かれます。

特に確認用のリファレンスモニタを決めたり、カラーマネジメントされているモニタを使っているわけではないので見え方はそれぞれの環境で多少違うかもしれませんが、気になると言われると調べないわけにはいかないので…

なおBlackmagicの全ての製品の話ではなく、対象は比較的安価に買えるHDMI出力がついているDeckLinkシリーズです。
Unity Editor上から簡単に映像出力できるので、使っている人はそれなりにいるのかな?

ちなみに映像は専門ではありません。
あくまで現象から対処案を出しただけです。
というか専門の人に教えて欲しいぐらいです…

結論

  • SDIを使いましょう
  • HDMIを使いたいならSDI-HDMI変換を使いましょう

検証環境

  • Windows10 Pro 21H2
  • Unity2020.3.30f1
  • AVProDecklink 1.9.2
  • Blackmagic DeckLink Mini Monitor 4k (Driver 12.2.2)
  • Blackmagic Video Assist 7インチ 12G
  • Blackmagic ATEM Mini Pro ISO
  • Blackmagic Micro Converter BiDirectional SDI/HDMI 3G

近年よくあるUnity Editorの映像をMonitor 4kで送出してATEMに入れる構成です。
まずはATEMは接続せず、Monitor 4kのHDMI/SDI OUTをVideo Assistのそれぞれの入力つなげて両方から収録出来るようにして検証します。

Monitor 4k---(HDMI/SDI)--->Video Assist

検証

Unityでカラーバーと3Dモデルを表示して、HDMIとSDIのそれぞれの出力結果をVideo Assistで収録(コーデックはProRes HQ)して確認します。

ニコニ・コモンズの南部185さん作成のカラーバー画像を使わせて頂きました。
https://commons.nicovideo.jp/material/nc210520

3Dモデルはササリーヌさん
http://aodamatei.sakura.ne.jp/castlevernier/

レンダリングパイプラインはURPです。
3DモデルはUniversal Toon Shader for URP 2.5.0、カラーバーはUnlitで描画しています。
注意点としてはDecklink Outputの設定でPixie Formatは 8-bit ARGBにしてください。8-bit UYVY 4:2:2だとまた別の原因があるのかSDIでも想定した色で出力されていません。

まずはSDIとHDMIのそれぞれの出力結果です。

SDI

HDMI

あれ?確かにちょっと違うような…HDMIの方がちょっと明るい?
差の絶対値で確認すると確かに違う。

SDIとHDMIの差の絶対値

何やら差が出てますねぇ
確認のため、Unity上の画像とSDIの差の絶対値を確認します。

エッジ部分に差が出るものの、全体としてはほぼ同じですね。
どうやらHDMIで出力した場合は指摘された通り「何か色違わない?」出力になっているようです。

拡大して同じ座標の色を確認すると、SDIは想定した色で出ているけどHDMIの方が何か違うぞ…?
例えばSDIのRGB(192,192,192)のところがHDMIだとRGB(205,205,205)になっていますね。

うーん、SDIは問題なくHDMIだけ違うということは…もしかしてHDMI出力のレンジか!?

HDMIは

  • フルレンジ:RGBの範囲は0~255
  • リミテッドレンジ:RGBの範囲は16~235

となっているので、もしHDMI出力がフルレンジで受信側がリミテッドレンジと解釈しているならば明るく表示されそう。

リミテッド→フルの変換はシェーダーで書くと

const float scale = 255.0 / (255.0 - 20.0 - 16.0);
const float offset = 16.0 / 255.0;
float4 col = ターゲット色

return ((col - offset) * scale);

になるので、当てはめて計算するとRGB(192,192,192)はRGB(205,205,205)になりますねw
どうやらビンゴかも。

そこで検証するためにAVProDecklinkのシェーダーを改造します。
といってもAVProDeckLink_toARGB.shaderのフラグメントシェーダーに3行追加するだけです。

float4 frag(v2f i) : COLOR
{
	// ~ 省略 ~

	// 最後にフル→リミテッド変換
	const float scale = (255.0 - 20.0 - 16.0) / 255.0;
	const float offset = 16.0 / 255.0;
	col = (col * scale) + offset;

	return col.argb;
} 

この改造で出力する映像のRGBをリミテッドの範囲にスケールします。
実際にこのリミテッド化したHDMI出力と前のSDI出力と差の絶対値を確認すると差がなくなりました。真っ黒な画像なので完全一致ですね。

これはMonitor 4kのHDMI出力自体はRGBフルレンジですが、どうやらリミテッドレンジと認識されて受信側でリミテッド→フル変換(実際にはフル→フル変換)が走っているようです。

んーどうしてこうなった…

対策

  • 気にしない。もしかしたら実写なら気がつかないかも…
  • シェーダーを改造して自前でRGBリミテッド化してからHDMI出力する。ただしSDI出力も影響を受けてしまう(リミテッドレンジで表示される)
  • SDIのみ使う。一番安全。

とはいえ、ATEMと繋げるならHDMIしかありません。
そこでSDI-HDMI変換を使うとどうなるかも検証しましょう。
SDI-HDMI変換機は各社から出ていますが、今回はBlackmagic Micro Converter BiDirectional SDI/HDMI 3Gを使いました。双方向に変換出来る便利なヤツです。

Monitor 4k---(SDI)--->SDI-HDMI Converter---(HDMI)--->ATEM---(HDMI)--->Video Assist

結果は問題なく表示出来ました。

もちろん自前RGBリミテッド化すれば

Monitor 4k---(HDMI)--->ATEM---(HDMI)--->Video Assist

でも正しく表示できました。でもこれだとSDIが(ry

最後に

HDMIはレンジ問題以外にもケーブルの長さや品質でトラブルを起こすことがあるので、費用はかかりますが出来るだけSDIを使うのが一番確実なのかもしれません。

Blackmagic製品はコストパフォーマンスに優れているので重宝していますが、ちょいちょいやらかしている印象もありますw
それでも今日も検証機材として大活躍!