具有表面input的MediaCodec:在后台录制

我正在处理一个video编码应用程序,当主机活动进入后台时,我想阻止该应用程序停止,或者屏幕循环closures/打开。

我的编码器的体系结构来自于CameraToMpegTest优秀的例子,在GLSurfaceView中增加了显示相机帧(参见下面的Github链接)。 我目前正在使用双态解决scheme执行后台录制:

  • 当托pipe活动在前台时,在每次调用GLSurfaceView.RendereronDrawFrame编码一个video帧。 这允许我以突发的方式访问GLSurfaceView的EGL状态,以免阻塞排队等待渲染器线程的其他事件。

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

但是,如果屏幕closures,GLSurfaceView的EGLContext会丢失,并且会发生新的onSurfaceCreated调用。 在这种情况下,我们必须重新创build连接到MediaCodecinput曲面的EGL窗口表面。 不幸的是,第二次调用eglCreateWindowSurface会产生:

 E/libEGL(18839): EGLNativeWindowType 0x7a931098 already connected to another API 

在调用之前,我释放连接到Android Surface的所有EGL资源 。

有没有办法交换连接到MediaCodec的inputSurface的EGLSurface?

我的testing应用程序的完整源代码在Github上 。 主要活动 。

更新我将这里学到的经验教训应用于基于MediaCodec和MediaMuxer类的Androidvideosdk 。 希望能帮助到你!

Solutions Collecting From Web of "具有表面input的MediaCodec:在后台录制"

先背景…

当你调用eglCreateWindowSurface() ,Android EGL包装调用你传入的Surface上的native_window_api_connect() 。这最终会变成BufferQueue生产者连接调用,这意味着这个EGL表面现在是Surface的唯一graphics缓冲区来源。

EGL表面保持连接到Surface直到EGL表面被破坏。 当它是时, 表面析构函数调用native_window_api_disconnect()来从BufferQueue断开EGL表面。 EGL表面是引用计数的,当表面传递给eglMakeCurrent()eglMakeCurrent()的计数递增,所以要销毁两件事情:

  1. 必须调用eglDestroySurface()
  2. EGL表面在任何线程中都不能是“当前”的

第二个项目需要调用eglMakeCurrent()与另一个EGL曲面(或EGL_NO_SURFACE ),或调用eglReleaseThread()在以前使用该表面的任何线程。 确认这一点的一个快速方法是在表面eglMakeCurrent() current和un-current时,在调用eglMakeCurrent()之前添加日志logging,并通过使用adb logcat -v threadtime查看logcat输出来比较线程ID。 使用eglGetCurrentSurface(EGL_DRAW)这样的EGL查询也可能会有用,以确认您正在执行使表面最新的线程中的un-current。

如果EGL表面没有被破坏,它将不会从Surface断开连接,并且试图连接一个新的生产者(通过调用具有新的EGL表面的eglCreateWindowSurface )将被拒绝,并且“已经连接”消息。

更新:我的实现现在在Grafikatesting项目中可用。 如果你安装了这个,select“显示+捕捉摄像头”,开始录制,切换电源,然后停止录制,你应该有一个完整的电影在中间很长的停顿。 您可以退出,select“播放video”,然后select“camera-test.mp4”进行查看。