xref: /aosp_15_r20/external/webrtc/sdk/objc/helpers/RTCCameraPreviewView.m (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1*d9f75844SAndroid Build Coastguard Worker/*
2*d9f75844SAndroid Build Coastguard Worker *  Copyright 2015 The WebRTC Project Authors. All rights reserved.
3*d9f75844SAndroid Build Coastguard Worker *
4*d9f75844SAndroid Build Coastguard Worker *  Use of this source code is governed by a BSD-style license
5*d9f75844SAndroid Build Coastguard Worker *  that can be found in the LICENSE file in the root of the source
6*d9f75844SAndroid Build Coastguard Worker *  tree. An additional intellectual property rights grant can be found
7*d9f75844SAndroid Build Coastguard Worker *  in the file PATENTS.  All contributing project authors may
8*d9f75844SAndroid Build Coastguard Worker *  be found in the AUTHORS file in the root of the source tree.
9*d9f75844SAndroid Build Coastguard Worker */
10*d9f75844SAndroid Build Coastguard Worker
11*d9f75844SAndroid Build Coastguard Worker#import "RTCCameraPreviewView.h"
12*d9f75844SAndroid Build Coastguard Worker
13*d9f75844SAndroid Build Coastguard Worker#import <AVFoundation/AVFoundation.h>
14*d9f75844SAndroid Build Coastguard Worker#import <UIKit/UIKit.h>
15*d9f75844SAndroid Build Coastguard Worker
16*d9f75844SAndroid Build Coastguard Worker#import "RTCDispatcher+Private.h"
17*d9f75844SAndroid Build Coastguard Worker
18*d9f75844SAndroid Build Coastguard Worker@implementation RTC_OBJC_TYPE (RTCCameraPreviewView)
19*d9f75844SAndroid Build Coastguard Worker
20*d9f75844SAndroid Build Coastguard Worker@synthesize captureSession = _captureSession;
21*d9f75844SAndroid Build Coastguard Worker
22*d9f75844SAndroid Build Coastguard Worker+ (Class)layerClass {
23*d9f75844SAndroid Build Coastguard Worker  return [AVCaptureVideoPreviewLayer class];
24*d9f75844SAndroid Build Coastguard Worker}
25*d9f75844SAndroid Build Coastguard Worker
26*d9f75844SAndroid Build Coastguard Worker- (instancetype)initWithFrame:(CGRect)aRect {
27*d9f75844SAndroid Build Coastguard Worker  self = [super initWithFrame:aRect];
28*d9f75844SAndroid Build Coastguard Worker  if (self) {
29*d9f75844SAndroid Build Coastguard Worker    [self addOrientationObserver];
30*d9f75844SAndroid Build Coastguard Worker  }
31*d9f75844SAndroid Build Coastguard Worker  return self;
32*d9f75844SAndroid Build Coastguard Worker}
33*d9f75844SAndroid Build Coastguard Worker
34*d9f75844SAndroid Build Coastguard Worker- (instancetype)initWithCoder:(NSCoder*)aDecoder {
35*d9f75844SAndroid Build Coastguard Worker  self = [super initWithCoder:aDecoder];
36*d9f75844SAndroid Build Coastguard Worker  if (self) {
37*d9f75844SAndroid Build Coastguard Worker    [self addOrientationObserver];
38*d9f75844SAndroid Build Coastguard Worker  }
39*d9f75844SAndroid Build Coastguard Worker  return self;
40*d9f75844SAndroid Build Coastguard Worker}
41*d9f75844SAndroid Build Coastguard Worker
42*d9f75844SAndroid Build Coastguard Worker- (void)dealloc {
43*d9f75844SAndroid Build Coastguard Worker  [self removeOrientationObserver];
44*d9f75844SAndroid Build Coastguard Worker}
45*d9f75844SAndroid Build Coastguard Worker
46*d9f75844SAndroid Build Coastguard Worker- (void)setCaptureSession:(AVCaptureSession *)captureSession {
47*d9f75844SAndroid Build Coastguard Worker  if (_captureSession == captureSession) {
48*d9f75844SAndroid Build Coastguard Worker    return;
49*d9f75844SAndroid Build Coastguard Worker  }
50*d9f75844SAndroid Build Coastguard Worker  _captureSession = captureSession;
51*d9f75844SAndroid Build Coastguard Worker  [RTC_OBJC_TYPE(RTCDispatcher)
52*d9f75844SAndroid Build Coastguard Worker      dispatchAsyncOnType:RTCDispatcherTypeMain
53*d9f75844SAndroid Build Coastguard Worker                    block:^{
54*d9f75844SAndroid Build Coastguard Worker                      AVCaptureVideoPreviewLayer *previewLayer = [self previewLayer];
55*d9f75844SAndroid Build Coastguard Worker                      [RTC_OBJC_TYPE(RTCDispatcher)
56*d9f75844SAndroid Build Coastguard Worker                          dispatchAsyncOnType:RTCDispatcherTypeCaptureSession
57*d9f75844SAndroid Build Coastguard Worker                                        block:^{
58*d9f75844SAndroid Build Coastguard Worker                                          previewLayer.session = captureSession;
59*d9f75844SAndroid Build Coastguard Worker                                          [RTC_OBJC_TYPE(RTCDispatcher)
60*d9f75844SAndroid Build Coastguard Worker                                              dispatchAsyncOnType:RTCDispatcherTypeMain
61*d9f75844SAndroid Build Coastguard Worker                                                            block:^{
62*d9f75844SAndroid Build Coastguard Worker                                                              [self setCorrectVideoOrientation];
63*d9f75844SAndroid Build Coastguard Worker                                                            }];
64*d9f75844SAndroid Build Coastguard Worker                                        }];
65*d9f75844SAndroid Build Coastguard Worker                    }];
66*d9f75844SAndroid Build Coastguard Worker}
67*d9f75844SAndroid Build Coastguard Worker
68*d9f75844SAndroid Build Coastguard Worker- (void)layoutSubviews {
69*d9f75844SAndroid Build Coastguard Worker  [super layoutSubviews];
70*d9f75844SAndroid Build Coastguard Worker
71*d9f75844SAndroid Build Coastguard Worker  // Update the video orientation based on the device orientation.
72*d9f75844SAndroid Build Coastguard Worker  [self setCorrectVideoOrientation];
73*d9f75844SAndroid Build Coastguard Worker}
74*d9f75844SAndroid Build Coastguard Worker
75*d9f75844SAndroid Build Coastguard Worker-(void)orientationChanged:(NSNotification *)notification {
76*d9f75844SAndroid Build Coastguard Worker  [self setCorrectVideoOrientation];
77*d9f75844SAndroid Build Coastguard Worker}
78*d9f75844SAndroid Build Coastguard Worker
79*d9f75844SAndroid Build Coastguard Worker- (void)setCorrectVideoOrientation {
80*d9f75844SAndroid Build Coastguard Worker  // Get current device orientation.
81*d9f75844SAndroid Build Coastguard Worker  UIDeviceOrientation deviceOrientation = [UIDevice currentDevice].orientation;
82*d9f75844SAndroid Build Coastguard Worker  AVCaptureVideoPreviewLayer *previewLayer = [self previewLayer];
83*d9f75844SAndroid Build Coastguard Worker
84*d9f75844SAndroid Build Coastguard Worker  // First check if we are allowed to set the video orientation.
85*d9f75844SAndroid Build Coastguard Worker  if (previewLayer.connection.isVideoOrientationSupported) {
86*d9f75844SAndroid Build Coastguard Worker    // Set the video orientation based on device orientation.
87*d9f75844SAndroid Build Coastguard Worker    if (deviceOrientation == UIInterfaceOrientationPortraitUpsideDown) {
88*d9f75844SAndroid Build Coastguard Worker      previewLayer.connection.videoOrientation =
89*d9f75844SAndroid Build Coastguard Worker          AVCaptureVideoOrientationPortraitUpsideDown;
90*d9f75844SAndroid Build Coastguard Worker    } else if (deviceOrientation == UIInterfaceOrientationLandscapeRight) {
91*d9f75844SAndroid Build Coastguard Worker      previewLayer.connection.videoOrientation =
92*d9f75844SAndroid Build Coastguard Worker          AVCaptureVideoOrientationLandscapeRight;
93*d9f75844SAndroid Build Coastguard Worker    } else if (deviceOrientation == UIInterfaceOrientationLandscapeLeft) {
94*d9f75844SAndroid Build Coastguard Worker      previewLayer.connection.videoOrientation =
95*d9f75844SAndroid Build Coastguard Worker          AVCaptureVideoOrientationLandscapeLeft;
96*d9f75844SAndroid Build Coastguard Worker    } else if (deviceOrientation == UIInterfaceOrientationPortrait) {
97*d9f75844SAndroid Build Coastguard Worker      previewLayer.connection.videoOrientation =
98*d9f75844SAndroid Build Coastguard Worker          AVCaptureVideoOrientationPortrait;
99*d9f75844SAndroid Build Coastguard Worker    }
100*d9f75844SAndroid Build Coastguard Worker    // If device orientation switches to FaceUp or FaceDown, don't change video orientation.
101*d9f75844SAndroid Build Coastguard Worker  }
102*d9f75844SAndroid Build Coastguard Worker}
103*d9f75844SAndroid Build Coastguard Worker
104*d9f75844SAndroid Build Coastguard Worker#pragma mark - Private
105*d9f75844SAndroid Build Coastguard Worker
106*d9f75844SAndroid Build Coastguard Worker- (void)addOrientationObserver {
107*d9f75844SAndroid Build Coastguard Worker  [[NSNotificationCenter defaultCenter] addObserver:self
108*d9f75844SAndroid Build Coastguard Worker                                            selector:@selector(orientationChanged:)
109*d9f75844SAndroid Build Coastguard Worker                                                name:UIDeviceOrientationDidChangeNotification
110*d9f75844SAndroid Build Coastguard Worker                                              object:nil];
111*d9f75844SAndroid Build Coastguard Worker}
112*d9f75844SAndroid Build Coastguard Worker
113*d9f75844SAndroid Build Coastguard Worker- (void)removeOrientationObserver {
114*d9f75844SAndroid Build Coastguard Worker  [[NSNotificationCenter defaultCenter] removeObserver:self
115*d9f75844SAndroid Build Coastguard Worker                                                  name:UIDeviceOrientationDidChangeNotification
116*d9f75844SAndroid Build Coastguard Worker                                                object:nil];
117*d9f75844SAndroid Build Coastguard Worker}
118*d9f75844SAndroid Build Coastguard Worker
119*d9f75844SAndroid Build Coastguard Worker- (AVCaptureVideoPreviewLayer *)previewLayer {
120*d9f75844SAndroid Build Coastguard Worker  return (AVCaptureVideoPreviewLayer *)self.layer;
121*d9f75844SAndroid Build Coastguard Worker}
122*d9f75844SAndroid Build Coastguard Worker
123*d9f75844SAndroid Build Coastguard Worker@end
124