我正在尝试实施条形码扫描仪。我有一个AVCaptureSession从AVCaptureDevice接收视频。我想支持所有方向。使用以下代码,当我运行应用程序时,纵向方向的一切都很好。但是在横向方向上,视图会旋转但视频输入不会旋转。所以我最终得到了一张90度的旋转视频。
当我实现 - (NSUInteger)supportedInterfaceOrientations方法时,一切都被锁定到纵向位置。
有谁能告诉我如何解决这个问题?
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self setupCaptureSession];
_previewLayer.frame = _previewView.bounds;
_previewView.center = self.view.center;
_previewView.backgroundColor = [UIColor redColor];
[_previewView.layer addSublayer:_previewLayer];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationWillEnterForeground:) name:UIApplicationWillEnterForegroundNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationDidEnterBackground:) name:UIApplicationDidEnterBackgroundNotification object:nil];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
[self startRunning];
}
-(void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
[self stopRunning];
}
-(void) setupCaptureSession
{
if (_captureSession)
return;
_videoDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
if (!_videoDevice)
{
NSLog(@"No video camera on this device");
return;
}
_captureSession = [[AVCaptureSession alloc]init];
_videoInput = [[AVCaptureDeviceInput alloc]initWithDevice:_videoDevice error:nil];
if ([_captureSession canAddInput:_videoInput])
{
[_captureSession addInput:_videoInput];
}
_previewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:_captureSession];
_previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
}
-(void) startRunning
{
if (_running)
return;
[_captureSession startRunning];
_running = YES;
}
- (void) stopRunning
{
if (!_running)
return;
[_captureSession stopRunning];
_running = NO;
}
/*
-(NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationLandscapeLeft|UIInterfaceOrientationLandscapeRight|UIInterfaceOrientationPortrait|UIInterfaceOrientationPortraitUpsideDown;
}
*/
编辑:
我尝试了以下代码,但previewLayer方向仍然是颠倒/横向。
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(orientationChanged)
name:UIDeviceOrientationDidChangeNotification
object:nil];
-(void) orientationChanged
{
if (self.interfaceOrientation == UIInterfaceOrientationPortraitUpsideDown)
[_previewLayer.connection setVideoOrientation:AVCaptureVideoOrientationPortraitUpsideDown];
if (self.interfaceOrientation == UIInterfaceOrientationPortrait)
[_previewLayer.connection setVideoOrientation:AVCaptureVideoOrientationPortrait];
if (self.interfaceOrientation == UIInterfaceOrientationLandscapeLeft)
[_previewLayer.connection setVideoOrientation:AVCaptureVideoOrientationLandscapeLeft];
if (self.interfaceOrientation == UIInterfaceOrientationLandscapeRight)
[_previewLayer.connection setVideoOrientation:AVCaptureVideoOrientationLandscapeRight];
}
答案 0 :(得分:10)
用以下
修复了它-(void) orientationChanged {
UIDeviceOrientation deviceOrientation = [UIDevice currentDevice].orientation;
if (deviceOrientation == UIInterfaceOrientationPortraitUpsideDown)
[_previewLayer.connection setVideoOrientation:AVCaptureVideoOrientationPortraitUpsideDown];
else if (deviceOrientation == UIInterfaceOrientationPortrait)
[_previewLayer.connection setVideoOrientation:AVCaptureVideoOrientationPortrait];
else if (deviceOrientation == UIInterfaceOrientationLandscapeLeft)
[_previewLayer.connection setVideoOrientation:AVCaptureVideoOrientationLandscapeLeft];
else
[_previewLayer.connection setVideoOrientation:AVCaptureVideoOrientationLandscapeRight];
}
答案 1 :(得分:7)
要在捕获的媒体中反映设备方向更改,您需要设置输出捕获连接的videoOrientation
属性。
AVCaptureOutput* output = <# Your capture output device #>; //reference to your device output, possibly of AVCaptureStillImageOutput or AVCaptureMovieFileOutput type
AVCaptureConnection* connection = [output connectionWithMediaType:AVMediaTypeVideo];
if ([connection isVideoOrientationSupported]) {
connection.videoOrientation = [self videoOrientationFromDeviceOrientation];
}
以下方法根据设备方向返回视频方向:
-(AVCaptureVideoOrientation)videoOrientationFromDeviceOrientation {
AVCaptureVideoOrientation result = [UIDevice currentDevice].orientation;
if ( result == UIDeviceOrientationLandscapeLeft )
result = AVCaptureVideoOrientationLandscapeRight;
else if ( result == UIDeviceOrientationLandscapeRight )
result = AVCaptureVideoOrientationLandscapeLeft;
return result;
}
希望你会发现它有用。
答案 2 :(得分:0)
我没有关于这个问题的新信息,但我认为两个答案都很好,而且只是半个故事。我今天在这个问题上工作了很长时间,并没有找到适合我情况的正确的答案。但差不多。
实际上您需要遵守这两种解决方案。您肯定需要相应地旋转预览图层。 但是如果你想让镜头处于相同的方向(而不是以某种方式切断),你需要做一个组合。
此外,我还要修复此问题:-[UIDevice orientation]
可让您了解房间内设备的真实方向。但您可能更好地依赖应用程序的界面方向,如下面的代码所示。
在我的情况下,我只支持横向(两者)并且有一个写入磁盘的录像机。在这里,我使用一个块来通知,因为我喜欢它们很多;)
// @property (nonatomic, retain) AVCaptureMovieFileOutput *videoFileOutput;
// @property (nonatomic, retain) AVCaptureVideoPreviewLayer *videoPreviewLayer;
- (void)viewDidLoad {
[super viewDidLoad];
void (^observerHandler)(NSNotification *) = ^(NSNotification *note) {
switch ([[UIApplication sharedApplication] statusBarOrientation]) {
case UIInterfaceOrientationLandscapeRight:
[[[self videoPreviewLayer] connection] setVideoOrientation:AVCaptureVideoOrientationLandscapeRight];
[[[self videoFileOutput] connectionWithMediaType:AVMediaTypeVideo] setVideoOrientation:AVCaptureVideoOrientationLandscapeRight];
break;
case UIInterfaceOrientationLandscapeLeft:
[[[self videoPreviewLayer] connection] setVideoOrientation:AVCaptureVideoOrientationLandscapeLeft];
[[[self videoFileOutput] connectionWithMediaType:AVMediaTypeVideo] setVideoOrientation:AVCaptureVideoOrientationLandscapeLeft];
break;
default:
break;
}
};
[self setOrientationObserver:[[NSNotificationCenter defaultCenter] addObserverForName:UIDeviceOrientationDidChangeNotification object:nil queue:[NSOperationQueue currentQueue] usingBlock:observerHandler]];
}