AVCaptureSession 获得与内置 iPhone 相机相同的设置

AVCaptureSession get same settings as built in iPhone camera

我已经坚持了很长一段时间。当我在 iPhone 上使用内置相机应用程序录制时,似乎有一个缩放系数。但是,当我在我的应用程序中使用 AVCaptureSession 时,我似乎无法获得相同的结果。这是我正在谈论的一个例子。顶部是从 iPhone 相机应用程序录制的,底部是使用 AVCaptureSession 在我的应用程序内部录制的。这就像发生了鱼眼效应。下面是我设置相机的代码。

- (void)configureCameraSession{
_captureSession = [AVCaptureSession new];

[_captureSession beginConfiguration];

_device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];

if(!_device){
    [self noValidCamera];
    return;
}

AVCaptureDeviceFormat *currentFormat;
int frameRate = 60;
for (AVCaptureDeviceFormat *format in _device.formats)
{
    NSArray *ranges = format.videoSupportedFrameRateRanges;
    AVFrameRateRange *frameRates = ranges[0];

    //CMVideoFormatDescriptionGet
    int resolutionWidth = CMVideoFormatDescriptionGetDimensions(format.formatDescription).width;
    if(frameRates.maxFrameRate > 59 && resolutionWidth >= 1920){
        CameraFormat *cformat = [[CameraFormat alloc] init];
        cformat.format = format;
        cformat.fps = 60;
        if(frameRates.maxFrameRate > 119){
            cformat.fps = 120;
        }
        if(frameRates.maxFrameRate > 239){
            cformat.fps = 240;
        }

        NSString *resolution;

        if(resolutionWidth > 1920){
            resolution = @"4K ";
        }
        else{
            resolution = [[NSNumber numberWithInt:CMVideoFormatDescriptionGetDimensions(format.formatDescription).height] stringValue];
            resolution = [resolution stringByAppendingString:@"p "];
        }

        //stringValue];
        NSString *fps = [[NSNumber numberWithInt:cformat.fps] stringValue];
        fps = [fps stringByAppendingString:@" FPS"];
        cformat.label = [resolution stringByAppendingString:fps];

        BOOL isUniqueFormat = YES;
        for(int i = 0; i < [_formatList count]; i++){
            if([_formatList[i].label isEqualToString:cformat.label]){
                isUniqueFormat = NO;
                break;
            }
        }
        if(isUniqueFormat){
            [_formatList addObject:cformat];
            frameRate = cformat.fps;
            currentFormat = cformat.format;
        }
    }
}

if(!currentFormat){
    [self noValidCamera];
    return;
}

_currentCameraFormat = _analysisViewController.currentCameraFormat;
if(_currentCameraFormat.fps == 0){
    _currentCameraFormatIndex = 0;
    _currentCameraFormat = _formatList[_currentCameraFormatIndex];
    _analysisViewController.currentCameraFormat = _currentCameraFormat;
    currentFormat = _currentCameraFormat.format;
    frameRate = _currentCameraFormat.fps;
}
else{
    currentFormat = _currentCameraFormat.format;
    frameRate = _currentCameraFormat.fps;
}

NSString *resolution;
if(CMVideoFormatDescriptionGetDimensions(currentFormat.formatDescription).width > 1920){
    resolution = @"4K ";
}
else{
    resolution = [[NSNumber numberWithInt:CMVideoFormatDescriptionGetDimensions(currentFormat.formatDescription).height] stringValue];
    resolution = [resolution stringByAppendingString:@"p "];
}
NSString *fps = [[NSNumber numberWithInt:frameRate] stringValue];
fps = [fps stringByAppendingString:@" FPS  ▼"];

[self.videoLabelButton setTitle:[resolution stringByAppendingString:fps] forState:UIControlStateNormal];

[_device lockForConfiguration:nil];
_device.activeFormat = currentFormat;
_device.activeVideoMinFrameDuration = CMTimeMake(1, frameRate);
_device.activeVideoMaxFrameDuration = CMTimeMake(1, frameRate);
[_device unlockForConfiguration];

//Input
AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:_device error:nil];
[_captureSession addInput:input];

//Output
_movieFileOutput = [[AVCaptureMovieFileOutput alloc] init];

if([_captureSession canAddOutput:_movieFileOutput]){
    [_captureSession addOutput:_movieFileOutput];
}

[self setMovieOutputOrientation];

//Preview Layer
_previewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:_captureSession];
_previewView = [[UIView alloc] initWithFrame:self.imageView.bounds];
[self addFocusToView:_previewView];
[_previewView addSubview:self.imageView];

_previewLayer.frame = _previewView.bounds;
_previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
[_previewView.layer addSublayer:_previewLayer];

_previewLayer.connection.videoOrientation = [self videoOrientationFromCurrentDeviceOrientation];

AVCaptureVideoStabilizationMode stabilizationMode = AVCaptureVideoStabilizationModeCinematic;
if ([_device.activeFormat isVideoStabilizationModeSupported:stabilizationMode]) {
    [_previewLayer.connection setPreferredVideoStabilizationMode:stabilizationMode];
}

[self.view addSubview:_previewView];
[self.view addSubview:self.topInfoBar];
[self.view addSubview:self.recordButton];
[self.view addSubview:self.doneButton];

[_captureSession commitConfiguration];
[_captureSession startRunning];

}

好吧,我终于明白了。问题是在某些格式上支持视频稳定性,因此 Apple 会尽可能使用它。问题是我没有在可能的时候打开它。基本上检查该选项是否可用于设备的活动格式并将其打开自动。

 AVCaptureConnection *videoConnection = nil;
for (AVCaptureConnection *connection in [_movieFileOutput connections]){
    for ( AVCaptureInputPort *port in [connection inputPorts]){
        if ([[port mediaType] isEqual:AVMediaTypeVideo]){
            videoConnection = connection;
        }
    }
}

if([videoConnection isVideoOrientationSupported]){
    [videoConnection setVideoOrientation:[self videoOrientationFromCurrentDeviceOrientation]];
}


//Check if we can use video stabilization and if so then set it to auto
if (videoConnection.supportsVideoStabilization) {
    videoConnection.preferredVideoStabilizationMode = AVCaptureVideoStabilizationModeAuto;
}