2023年1月18日水曜日

インターレースとプログレッシブの混成ファイルの扱い方

60i + 24p

 何とは言いませんが、30fps[29.97fps]インターレース(=60i)24fps[23.976fps]プログレッシブ(=24p)混成構成であるmpeg2を扱うことになりました※1。
 AviutlやAvisynthで普通に読み込みはできるものの、デインターレースや逆テレシネ化を行うとフレームレートないしビデオ長が狂って正しい成果物を得ることができずかなり悩みました。今回それを自力解決できたので記します。
 ちなみに下記の内容は「インターレース解除せずにプログレッシブにしちゃった」系のエセインターレースに対処するものではありません。
 
※1 正しくは今回の24pは48iの内部構造でありインターレースの一種と捉えられるが、実際の挙動と説明上の簡便さを踏まえプログレッシブと表現する。

対象とする環境

入力:
 60iと24pの混成mpeg2
 
動画編集ソフト:
 Aviutl、Avisynth
 
デコーダプラグイン:
 L-SMASH Works
 

原因

 デコーダ段階では混成フレームレートを正しく認識して処理されるものの、後続のフィルターではプログレッシブなのかインターレースなのか正確に判定する術がないため、フレームレートかビデオ長が狂います。フレームレートが狂うと言っても、可変フレームレートになるのではなく、少ないフレームを実ビデオ長に伸長するので音ズレが顕著になります。
 

対処法

Aviutl

「ファイル」「環境設定」「入力プラグインの設定」「L-SMASH Works... の設定」
Apply repeat flag」にチェックを入れる。ついでに「Field dominance」をTop->Bottomに。
そして動画を読み込み直す。

Avisynth

LWLibavVideoSource関数のパラメータに「repeat=true,dominance=1」を付与。

(RFF出てくる際のフィールドオーダーはどうせTFFなのでTopBottomで固定していいと思う)

詳しい解説

 MPEG2のフレーム(正確には拡張ピクチャヘッダ)にはプログレッシブをインターレースの形式で扱うためのRFF(Repeat First Field)というフラグがあります。
 通常、30pを60iにする際は1フレームを2フィールドに分割しますが、24pを60iにする際はそのまま2分割しても48iで足りないため、3-2プルダウンと言って各フレームを3フィールドないし2フィールドに分割して、2フレームから5フィールドを作ることで60iにかさ増しする戦法を取ります(テレシネ化)。なお、24pからかさ増しされた60iを再生機サイドでインターレース解除しても生成されるのは30pであり、24pにするには無駄なフレームを間引きしなくてはいけません。これが逆テレシネ化です。
 テレシネ化は、60iにするためだけに貴重なビットレートを割いて冗長なフレームを作り出す明らかに無駄な作業です。そこで、24pを実データ48iとして送出して、再生機サイドでテレシネ化して60iにするなり24pに戻すなりする方法があります。こういうフレームのマーカーとして機能するのがRFFです。
 RFFがついているフレームは、Repeat First Fieldの名前の通り、最初のフィールドを3フィールド目に転用します。フレームの半数にRFFがあると、ちょうど2フレームから5フィールドを生成できるので再生機サイドで60フィールド/秒を再現できます。また、RFFを無視すると2フィールドから1フレームを合成して24pに戻すこともできます。
 L-SMASH Worksのデフォルト設定では「Apply repeat flag」がオフになっているためプログレッシブにしてくれます。しかし60iと24pが混在して件のような困った状況になります。ゆえにオンにすることで、RFFのある区間も60iに変換され、全体が60iのごく普通の動画として扱えるようになるのです。結局24p化するので無駄な作業といえばそのとおりなのですが、扱いやすには天地の差があります。