【问题标题】:AVCaptureSession with multiple orientations issue具有多个方向问题的 AVCaptureSession
【发布时间】:2013-11-16 20:31:16
【问题描述】:

我正在尝试实现条形码扫描仪。我有一个从 AVCaptureDevice 接收视频的 AVCaptureSession。我想支持所有方向。使用以下代码,当我运行应用程序时,纵向方向一切正常。然而,在横向,视图会旋转,但视频输入不会。所以我最终得到了一个 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];
}

【问题讨论】:

    标签: ios iphone ipad avfoundation


    【解决方案1】:

    用下面的方法解决了这个问题

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

    【讨论】:

    • 我的视频总是以纵向模式保存。有什么想法吗?
    【解决方案2】:

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

    希望对您有所帮助。

    【讨论】:

    • @Julian 很高兴它有帮助
    【解决方案3】:

    我没有关于这个问题的新信息,但我认为提供的两个答案都很好,而且仍然只是故事的一半。我今天在这个问题上工作了很长时间,但没有找到适合我情况的正确答案。不过差不多。

    实际上,您需要同时遵守这两种解决方案。您肯定需要相应地旋转预览层。 但是,如果您想让素材处于相同的方向(而不是以某种方式截断),则需要进行组合。

    我还包括一个修复:-[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]];
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-08-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多