带表面输入的MediaCodec:在后台录制

dbr*_*bro 10 android mediacodec

我正在开发一个视频编码应用程序,我希望阻止在托管活动进入后台时停止,或者屏幕循环开/关.

我的编码器的架构源自出色的CameraToMpegTest示例,并在GLSurfaceView中添加了显示相机帧(请参阅下面的Github链接).我目前正在使用双态解决方案进行背景录制:

  • 当托管活动是在前台,在每个呼叫中的一个视频帧编码到GLSurfaceView.RendereronDrawFrame.这允许我以突发方式访问GLSurfaceView的EGL状态,以便不阻止排队到渲染器线程的其他事件.

  • 当托管活动进入后台时,停止onDrawFrame编码并在循环内的另一个后台线程上编码帧.此模式与CameraToMpegTest示例相同.

但是,如果屏幕关闭,GLSurfaceView的EGLContext将丢失并发生新的调用onSurfaceCreated.在这种情况下,我们必须重新创建连接到MediaCodec输入Surface的EGL窗口表面.不幸的是,第二次调用eglCreateWindowSurface产生:

E/libEGL(18839): EGLNativeWindowType 0x7a931098 already connected to another API
Run Code Online (Sandbox Code Playgroud)

在致电之前,我发布了连接到Android Surface的所有EGL资源.

有没有办法交换连接到MediaCodec输入Surface的EGLSurface?

我的测试应用程序的完整源代码是在Github上.主要活动.

更新我根据MediaCodec和MediaMuxer类将此处学到的经验应用到Android视频sdk中.希望能帮助到你!

fad*_*den 9

背景首先......

当你打电话eglCreateWindowSurface()时,Android的EGL包装通话native_window_api_connect()Surface你过去了.这最终变成了BufferQueue制片人连接的呼叫,这意味着该EGL表面现在是图形缓冲区的的唯一来源Surface.

EGL表面保持连接Surface直到EGL表面被破坏.如果是,表面析构函数会调用native_window_api_disconnect()断开EGL表面与BufferQueue.EGL表面是引用计数的,当表面传递给refcount时会递增,eglMakeCurrent()因此必须发生两件事:

  1. eglDestroySurface() 必须被召唤
  2. EGL表面在任何线程中都不能是"当前的"

第二项需要在之前使用过曲面的任何线程上调用eglMakeCurrent()另一个EGL曲面(或EGL_NO_SURFACE)或调用eglReleaseThread().确认完成此操作的一种快速方法是eglMakeCurrent()在表面变为当前和不当时调用之前添加日志记录,并通过查看logcat输出来比较线程ID adb logcat -v threadtime.使用EGL查询可能也很有用,例如eglGetCurrentSurface(EGL_DRAW)确认您在使表面处于当前状态的线程中执行非当前操作.

如果EGL表面没有被破坏,它将不会与之断开连接Surface,并且尝试连接新的生产者(通过eglCreateWindowSurface使用新的EGL表面调用)将被"已连接"消息拒绝.

更新:我的实现现在可以在Grafika测试项目中获得.如果你安装它,选择"显示+捕捉相机",开始录制,切换电源,然后停止录制,你应该有一个完整的电影,中间有一个很长的停顿.您可以退出,选择"播放视频",然后选择"camera-test.mp4"进行查看.