在没有预览的情况下录制时,尺寸不在有效集

时间:2018-01-23 21:28:24

标签: 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并启动捕获会话的代码:

 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());
        }
    }

我已经尝试搞乱调用顺序和输出格式/编码器而没有运气。我确信我拥有所有必需的权限。提前感谢您的时间!

1 个答案:

答案 0 :(得分:1)

此设备最有可能支持LEGACY级别的camera2;检查INFO_SUPPORTED_HARDWARE_LEVEL的输出是什么。

LEGACY设备在传统的android.hardware.Camera API之上有效地运行camera2(比这更复杂,但大致如此);结果,他们通过camera2的能力受到限制。

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

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

您可以验证已弃用的Camera API中支持的预览尺寸集是否与您在错误中获得的列表相匹配;如果它没有,那么在生成列表时可能存在操作系统错误,因此很容易知道。

但总的来说,无论盒子侧面的功能列表是什么,您都无法请求相机的CameraCharacteristics StreamConfiguraitonMap中未列出的大小。有时,OEM相机应用程序具有神奇的钩子,以启用普通应用程序无法实现的功能;通常因为该功能仅适用于一些非常特定的情况,普通应用程序不知道如何复制。