视频录制和onPreviewFrame同时回调 [英] Video recording and onPreviewFrame callback at the same time

查看:636
本文介绍了视频录制和onPreviewFrame同时回调的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用MediaRecorder录制视频,并从onPreviewFrame回调方法中获取原始帧(字节数组)

I'm trying to record video using MediaRecorder and get raw frames (byte arrays) from onPreviewFrame callback method

似乎并不是那么容易,mb甚至不可能,我也不知道...

Seems it's not that easy, mb it's not even possible, I don't know...

但是我发现了一些答案(针对类似问题),有人说您应该在调用MediaRecorder.start()之后重新连接相机实例(Camera.reconnect()),然后再次设置预览回调

But I found some answers (for similar questions) and people say that you should reconnect camera instance (Camera.reconnect()) after calling MediaRecorder.start() and set preview callback again

我尝试了类似的方法,但是它不起作用(录音有效,但从未调用onPreviewFrame)

I tried something like this but it doesn't work (recording works but onPreviewFrame is never called)

我也尝试在MediaRecorder.start()之后调用Camera的stopPreviewstartPreview方法,但是当我们尝试停止录制(MediaRecorder.stop())后此类动作应用程序将停止响应(它变为冻结)

I also tried to call Camera's stopPreview and startPreview methods after MediaRecorder.start() but seems we should not do it otherwise when I try to stop recording (MediaRecorder.stop()) after such actions app will stop responding (it becomes frozen)

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.sample_main);
    mPreview = findViewById(R.id.surface_view);
    new Handler().postDelayed(new Runnable() {
        @Override
        public void run() {
            testVideoRecording();
        }
    }, 1000);
}

@Override
public void onPreviewFrame(byte[] bytes, Camera camera) {
    Log.i(TAG, "onPreviewFrame");
}

private void testVideoRecording() {
    mCamera = Camera.open();

    Camera.Parameters parameters = mCamera.getParameters();
    List<Camera.Size> mSupportedPreviewSizes = parameters.getSupportedPreviewSizes();
    List<Camera.Size> mSupportedVideoSizes = parameters.getSupportedVideoSizes();
    Camera.Size optimalSize = CameraHelper.getOptimalVideoSize(mSupportedVideoSizes,
            mSupportedPreviewSizes, mPreview.getWidth(), mPreview.getHeight());

    CamcorderProfile profile = CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH);
    profile.videoFrameWidth = optimalSize.width;
    profile.videoFrameHeight = optimalSize.height;

    parameters.setPreviewSize(profile.videoFrameWidth, profile.videoFrameHeight);
    mCamera.setParameters(parameters);
    try {
        mCamera.setPreviewTexture(mPreview.getSurfaceTexture());
    } catch (IOException e) {
        e.printStackTrace();
    }

    mCamera.setPreviewCallback(this);

    mMediaRecorder = new MediaRecorder();

    // Step 1: Unlock and set camera to MediaRecorder
    mCamera.unlock();
    mMediaRecorder.setCamera(mCamera);

    // Step 2: Set sources
    mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.DEFAULT);
    mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);

    // Step 3: Set a CamcorderProfile (requires API Level 8 or higher)
    mMediaRecorder.setProfile(profile);

    // Step 4: Set output file
    mOutputFile = new File(Environment.getExternalStorageDirectory()
            + File.separator + "test.mp4");
    if (mOutputFile.exists()) mOutputFile.delete();

    mMediaRecorder.setOutputFile(mOutputFile.getPath());

    // Step 5: Prepare configured MediaRecorder
    try {
        mMediaRecorder.prepare();
    } catch (IOException e) {
        e.printStackTrace();
    }
    mMediaRecorder.start();

    // Step 6: try to set preview frame callback

    //mCamera.stopPreview();

    try {
        mCamera.reconnect();
    } catch (IOException e) {
        e.printStackTrace();
    }

    /*try {
        mCamera.setPreviewTexture(mPreview.getSurfaceTexture());
    } catch (IOException e) {
        e.printStackTrace();
    }*/

    mCamera.setPreviewCallback(this);

    //mCamera.startPreview();
}

所以我想知道是否甚至可以同时使用MediaRecorder和预览帧回调.如果是,那该怎么做呢?

So I want to know if it's even possible to use MediaRecorder and preview frame callback at the same time. If yes then how to do it properly?

推荐答案

首先,我强烈建议从已弃用的 Camera API(Camera.open(),…)切换到新的 camera2 API ,除非您的目标设备是都低于Android API21.新的API更加强大和灵活.例如,它本身就在同一 CaptureSession 中支持多个目标(使用此处是在同一会话中使用MediaRecorder和ImageReader的示例.

First of all, I strongly recommend to switch from the deprecated Camera API (Camera.open(), …) to the new camera2 API, unless your target devices are all below Android API 21. The new API is much more powerful and flexible. For example, it natively supports multiple targets in same CaptureSession (with limitations depending on CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL). Here is an example of using MediaRecorder and ImageReader in the same session.

当camera2在设备上处于LEGACY级别时,直接使用旧的API(这是此类摄像机的本机语言)可能仍然更安全.

When camera2 is at LEGACY level on the device, it may still be safer to use the old API directly (this is the native language of such cameras).

如果您仍然使用旧的API,请考虑使用MediaCodec录制视频的样本之一和MediaMuxer.它比MediaRecorder强大,但需要更多工作.

If you are stuck with the old API, consider one of the samples that record video using MediaCodec and MediaMuxer. It is more powerful than MediaRecorder, but requires more work.

很明显,要发现的是MediaCodec出现在API 21中,所以这些示例大多是与LEGACY设备相关.

The catch, obviously, is that MediaCodec appears at API 21, so these examples are mostly relevant for LEGACY devices.

如果您确实必须使用旧设备,则别无选择,只能运行一些替代的视频编码器,这些编码器由onPreviewFrame()回调中提供的帧提供.

If you really must work with old devices, you have no choice but run some alternative video encoder, fed from the frames that come to you in onPreviewFrame() callback.

这篇关于视频录制和onPreviewFrame同时回调的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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