带Surface输入的MediaCodec:生成分块输出

我试图通过MediaCodec.createInputSurface()从CameraPreview数据生成短序列mp4文件。 但是,重新创建MediaCodec及其关联的Surface需要停止相机以允许对mCamera.setPreviewTexture(...)进行另一次调用。 这种延迟会导致不可接受的丢帧数量。

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

(我正在调整fadden的CameraToMpegTest示例,我的完整代码在这里)

不成功的尝试:

调用MediaCodec.signalEndOfInputStream() ,排空MediaCodec ,然后调用块之间的MediaCodec.flush()会在第二次调用MediaCodec.signalEndOfInputStream()产生IllegalStateException

调用MediaCodec.signalEndOfInputStream() ,耗尽MediaCodec ,然后调用MediaCodec.stop(); MediaCodec.configure(...), MediaCodec.start() MediaCodec.stop(); MediaCodec.configure(...), MediaCodec.start()块之间的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。 完整的解决方案来源在这里。


signalEndOfInputStream()调用更新MediaCodec堆栈中各个层的状态。 您可以从MediaCodecTest中的测试上面的注释中了解什么操作是有效的,但总的来说MediaCodec的行为根本不是为“非常规”用途定义的。

所以你必须看看代码。 输入表面的生命周期与OMXNodeInstance的生命周期相关联; 它由GraphicBufferSource表示。 一旦发出EOS信号,GraphicBufferSource将忽略其他帧(请参见第426行)。 如果不拆除GraphicBufferSource,则无法重置EOS标志,但是当您这样做时,它将断开Surface底层的缓冲队列。

所以我不认为你将能够停止/重新启动MediaCodec并继续使用Surface。

但是......你不需要。 CameraToMpegTest将相机预览路由到SurfaceTexture,然后使用GLES将纹理渲染到编码器的输入表面。 SurfaceTexture与编码器分离,不需要改变。 我认为需要改变的是CodecInputSurface,它使用MediaCodec中的Surface调用eglCreateWindowSurface()来告诉GLES在哪里绘制。 如果你在那里添加一个新的“更新Surface”API(销毁旧的EGLSurface,创建新的EGLSurface,eglMakeCurrent),并且每当你创建一个新的MediaCodec时调用它,我想这一切都会奏效。

更新以解决评论

只改变EGLSurface是很重要的。 checkAndUpdateEglStateLocked()函数进行检查,以确保EGLDisplayEGLContext设置后不会更改。 你不能在CodecInputSurface中调用release() / eglSetup() ,因为它改变了EGLContext 。 你只是想破坏并重新创建EGLSurface

链接地址: http://www.djcxy.com/p/92531.html

上一篇: MediaCodec with Surface input: Producing chunked output

下一篇: MediaCodec and Camera: colorspaces don't match