带Surface输入的MediaCodec:在后台录制

我正在制作一个视频编码应用程序,当主持人活动进入后台时,我想阻止该应用程序停止,或者屏幕循环关闭/打开。

我的编码器的体系结构源自出色的CameraToMpegTest示例,此外还向GLSurfaceView显示相机帧(请参阅下面的Github链接)。 我目前正在使用双状态解决方案执行背景录制:

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

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

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

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

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

    有没有办法将连接到MediaCodec输入表面的EGLSurface交换?

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

    更新我将这里学到的经验应用到基于MediaCodec和MediaMuxer类的Android视频sdk中。 希望能帮助到你!


    先背景...

    当您调用eglCreateWindowSurface() ,Android EGL封装器会调用您传入的Surface上的native_window_api_connect() 。最终会变成BufferQueue生成器连接调用,这意味着此EGL曲面现在是Surface的唯一图形缓冲区来源。

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

  • 必须调用eglDestroySurface()
  • EGL表面在任何线程中都不能是“电流”
  • 第二项需要在任何之前使用过曲面的线程上调用eglMakeCurrent()与另一个EGL曲面(或EGL_NO_SURFACE ),或者调用eglReleaseThread() 。 确认这一点的一个快速方法是在表面eglMakeCurrent()当前和非当前时,在调用eglMakeCurrent()之前添加日志记录,并通过使用adb logcat -v threadtime查看logcat输出来比较线程ID。 使用eglGetCurrentSurface(EGL_DRAW)等EGL查询来确认您正在执行使表面最新的线程中的非当前值也可能很有用。

    如果EGL曲面没有被破坏,它将不会与Surface断开连接,并尝试连接一个新的生成器(通过调用具有新EGL曲面的eglCreateWindowSurface )将被“已连接”消息拒绝。

    更新:我的实现现已在Grafika测试项目中提供。 如果你安装了这个软件,选择“显示+捕获摄像头”,开始录制,切换电源,然后停止录制,你应该有一个完整的电影在中间很长的停顿。 您可以退出,选择“播放视频”,然后选择“camera-test.mp4”进行查看。

    链接地址: http://www.djcxy.com/p/92533.html

    上一篇: MediaCodec with Surface Input: Recording in background

    下一篇: MediaCodec with Surface input: Producing chunked output