ストリームをデコードして再エンコードし、途中でフレームをドロップする必要があります。60 fps ビデオのタイム スタンプを単純に半分にすると、120 fps ビデオになります。
生の H.264 ビデオ ストリームには、タイムスタンプが埋め込まれていないことに注意してください。MediaExtractor によって解析され、MediaMuxer によって追加された .mp4 ラッパーは、タイミング情報を保持します。MediaCodec インターフェースは、プレゼンテーション タイム スタンプを受け入れて生成するように見えますが、ほとんどの場合、正しいフレームに関連付けられたタイムスタンプを維持するためにタイム スタンプを渡すだけです。フレームはエンコーダーによって並べ替えることができます。(一部のエンコーダーは、タイムスタンプを調べてビット レートの目標を達成しようとするため、偽の値を渡すことはできません。)
DecodeEditEncodeの例のようなことができます。デコーダーが を呼び出すとき、releaseOutputBuffer()
1 フレームおきに render 引数に「false」を渡すだけです。
画面記録用の仮想ディスプレイなど、他のソースからビデオ フレームを受け入れる場合、エンコーダの Surface をディスプレイに直接渡すことはできません。SurfaceTexture を作成し、そこからSurfaceを作成し、到着したフレームを処理する必要があります。DecodeEditEncode の例はまさにこれを行い、各フレームを GLES シェーダーで変更します。
ただし、画面の記録にはさらに問題があります。仮想ディスプレイからのフレームは、固定フレーム レートではなく、生成されたときに到着し、可変フレーム レート ビデオを生成します。たとえば、次のような一連のフレームがあるとします。
[1] [2] <10 seconds pass> [3] [4] [5] ...
ほとんどのフレームは 16.7 ミリ秒間隔 (60 fps) で到着していますが、表示が更新されていないときはギャップがあります。記録が 1 フレームおきに取得される場合、次のようになります。
[1] <10+ seconds pass> [3] [5] ...
間違ったフレームで 10 秒間一時停止してしまいます。これは、 1と2の間に多くの動きがあった場合に目立ちます。これを正しく機能させるには、フレーム ドロップにある程度の知性が必要です。たとえば、固定フレーム レートの 30fps ビデオを生成するために、必要に応じて前のフレームを繰り返します。