android - 在没有预览的情况下录制时,尺寸不在有效设置中

标签 android resolution android-camera2

我正在尝试使用 Vivo X20 (7.1.1) 和camera2 api 录制视频,而不使用预览和录制声音(严格仅录制高清视频)。

我目前陷入困境,因为我无法弄清楚如何成功调用 MediaRecorder.setVideoSize() 并录制高清视频。目前,当我运行应用程序时,日志显示错误:尺寸 (w=1920, h=1080) 和格式 0x1 的表面无效,尺寸不在有效集中:[1440x1080、1280x960、1280x720、960x540、800x480、720x480、 768x432、640x480、384x288、352x288、320x240、176x144]

手机自带的相机应用程序可以录制高达 4K 的视频,所以我肯定错过了一些东西。 CameraManager总共识别出两个摄像头设备。当我使用 CameraCharacteristics 中的 getOutPutFormats() 时,它显示两个相机的相同有效分辨率集,并且与上述错误消息的范围相同。

下面是我用来初始化 MediaRecorder 并启动捕获 session 的代码:

 public void StartRecordingVideo() {
        Initialize();
        recordingVideo = true;
        cameraManager = (CameraManager) this.getSystemService(Context.CAMERA_SERVICE);



    try {
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED) {
            String[] cameraIDs = cameraManager.getCameraIdList();
            //LogAllCameraInfo();
            if (cameraIDs != null)
            {
                for(int x = 0; x < cameraIDs.length; x++)
                {
                    Log.d(LOG_ID, "ID: " + cameraIDs[x]);
                }
            }

            cameraManager.openCamera(deviceCameraID, cameraStateCallback, handler);

            Log.d(LOG_ID, "Successfully opened camera");
        }
        else
        {
            throw new IllegalAccessException();
        }

    }
    catch (Exception e)
    {
        recordingVideo = false;
        Log.e(LOG_ID, "Error during record video start: " + e.getMessage());
    }
}
 private void Initialize()
    {
        videoRecordThread = new HandlerThread("video_capture");
        videoRecordThread.start();
        handler = new Handler((videoRecordThread.getLooper()));

        try
        {
            vidRecorder = new MediaRecorder();
            vidRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
           vidRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
            vidRecorder.setVideoFrameRate(30);
            vidRecorder.setCaptureRate(30);

            vidRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.DEFAULT);
            vidRecorder.setVideoEncodingBitRate(10000000);

            vidRecorder.setVideoSize(1920, 1080);
            String videoFilename = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)+ File.separator + System.currentTimeMillis() + ".mp4";
            vidRecorder.setOutputFile(videoFilename);

            Log.d(LOG_ID, "Starting video: " + videoFilename);
            vidRecorder.prepare();
        }
        catch (Exception e)
        {
            Log.e(LOG_ID, "Error during Initialize: " + e.getMessage());

        }
    }

以及 onReady/onSurfacePrepared/Camera onOpened 回调:

  @Override
        public void onReady(CameraCaptureSession session) {
            Log.d(LOG_ID, "onReady: ");
            super.onReady(session);
            try {
                CaptureRequest.Builder builder = deviceCamera.createCaptureRequest(CameraDevice.TEMPLATE_RECORD);

                builder.addTarget(vidRecorder.getSurface());
                CaptureRequest request = builder.build();
                session.setRepeatingRequest(request, null, handler);
                vidRecorder.start();
            } catch (CameraAccessException e) {
                Log.d(LOG_ID, "Error on Ready: " + e.getMessage());

            }
        }




        @Override
        public void onSurfacePrepared(CameraCaptureSession session, Surface surface) {
            Log.d(LOG_ID, "onSurfacePrepared: ");

            super.onSurfacePrepared(session, surface);
        }




    @Override
    public void onOpened(CameraDevice camera) {
        Log.d(LOG_ID, "onOpened: ");
        deviceCamera = camera;

        try {
            camera.createCaptureSession(Arrays.asList(vidRecorder.getSurface()), recordSessionStateCallback, handler);
        } catch (CameraAccessException e) {
            Log.d(LOG_ID, "onOpened: " + e.getMessage());
        }
    }

我尝试过打乱调用顺序和输出格式/编码器,但没有成功。我确信我拥有所有必需的权限。预先感谢您的宝贵时间!

最佳答案

该设备很可能支持旧版级别的camera2;检查 INFO_SUPPORTED_HARDWARE_LEVEL 的输出是。

旧版设备在旧版 android.hardware.Camera API 之上有效运行camera2(比这更复杂,但大致正确);因此,他们通过camera2的功能受到限制。

最大录制分辨率是一个重要问题; android.hardware.Camera 通过一条神奇路径记录视频,LEGACY 映射层无法直接使用该路径(不涉及 Surface)。因此,camera2 LEGACY 只能以 android.hardware.Camera 支持的最大预览分辨率进行录制,而不能以最大录制分辨率进行录制。

听起来该设备不支持 1:1 1080p 预览,这对于最近推出的设备来说非常不寻常。

您可以验证已弃用的相机 API 中支持的预览尺寸集是否与您在错误中获得的列表相匹配;如果没有,那么生成列表时可能存在操作系统错误,因此最好了解一下。

但一般来说,无论包装盒侧面的功能列表如何说明,您都无法请求相机的 CameraCharacteristics StreamConfiguraitonMap 中未枚举的尺寸。有时,OEM 相机应用程序具有神奇的钩子(Hook)来启用普通应用程序无法使用的功能;通常是因为该功能仅在某些非常非常特定的情况下起作用,而普通应用程序不知道如何复制这些情况。

关于android - 在没有预览的情况下录制时,尺寸不在有效设置中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48411125/

相关文章:

android - 3d css 转换 (translateZ) 不能在 android 4.0.3 上运行?

android - uiAutomator 在 4.1.2 设备上失败

android - 将 "/app"而不是 "/appinst"与 android :pathPattern (working on an intent-filter) 匹配

java - 安卓相机: Unboxing of 'characteristics.get(CameraCharacteristics.LENS_FACING)' may produce NPE

android - 访问被拒绝查找属性 "camera.hal1.packagelist"

Android camera2 - 支持深度输出的设备

java - 有没有办法将 Key 存储在我从 Firebase 对象转换的类中?

java - Android:问题图像分辨率

java - 不同分辨率下的全屏 Swing 应用

android - 如何以编程方式从android中的像素计算dp