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;
}
我已经坚持了很长一段时间。当我在 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;
}