11

Я реализовал код ниже, чтобы изменить ориентацию AVCaptureVideoSession основанную на UIInterfaceOrientation:Quick 180 вращение результатов устройств IOS в камере просмотра вверх-вниз

- (AVCaptureVideoOrientation)interfaceOrientationToVideoOrientation:(UIInterfaceOrientation)orientation { 
    switch (orientation) { 
     case UIInterfaceOrientationPortrait: 
      return AVCaptureVideoOrientationPortrait; 
     case UIInterfaceOrientationPortraitUpsideDown: 
      return AVCaptureVideoOrientationPortraitUpsideDown; 
     case UIInterfaceOrientationLandscapeLeft: 
      return AVCaptureVideoOrientationLandscapeLeft; 
     case UIInterfaceOrientationLandscapeRight: 
      return AVCaptureVideoOrientationLandscapeRight; 
     default: 
      break; 
    } 
    NSLog(@"Warning - Didn't recognise interface orientation (%ld)",(long)orientation); 
    return AVCaptureVideoOrientationPortrait; 
} 

Этот код работает почти идеально. Однако возникает одна проблема: если вы быстро вращаете iOS-устройство на 180 градусов, камера будет отображаться с ног на голову.

Вот что вид камеры выглядит перед вращением:

enter image description here

А вот как это выглядит после вращения:

enter image description here

Кроме того, здесь моя реализация viewDidLayoutSubviews:

- (void)viewDidLayoutSubviews { 

    [super viewDidLayoutSubviews]; 

    previewLayer.frame = self.view.bounds; 

    self.view.translatesAutoresizingMaskIntoConstraints = NO; 
    previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill; 
    [self.view.layer addSublayer:previewLayer]; 

    if (previewLayer.connection.supportsVideoOrientation) { 
     previewLayer.connection.videoOrientation = [self interfaceOrientationToVideoOrientation:[UIApplication sharedApplication].statusBarOrientation]; 
    } 
} 

Есть ли у кого-нибудь представление о том, почему просмотр камеры будет перевернут, когда произойдет поворот на 180 градусов?

+0

Я видел это в Apple, инструменты, поэтому я не уверен, что это ваша ошибка. –

+0

@PaulCezanne Ах, интересно! Какие? Я просто попытался воспроизвести его в приложении для камеры и не смог этого сделать. – narner

+0

Я видел его в камере и сообщениях, но, возможно, я запустил Camera from Messages. Не могу вспомнить. Я также думаю, что это произошло больше в iOS8.0, но не помню, как недавно я видел его у камеры, но я, конечно, видел вращательную странность в 8.3 при запуске камеры из сообщений. –

ответ

4

Я имел такую ​​же проблему, прежде чем здесь, что решить мою проблему.

Я объявил глобальную переменную:

@interface YourViewController() 
{ 
    ... 
    UIDevice *iOSDevice; 
} 

.. 

@end 

Под implementation (файл .m) я объявил NSNotification наблюдатель под -viewWillAppear как:

@implementation YourViewController 

-(void)viewWillAppear:(BOOL)animated 
{ 
    [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications]; 

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(orientationChanged:) name:UIDeviceOrientationDidChangeNotification object:[UIDevice currentDevice]]; 

} 

-(void)viewWillDisappear:(BOOL)animated 
{ 
    [[NSNotificationCenter defaultCenter]removeObserver:self name:UIDeviceOrientationDidChangeNotification object:nil]; 
} 

- (void)orientationChanged:(NSNotification *)notification 
{ 
    iOSDevice = notification.object; 

    previewLayer.connection.videoOrientation = [self interfaceOrientationToVideoOrientation]; 

    //or 

    [self setAutoVideoConnectionOrientation:YES]; 

} 

Я сделал функцию, которая возвращает ориентацию скопированный текущее устройство вроде:

Возьмите добычу в моем методе -interfaceOrientationToVideoOrientation, он преобразует iOSDevice.orientation в AVCaptureVideoOrientation же с тем, что там у вас ..


(В моем случае мне нужно это функции, перечисленные ниже, но взгляните на это может быть полезно для вас по какой-то причине)

- (AVCaptureVideoOrientation)interfaceOrientationToVideoOrientation 
{ 
    switch (iOSDevice.orientation) { 

     case UIInterfaceOrientationPortraitUpsideDown: 

      return AVCaptureVideoOrientationPortraitUpsideDown; 

     case UIInterfaceOrientationLandscapeLeft: 

      return AVCaptureVideoOrientationLandscapeLeft; 

     case UIInterfaceOrientationLandscapeRight: 

      return AVCaptureVideoOrientationLandscapeRight; 

     default: 
     case UIDeviceOrientationPortrait: 
      return AVCaptureVideoOrientationPortrait; 
    } 
} 

- (AVCaptureConnection *)setAutoVideoConnectionOrientation:(BOOL)status 
{ 
    AVCaptureConnection *videoConnection = nil; 

    //This is for me 
    //for (AVCaptureConnection *connection in stillImageOutput.connections) { 

    //This might be for you 
    for (AVCaptureConnection *connection in previewLayer.connection) { 

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

       if (status == YES) 
       { 
        [videoConnection setVideoOrientation:[self interfaceOrientationToVideoOrientation]]; 
       } 
       else 
       { 
        [videoConnection setVideoOrientation:AVCaptureVideoOrientationPortrait]; 
       } 
      } 
      if (videoConnection) 
      { 
       break; 
      } 
     } 
    } 
    return videoConnection; 
} 

Редактировать

Для ориентации по умолчанию: вам необходимо проверить «текущую» ориентацию.

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 

    // assuming you finish setting the `previewLayer` 

    .. 
    // after all of that code, when the view is ready for displaying 
    // if you implemented this approach the best thing to do is: 

    // set this 
    iOSDevice = [UIDevice currentDevice]; 

    // then call 
    previewLayer.connection.videoOrientation = [self interfaceOrientationToVideoOrientation]; 
    // to update the `previewLayer.connection.videoOrientation ` for default orientation   

} 

Примечание:

Использование NSNotificationCenter пусть вращение устройства будет решено первым, прежде чем вызвал ..

Надеется, что это есть помощь вам ..

+0

Это работает почти отлично! Единственная проблема, с которой я сейчас сталкиваюсь, заключается в том, что если я запустил приложение на iPad и начну в ландшафтном режиме, просмотр камеры будет отображаться в альбомной ориентации. Если я поверну устройство к портрету, а затем вернусь к пейзажу, камера отобразит его правильно. – narner

+1

@narner, о том, что вам нужно проверить ориентацию внутри '-viewDidLoad' .. для настройки по умолчанию .. извините, я не включил это здесь. Я думал, что у вас уже есть этот. – 0yeoj

+0

Это имеет смысл. Итак, что-то вроде 'previewLayer.connection.videoOrientation = [[UIDevice currentDevice] ориентация];'? – narner

5

Я считаю, что это происходит потому, что viewDidLayoutSubviews не вызывается, когда представление изменяется с ориентации Portrait на UpsideDown. Когда вы вращаетесь очень быстро, он идет от одного к другому прямо. Если вы медленно вращаетесь, он проходит через ландшафтную ориентацию, и поэтому вызывается viewDidLayoutSubviews, а затем ваш метод.

Советуем использовать один из методов, вызываемых при изменении ориентации. Я знаю, что Apple советует использовать их все меньше и меньше, потому что они хотят, чтобы представления менялись при изменении размера, но бывают случаи, подобные этому, когда вам действительно нужно знать, что ориентация изменилась.

Например, вы можете зарегистрироваться, чтобы получить эти уведомления: UIApplicationDidChangeStatusBarOrientationNotification

+0

Понимаю, это имело бы смысл. Таким образом, вы предлагаете положить код, который я сейчас имею в 'viewDidLayoutSubviews', внутри чего-то вроде' - (void) orientationChanged: (NSNotification *) notification' или 'adjustViewsForOrientation', правильно? – narner

+0

Я бы сказал, что вам нужно только поставить последний 'if' в' orientationChanged: '. Остальная часть кода, который обрабатывает изменение размера представления, очень хорошо помещается в 'viewDidLayoutSubviews'. Я не думаю, что вы должны добавить этот подуровень при каждом вызове метода. – pteofil

+0

Это также имеет смысл. Где, по вашему мнению, было бы лучше разместить этот подуровень? (Извините за вопросы, это немного вредит моей голове, ха-ха). – narner

Смежные вопросы