본문 바로가기
ios 뽀개기/objective-c

ios 카메라 화면 자동회전 (camera auto rotation)

by 인생여희 2019. 3. 8.
반응형

ios 카메라 화면 자동회전 (camera auto rotation)




코드



#import <AVFoundation/AVFoundation.h>

#import "ViewController.h"



//화면 전체 가로, 세로길이 구하기

#define kScreenWidth  [UIScreen mainScreen].bounds.size.width

#define kScreenHeight [UIScreen mainScreen].bounds.size.height


//screen orientation

bool g_isPortraitMode;                                      //현재 세로냐 가로냐

float _screenWidth_Landscape;                       // 가로일때 가로길이

float _screenHeight_Landscape;                      //가로일때 세로길이

float _screenWidth_Portrait;                            //세로일때 가로길이

float _screenHeight_Portrait;                           //세로일때 세로길이




@interface ViewController () <AVCaptureVideoDataOutputSampleBufferDelegate>

{

    CGRect s_frame;

}


@property (weak, nonatomic) IBOutlet UIButton *button;

@property (nonatomic,strong) AVCaptureSession *captureSession;

@property (nonatomic,strong) AVCaptureVideoPreviewLayer *captureVideoPreviewLayer;

@property (nonatomic,strong) AVCaptureVideoDataOutput *captureOutput;


@end


@implementation ViewController




- (void)viewDidLoad {

    [super viewDidLoad];

   NSLog(@"viewDidLoad 실행");

    

    // 가로, 세로 스크린사이즈를 전역 변수에 할당

    [self initScreenSizeParam];


    

    //새로 화면으로 초기화

    g_isPortraitMode = true;

    [[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"isPortraitMode"];

    [[NSUserDefaults standardUserDefaults] synchronize];

    [self setScreenOrientation:UIInterfaceOrientationPortrait];

    //설정 해주고

    s_frame = CGRectMake(0, 0, _screenWidth_Portrait, _screenHeight_Portrait);


   

    //화면이 세로 or 가로로 바뀔때마다 특정 함수를 호출한다.

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(deviceOrientationDidChage:) name:UIDeviceOrientationDidChangeNotification object:nil];


    

    //카메라 초기화

    [self initCapture];


    //

   [self.view bringSubviewToFront:_button];

}



- (void)viewWillAppear:(BOOL)animated {

    [super viewWillAppear:animated];

    NSLog(@"viewWillAppear 실행");

    NSLog(@"g_isPortraitMode : %@" , (g_isPortraitMode ? @"true - 세로" : @"false - 가로"));

    if (g_isPortraitMode) {

        [self rotateVideo:UIInterfaceOrientationPortrait];

        [self updateViewUIWhenRotatedWithPortraitMode:YES];

    }

}


//오리엔테이션이 바뀌면 위젯 상태를 조정할 수 있습니다.

- (void)updateViewUIWhenRotatedWithPortraitMode:(BOOL)isPortraitMode {

    if (isPortraitMode) {

        

    }else {

        

    }

}


#pragma step 7.

-(void)initCapture {

     NSLog(@"step 7. initCapture 실행");

    //후방카메라 객체 만들기

    AVCaptureDevice *inputDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];

    

    //입력데이터객체 만들기

    AVCaptureDeviceInput *captureInput = [AVCaptureDeviceInput deviceInputWithDevice:inputDevice error:nil];

    

    //입력객체 null 체크

    if(!captureInput){

        NSLog(@"captureInput is null !");

        return;

    }

    

    //비디오 출력객체 만들기

    _captureOutput = [[AVCaptureVideoDataOutput alloc] init];

    [_captureOutput setSampleBufferDelegate:self queue:dispatch_get_main_queue()];

    

    NSString *key = (NSString *)kCVPixelBufferPixelFormatTypeKey;

    NSNumber *value = [NSNumber numberWithUnsignedInt:kCVPixelFormatType_32BGRA];

    NSDictionary *videoSettings = [NSDictionary dictionaryWithObject:value forKey:key];

    

    [_captureOutput setVideoSettings:videoSettings];

    

    //세션 객체 생성

    self.captureSession = [[AVCaptureSession alloc] init];

    

    NSString *preset;

    if(!preset) preset = AVCaptureSessionPreset1920x1080;

    

    //세션에 프리셋을 넣을 수 있다면

    if ([_captureSession canSetSessionPreset:preset]) {

        self.captureSession.sessionPreset = preset;

    }else{

        self.captureSession.sessionPreset = AVCaptureSessionPresetHigh;

    }

    

    //세션에 입력 객체를 넣을 수 있다면

    if ([self.captureSession canAddInput:captureInput]) {

        [self.captureSession addInput:captureInput];

    }

    

    //세션에 출력 객체를 넣을 수 있다면

    if ([self.captureSession canAddOutput:_captureOutput]) {

        [self.captureSession addOutput:_captureOutput];

    }

    

    //비디오 미리보기 레이어 객체가 없다면

    if (!self.captureVideoPreviewLayer) {

        self.captureVideoPreviewLayer = [AVCaptureVideoPreviewLayer layerWithSession:self.captureSession];

    }

    

    //프레임 위치 및 크기 셋팅

    s_frame.origin.x = 0;

    s_frame.origin.y = 0;

    

    NSLog(@"initCapture - g_isPortraitMode : %@" , (g_isPortraitMode ? @"true - 세로" : @"false - 가로"));

    if (g_isPortraitMode) {

        NSLog(@"initCapture s_frame : 세로 셋팅 *" );

        s_frame.size.width = _screenWidth_Portrait;

        s_frame.size.height = _screenHeight_Portrait;

    }else{

         NSLog(@"initCapture s_frame : 가로 셋팅 *" );

        s_frame.size.width = _screenWidth_Landscape;

        s_frame.size.height = _screenHeight_Landscape;

    }

    

    self.captureVideoPreviewLayer.frame = s_frame;

    NSLog(@"initCapture s_frame : %@" , NSStringFromCGRect(s_frame));

    

    self.captureVideoPreviewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;

    if ([[self.captureVideoPreviewLayer connection] isVideoOrientationSupported]) {

         NSLog(@"isVideoOrientationSupported - 가능!");

        [self.captureVideoPreviewLayer.connection setVideoOrientation:AVCaptureVideoOrientationLandscapeRight];

    }

    

    [self.view.layer addSublayer:self.captureVideoPreviewLayer];

    [self.captureSession startRunning];

    

}



#pragma step 6.

-(void)adjustAVOutputDataOrientaion:(AVCaptureVideoOrientation)aOrientation{

    NSLog(@"step 6 adjustAVOutputDataOrientaion 진입");

    NSLog(@"aOrientation  :%ld" , (long)aOrientation);

    

    for (AVCaptureConnection *connection in _captureOutput.connections) {

        for (AVCaptureInputPort *port in [connection inputPorts]) {

            if ([[port mediaType] isEqual:AVMediaTypeVideo]) {

                if ([connection isVideoOrientationSupported]) {

                    [connection setVideoOrientation:aOrientation];

                }

            }

        }

    }

}


#pragma step 5.

//비디오 회전

-(int) rotateVideo:(UIInterfaceOrientation)interfaceOrientation {

     NSLog(@"step 5. rotateVideo 진입");

    NSLog(@"step 5 interfaceOrientation  :%ld" , (long)interfaceOrientation);

    if (_captureSession != NULL) {

        NSLog(@"_captureSession is not null when video rotate");

        //호출후에 는 출력을 추가 또는 제거 하거나 개별 캡처 입력 또는 출력 속성을 구성하거나 변경할 수 있습니다.

        //사용자가 호출 할 때까지 실제로 변경되지 않으며 , 이 때 변경 사항이 적용됩니다.begin

        [_captureSession beginConfiguration];

        CALayer *previewViewLayer = [self.view layer];

        NSArray *subviews= previewViewLayer.sublayers;

        

        int i = 0;

        NSLog(@"subviews count : %lu" , (unsigned long)[subviews count]);

        

        while (true) {

            NSLog(@" i  : %d" ,  i );

            

            //서브 레이어 수보다 i 가 크면

            if (i > [subviews count]) {

                break;

            }

            

            id layer = [subviews objectAtIndex:i];

            

            if ([layer isKindOfClass:[AVCaptureVideoPreviewLayer class]] == TRUE) {

                

                //변경된 프레임 할당하는 곳!!

                [layer setFrame:s_frame];

          

            

            switch (interfaceOrientation) {

                case UIInterfaceOrientationPortrait:

                    NSLog(@"UIInterfaceOrientationPortrait = Portrait");

                    [[layer connection] setVideoOrientation:AVCaptureVideoOrientationPortrait];

                    [self adjustAVOutputDataOrientaion:AVCaptureVideoOrientationPortrait];

                    break;

                case UIInterfaceOrientationPortraitUpsideDown:

                    NSLog(@"UIInterfaceOrientationPortrait = PortraitUpsideDown");

                    [[layer connection] setVideoOrientation:AVCaptureVideoOrientationPortraitUpsideDown];

                    [self adjustAVOutputDataOrientaion:AVCaptureVideoOrientationPortraitUpsideDown];

                    break;

                case UIInterfaceOrientationLandscapeLeft:

                    NSLog(@"UIInterfaceOrientationLandscapeLeft");

                    [[layer connection] setVideoOrientation:AVCaptureVideoOrientationLandscapeLeft];

                    [self adjustAVOutputDataOrientaion:AVCaptureVideoOrientationLandscapeLeft];

                    break;

                case UIInterfaceOrientationLandscapeRight:

                   NSLog(@"UIInterfaceOrientationLandscapeRight");

                    [[layer connection] setVideoOrientation:AVCaptureVideoOrientationLandscapeRight];

                    [self adjustAVOutputDataOrientaion:AVCaptureVideoOrientationLandscapeRight];

                    break;

                default:

                    break;

            }

                break;

              }

            i++;

        }

        //캡쳐 세션의 구성변경 커밋

        [_captureSession commitConfiguration];

        

    }else if(![_captureSession isRunning]){

        NSLog(@"_captureSession is not running when rotate video");

    }

    return 0;

}




#pragma step 4.

-(BOOL)rotateToInterfaceOrientation:(UIInterfaceOrientation) interfaceOrientation{

    

     NSLog(@"step 4. rotateToInterfaceOrientation 진입");

     NSLog(@"interfaceOrientation  :%ld" , (long)interfaceOrientation);

    

    //가로 왼쪽이거나, 가로오른쪽일때 비디오 회전하기!

    if((interfaceOrientation == UIInterfaceOrientationLandscapeLeft) || (interfaceOrientation == UIInterfaceOrientationLandscapeRight)|| (interfaceOrientation == UIInterfaceOrientationPortrait)) {

        //rotate video

         NSLog(@"비디오 회전해!!");

        [self rotateVideo:interfaceOrientation];

    }else{

        return NO;

    }

    return YES;

}



#pragma step 3.

-(void) deviceOrientationDidChage:(NSNotification *) notification{

     NSLog(@"step 3. deviceOrientationDidChage 진입");

    //현재 디바이스 오리엔테이션 구하기

    UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];

    

    //세로 : 1,   거꾸로 : 2, 가로왼쪽 : 3,   가로오른쪽 : 4

    NSLog(@"현재 디바이스 상태는 %ld 입니다", (long)orientation);

    

    //디바이스 상태가 변경되면 처리할 내용

    if (orientation == UIDeviceOrientationLandscapeLeft) {

         NSLog(@"현재 디바이스 상태는 가로 왼쪽 입니다.");

        //현재 오리엔테이션이 가로면 비디오 회전해주기

        g_isPortraitMode = false;

        [[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"isPortraitMode"];

        [[NSUserDefaults standardUserDefaults] synchronize];

        s_frame = CGRectMake(0, 0, _screenWidth_Landscape, _screenHeight_Landscape);

        [self rotateToInterfaceOrientation:(UIInterfaceOrientation)orientation];

    }else if(orientation == UIDeviceOrientationLandscapeRight){

        NSLog(@"현재 디바이스 상태는 가로 오른쪽 입니다.");

        //현재 오리엔테이션이 가로면 비디오 회전해주기

        g_isPortraitMode = false;

        [[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"isPortraitMode"];

        [[NSUserDefaults standardUserDefaults] synchronize];

        s_frame = CGRectMake(0, 0, _screenWidth_Landscape, _screenHeight_Landscape);

        [self rotateToInterfaceOrientation:(UIInterfaceOrientation)orientation];

    }else if (orientation == UIDeviceOrientationPortrait){

        NSLog(@"현재 디바이스 상태는 세로 입니다.");

        g_isPortraitMode = true;

        [[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"isPortraitMode"];

        [[NSUserDefaults standardUserDefaults] synchronize];

        //[self setScreenOrientation:UIInterfaceOrientationPortrait];

        //프레임을 재 설정 해주고

        s_frame = CGRectMake(0, 0, _screenWidth_Portrait, _screenHeight_Portrait);

        //비디오를 세로로 돌리기

          [self rotateToInterfaceOrientation:(UIInterfaceOrientation)orientation];

    }

    

    

    

   

   

    

    

    

//    NSLog(@"deviceOrientationDidChage - g_isPortraitMode : %@" , (g_isPortraitMode ? @"true - 세로" : @"false - 가로"));

//

//    //특정한 오리엔테이션 무시하기

//    if (g_isPortraitMode || orientation == UIDeviceOrientationFaceUp || orientation == UIDeviceOrientationFaceDown || orientation == UIDeviceOrientationUnknown  || orientation == UIDeviceOrientationPortrait || orientation == UIDeviceOrientationPortraitUpsideDown){

//         NSLog(@"특정한 오리엔테이션 무시하기");

//        return;

//    }

    

    

 

    

}




#pragma step 2.

- (void)initScreenSizeParam {

    NSLog(@"step 2. initScreenSizeParam 실행");

    

    CGFloat screenW = kScreenWidth;

    CGFloat screenH = kScreenHeight;

    

    //가로길이가 세로길이 보다 작으면 , 즉 디바이스가 portraite 모드 일때

    if (screenW < screenH) {

         NSLog(@"screenW < screenH" );

        screenW = kScreenHeight;                 //screenW = 667

        screenH = kScreenWidth;                  //screenH = 375

    }

    

    

    NSLog(@"screenW : %f" ,screenW );

    NSLog(@"screenH : %f" ,screenH );

    

    

    _screenWidth_Landscape = screenW;       // 667

    _screenHeight_Landscape = screenH;      //  375


    _screenHeight_Portrait = screenW;           // 667

    _screenWidth_Portrait =screenH;            //375

    

    NSLog(@"_screenWidth_Landscape : %f" , _screenWidth_Landscape );

    NSLog(@"_screenHeight_Landscape : %f" , _screenHeight_Landscape );

    NSLog(@"_screenHeight_Portrait : %f" , _screenHeight_Portrait );

    NSLog(@"_screenWidth_Portrait : %f" , _screenWidth_Portrait );

}




#pragma step 1.

//앱 은 먼저 supportedInterfaceOrientations 메소드를 실행 한 다음 ViewDidLoad 메소드를 실행합니다.

//g_isPortraitMode 값을 설정합니다. - 화면이 바뀔때 항상 먼저 호출됨


//-(UIInterfaceOrientationMask)supportedInterfaceOrientations {

//    NSLog(@"step 1. supportedInterfaceOrientations 호출");

//

//    //스크린 모드 변수

//    UIInterfaceOrientationMask screenMode;

//    // 세로인지 가로인지 체크

//    if([[NSUserDefaults standardUserDefaults] boolForKey:@"isPortraitMode"]){

//        g_isPortraitMode = true;

//        screenMode = UIInterfaceOrientationMaskPortrait;

//         NSLog(@" !! supportedInterfaceOrientations 실행 - Portrait");

//    }else{

//        g_isPortraitMode = false;

//        screenMode = UIInterfaceOrientationMaskLandscape;

//         NSLog(@" !!  supportedInterfaceOrientations 실행 - Landscape");

//    }

//    //defalt 스크린 모드 리턴 (세로 or 가로)

//    return screenMode;

//}



//버튼 클릭했을 때 -> 디바이스에 오리엔테이션 설정해주기 -> step 1 supportedInterfaceOrientations호출

- (IBAction)buttonAction:(UIButton *)sender {

    

     NSLog(@"buttonAction 작동" );

    

    sender.selected = !sender.selected;

    

    if(sender.isSelected) {    // Portrait

        g_isPortraitMode = true;

        [[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"isPortraitMode"];

        [[NSUserDefaults standardUserDefaults] synchronize];

        [self setScreenOrientation:UIInterfaceOrientationPortrait];

        //프레임을 재 설정 해주고

        s_frame = CGRectMake(0, 0, _screenWidth_Portrait, _screenHeight_Portrait);

        //비디오를 세로로 돌리기

        [self rotateVideo:UIInterfaceOrientationPortrait];

        

        [self updateViewUIWhenRotatedWithPortraitMode:YES];

        

    }else {  // Landscape

        g_isPortraitMode = false;

        [[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"isPortraitMode"];

        [[NSUserDefaults standardUserDefaults] synchronize];

        

        [self setScreenOrientation:UIInterfaceOrientationLandscapeRight];

        s_frame = CGRectMake(0, 0, _screenWidth_Landscape, _screenHeight_Landscape);

        [self rotateVideo:UIInterfaceOrientationLandscapeRight];

        

        [self updateViewUIWhenRotatedWithPortraitMode:NO];

    }

    

}





//디바이스에 오리엔테이션 설정해주기 -> step 1 호출

- (void)setScreenOrientation:(UIInterfaceOrientation)orientation {

    

    NSLog(@"setScreenOrientation  :%ld" , (long)orientation);

    

    if ([[UIDevice currentDevice] respondsToSelector:@selector(setOrientation:)]) {

        

        SEL selector = NSSelectorFromString(@"setOrientation:");

        

        NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[UIDevice instanceMethodSignatureForSelector:selector]];

        

        [invocation setSelector:selector];

        

        [invocation setTarget:[UIDevice currentDevice]];

        

        int val = orientation;//

        

        [invocation setArgument:&val atIndex:2];

        

        //step 1을 호출 ?

        [invocation invoke];

        NSLog(@"setScreenOrientation  end!");

    }

}



- (void)didReceiveMemoryWarning {

    [super didReceiveMemoryWarning];

    // Dispose of any resources that can be recreated.

}


@end



결과화면





반응형

'ios 뽀개기 > objective-c' 카테고리의 다른 글

core audioqueue player 에 대하여  (0) 2019.03.28
core audio queue service (ios recording)  (0) 2019.03.26
코어오디오 MediaPlayer 구현  (1) 2019.03.04
엔터프라이즈 계정으로 배포  (0) 2019.02.15
이미지 자르기  (0) 2019.01.27

댓글