僕はずっとDGIndexを使い続けているのですが、L-SMASHってデコーダ(とは言ってもffmpegに渡すだけ?)もあったんですね。
ずっと、正しいコンテナ実装するぜ!っていうプロジェクトだけだと思ってました・・・
ffmsはtsでフレームアキュレートではないという欠点があったのですが、こちらでは-ss的な何かで正しくなっているのでしょうか。
・・・AAC抽出時の音合わせとかどうすればよいんだろう・・・LWLibavAudioSourceからの再エンコードとか?
まずはちゃんとreadme読むか・・・
→やっぱりちゃんと書いてあった
av_syncDGIndexは先頭GOPのBフレーム部分をフレーム数として数える、という特徴があるのですが、それと同じ?
LWLibavVideoSource読み込み時のインデックスファイル(またはファイルを生成せず
内部的に生成したインデックス)で設定された映像ストリームと音声を同期させて、音ズレを防ぎます。
ただし、映像・音声ともに Libav で読み込まれていることが同期条件となります。
先頭フレームが音声の同期ポイントとなりますが、ffmpegを用いてMPEG系映像を表示する場合、先頭GOPのIピクチャ、またはデコードが保証されないBおよびPピクチャが先頭にある場合は最初のIピクチャで代替表示するため、ClosedGOPとOpenGOPでは表示ルールが若干異なります(いずれも音声は同期する)。* 当プラグインは ffmpeg を使用しています。
Libav を用いている場合も先頭フレームが同期ポイントとなりますが、OpenGOP等のようにBピクチャ始まりであってもIピクチャで代替表示せず、壊れていても強制表示します。
=true インデックスファイルで指定されている映像ストリームと音声を同期します
=false 音声を同期させません(デフォルト)
とか思っていたのでですが、 何かが違う・・・
どうも、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 件のコメント:
コメントを投稿