具有多个方向的AVCaptureSession问题

我正试图实施一个条码扫描器。 我有一个从AVCaptureDevice中获取video的AVCaptureSession。 我想支持所有的方向。 用下面的代码,当我运行应用程序时,纵向方向上的一切都很好。 但是在横向方向上,视图旋转,但videoinput不会。 所以我最终得到一个90度旋转的video。

当我实现 – (NSUInteger)supportedInterfaceOrientations方法,那么一切都被locking到肖像位置。

谁能告诉我如何解决这个问题?

- (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; } */ 

编辑:

我尝试了下面的代码,但预览图方向仍然是颠倒/侧身。

  [[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]; } 

嗯修正了以下

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

要在捕获的媒体中反映设备方向更改,您需要设置输出捕获连接的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]; } 

下面的方法返回基于设备方向的video方向:

 -(AVCaptureVideoOrientation)videoOrientationFromDeviceOrientation { AVCaptureVideoOrientation result = [UIDevice currentDevice].orientation; if ( result == UIDeviceOrientationLandscapeLeft ) result = AVCaptureVideoOrientationLandscapeRight; else if ( result == UIDeviceOrientationLandscapeRight ) result = AVCaptureVideoOrientationLandscapeLeft; return result; } 

希望你会觉得有帮助。

我在这个问题上没有新的信息,但我认为这两个答案都是好的,仍然只有一半。 我今天在这个问题上工作了很长时间,没有find正确的答案。 但几乎。

其实你需要遵守这两个解决scheme。 您一定需要相应地旋转预览图层。 但是,如果你想在相同的方向(而不是以某种方式切断)的镜头,你需要做一个组合。

此外,我还包括一个解决scheme: -[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]]; }