媒体codeC与表面输入:记录在后台 [英] MediaCodec with Surface Input: Recording in background

查看:1570
本文介绍了媒体codeC与表面输入:记录在后台的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的工作,我想prevent从停车时举办活动进入背景或屏幕周期的视频编码应用程序关闭/开启。

I'm working on a video encoding application which I want to prevent from stopping when the hosting Activity enters the background, or the screen cycles off/on.

我的恩codeR架构从优秀 CameraToMpegTest 的例子得出,通过添加显示摄像机帧到GLSurfaceView(见下文Github的链接)。我目前正在执行后台记录与两个国家的解决方案:

The architecture of my encoder is derived from the excellent CameraToMpegTest example, with the addition of displaying camera frames to a GLSurfaceView (see Github links below). I'm currently performing background recording with a two-state solution:

  • 在举办活动是在前台,EN code一个视频帧每次调用 GLSurfaceView.Renderer onDrawFrame 。这使我获得了GLSurfaceView的EGL状态爆发,以免阻止其他事件排队到渲染线程。

  • When the hosting Activity is in the foreground, encode one video frame on each call to the GLSurfaceView.Renderer's onDrawFrame. This allows me access to the GLSurfaceView's EGL state in bursts so as not to block other events queued to the renderer thread.

在主办活动进入后台,停止 onDrawFrame 编码和连接code帧在一个循环中的另一个后台线程。这个模式是相同的CameraToMpegTest示例

When the hosting Activity enters the background, halt the onDrawFrame encoding and encode frames on another background thread within a loop. This mode is identical to the CameraToMpegTest example.

然而如果屏幕电源关闭的GLSurfaceView的EGLContext丢失,新的呼叫 onSurfaceCreated 出现。在这种情况下,我们不得不重新创建EGL窗口表面连接到媒体codeC的输入表面。不幸的是这第二个呼叫<一个href="http://www.khronos.org/registry/egl/sdk/docs/man/xhtml/eglCreateWindowSurface.html"><$c$c>eglCreateWindowSurface生产:

However if the screen is powered off the GLSurfaceView's EGLContext is lost and a new call to onSurfaceCreated occurs. In this case we have to re-create the EGL window surface connected to MediaCodec's input Surface. Unfortunately this 2nd call to eglCreateWindowSurface produces:

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

在此之前打电话,我release连接到Android表面所有EGL资源。

Prior to calling, I release all EGL resources connected to the Android Surface.

有没有办法交换连接到媒体codeC的输入表面的EGLSurface?

Is there a way to swap the EGLSurface connected to MediaCodec's input Surface?

我的测试应用程序的完整的源代码是 Github上。 <一href="https://github.com/OnlyInAmerica/FFmpegTest/blob/service/src/com/example/ffmpegtest/HWRecorderActivity.java">Main活动。

The complete source of my test application is on Github. Main Activity.

更新我申请了学到的知识变成视频SDK为Android 的基础在媒体codeC&放大器; MediaMuxer类。希望它可以帮助!

Update I applied the lessons learned here into a video sdk for Android based on the MediaCodec & MediaMuxer classes. Hope it helps!

推荐答案

背景第一...

当你调用 eglCreateWindowSurface(),Android的<一个href="https://android.googlesource.com/platform/frameworks/native/+/kitkat-release/opengl/libs/EGL/eglApi.cpp">EGL包装调用 native_window_api_connect()表面你通过了。这最终变成了 BufferQueue 制片连接通话,这意味着该EGL地表现在的图形缓冲区为表面的唯一来源

When you call eglCreateWindowSurface(), the Android EGL wrapper calls native_window_api_connect() on the Surface you passed in. This eventually turns into a BufferQueue producer connect call, which means that this EGL surface is now the sole source of graphics buffers for the Surface.

东瀛表面保持连接到表面,直到EGL表面被破坏。当它是,则<一href="https://android.googlesource.com/platform/frameworks/native/+/kitkat-release/opengl/libs/EGL/egl_object.cpp">surface析构函数调用 native_window_api_disconnect()来断开 BufferQueue 的EGL表面。东瀛表面是引用计数,与当表面传递给递增引用计数 eglMakeCurrent()这样被摧毁两件事情一定会发生:

The EGL surface stays connected to the Surface until the EGL surface is destroyed. When it is, the surface destructor calls native_window_api_disconnect() to disconnect the EGL surface from the BufferQueue. The EGL surface is reference-counted, with the refcount incremented when the surface is passed to eglMakeCurrent() so to be destroyed two things must happen:

  1. eglDestroySurface()必须名为
  2. 东瀛表面不得以任何线程当前
  1. eglDestroySurface() must be called
  2. the EGL surface must not be "current" in any thread

第二项需要调用 eglMakeCurrent()与另一个EGL表面(或 EGL_NO_SURFACE ),或调用 eglReleaseThread(),上了previously使用的表面的任何线索。一个快速的方法来确认,这样做是为了调用之前添加记录 eglMakeCurrent()当表面是由当前的和未电流,并通过观察比较线程ID在logcat的输出亚行logcat -v threadtime 。这也可能是有用的用EGL查询像 eglGetCurrentSurface(EGL_DRAW)来确认你正在做的联合国目前在做了表面电流的线程。

The second item requires calling eglMakeCurrent() with another EGL surface (or EGL_NO_SURFACE), or calling eglReleaseThread(), on any thread that had previously used the surface. One quick way to confirm that this is done is to add logging before calls to eglMakeCurrent() when the surface is made current and un-current, and compare the thread IDs by viewing the logcat output with adb logcat -v threadtime. It may also be useful to use EGL queries like eglGetCurrentSurface(EGL_DRAW) to confirm that you're doing the un-current in the thread that has made the surface current.

如果东瀛表面不被破坏,也不会从表面断开,并尝试连接一个新的生产(通过调用 eglCreateWindowSurface 用新的EGL表面)将与已连接的消息被拒绝。

If the EGL surface isn't destroyed, it won't disconnect from the Surface, and attempts to connect a new producer (by calling eglCreateWindowSurface with a new EGL surface) will be rejected with the "already connected" message.

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

Update: My implementation is now available in the Grafika test project. If you install this, select "Show + capture camera", start recording, toggle the power, and then stop recording, you should have a complete movie with a long pause in the middle. You can back out, select "Play video", and choose "camera-test.mp4" to view it.

这篇关于媒体codeC与表面输入:记录在后台的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆