読者です 読者をやめる 読者になる 読者になる

ぬうぱんの備忘録

技術系のメモとかいろいろ

作った曲一覧はこちら

ffmpeg(libav)でシークする時の注意点

C++ トラブルシューティング ffmpeg

何があった

libavformatとかあそこらへんのAPIを触っていて動画の読み込みをしている時の話。
任意秒にシークした直後、Iフレームが来るまで正常に映像がデコードされないという問題が起きた。
絵面としては黒画面をベースに差分だけが表示される感じ。

解決法

``av_seek_frame(format_context, video_stream, time_stamp, AVSEEK_FLAG_BACKWARD);''でシークした直後に``avcodec_flush_buffers(codec_context);''を呼び出してデコーダの状態を初期化する必要がある。チュートリアルにそんなの書いてなかった(小並感)
その後普通に``av_read_frame(format_context, packet);''から始まる読み込み&デコードするコードを走らせれば正常にデコードされる。
なお、何処かで見た説明では``AVSEEK_FLAG_BACKWARD''を指定すると指定タイムスタンプ直近のIフレームまで遡ってそこからデコードが始まる(直後のav_read_frameではその遡った所のパケットが読み込まれる)みたいな感じだった気がするが、実際には指定タイムスタンプピッタリからデコードが始まる気がする。気のせい?

感想

コンテキストという形で状態持ってるし内部状態クリーンするのは当たり前といえば当たり前なんだけど、seek関数でデコーダのフラッシュしてくれても良い気もする。それが出来ない理由とかあるんですかね?