どんぶらアニマル さんぽ道

CBR250RR(MC22)とNSR80(HCO6)とAPE50(AC16)を中心とした備忘録。

TSを(実用的に)再生できるようにVLCを改造:スキップ(シーク)対応

 
前回、VLCのビルドができたので、MPEG2-TSを再生するにあたって不便な点を改修する。
以下の(自分にとって)優先度の高い項目からやっつける。
 
・スキップ(±15秒、±1分、±3分)ができるようにする(今回はこれ)
・ジューム再生の対応
・ワンセグ的サブストリームが再生されるコンテンツの対策
・音声多重(デュアルモノ)の切り替えの対応
・音の出ないコンテンツの対策
 
 
VLCのTS再生でスキップ

この先でスキップボタンと呼んでいるのは上記の再生/一時停止ボタンの左右にあるボタンのこと。

スキップ(15秒、1分、3分)ができるようにする

ネットワーク経由のMPEG2-TSはdurationが得られない故にスキップボタンが機能しないので有効化する。
ローカルのファイルの場合は、ファイルをスキャンしてdurationを取得してるっぽいが、ネットワーク経由だと時間がかかるのでやらない仕様の模様。
とは言え、DLNAの場合はDMSがタイムベースシークに対応している場合はresourceにdurationが存在するのでそれを使えばいい。で、我が家のDMSを再確認したら全てバイトレンジベースになってたのでこの方法は不採用。
 
バイトレンジの場合、ビットレートからシーク先のファイル位置を推定し、そこが目的位置とずれていたら再取得して目的位置を探しだすが、VLCはHTTPの取得部とdemuxerが別モジュールになっているのでdemuxerで取り出したDTS、またはPTSからHTTP部に再取得を依頼するにはいくつもの壁を乗り越える必要があり、VLCの作りを全く知らないところから始めるにはとても時間がかかりそうなので今回は不採用。
 
オリジナルの状態でもfast seekを有効にするとシークバーにフォーカスしてのシークはdurationの約5%単位でのシークができているので、これを利用する方法を試してみる。
(シークバーの再生表示位置とコンテンツの位置が合ってるのでVLCはどこかに時間の情報を持ってるはずなんだけどなぁ。。。)
 
実際の制御の考え方は、シークバーの1ステップが何秒に相当するかを算出し、現在のシークバーの位置にスキップしたい時間に相当するステップ数を加算し、シークバーを自動的に動かすというもの。
目標位置 = 現在のシークバーのステップ位置 + スキップ時間 / 1ステップあたりの時間
 
スキップ時間に相当するステップ数の導き出し方は下記になる。
1ステップあたりの時間 = (現在の時間 / 現在のステップ位置)
 
オリジナルのfast seekはDTSやPTSを使わず、ビットレート等からファイル位置を推定して動いているのでアナウンス通り精度が低い。更にシークバーのmaxは1,000ステップとなっていて、1時間番組だと
1ステップあたりの時間 = (1 × 60 × 60)秒 / 1,000ステップ = 3.6秒
となり、最大3.6秒の誤差が生じる。
 
そこで、できるだけ簡単に精度を上げるため、maxステップ数を100倍の100,000に変更した。
これで1時間番組は
1ステップあたりの時間 = (1 × 60 × 60)秒 / 100,000ステップ = 0.036秒
となり、8時間番組でも
1ステップあたりの時間 = (8 × 60 × 60)秒 / 100,000ステップ = 0.288秒
となり、実用上1秒の精度は維持できる。
あくまで、ステップ位置の算出精度であり、実際の位置の精度は別問題。
 
圧縮された上に多重化までされたTSのfast seekでは位置だしの精度に限界があるけど、まあ許せる程度の動きはするようになった感じ。実際、コンテンツやコンテンツの位置によって変わるが15秒スキップは概ね±5秒程度の精度。コンテンツの先頭付近は理論通り精度が低く、10秒以上ずれることがあるが、終わりに近づくにつれて精度が上がる傾向にある。しばらく運用して使い物になるか様子を見る。
 

使い方/仕様

VLCには以下の設定をしておく。
「設定」→「ビデオ」→「高速シークを常に使用」をオン
 
テレビのリモコンを使う上で、いちいちOSDを出してスキップボタンにフォーカスしてクリックなんてやってられないので以下のようにダイレクトボタンを割り当てた。(スマホでデバッグするためにUSBテンキーでも動かせるようにキーを割り当ててる)
 
・早送りボタン:+オリジナルの「制御設定」→「進める/戻るの遅延時間」の設定時間
・早戻しボタン:ーオリジナルの「制御設定」→「進める/戻るの遅延時間」の設定時間
・青ボタン:+1分(10キーの3)
・赤ボタン:-1分(10キーの7)
・緑ボタン:+3分(10キーの9)
・黄ボタン:-3分(10キーの1)
 
難点は色ボタンが他のボタンと遠いこと。。。
長時間番組でもっと粗くスキップしたい場合はシークバーを使う。
長押しは考慮していない。
 
上記ボタン操作をするとOSDを表示し、「制御設定」→「ビデオプレーヤが隠れた遅延を制御」の設定時間経過後にOSDは消える。
 

コード

結果的にはJava側だけで対処したが、最初はPTSを見てずれていたら再取得をする方法も試そうとしてnative側もいろいろいじって、実験コードの残骸や、失敗したコード、デバッグコードなどが散在しているので整理してから。。。
 
 
 
気が向いたら感想をお願いします。(ログイン不要、ボタンを押すだけです)