【发布时间】:2018-04-16 04:42:20
【问题描述】:
我在 Android 上进行背景视频录制的第一次体验是使用 JavaCV FFMpegRecoder。它很容易实现,只需在活动中创建相机实例,在服务中设置PreviewCallback 侦听器,在onPreviewFrame 上只需将字节发送到 FFMpegRecorder 并且不要在 onPause 或 onStop 中破坏(断开)相机当然
但是 FFMpegRecorder 不是很好(cpu、内存使用)
所以我找到了 INDExOS m4m 库(由 Intel 提供):https://github.com/INDExOS/media-for-mobile
它有CameraCapturerActivity.java - https://github.com/INDExOS/media-for-mobile/blob/master/samples/src/main/java/org/m4m/samples/CameraCapturerActivity.java
看来真的不怎么吃资源
我决定尝试在后台模式下录制,我只是简单地评论了它的 onPause 方法,其中执行停止录制和预览方法,但它只是不录制任何内容(在最后一帧冻结),直到我返回活动
当我将PreviewCallback 侦听器设置为此类时,onPreviewFrame 在后台发送字节正常,似乎SurfaceTexture 的onFrameAvailable 与在 m4m 库中传递帧相关时@987654335 停止@是从Activity调用的
图书馆有两个onFrameAvailable 听众:
- 首先在 PreviewRender.java - https://github.com/INDExOS/media-for-mobile/blob/master/android/src/main/java/org/m4m/android/PreviewRender.java#L241,似乎类包含与在视图类中显示帧相关的所有内容(因此对于录制视频应该不重要)
- CameraSource.java 中的第二个 - https://github.com/INDExOS/media-for-mobile/blob/master/android/src/main/java/org/m4m/android/CameraSource.java#L222
似乎这是获取帧的主要类,我猜它是用于视频录制的
但似乎这些类在某些方面仍然相关
例如,如果我在CameraCapturerActivity.java 中评论createPreview 方法
private void createPreview() {
surfaceView = new GLSurfaceView(getApplicationContext());
surfaceView.setDebugFlags(GLSurfaceView.DEBUG_CHECK_GL_ERROR);
((RelativeLayout) findViewById(R.id.camera_layout)).addView(surfaceView, 0);
preview = capture.createPreview(surfaceView, camera);
preview.setFillMode(fillMode);
if (getRequestedOrientation() == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT) {
capture.setOrientation(90);
} else if (getRequestedOrientation() == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) {
capture.setOrientation(0);
}
preview.start();
}
应用会运行正常,当然我不会看到帧,但是尝试按下录制按钮时录制将无法正常工作,因此如果未创建预览,录制将无法正常工作
所以我需要帮助来了解这一切是如何工作的,如何在我离开活动时暂停预览但在后台继续录制并在再次返回活动时恢复预览。我没有使用SurfaceTexture, GLSurfaceView,只使用普通的SurfaceView及其持有者回调onSurfaceCreated,onSurfaceChanged,..
我只是在项目中没有看到类似于 onSurfaceDestroy 的内容,当用户离开活动时会停止记录
我看到了OpenGl API,纹理也用在Grafika项目https://github.com/google/grafika
所以我相信有些人使用过类似的东西并且知道SurfaceTexture 及其回调(onFrameAvailable,..)是如何工作的
当然,很多事情都与 m4m 库代码设计本身有关,但是当您不使用所有这些(opengl、surfacetexture...)时,仍然很难理解一些事情 p>
更新
现在我对 EGLContext 有了一些了解,我们必须将其设置为特定的源(用于预览或录制 - 编码器)
我成功让Grafika录制示例在后台工作https://github.com/google/grafika/blob/master/src/com/android/grafika/ContinuousCaptureActivity.java
在那个示例类中,我评论了 onPause 中的所有内容,删除了 mDisplaySurface 并做了其他事情
onFrameAvailable 现在看起来像这样:
@Override // SurfaceTexture.OnFrameAvailableListener; runs on arbitrary thread
public void onFrameAvailable(SurfaceTexture surfaceTexture) {
Log.d(TAG, "frame available");
if (mEglCore == null) {
return;
}
mEncoderSurface.makeCurrent();
mCameraTexture.updateTexImage();
mCameraTexture.getTransformMatrix(mTmpMatrix);
if (!mFileSaveInProgress) {
GLES20.glViewport(0, 0, VIDEO_WIDTH, VIDEO_HEIGHT);
mFullFrameBlit.drawFrame(mTextureId, mTmpMatrix);
drawExtra(mFrameNum, VIDEO_WIDTH, VIDEO_HEIGHT);
mCircEncoder.frameAvailableSoon();
mEncoderSurface.setPresentationTime(mCameraTexture.getTimestamp());
mEncoderSurface.swapBuffers();
}
mFrameNum++;
//mHandler.sendEmptyMessage(MainHandler.MSG_FRAME_AVAILABLE);
}
所以现在当我按下主页按钮时,它仍然会将帧记录到一个文件中,我以后可以看到它
现在我需要回到 m4m 库,因为它可以录制音频并具有用于帧处理的实用程序
【问题讨论】:
标签: android