ipadOS External cameras

ipad 链接拓展摄像头的条件

1.USB-C接口,使用时需确认USB video Class(UVC),这个给USB设备定义了一个标准的视屏输入流
好像也可以使用HDMI

可以使用webCamera和external camera

AVFoundation

用于处理视频多媒体数据的创建,编辑,播放和捕获,是音频视频功能的基础库。
有什么功能呢:
1.可以支持多种音频视频格,用来播放音频和视频
2.通过麦克风和摄像头录制音频视频内容
3.可以对视频内容进行编辑添加特效等
4.支持处理音视频文件的元数据,如标题,作者,描述
5.将多个音视频文件 混合成一个文件

AVCapture-prefixed

在这里插入图片描述

两种摄像头

userPreferredCamera(read/write)

AVCaptureDevice.userPreferredCamera

用户选择想用哪个camera,应该在摄像头接入app时就要设置

systemPreferedCamera(read only)

AVCaptureDevice.systemPreferedCamera

由系统决定哪个摄像头是最适合的,一般系统识别是前置摄像头,如果你想让他用后置,也可以去修改这个行为

他会先去检查userPreferredCamera 如果

使用external camera的流程

app先使用AVCaptureDevices表示camera和microphone,这里面封装了AVCaptureDeviceInput来嵌入一个 ???这里在说什么

AVCaptureSession

AVCaptureSession是一个central control object of the AVCapture graph
AVCaptureSession会接收捕获设备的数据(比如说camera,microphone),然后将数据封装后给输出设备(比如说sceen)有的时候会放到一个文件中,甚至变成一张图片

AVCaptureOutputs

包含movieFile,Phote,VideoData,AudioData,MetaData,DepthData
MovieFileOutput: 会记录QuickTime movies
PhotoOutput: captures high-quality stills and live photos
Data outputs:deliver video or audio buffers from the camera or mic to your app
MetaData,DepthData:for live camera preview ,is a special type of output

AVCaptureVideoPreviewLayer

是CALayer的子类

AVCaptureVideoOrientation

build in camera是使用AVCaptureVideoOrientation来实现选择,因为build in camera是依赖于ipad rotation
但是很明显拓展摄像头是不能通过ipad方向来旋转
并且这个在IOS17是被禁止的,一般使用时是通过获取UIDeviceOrientation转化成AVCaptureVideoOrientation

UIDeviceOrientation deviceOrientation = [UIDevice currentDevice].orientation;//获取当前设备(pad)的方向
self.previewView.videoPreviewLayer.connection.videoOrientation = (AVCaptureVideoOrientation)deviceOrientation;

这种方式只能直接获取到[UIDevice currentDevice].orientation; 或者appBar的orientation,那现在就两种办法:
1.使用原来的办法但是在external的时候不做操作
2.需要一个方法来判断出摄像头是否发生了旋转
取而代之的新API是下面这个

AVCaptureDeviceRotationCoordinator

作用:主要获取设备和preview相对于重力的偏移角度
这个类初始化需要一个AVCaptureDevice(主要用于更新videoRotationAngleForHorizonLevelCapture属性)和可选的一个CALayer(主要用于更新videoRotationAngleForHorizonLevelPreview)(用于显示camera的video的preview)
有两个properties:
a video rotation angle for horizon-level preview
a separate angle for horizon-level capture
都是read only
horizon-level preview的意思是无论设备是纵向,横向,倒置相机的视频帧都是相对于重力垂直,也就是通过这个实例获取的角度都是相对于重力垂直,也就是我们只需要通过上面给的两个属性来获取角度就可以了

initWithDevice:preViewLayer:

创建一个协调器
这个协调器可以提供单独的补偿角度给 app使用的capture device content和camera preview,通过让app的captureDeviceContent或者CameraPreview旋转补偿角度就可以相对于重力垂直

//创建一个协调器:传入参数self.videoDeviceInput.device 为当前摄像头设备对象(),
self.videoDeviceRotationCoordinator = [[AVCaptureDeviceRotationCoordinator alloc] initWithDevice:self.videoDeviceInput.device previewLayer:self.previewView.videoPreviewLayer];
self.previewView.videoPreviewLayer.connection.videoRotationAngle = self.videoDeviceRotationCoordinator.videoRotationAngleForHorizonLevelPreview;

videoRotationAngleForHorizonLevelPreview

主要用于调整preview
Use the videoRotationAngleForHorizonLevelPreview to display video frames in the CALayer passed to the coordinator’s initializer.
会描述需要多少角度应用与preview,这个角度是相对于UIKit或者swiftUI的坐标系

videoRotationAngleForHorizonLevelCature

主要用于调整photos 和 movies
这个属性描述了camera的物理方向

每一个external camera 可以被看作一个ACVaptureDevice instance
三个重要的属性:media type ,device type ,position
AVMediaType.video
AVCaptureDevice.DeviceType.external
AVCaptureDevice.Position.unspecified

external camera相较于build-in camera需要更注意,因为user可以connect和disconnect

if reconnected,camera is represented by a new AVCaptureDevice
可以通过key-value observe来检测连接
AVCaptureDevice.isConnected和AVCaptureDevice.DiscoverySession.devices

当设备连接状态发生改变的时候AVCaptureDevices也会post a norifications
AVCaptureDeviceWasConnected
AVCaptureDeviceWasDisconnected
然后将这些消息发送到background queues
synchronize with AVCaptureSession and UI

isVideoRotationAngleSupported

会检查这个连接是否支持角度的旋转,并不是所有的连接都可以旋转,只有传输视频或者深度媒体数据的连接

videoRotationAngle

给这个属性设置一个合适的值可以让preview旋转

videoRotationAngleForhorizonLevelPreview

显示一个camerade preview

避免通过设置视频数据输出的 AVCaptureConnection 的角度来请求旋转。改变连接的角度会导致帧传送中断,因为捕捉渲染管道需要重新配置以应用新的旋转角度。相反,您应该旋转显示摄像头预览的 CALayer
如果您的应用程序使用带有 AVAssetWriter 用于录制自定义电影的视频数据输出,请避免使用 AVCaptureConnection 旋转视频。相反,使用 AVAssetWriterInput 实例的 transform 属性来设置旋转,这会更改输出文件的元数据。使用这种方法,视频应用程序会在播放期间应用旋转,这比使用捕捉连接旋转每一帧更节能。您的应用程序需要将旋转角度从度数转换为弧度,因为资产编写器输入使用的是应用旋转的 CGAffineTransform,它以弧度来应用旋转。

专业用语

build-in camera 内置摄像头

quick time movies

苹果公司开发的多媒体技术和容器格式 QuickTime(快速时间)创建的电影文件。QuickTime 是一种广泛用于音频、视频和动画的多媒体技术,而 QuickTime Movie 是一种常见的文件格式,用于存储包含音频、视频和文本等元素的多媒体内容。

MetaData(元数据):

元数据是描述数据的数据,它提供有关数据的信息,如创建日期、作者、文件大小、分辨率等。在照片领域,元数据可以包括照片的拍摄日期、相机型号、曝光时间、焦距等信息。元数据可以帮助您更好地组织、管理和了解您的照片集。

FaceTime

总是使用前置或者拓展摄像头
但是当拓展摄像头接入时就会隐藏切换摄像头的btn

如何升级到IOS17

进入 Apple Beta 版软件计划 网站 sign in后点击IOS17然后在ipad上
settings->general->software update->beta update选择IOS17 public就行了

apple demo

CACam
必须是IOS17,并且不能允许在simulate上,因为xcode是没有权限访问camera的

在AVCaptureSession delegate any interaction 时是将一个事件放到dedicated serial dispatch queue(sessionQUeue 并不是main queue)
就是不会阻碍其他事件

请添加图片描述

这些被使用的microphone或者camera都需要用户授予权限,AVFoundation用AVAuthorizationStatus枚举了权限state,来辨别哪些device是restricted(受限),denied等等

通过使用discovery session来列出有效的设备类型,比如说有broken camera(损坏的摄像机)就不算作有效的device

每一个AVCaptionDevice就表示已一个拓展camera

external camera

有三种重要数据
media type,device type,position(the external camera device position is unspecified.
用三个属性可以去发现这个external camera 通过API

position决定是否是external camera

AVCaptureDevicePosition currentPosition = currentVideoDevice.position;

typedef NS_ENUM(NSInteger, AVCaptureDevicePosition) {
    AVCaptureDevicePositionUnspecified = 0,
    AVCaptureDevicePositionBack        = 1,
    AVCaptureDevicePositionFront       = 2,
} API_AVAILABLE(macos(10.7), ios(4.0), macCatalyst(14.0), tvos(17.0)) API_UNAVAILABLE(visionos) API_UNAVAILABLE(watchos);

Depth(深度):

在图像处理中,“depth” 通常指的是图像的深度或色彩深度。它表示图像中每个像素所能够表示的颜色或灰度级的数量。较高的深度意味着图像具有更多的色彩细节和灰度级,而较低的深度则会导致图像失去一些细节。常见的图像深度包括8位(256种颜色)、16位(65536种颜色)和24位(约1600万种颜色)等。

AVCaptureDeviceTypeBuiltInWideAngleCamera:

表示内置的广角摄像头设备,通常是一种标准的前置或后置摄像头,用于常规的照片和视频捕获。

AVCaptureDeviceTypeBuiltInDualCamera:

表示内置的双摄像头设备,通常包括一个广角摄像头和一个长焦摄像头,可用于实现光学变焦等功能。

AVCaptureDeviceTypeBuiltInTrueDepthCamera:

表示内置的 TrueDepth 摄像头设备,通常在支持 Face ID 的设备上使用,可用于进行面部识别、人脸跟踪等功能。

AVCaptureDeviceTypeBuiltInUltraWideCamera:

对应设备上的超广角摄像头。
提供更宽广的视野,适用于拍摄大景、建筑物等。

AVCaptureDeviceTypeBuiltInDualWideCamera:

对应设备上的双广角摄像头系统。
提供了两个广角摄像头,可用于实现更灵活的拍摄设置,例如景深效果等。

AVCaptureDevicePreviewLayer

会默认镜像拓展摄像头

问题

如果是要真机编译就需要xcode改为 xcode15 beta
官网下载

代码逻辑

在这里插入图片描述

流程

configureSession//入口

VCaptureDevice *videoDevice = AVCaptureDevice.systemPreferredCamera;//获取systemPreferredCamera
//获取UserPerredCamera
    NSUserDefaults *userDefaults = NSUserDefaults.standardUserDefaults;
	[userDefaults boolForKey:@"setInitialUserPreferredCamera"]


//如果都没找到就直接设置backCamera
AVCaptureDeviceDiscoverySession *backVideoDeviceDiscoverySession = [AVCaptureDeviceDiscoverySession discoverySessionWithDeviceTypes:@[AVCaptureDeviceTypeBuiltInDualCamera, AVCaptureDeviceTypeBuiltInWideAngleCamera] mediaType:AVMediaTypeVideo position:AVCaptureDevicePositionBack];
videoDevice = backVideoDeviceDiscoverySession.devices.firstObject;
        
AVCaptureDevice.userPreferredCamera = videoDevice;
        
[userDefaults setBool:YES forKey:@"setInitialUserPreferredCamera"];

//设置device input
    AVCaptureDeviceInput* videoDeviceInput = [AVCaptureDeviceInput deviceInputWithDevice:videoDevice error:&error];

//添加systemPerferredCamera观察者
    [AVCaptureDevice addObserver:self forKeyPath:@"systemPreferredCamera" options:NSKeyValueObservingOptionNew context:SystemPreferredCameraContext];


createDeviceRotationCoordinator//还不知道干嘛的

函数

discoverySessionWithDeviceTypes

+ (instancetype)discoverySessionWithDeviceTypes:(NSArray<AVCaptureDeviceType> *)deviceTypes
                                      mediaType:(AVMediaType)mediaType
                                       position:(AVCaptureDevicePosition)position;

用于发现麦克风和摄像头设备
deviceTypes 指定搜索设备类型例如AVCaptureDeviceTypeBuiltInWideAngleCamera、AVCaptureDeviceTypeBuiltInMicrophone

mediaType指定要搜索的媒体类型 例如:AVMediaTypeVideo,AVMediaTypeAudio
position:一个 AVCaptureDevicePosition 类型的常量,指定了要搜索的摄像头位置,可以是前置 (AVCaptureDevicePositionFront)、后置 (AVCaptureDevicePositionBack) 或未指定 (AVCaptureDevicePositionUnspecified)

format

NSArray<AVCaptureDeviceFormat *> *formats
表示摄像头的捕获类型,不同格式具有不同的分辨率,帧率,其他捕获参数

code scanner

启动时时使用back-facing,不允许用户选择camera

change Camera模块

AVCam 是默认采用system perform camera,如果没有指定,就查看当前摄像头,如果是拓展摄像头获取前置摄像头则切换成后置,如果是后置则优先切拓展,再切前置,所以如果有拓展的情况下好像切不到前置?

是默认选择后置摄像头

代码逻辑

在configureSession的时候也就是刚起会时
会获取systemPreferredCamera和userPreferredCamera如果这两个都没有设置就采用后置摄像头

AVCaptureDevice *videoDevice = AVCaptureDevice.systemPreferredCamera;//获取systemPreferredCamera
NSUserDefaults *userDefaults = NSUserDefaults.standardUserDefaults;
[userDefaults boolForKey:@"setInitialUserPreferredCamera"]//判断是否设置userdefault

通过KVO监测systemPreferredCamera

static void*  SystemPreferredCameraContext = &SystemPreferredCameraContext;
[AVCaptureDevice addObserer:ser forKeyPath:@"systemPreferredCamera"] options:NSKeyValueObservingOptionNew context:SystemPreferredCameraContext];

当systemPreferredCamera发生变化时设置systemPreferredCamera

- (void) observeValueForKeyPath:(NSString*)keyPath
                       ofObject:(id)object
                         change:(NSDictionary*)change
                        context:(void*)context
{
	if (context == SystemPreferredCameraContext) {
        AVCaptureDevice *systemPreferredCamera = change[NSKeyValueChangeNewKey];
        
        // Don't switch cameras if movie recording is in progress.
        if (self.movieFileOutput.isRecording) {
            return;
        }
        if (self.videoDeviceInput.device == systemPreferredCamera) {
            return;
        }
        
        [self changeCamera:systemPreferredCamera isUserSelection:NO completion:nil];
    }
}

Orientation

有几个Orientation

window Orientation

self.view.window.windowScene.interfaceOrientation;
应该是用户界面显示的window Orientation,应该可以理解为操作界面,这个值会被系统自动更新
UIInterfaceOrientation包含:

UIInterfaceOrientationPortrait           = UIDeviceOrientationPortrait,
UIInterfaceOrientationPortraitUpsideDown = UIDeviceOrientationPortraitUpsideDown,
UIInterfaceOrientationLandscapeLeft      = UIDeviceOrientationLandscapeRight,
UIInterfaceOrientationLandscapeRight     = UIDeviceOrientationLandscapeLeft

例如一般会先初始化videoOrientation = AVCaptureVideoOrientationPortrait//先设置为垂直
然后判断window orientation是否是unknown
如果不是就将当前prientation设置为window的
然后将previewView.videoPreviewLayer.connection.videoOrientation也设置为这个方向

device orientation

Device Orientation

UIDeviceOrientation deviceOrientation = [UIDevice currentDevice].orientation;

自动更新时时让
previewView.videoPreviewLayer.connection.videoOrientation = [UIDevice currentDevice].orientation;

video Orientation

Capture Connection Orientation
摄像头采集的视频数据的方向,这个是真实影响摄像头显示方向的orientation

self.previewLayer.connection.videoOrientation

previewLayer orientation

Preview Layer Orientation
只是单纯影响图层的显示比如说出现白边

self.previewLayer.orientation

在 AVCaptureVideoPreviewLayer 中,设置 connection.videoOrientation 与设置 previewLayer.orientation 是相互关联的。当设置 connection.videoOrientation 时,previewLayer.orientation 也会自动发生变化,以保持一致性。

这种关联是因为 AVCaptureVideoPreviewLayer 是专门用于显示摄像头采集数据的图层,而 videoOrientation 决定了摄像头采集数据的方向,从而也影响了图层的方向。因此,当你设置 connection.videoOrientation 时,previewLayer.orientation 会自动同步,以确保预览图层正确显示摄像头采集的视频。

这样的设计使得在应对设备旋转等情况时更加方便,你只需设置 connection.videoOrientation,而不必手动调整 previewLayer.orientation。在内部实现中,AVCaptureVideoPreviewLayer 监听了 connection.videoOrientation 的变化,并相应地调整了自身的方向属性。

因此,你只需关注设置 connection.videoOrientation,而 previewLayer.orientation 将会自动同步,无需额外的手动操作。

旋转问题

external camera rotation

build in camera是使用AVCaptureVideoOrientation来实现选择previewView.videoPreviewLayer.connection.videoOrientation = [UIDevice currentDevice].orientation;因为build in camera是依赖于ipad设备的rotation,通常的一个ipad在使用build in camer时,设备进行了倒置,会出现两个操作:
1.设备发生了倒置。
2.摄像头发生了倒置。
此时因为autolayout的关系,当设备旋转180度时,相应的view也会进行旋转,让我们在看到的界面适配,但是此时由于摄像头也发生了旋转,所以此时看到的视频流就是倒置的,此时就需要将render view也倒置过来。所以build in camera是需要多一步操作的,

但是很明显external camera是不能通过ipad方向来旋转,他甚至是不需要去旋转render
并且这个在IOS17是被禁止的,一般使用时是通过获取UIDeviceOrientation转化成AVCaptureVideoOrientation

当ipad发生旋转时
view的bounds会发生变化
UIViewController会先调用viewWillLayoutSubviews
然后UIView会调用layoutSubviews

会出现问题的情况:
比如说ipad长宽为1000和200
当你设置一个button的位置为300 100时
在横屏时可以显示 但是竖屏时就会出现问题

坐标系问题

在这里插入图片描述
后置摄像头是右上角为原点

问题

Q:假设不做任何代码逻辑操作,且使用内置摄像头
那么假设一个情况:1.摄像头正置,设备倒置,是否会出现设备上显示了倒置图像?、
2.摄像头倒置,设备正置,是否会出现倒置图像?
那么此时倒置设备:设备和摄像头同时倒置,摄像头拍摄图像是倒置的,设备是倒置的,那不是应该显示正置图像吗?

A:情况1应该不会显示倒置图像,而是正置的,因为会自动旋转相关view,所以同时倒置时,摄像头提供的图像是倒置,但是设备倒置时相关view会旋转为正置,所以相加此时显示的就是倒置

当我使用ipad内置摄像头拍摄时,将ipad顺时针旋转了90度,此时底层的操作是否是:首先autolayout将preview重新布局,逆时针旋转90度保证preview垂直于水平面,这之前是系统自动完成的操作,此时因为内置摄像头也跟着设备顺时针旋转了90度所以此时ipad上看到的画面其实是顺时针旋转了90度的图像,我需要通过代码将preview逆时针旋转90度来回正图像

看一下这些
简述的

知乎的

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值