私の目標は、複数のビデオ ファイルからビデオ フラグメントを接合することです。フラグメントは、任意の開始時間と終了時間によって定義されます。最初は mp4parser のようなライブラリを使用して実行したかったのですが、同期 (IFRAME) ポイントでしかストリームをカットできませんが、より高い精度が必要です。
私のシナリオは、ファイルからエンコードされたストリームを抽出する->デコード->エンコード->結果をmp4ファイルに多重化することです。現在、一般的にコードは機能しますが、結果のビデオはホワイト ノイズです。Nexus-S および Galaxy-S3 でテスト済み。私のコードは、いくつかの例を組み合わせたものです。
- MoviePlayer.java に基づいて以前に記録されたファイルを読み取る
- デコード-エンコード: DecodeEditEncodeTest.java
- ビデオ ストリームを mp4 に多重化する - さらに別の例ですが、ここでは関係ありません
途中でフレームを処理する必要がないため、例を単純化したいと思います。Surface を介さずに、デコーダー出力からエンコーダー入力にバッファーを供給しようとしました。全体的なプロセスは、コードが完了するまで実行され、再生可能なビデオ ファイルが生成されるという意味で機能しました。ただし、ファイルの内容はホワイト ノイズです。
これは、フレームをデコーダーからエンコーダーに送るコードのスニペットです。何が間違っていて、それを機能させる方法は?
...
} else { // decoderStatus >= 0
if (VERBOSE) Log.d(TAG, "surface decoder given buffer "
+ decoderStatus + " (size=" + info.size + ")");
// The ByteBuffers are null references, but we still get a nonzero
// size for the decoded data.
boolean doRender = (info.size != 0);
// As soon as we call releaseOutputBuffer, the buffer will be forwarded
// to SurfaceTexture to convert to a texture. The API doesn't
// guarantee that the texture will be available before the call
// returns, so we need to wait for the onFrameAvailable callback to
// fire. If we don't wait, we risk rendering from the previous frame.
// decoder.releaseOutputBuffer(decoderStatus, doRender);
if (doRender) {
// This waits for the image and renders it after it arrives.
// if (VERBOSE) Log.d(TAG, "awaiting frame");
// outputSurface.awaitNewImage();
// outputSurface.drawImage();
// // Send it to the encoder.
// inputSurface.setPresentationTime(info.presentationTimeUs * 1000);
// if (VERBOSE) Log.d(TAG, "swapBuffers");
// inputSurface.swapBuffers();
encoderStatus = encoder.dequeueInputBuffer(-1);
if (encoderStatus >= 0) {
encoderInputBuffers[encoderStatus].clear();
decoderOutputBuffers[decoderStatus].position(info.offset);
decoderOutputBuffers[decoderStatus].limit(info.offset + info.size);
encoderInputBuffers[encoderStatus].put(decoderOutputBuffers[decoderStatus]);
encoder.queueInputBuffer(encoderStatus, 0, info.size, info.presentationTimeUs*1000, 0);
}
}
decoder.releaseOutputBuffer(decoderStatus, false);
...