0

私の目標は、複数のビデオ ファイルからビデオ フラグメントを接合することです。フラグメントは、任意の開始時間と終了時間によって定義されます。最初は 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);
...
4

1 に答える 1