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

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

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

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

不成功的尝试:

调用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.完整的解决方案来源是@L_502_1@.

解决方法

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性能优化——之控件的优化 前面讲了图像的优化,接下...
前言 上一篇已经讲了如何实现textView中粗字体效果,里面主要...
最近项目重构,涉及到了数据库和文件下载,发现GreenDao这个...
WebView加载页面的两种方式 一、加载网络页面 加载网络页面,...
给APP全局设置字体主要分为两个方面来介绍 一、给原生界面设...
前言 最近UI大牛出了一版新的效果图,按照IOS的效果做的,页...