ハイライト
VideoToolbox には低遅延 H.264 ハードウェアエンコードモードが追加され、フレーム並べ替えをなくし、ビットレートコントローラがネットワーク変化へ素早く適応できる。720p@30fps では約 100ms の遅延を削減でき、時間方向スケーラビリティと長期参照フレームにも対応する。
主な内容
ビデオ会議アプリを開発している。ユーザーから、会話に遅延があり、互いに話を遮ってしまうというフィードバックがあった。遅延はどこから来るのだろうか。
動画エンコーダ内部には通常、フレーム並べ替えバッファがある(B-frame で圧縮効率を高めるため)。これにより 3-5 フレームの遅延が発生する。ビットレートコントローラのネットワーク変化への応答も比較的遅い。これらが重なると、エンドツーエンドの遅延は 200ms を超えることがある。
VideoToolbox の新しい低遅延モードは、この問題に特化している。
詳細
低遅延モードの仕組み
(02:05)
低遅延モードには 2 つの重要な最適化がある。
- フレーム並べ替えをなくす。1 入力 1 出力のエンコードモードを採用し、各フレームは入力後すぐにエンコードして出力され、後続フレームを待たない。
- 高速なビットレート適応。ビットレートコントローラがネットワーク変化へより速く応答し、輻輳による遅延を減らす。
720p@30fps の動画では、低遅延モードにより約 100ms の遅延を削減できる。これはビデオ会議では非常に重要だ。
(03:14)
キーポイント:
- 低遅延モードは常にハードウェアアクセラレーションエンコードを使う
- H.264 エンコードのみをサポートする
- iOS と macOS の両方でサポートされる
- 圧縮効率はデフォルトモードよりわずかに低いが、遅延は大きく下がる
低遅延モードを有効にする
(05:03)
有効化は簡単で、compression session の作成時に flag を 1 つ設定するだけだ。
var encoderSpecification: CFMutableDictionary = CFDictionaryCreateMutable(
kCFAllocatorDefault,
0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks
)
// 低遅延ビットレート制御を有効にする
CFDictionarySetValue(
encoderSpecification,
kVTVideoEncoderSpecification_EnableLowLatencyRateControl,
kCFBooleanTrue
)
// compression session を作成
let session = VTCompressionSessionCreate(
allocator: kCFAllocatorDefault,
width: 1280,
height: 720,
codecType: kCMVideoCodecType_H264,
encoderSpecification: encoderSpecification,
imageBufferAttributes: nil,
compressedDataAllocator: nil,
outputCallback: outputHandler,
refcon: &context,
compressionSessionOut: &session
)
// ビットレートを設定(通常と同じ)
VTSessionSetProperty(
session,
key: kVTCompressionPropertyKey_AverageBitRate,
value: 2000000 as CFNumber // 2 Mbps
)
(05:03)
キーポイント:
kVTVideoEncoderSpecification_EnableLowLatencyRateControlで低遅延モードを有効にする- その他の設定(ビットレート、解像度)は通常と同じ
- エンコーダは自動的にハードウェアアクセラレーションを使用する
- 出力コールバックでエンコード済みフレームを受け取る
新しい Profile のサポート
(06:10)
低遅延モードには 2 つの profile が追加された。
- Constrained Baseline Profile (CBP):低コストのアプリ向けで、互換性が最も高い
- Constrained High Profile (CHP):圧縮効率が高く、帯域幅が限られる場面に適している
// Constrained Baseline Profile を使用
VTSessionSetProperty(
session,
key: kVTCompressionPropertyKey_ProfileLevel,
value: kVTProfileLevel_H264_ConstrainedBaseline_AutoLevel
)
// Constrained High Profile を使用
VTSessionSetProperty(
session,
key: kVTCompressionPropertyKey_ProfileLevel,
value: kVTProfileLevel_H264_ConstrainedHigh_AutoLevel
)
(07:35)
キーポイント:
- CBP は互換性が最も高く、ほぼすべてのデコーダでサポートされる
- CHP は圧縮効率がより高い
- 相手側のデコード能力に応じて profile を選ぶ
AutoLevelにより、エンコーダが level を自動選択する
時間方向スケーラビリティ
(07:54)
多人数のビデオ会議では、受信者ごとに利用できる帯域幅が異なる。従来の方法では受信者ごとに別々のストリームをエンコードするため、効率が低い。
時間方向スケーラビリティでは 1 つのストリームだけをエンコードし、フレームを 2 つのレイヤーに分ける。
- Base layer:半分のフレームレートを含み、単独でデコードできる
- Enhancement layer:補完フレームを含み、base layer と組み合わせて完全なフレームレートを提供する
// base layer のフレームレート比率を設定
VTSessionSetProperty(
session,
key: kVTCompressionPropertyKey_BaseLayerFrameRateFraction,
value: 0.5 as CFNumber // フレームの半分を base layer へ割り当てる
)
// base layer のビットレート比率を設定
VTSessionSetProperty(
session,
key: kVTCompressionPropertyKey_BaseLayerBitRateFraction,
value: 0.6 as CFNumber // ビットレートの 60% を base layer へ割り当てる
)
(11:15)
キーポイント:
- base layer のフレームレートは入力の半分
- base layer のビットレートは総ビットレートの 60%-80% が推奨される
- 低帯域幅の受信者は base layer だけを受け取る
- 高帯域幅の受信者は base + enhancement layer を受け取る
- enhancement layer のフレーム損失は他のフレームに影響しない
最大フレーム量子化パラメータ
(12:26)
フレーム QP(Quantization Parameter)は画質とビットレートを制御する。QP が低いほど画質は高くなり、ビットレートは大きくなる。
低遅延モードでは、許可する最大 QP を設定し、複雑なシーンでエンコーダが画質を過度に下げるのを防げる。
VTSessionSetProperty(
session,
key: kVTCompressionPropertyKey_MaxAllowedFrameQP,
value: 30 as CFNumber // QP の上限は 30
)
(14:22)
キーポイント:
- QP の範囲は 1-51
- 上限を設定すると、エンコーダはそれより高い QP を使用しない
- ビットレート予算が不足した場合、エンコーダは画質を下げるのではなくフレームを落とす
- 画面共有など、文字の鮮明さが必要な場面に適している
長期参照フレーム(LTR)
(14:45)
ネットワークでパケットロスが発生すると、デコーダはリフレッシュフレームを要求する必要がある。従来の方法では I-frame(キーフレーム)を送信するが、I-frame は大きく、ネットワーク状態が悪いと輻輳を悪化させる可能性がある。
LTR は、より小さな予測フレーム(LTR-P)を使って I-frame の代わりにリフレッシュを行う。
// LTR を有効にする
VTSessionSetProperty(
session,
key: kVTCompressionPropertyKey_EnableLTR,
value: kCFBooleanTrue
)
// エンコーダは出力内で確認が必要な LTR フレームをマークする
// アプリケーション層が確認を受け取ったら、AcknowledgedLTRTokens でエンコーダへ通知する
// リフレッシュフレームを要求する
VTSessionSetProperty(
session,
key: kVTCompressionPropertyKey_ForceLTRRefresh,
value: kCFBooleanTrue
)
(17:07)
キーポイント:
- LTR フレームは通常の P-frame より少し大きいが、I-frame よりははるかに小さい
- アプリケーション層はフレーム確認とリトライロジックを担当する
- 確認済みの LTR がない場合、エンコーダは I-frame にフォールバックする
- ネットワークが不安定な場面に適している
重要ポイント
-
ビデオ会議アプリで低遅延エンコードを有効にする。1 行の設定で遅延を約 100ms 削減できる。主な API:
kVTVideoEncoderSpecification_EnableLowLatencyRateControl。 -
時間方向スケーラビリティで多人数会議を最適化する。1 つのストリームで帯域幅の異なる受信者に対応でき、複数ストリームをエンコードするより省電力。主な API:
kVTCompressionPropertyKey_BaseLayerFrameRateFraction。 -
画面共有向けに最大 QP を設定する。複雑なシーンで文字や UI がぼやけるのを防ぐ。主な API:
kVTCompressionPropertyKey_MaxAllowedFrameQP。 -
LTR で低品質ネットワークからの回復力を高める。パケットロス後は LTR-P フレームでリフレッシュし、I-frame より早く到達する。主な API:
kVTCompressionPropertyKey_EnableLTR。 -
相手側のデコード能力に応じて profile を選ぶ。ローエンドデバイスとの通信には CBP、ハイエンドデバイスとの通信には CHP を使う。主な API:
kVTCompressionPropertyKey_ProfileLevel。
関連セッション
- What’s new in AVFoundation — AVFoundation の非同期プロパティ読み込み新 API
- Evaluate videos with the Advanced Video Quality Tool — AVQT 動画品質評価ツール
- Edit and play back HDR video with AVFoundation — AVFoundation による HDR 動画の編集と再生
コメント
GitHub Issues · utterances