我的编码器的架构源于优秀的CameraToMpegTest示例,另外还有一个GLSurfaceView显示相机框架(参见下面的Github链接).我正在使用双状态解决方案执行背景录制:
>当主机活动处于前台时,在每次调用GLSurfaceView.Renderer的onDrawFrame时对一个视频帧进行编码.这允许我以突发形式访问GLSurfaceView的EGL状态,以便不阻止排队到渲染器线程的其他事件.
>当主机活动进入后台时,停止onDrawFrame编码,并对循环中另一个后台线程上的帧进行编码.此模式与CameraToMpegTest示例相同.
但是如果屏幕关闭,GLSurfaceView的EGLContext将丢失,并且对onSurfaceCreated发出新的调用.在这种情况下,我们必须重新创建连接到MediaCodec的输入Surface的EGL窗口表面.不幸的是,第二次呼叫eglCreateWindowSurface
产生:
E/libEGL(18839): EGLNativeWindowType 0x7a931098 already connected to another API
在打电话之前,我release all EGL resources connected to the Android Surface.
有没有办法交换连接到MediaCodec输入表面的EGLSurface?
我的测试应用程序的完整来源是Github. Main Activity.
更新我将这里的经验教训应用于video sdk for Android,基于MediaCodec& Mediamuxer类.希望有帮助!
解决方法
当您调用eglCreateWindowSurface()时,Android EGL wrapper会调用您传入的Surface的native_window_api_connect(),最终会变成一个BufferQueue生产者连接调用,这意味着这个EGL表面现在是Surface的图形缓冲区的唯一来源.
EGL表面保持连接到表面,直到EGL表面被破坏.当它是,surface destructor调用native_window_api_disconnect()来断开EGL表面与BufferQueue. EGL表面是引用计数的,当表面传递到eglMakeCurrent()时,引用计数增加,以便被破坏两件事情必须发生:
> eglDestroySurface()必须被调用
> EGL表面在任何线程中都不能为“current”
第二个项目需要使用另一个EGL表面(或EGL_NO_SURFACE)调用eglMakeCurrent(),或者在之前使用过曲面的任何线程上调用eglreleaseThread().确认此操作的一个快速方法是在表面为当前和不可用的情况下,在调用eglMakeCurrent()之前添加日志记录,并通过使用adb logcat -v threadtime查看logcat输出来比较线程ID.使用EGL查询(如eglGetCurrentSurface(EGL_DRAW))可能会有用,以确认您在线程中做出表面电流的当前状态.
如果EGL表面没有被破坏,它将不会与Surface断开连接,并且尝试连接一个新的生产者(通过调用eglCreateWindowSurface和一个新的EGL表面)将被“已经连接”的消息被拒绝.
更新:我的实现现在可以在Grafika test project.如果你安装它,选择“显示捕获相机”,开始录制,切换电源,然后停止录制,你应该有一个完整的电影在中间有一个长暂停.您可以退出,选择“播放视频”,然后选择“camera-test.mp4”进行查看.