ipadOS External cameras

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

可以使用webCamera和external camera

AVFoundation

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

AVCapture-prefixed

在这里插入图片描述

两种摄像头

userPreferredCamera(read/write)
用户选择想用哪个camera,应该在摄像头接入app时就要设置

systemPreferedCamera(read only)
由系统决定哪个摄像头是最适合的,一般系统识别是前置摄像头,如果你想让他用后置,也可以去修改这个行为
他会先去检查user PreferredCamera 如果

使用external camera的流程

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

AVCaptureSession

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

AVCapturePutputs

包含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;
self.previewView.videoPreviewLayer.connection.videoOrientation = (AVCaptureVideoOrientation)deviceOrientation;

所以在IOS17就打算旋转拓展摄像头来匹配ipad的orientation方向,
取而代之的新API

AVCaptureDeviceRotationCoordinator

这个类初始化需要一个AVCaptureDevice(主要用于更新videoRotationAngleForHorizonLevelCature属性)和可选的一个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的意思是无论设备是纵向,横向,倒置相机的视频帧都是相对于重力垂直
AVCaptureDeviceRotationCoordinator实例会负责更新videoRotationAngleForHorizonLevelPreview

initWithDevice:preViewLayer:

创建一个协调器提供单独的补偿角度给app使用的capture device content和camera preview

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 内置摄像头

如何升级到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);

quick time movies

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

MetaData(元数据):

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

Depth(深度):

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

AVCaptureDeviceTypeBuiltInWideAngleCamera:

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

AVCaptureDeviceTypeBuiltInDualCamera:

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

AVCaptureDeviceTypeBuiltInTrueDepthCamera:

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

AVCaptureDevicePreviewLayer

会默认镜像拓展摄像头

问题

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

代码逻辑

在这里插入图片描述

FaceTime

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

流程

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,如果没有指定,就查看当前摄像头,如果是拓展摄像头获取前置摄像头则切换成后置,如果是后置则优先切拓展,再切前置,所以如果有拓展的情况下好像切不到前置?

是默认选择后置摄像头

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

UIDeviceOrientation deviceOrientation = [UIDevice currentDevice].orientation;

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

旋转问题

原先的选择方法就是让previewView.videoPreviewLayer.connection.videoOrientation = [UIDevice currentDevice].orientation;
让preview去匹配设备的旋转方向,
原先能有用是因为当设备倒置时,摄像头拍摄的图像其实也是倒置的,所以此时再将preview翻转一下就正常了。
但是如果选择了拓展摄像头就会发现,设备倒置时,摄像头可能没有倒置,所以拍摄出来的图片没有倒置,但是设备倒置了,此时就会让图像倒置了,看起来就像没有做旋转操作一样。
那么目前的问题在于在不能再监测设备的旋转,而是应该观察摄像头是否发生了旋转。因为preview其实是会自动恢复垂直,所以其实只要摄像头是正的就一定是真正的。

问题

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

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

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

但是现在还不是很能理解AVCam里面使用videoRotationAngleForHorizonLevelPreview在preview发生角度变化时去调整preview的角度,那这个和调整ipad角度有什么区别

猜你喜欢

转载自blog.csdn.net/qq_43535469/article/details/132313404