android – 具有表面输入的MediaCodec:在后台录制

我正在开发一种视频编码应用程序,当主机活动进入后台时,我想防止停止,或屏幕关闭/开启.

我的编码器的架构源于优秀的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”进行查看.

相关文章

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