继续在后台录制视频 - SurfaceTexture,GLSurfaceView

时间:2017-10-08 22:01:09

标签: android

我在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及其持有人回调onSurfaceCreatedonSurfaceChanged,..

我只是在项目中看不到与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库,导致它录制音频并具有用于帧处理的工具

1 个答案:

答案 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;
    }