gpt4 book ai didi

android - 如何在Android的camera2 API中复用MediaRecorder的Surface?

转载 作者:塔克拉玛干 更新时间:2023-11-02 21:08:14 24 4
gpt4 key购买 nike

所以我整个周末都在玩 camera2 api。现在我开始理解事物是如何连接在一起的。在测试 API 以实现视频录制应用程序时,我遇到了困难。

我首先更改 Android Camera2Video Sample根据我的需要。让我烦恼的是,在每次录制过程之后,都会重新创建相机 session 。更糟糕的是,当开始录制 session 时,预览 session 将首先被销毁并创建录制 session 。录制 session 完成后,它会被销毁并创建一个新的预览 session 。

文档明确指出:

Creating a session is an expensive operation and can take several hundred milliseconds... CameraCaptureSession Documentation

结果看起来很难看,当我点击录制并停止时,屏幕卡顿。我想改进这种行为,所以我摆弄了代码。

我现在要做的是创建我唯一的 CameraSession,我在其中添加预览表面(TextureView)以及来自已创建的 的表面MediaRecorder 通过调用其 getSurface 方法。这适用于第一个视频,但当我 try catch 第二个视频时,我得到一个 IllegalArgumentException: Bad argument passed to camera service。我认为这是因为当我重置 MediaRecorder 时,我在创建时传递给 CameraSessionMediaRecorder 表面以某种方式被破坏或更改准备新的录音。

我现在的问题是,有没有办法解决这个问题? (setInputSurface(Surface surface)) 可能是,但是 api 级别太高,所以我没有测试它。

这里是对相关代码 fragment 的快速概述:

  1. 设置MediaRecorder

    private void setUpMediaRecorder() throws IOException {
    if (mMediaRecorder == null) {
    mMediaRecorder = new MediaRecorder();
    }
    mMediaRecorder.setVideoEncodingBitRate(5000000);
    mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
    mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
    mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
    mMediaRecorder.setVideoFrameRate(24);
    mMediaRecorder.setVideoSize(mVideoSize.getWidth(), mVideoSize.getHeight());
    mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
    mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
    mMediaRecorder.setOrientationHint(SENSOR_ORIENTATION_DEFAULT_DEGREES);
    mNextVideoAbsolutePath = getVideoFilePath();
    mMediaRecorder.setOutputFile(mNextVideoAbsolutePath);
    mMediaRecorder.prepare();
    }
  2. 创建强大的录制 session

    SurfaceTexture texture = mTextureView.getSurfaceTexture();
    texture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight());

    List<Surface> surfaces = new ArrayList<>();
    // Set up Surface for the camera preview
    mPreviewSurface = new Surface(texture);
    surfaces.add(mPreviewSurface);

    // Set up Surface for the MediaRecorder
    mRecorderSurface = mMediaRecorder.getSurface();
    surfaces.add(mRecorderSurface);

    // create the capture session
    mCameraDevice.createCaptureSession(surfaces, new CameraCaptureSession.StateCallback() {

    @Override
    public void onConfigured(@NonNull CameraCaptureSession cameraCaptureSession) {
    mCameraSession = cameraCaptureSession;

    // now that the session is created, start using it for the preview
    showPreview();
    }

    @Override
    public void onConfigureFailed(@NonNull CameraCaptureSession cameraCaptureSession) {
    ....
    }
    }
    }, mBackgroundHandler);
    } catch (CameraAccessException) {
    e.printStackTrace();
    }

    void showPreview() {
    mPreviewBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
    mPreviewBuilder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO);
    mPreviewBuilder.addTarget(mPreviewSurface);
    mCameraSession.setRepeatingRequest(mPreviewBuilder.build(), null, mBackgroundHandler);
    }
  3. 开始录制视频

    mVideoBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_RECORD);
    mVideoBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_VIDEO);
    mVideoBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON);
    mVideoBuilder.addTarget(mPreviewSurface);
    mVideoBuilder.addTarget(mRecorderSurface);
    // set the request for the capture
    mCameraSession.setRepeatingRequest(mVideoBuilder.build(), null, mBackgroundHandler);
    // Start recording
    mMediaRecorder.start();
  4. 停止录音

    mMediaRecorder.stop();
    mMediaRecorder.reset();
    showPreview();
    setUpMediaRecorder(); // this is key to not get an error from the MediaRecorder

所有这一切都很完美,视频录制开始和停止时没有任何问题!这很棒,但是当我返回第 3 步(第 4 步之后)时,我得到了上述 IllegalArgumentException: Bad argument passed to camera service。我一直在用头撞墙,但我找不到解决这个问题的方法。

非常感谢任何帮助!

谢谢!

最佳答案

查看 MediaRecorder#setInputSurface(android.view.Surface) :

Configures the recorder to use a persistent surface when using SURFACE video source.

我在尝试弄清楚如何重用 MediaRecorder 捕获表面时偶然发现了它。这样,您可以将持久表面设置为捕获 session 的输出表面之一,并且您不必重新创建捕获 session 来更改从新的 prepare() 调用生成的 MediaRecorder 表面。

Google Nexus 和 Pixel 相机应用程序能够开始和停止视频录制而不会在预览中出现任何卡顿,因此绝对有可能以某种方式做到这一点。

关于android - 如何在Android的camera2 API中复用MediaRecorder的Surface?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41926591/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com