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

前端之家收集整理的这篇文章主要介绍了android – 带Surface输入的MediaCodec:生成分块输出前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我正在尝试通过MediaCodec.createInputSurface()从CameraPreview数据生成短序列mp4文件.但是,重新创建MediaCodec及其关联的Surface需要停止相机以允许再次调用mCamera.setPreviewTexture(…).该延迟导致不可接受的丢帧量.

因此,我需要定期生成CODEC_CONFIG和END_OF_STREAM数据,而无需重新创建输入Surface,因此必须调用mCamera.setPreviewTexture(…).假设MediaFormat没有变化,这可能吗?

(我正在调整fadden的CameraToMpegTest示例.我的完整代码here)

不成功的尝试:

调用MediaCodec.signalEndOfInputStream(),耗尽MediaCodec,然后在块之间调用MediaCodec.flush()会在第二次调用MediaCodec.signalEndOfInputStream()时产生IllegalStateException.

调用MediaCodec.signalEndOfInputStream(),然后调用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.完整的解决方案来源是here.

解决方法

signalEndOfInputStream()调用更新MediaCodec堆栈中各个层的状态.您可以从 MediaCodecTest中的测试上方的注释中了解哪些操作有效,但总的来说,MediaCodec的行为根本没有为“异常”用途定义.

所以你必须看看代码.输入表面的寿命与OMXNodeInstance的寿命相关;它由GraphicBufferSource表示.一旦您发出EOS信号,GraphicBufferSource将忽略其他帧(见line 426).没有拆除GraphicBufferSource就无法重置EOS标志,但是当你这样做时它会断开Surface底层的缓冲队列.

因此,我认为您无法停止/重新启动MediaCodec并继续使用Surface.

但是……你不应该这样做. CameraToMpegTest将相机预览路由到SurfaceTexture,然后使用GLES将纹理渲染到编码器的输入表面上. SurfaceTexture与编码器分离,不需要更改.我认为需要改变的是CodecInputSurface,它使用MediaCodec中的Surface调用eglCreateWindowSurface()来告诉GLES在哪里绘制.如果你在那里添加一个新的“更新Surface”API(破坏旧的EGLSurface,创建新的EGLSurface,eglMakeCurrent),并在你启动一个新的MediaCodec时调用它,我认为它一切正常.

更新以解决评论

重要的是您只需更改EGLSurface. GLConsumer.cpp中的checkAndUpdateEglStateLocked()函数检查以确保EGLDisplay和EGLContext在设置后不会更改.您不能在CodecInputSurface中调用release()/ eglSetup(),因为它会更改EGLContext.您只想破坏并重新创建EGLSurface.

猜你在找的Android相关文章