2018/05/04

もうこれでいい気がする

L-SMASH Works r935

僕はずっとDGIndexを使い続けているのですが、L-SMASHってデコーダ(とは言ってもffmpegに渡すだけ?)もあったんですね。
ずっと、正しいコンテナ実装するぜ!っていうプロジェクトだけだと思ってました・・・

ffmsはtsでフレームアキュレートではないという欠点があったのですが、こちらでは-ss的な何かで正しくなっているのでしょうか。
・・・AAC抽出時の音合わせとかどうすればよいんだろう・・・LWLibavAudioSourceからの再エンコードとか?
まずはちゃんとreadme読むか・・・
→やっぱりちゃんと書いてあった
av_sync
LWLibavVideoSource読み込み時のインデックスファイル(またはファイルを生成せず
内部的に生成したインデックス)で設定された映像ストリームと音声を同期させて、音ズレを防ぎます。
ただし、映像・音声ともに Libav で読み込まれていることが同期条件となります。

先頭フレームが音声の同期ポイントとなりますが、ffmpegを用いてMPEG系映像を表示する場合、先頭GOPのIピクチャ、またはデコードが保証されないBおよびPピクチャが先頭にある場合は最初のIピクチャで代替表示するため、ClosedGOPとOpenGOPでは表示ルールが若干異なります(いずれも音声は同期する)。* 当プラグインは ffmpeg を使用しています。

Libav を用いている場合も先頭フレームが同期ポイントとなりますが、OpenGOP等のようにBピクチャ始まりであってもIピクチャで代替表示せず、壊れていても強制表示します。

=true インデックスファイルで指定されている映像ストリームと音声を同期します
=false 音声を同期させません(デフォルト)
DGIndexは先頭GOPのBフレーム部分をフレーム数として数える、という特徴があるのですが、それと同じ?

とか思っていたのでですが、 何かが違う・・・
どうも、DGIndexは完全なGOPからしか始まらない?のに対し、L-SMASHは上述の通り不完全なGOPからでも始まるようです。

先頭フレーム例
d2v:     BBIBBPBBPBBPBBP
lwi:PBBP BBIBBPBBPBBPBBP
gl :       IBBPBBPBBPBBP

サンプルのtsではDGIndexはlwiでkey=1となっているGOPから始まっているのに対し、l-smashはその1つ前のGOP(の一部)が存在するので。lwi(とソース)を眺める限りではpic=1がIフレーム、pic=2はPフレーム、pic=3はBフレームのようです。
音合わせはL-SMASHでデコードしたものを再エンコードするか、PTSを見て合わせるのが確実なんでしょうね。
ではそのためのスクリプトを作らねば。はて・・・どうしてこうなった・・・

あと、lwiを眺めていて知ったのですが、tsはPTS(再生時間)ではなく、DTS(デコード時間)の順番でデータが詰め込まれているようです。
Bは前後のPorIがないとデコードできないため、BBIBBPはIBBPBBとでいう順でデコードされます。

再生順に並べたとき
PTS  123456789ABCDEF
     BBIBBPBBPBBPBBP
DTS  120453786AB9DEC

デコード順に並べたとき(tsに入ってる順番)
PTS 312645978CABFDE
    IBBPBBPBBPBBPBB
DTS 0123456789ABCDE

ということはみんなPTSでは"BBIBBPBBPBBPBBP"、DTSでは"IBBPBBPBBPBBPBB"という並びで話をしているんでしょうね。
どっちも"BBIBBPBBPBBPBBP"になってるといえばそうなのですが・・・。
そんなことを考えていると、完全なフレームを得られるところから始めるm2vの実装も、存在するフレームからデコードするというL-SMASHも、GOP単位で考えようというDGIndexの考え方も、どれも正しいような。考え方の違いでしょうね。
いや、なんでこんなことを考え出したかというと、TSに入ってるフレーム(DTS)がBBIBB・・・で始まったときに5フレーム目まで正しい映像が出てこない、というのはなんでだろうと思ったので。(3つ目で完全なフレームが得られるのかと思ってた)


 ■速度

で、DGDecodeとm2vとLWLibavVideoSourceで比べてみた結果、速度的にはL-SMASH  > m2v > DGDecodeといった感じ。
・・・あれ?昔調べた限りではm2vよりDGDecのが早かった気がしたけど・・・
→再確認したところ、実際にフィルタをかけて速度を測るかどうかでなんか違う・・・
フィルタなし
 -DGDec     :248.398
 -m2v         :212.956
 -L-SMASH :915.274

フィルタ(TFM,TDecimate,FluxSmoothT,Spline144Resize,dfttest,unsharpHQ)あり
 -DGDec    :24.384
 -m2v        :25.673
 -L-SMASH:26.958

単体の速度とフィルタ時の速度がDGdecとm2vで逆転する・・・何故だ・・・並列処理ができるかどうかかな・・・?

追加でx264に突っ込んだ時もやってみた。

 -DGDec    :23.77
 -m2v        :24.16
 -L-SMASH:26.05
・・・やっぱりよくわからん。m2vとDGDecの差は誤差ですかね。とりあえずL-SMASH(というかffmpeg?)が早いということはわかります。


■音合わせ模索中

映像フレームの数え方メモ
  L-SMASH:先頭フレーム(フレームがたとえ不完全なGOPでも)からカウントスタート
  DGIndex:完全な(Iフレームがある)GOPの先頭からカウントスタート。なんとなくBBIBBPBBPBBPBBPがデフォな気がするので、Iフレームの2フレーム前から始まりそうな。
  m2v:(ちゃんと確認してませんが)多分Iフレームからカウントスタート
だと思う・・・多分


ts→aacで出てくるaacの同期ポイント
  ts2aac -e 0では最初のIフレームから。
  ts2aac -B -e 0では最初のIフレームからBフレームまで遡ったところから。上述の理由で大抵2フレーム分遡るような

ということで、
  1.適当なavsでlwiを吐かせ、先頭フレームのPTSを得る
  2.ts2aacでaacを吐かせて、表示から出力されたaacのPTSを得る
  3.aacのPTSとlwiの映像のPTSを比較してdelayを計算する(なんとなくプラスの値になりそうな)
  4.delayをaacの名前に反映させる
でOKかな?
・・・ LWLibavVideoSourceに先頭フレームをIフレーム(もしくはDGIndex互換)にするようなオプションがあればいいんですが・・・。
AudioSourceの方もずらす必要がありますし、そもそもそういうもの(tsに特化したフィルタ)ではないので仕方のないところでしょうか。
ソースをちゃんと読み切る能力もないですし、そのうちスクリプトを作ってみましょう

0 件のコメント:

コメントを投稿