4

動画を作成するアプリを作成しています。問題は、フレーム取得プロセスが十分に速くない場合があることです (ほとんどの場合)。

私が現在行っているのは、遅れた場合に現在のフレームの取得をスキップすることですが、FFMPEG/libavcodec は、渡すすべてのフレームを次のフレームと見なすため、2 フレームのうち 1 つをドロップすると、20 秒のビデオ10 しか持続しません。サウンド処理がはるかに高速であるため、サウンドを追加するとすぐに問題が発生します...

FFMPEG に伝えたいのは、「最後のフレームは当初の意図よりも 2 倍長く続く必要がある」、またはリアルタイムで処理できるものなら何でもいいということです。

ある時点でフレームをスタックしようとしましたが、これによりすべてのメモリが失われます(ハードドライブにフレームを「スタック」しようとしましたが、予想どおり遅くなりました)

手動でptsを操作する必要があると思いますが、私の試みはすべて失敗し、VLCなどのffmpegを使用する他のアプリコードを読むことはあまり役に立ちませんでした...だから、どんなアドバイスも大いに役立ちます感謝!

よろしくお願いします!

4

4 に答える 4

1

出力はおそらく可変フレームレート (vfr) と見なされますが、フレームが到着したときにウォールクロック時間を使用してタイムスタンプを生成し、それをエンコードする前に AVFrame に適用するだけです。フレームは再生時に正しい時間に表示されます。

これを行う方法の例 (少なくとも独自のタイムスタンプ部分の指定) については、ffmpeg ディストリビューションの doc/examples/muxing.c を参照してください (現在の git pull の 491 行目):

frame->pts += av_rescale_q(1, video_st->codec->time_base, video_st->time_base);

ここで、作成者は、ビデオストリームのタイムベースに再スケーリングされたビデオコーデックのタイムベースでフレームのタイムスタンプを 1 ずつ増やしていますが、あなたのケースでは、任意のタイムベースから出力ビデオストリームのタイムベースにフレームをキャプチャし始めてからの秒数を単純に再スケーリングできます (上記の例のように)。たとえば、任意のタイムベースが 1/1000 で、キャプチャを開始してから 0.25 秒のフレームを受信した場合、次のようにします。

AVRational my_timebase = {1, 1000};
frame->pts = av_rescale_q(250, my_timebase, avstream->time_base);

次に、通常どおりフレームをエンコードします。

于 2013-03-07T05:21:05.807 に答える
0

多くの(ほとんど?)ビデオフォーマットでは、フレームを除外することはできません。代わりに、時間内に新しいビデオフレームを取得できない場合は、古いビデオフレームを再利用してみてください。

于 2011-07-05T21:32:24.587 に答える
0

ただのアイデア..処理が遅れているときに、同じフレームをもう一度渡そうとしましたか(そして現在のフレームをドロップしましたか)?複製されたフレームをすばやく処理できるかもしれません。

于 2011-07-05T21:32:42.940 に答える
0

マルチコア処理用のこのffmpegコマンドラインスイッチ-threads ...があるので、APIで同様のことができるはずです(方法はわかりませんが)。これで問題が解決する場合があります。

于 2011-07-05T22:35:21.320 に答える