7

我正在尝试通过 CameraPreview 数据生成简短的连续 mp4 文件MediaCodec.createInputSurface()。但是,重新创建MediaCodec及其关联的 Surface 需要停止相机以允许再次调用mCamera.setPreviewTexture(...). 这种延迟会导致不可接受的丢帧数量。

因此我需要定期生成CODEC_CONFIGandEND_OF_STREAM数据而不重新创建输入 Surface,因此必须调用mCamera.setPreviewTexture(...). MediaFormat假设不变,这可能吗?

(我正在改编fadden的CameraToMpegTest示例。我的完整代码在这里

不成功的尝试:

调用MediaCodec.signalEndOfInputStream(),排空MediaCodec,然后MediaCodec.flush()在块之间调用会IllegalStateException在第二次调用MediaCodec.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 在哪里绘制。如果您在那里添加一个新的“更新 Surface”API(销毁旧的 EGLSurface,创建新的 EGLSurface,eglMakeCurrent),并在您启动新的 MediaCodec 时调用它,我认为这一切都会正常工作。

更新以解决评论

重要的是您只更改EGLSurface. GLConsumer.cpp中的checkAndUpdateEglStateLocked()函数会检查以确保和设置后不会更改。您不能在 CodecInputSurface 中调用/因为它会更改. 您只想销毁并重新创建.EGLDisplayEGLContextrelease()eglSetup()EGLContextEGLSurface

于 2013-09-30T22:31:28.123 回答