7

経由で CameraPreview データから短いシーケンシャル mp4 ファイルを生成しようとしていますMediaCodec.createInputSurface()。ただし、MediaCodecとそれに関連付けられているサーフェスを再作成するには、カメラを停止して への別の呼び出しを許可する必要がありmCamera.setPreviewTexture(...)ます。この遅延により、許容できない量のドロップ フレームが発生します。

したがって、入力サーフェスを再作成せずにCODEC_CONFIGとデータを定期的に生成する必要があるため、を呼び出す必要があります。が変更されていないと仮定すると、これは可能ですか?END_OF_STREAMmCamera.setPreviewTexture(...)MediaFormat

(私は fadden のCameraToMpegTestの例を適応させています。私の完全なコードはこちらです)

失敗した試行:

を呼び出しMediaCodec.signalEndOfInputStream()、 をドレインし、チャンク間でMediaCodec呼び出すと、への 2 回目の呼び出しで が生成されます。MediaCodec.flush()IllegalStateExceptionMediaCodec.signalEndOfInputStream()

を呼び出しMediaCodec.signalEndOfInputStream()、 を排出してMediaCodecから、MediaCodec.stop(); MediaCodec.configure(...), MediaCodec.start()再度呼び出さずにチャンク間で呼び出すとMediaCodec.createInputSurface()、次のエラーが発生します。

    09-30 13:12:49.889  17638-17719/x.xx.xxxx E/Surface﹕ queueBuffer: error queuing buffer to SurfaceTexture, -19
09-30 13:12:49.889  17638-17719/x.xx.xxxx E/IMGSRV﹕ :0: UnlockPostBuffer: Failed to queue buffer 0x592e1e70
09-30 13:12:49.889  17638-17719/x.xx.xxxx E/CameraToMpegTest﹕ Encoding loop exception!
09-30 13:12:49.889  17638-17719/x.xx.xxxx W/System.err﹕ java.lang.RuntimeException: eglSwapBuffers: EGL error: 0x300b
09-30 13:12:49.896  17638-17719/x.xx.xxxx W/System.err﹕ at x.xx.xxxx.ChunkedHWRecorder$CodecInputSurface.checkEglError(ChunkedHWRecorder.java:731)
09-30 13:12:49.896  17638-17719/x.xx.xxxx W/System.err﹕ at x.xx.xxxx.ChunkedHWRecorder$CodecInputSurface.swapBuffers(ChunkedHWRecorder.java:713)
09-30 13:12:49.896  17638-17719/x.xx.xxxx W/System.err﹕ at x.xx.xxxx.ChunkedHWRecorder.startRecording(ChunkedHWRecorder.java:164)
09-30 13:12:49.896  17638-17719/x.xx.xxxx W/System.err﹕ at x.xx.xxxx.HWRecorderActivity$CameraToMpegWrapper.run(HWRecorderActivity.java:76)
09-30 13:12:49.896  17638-17719/x.xx.xxxx W/System.err﹕ at java.lang.Thread.run(Thread.java:841)

解決しました fadden に感謝します。完全なソリューション ソースはここにあります。

4

1 に答える 1

10

このsignalEndOfInputStream()呼び出しは、MediaCodec スタック内のさまざまなレイヤーの状態を更新します。MediaCodecTestのテストの上のコメントから、どの操作が有効かをある程度理解できますが、概して、MediaCodec の動作は単に「異常な」用途に対して定義されていません。

したがって、コードを確認する必要があります。入力サーフェスの有効期間はOMXNodeInstanceの有効期間に関連付けられています。それはGraphicBufferSourceによって表されます。EOS を通知すると、GraphicBufferSource は追加のフレームを無視します (行 426を参照)。GraphicBufferSource を破棄せずに EOS フラグをリセットする方法はありませんが、これを行うと、Surface の下にあるバッファー キューが切断されます。

したがって、MediaCodec を停止/再起動して Surface を使い続けることはできないと思います。

ただし... その必要はありません。CameraToMpegTest はカメラ プレビューを SurfaceTexture にルーティングし、GLES を使用してテクスチャをエンコーダの入力サーフェスにレンダリングします。SurfaceTexture はエンコーダーから分離されているため、変更する必要はありません。変更する必要があるのは CodecInputSurface だと思います。これはeglCreateWindowSurface()、MediaCodec から Surface を呼び出して、GLES にどこに描画するかを伝えます。そこに新しい「更新サーフェス」API を追加し (古い EGLSurface を破棄し、新しい EGLSurface、eglMakeCurrent を作成します)、新しい MediaCodec をスピンアップするたびにそれを呼び出すと、すべてうまくいくと思います。

コメントに対処するための更新:

のみを変更することが重要ですEGLSurfaceGLConsumer.cppcheckAndUpdateEglStateLocked()関数は、とが設定されると変更されないことを確認します。を変更するため、CodecInputSurface で/を呼び出すことはできません。を破棄して再作成するだけです。EGLDisplayEGLContextrelease()eglSetup()EGLContextEGLSurface

于 2013-09-30T22:31:28.123 に答える