我在Android上使用背景视频录制的第一次经历是使用JavaCV FFMpegRecoder。它很容易实现,只需在活动中创建相机实例,在服务中设置PreviewCallback
侦听器,在onPreviewFrame
上只需将字节发送到FFMpegRecorder并且不要破坏(断开)相机onPause或onStop当然
但是FFMpegRecorder并不是那么好(cpu,内存使用)
所以我找到了 INDExOS m4m 库(英特尔):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
会在后台发送字节,似乎onFrameAvailable
SurfaceTexture
与{strong> m4m 从活动
onPause
时,strong>库已停止
库有两个onFrameAvailable
个侦听器:
似乎这是获取帧的主要类,我想它用于视频录制
但似乎那些类仍然存在相关的事情
例如,如果我在createPreview
CameraCapturerActivity.java
方法
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,...)
更新
现在我对 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库,导致它录制音频并具有用于帧处理的工具
答案 0 :(得分:0)
在Grafika,所有视频都记录在内部存储中。 尝试更改视频的输出路径以在其他播放器中查看。这样的事情:
File outputFile = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
boolean isPresent = true;
if (!outputFile.exists()) {
isPresent = outputFile.mkdir();
}
if (isPresent) {
outputFile = new File(outputFile.getAbsolutePath(),"camera-test.mp4");
} else {
// Failure
}
您可以更改CameraCaptureActivity(显示+相机捕捉)示例以执行您想要的操作。注释OnPause方法并改变openCamera:
private void openCamera(int desiredWidth, int desiredHeight) {
if (mCamera != null) {
return;
}