輸入設(shè)備AVCaptureDevice 繼承自NSObject
:是關(guān)于相機(jī)硬件的接口训枢,用于配置底層硬件的屬性(例如相機(jī)聚焦筛严、白平衡醉旦、感光度ISO、曝光、幀率车胡、閃光燈檬输、縮放等),這些底層硬件包括前置攝像頭匈棘、后置攝像頭丧慈、麥克風(fēng)、閃光燈等羹饰。使用AVCaptureDevice
向AVCaptureSession
對(duì)象提供輸入數(shù)據(jù)(如音頻或視頻)伊滋。
1、驗(yàn)證授權(quán)
1.1队秩、請(qǐng)求用戶授權(quán)指定的媒體類型
為保護(hù)用戶隱私笑旺,應(yīng)用在使用相機(jī)或者麥克風(fēng),總是需要用戶授權(quán)才能正常使用馍资。當(dāng)應(yīng)用第一次為需要權(quán)限的媒體類型創(chuàng)建任何AVCaptureDeviceInput
對(duì)象時(shí)筒主,系統(tǒng)會(huì)自動(dòng)顯示一個(gè)alert
以請(qǐng)求用戶授權(quán)。
調(diào)用下述類方法鸟蟹,可以讓應(yīng)用直接獲取用戶授權(quán)乌妙,而不是需要等到創(chuàng)建AVCaptureDeviceInput
對(duì)象時(shí),系統(tǒng)自動(dòng)顯示一個(gè)alert
以請(qǐng)求用戶授權(quán)建钥。
+ (void)requestAccessForMediaType:(AVMediaType)mediaType completionHandler:(void (^)(BOOL granted))handler;
該方法有兩個(gè)參數(shù):
- 第一個(gè)參數(shù):
AVMediaType mediaType
:媒體類型常量藤韵,可以是AVMediaTypeVideo
,也可以是AVMediaTypeAudio
熊经;如果沒有提供媒體類型泽艘,將拋出異常NSInvalidArgumentException
。 - 第二個(gè)參數(shù):
(void (^)(BOOL granted))handler
:獲得用戶響應(yīng)后將調(diào)用的塊镐依;塊中參數(shù)BOOL granted
如果用戶授予使用硬件的權(quán)限匹涮,則返回YES;否則返回NO。注意:塊回調(diào)可能在任意線程槐壳,如果要處理UI然低,請(qǐng)回歸主線程。
該方法是異步調(diào)用务唐,被調(diào)用時(shí)允許客戶端繼續(xù)運(yùn)行雳攘,不會(huì)堵塞當(dāng)前線程。在被授予訪問權(quán)限之前绍哎,任何AVMediaType
類型的AVCaptureDevice
都將關(guān)閉靜默音頻樣本或黑色視頻幀来农。
如果調(diào)用該方法之前,已經(jīng)顯示alert
以請(qǐng)求用戶授權(quán)崇堰,不管用戶同意授權(quán)或者拒絕授權(quán),該方法的回調(diào)都會(huì)立即返回用戶曾經(jīng)的授權(quán)結(jié)果,而不會(huì)再次去顯示一個(gè)alert
以請(qǐng)求用戶授權(quán)海诲。
應(yīng)用程序必須在配置信息
info.plist
中提供使用NSCameraUsageDescription
或NSMicrophoneUsageDescription
信息的解釋繁莹。iOS在最初請(qǐng)求用戶許可時(shí)顯示了這個(gè)解釋,然后在設(shè)置應(yīng)用程序中顯示特幔。在沒有使用說明的情況下啟動(dòng)AVCaptureSession
會(huì)引發(fā)異常咨演。
當(dāng)應(yīng)用在手機(jī)上,沒有請(qǐng)求用戶授權(quán)時(shí)蚯斯,執(zhí)行下述代碼薄风,將會(huì)顯示一個(gè)alert
以請(qǐng)求用戶授權(quán)
[AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) {
NSLog(@"granted --- %d currentThread : %@",granted,NSThread.currentThread);
}];
NSLog(@"currentThread : %@",NSThread.currentThread);
我們點(diǎn)擊同意,觀察打印結(jié)果:
14:06:49 currentThread : <NSThread: 0x17006ee80>{number = 1, name = main}
14:06:54 granted --- 1 currentThread : <NSThread: 0x174070600>{number = 3, name = (null)}
可以看到handler
中返回YES拍嵌,并且handler
的響應(yīng)在任意線程中
注意:
(void (^)(BOOL granted))handler
回調(diào)可能在任意線程遭赂,如果要處理UI,請(qǐng)確保在主線程横辆。
1.2撇他、獲取關(guān)于指定媒體類型的授權(quán)狀態(tài)
為保護(hù)用戶隱私,應(yīng)用在使用相機(jī)或者麥克風(fēng)狈蚤,總是需要用戶授權(quán)才能正常使用困肩。當(dāng)應(yīng)用第一次為需要權(quán)限的媒體類型創(chuàng)建任何
AVCaptureDeviceInput
對(duì)象時(shí),系統(tǒng)會(huì)自動(dòng)顯示一個(gè)alert
以請(qǐng)求用戶授權(quán)脆侮。
為獲悉應(yīng)用程序是否獲取指定媒體類型的權(quán)限锌畸,應(yīng)用可以調(diào)用下述類方法獲取授權(quán)狀態(tài):
+ (AVAuthorizationStatus)authorizationStatusForMediaType:(AVMediaType)mediaType;
該方法同步調(diào)用,會(huì)立即返回授權(quán)狀態(tài)靖避;如果此方法返回AVAuthorizationStatusNotDetermined
潭枣,則可以調(diào)用+ requestAccessForMediaType:completionHandler:
以提示用戶記錄權(quán)限。
我們不妨執(zhí)行下述代碼筋蓖,分析打印結(jié)果:
switch ([AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo])
{
case AVAuthorizationStatusNotDetermined:
[AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) {
NSLog(@"granted --- %d currentThread : %@",granted,NSThread.currentThread);
}];
NSLog(@"用戶尚未授予或拒絕該權(quán)限:AVAuthorizationStatusNotDetermined");
break;
case AVAuthorizationStatusRestricted:
NSLog(@"不允許用戶訪問媒體捕獲設(shè)備:AVAuthorizationStatusRestricted");
break;
case AVAuthorizationStatusDenied:
NSLog(@"用戶已經(jīng)明確拒絕了應(yīng)用訪問捕獲設(shè)備:AVAuthorizationStatusDenied");
break;
case AVAuthorizationStatusAuthorized:
NSLog(@"用戶授予應(yīng)用訪問捕獲設(shè)備的權(quán)限:AVAuthorizationStatusAuthorized");
break;
default:
break;
}
NSLog(@"currentThread : %@",NSThread.currentThread);
/****************** 打印結(jié)果 *************************
14:24:54 用戶已經(jīng)明確拒絕了應(yīng)用訪問捕獲設(shè)備:AVAuthorizationStatusDenied
14:24:54 currentThread : <NSThread: 0x170264e00>{number = 1, name = main}
****************************************************/
注意:使用
AVMediaTypeVideo
或AVMediaTypeAudio
以外的任何媒體類型調(diào)用此方法都會(huì)引發(fā)異常NSInvalidArgumentException
卸耘。
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** +[AVCaptureDevice authorizationStatusForMediaType:] The passed mediaType text is not supported'
*** First throw call stack:
(0x1836e2fe0 0x182144538 0x18b1008c0 0x1000a2b04 0x18982c838 0x18982c5a8 0x1898cc09c 0x1898cb870 0x1898cb424 0x1898cb388 0x189811cc0 0x186a02274 0x1869f6de8 0x1869f6ca8 0x18697234c 0x1869993ac 0x186999e78 0x1836909a8 0x18368e630 0x1835bedc4 0x18987efc8 0x189879c9c 0x1000a62f0 0x1825cd59c)
libc++abi.dylib: terminating with uncaught exception of type NSException
1.3、媒體類型AVMediaType
媒體類型AVMediaType是使用typedef
修飾的標(biāo)識(shí)符粘咖,提供各種媒體類型:
值 | 描述 |
---|---|
AVMediaTypeVideo |
指定視頻 |
AVMediaTypeAudio |
指定音頻 |
AVMediaTypeText |
指定文本 |
AVMediaTypeClosedCaption |
指定閉路內(nèi)容 |
AVMediaTypeSubtitle |
指定字幕 |
AVMediaTypeTimecode |
指定一個(gè)時(shí)間代碼 |
AVMediaTypeMetadata |
指定元數(shù)據(jù) |
AVMediaTypeMuxed |
指定mux媒體 |
AVMediaTypeMetadataObject |
|
AVMediaTypeDepthData |
1.4蚣抗、授權(quán)狀態(tài)AVAuthorizationStatus
授權(quán)狀態(tài)AVAuthorizationStatus是個(gè)枚舉類型,提供有關(guān)使用捕獲設(shè)備AVCaptureDevice
權(quán)限信息的常量:
值 | 描述 |
---|---|
AVAuthorizationStatusNotDetermined |
用戶尚未授予或拒絕該權(quán)限瓮下, |
AVAuthorizationStatusRestricted |
不允許用戶訪問媒體捕獲設(shè)備翰铡。這個(gè)狀態(tài)通常是看不到的:用于發(fā)現(xiàn)設(shè)備的AVCaptureDevice 類方法不會(huì)返回用戶被限制訪問的設(shè)備。 |
AVAuthorizationStatusDenied |
用戶已經(jīng)明確拒絕了應(yīng)用訪問捕獲設(shè)備 |
AVAuthorizationStatusAuthorized |
用戶授予應(yīng)用訪問捕獲設(shè)備的權(quán)限 |
1.5讽坏、使用例子
+ (void)getAuthorizationStatus:(void(^)(void))authorizedBlock
{
switch ([AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo]){
case AVAuthorizationStatusNotDetermined:{
[AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted){
if (granted){
dispatch_async(dispatch_get_main_queue(), ^{
if (authorizedBlock) {
authorizedBlock();
}
});
}
NSLog(@"granted --- %d currentThread : %@",granted,NSThread.currentThread);
}];
NSLog(@"用戶尚未授予或拒絕該權(quán)限:AVAuthorizationStatusNotDetermined");
}
break;
case AVAuthorizationStatusRestricted:
NSLog(@"不允許用戶訪問媒體捕獲設(shè)備:AVAuthorizationStatusRestricted");
break;
case AVAuthorizationStatusDenied:
{
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"沒有權(quán)限" message:@"該功能需要授權(quán)使用你的相機(jī)" preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"拒絕" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {}];
UIAlertAction *okAction = [UIAlertAction actionWithTitle:@"授權(quán)" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
NSURL *url= [NSURL URLWithString:UIApplicationOpenSettingsURLString];
if (@available(iOS 10.0, *)){
if( [[UIApplication sharedApplication]canOpenURL:url] ) {
[[UIApplication sharedApplication]openURL:url options:@{}completionHandler:^(BOOL success) {
}];
}
}else{
if( [[UIApplication sharedApplication]canOpenURL:url] ) {
[[UIApplication sharedApplication]openURL:url];
}
}
}];
[alertController addAction:cancelAction];
[alertController addAction:okAction];
[UIApplication.sharedApplication.keyWindow.rootViewController presentViewController:alertController animated:YES completion:nil];
NSLog(@"用戶已經(jīng)明確拒絕了應(yīng)用訪問捕獲設(shè)備:AVAuthorizationStatusDenied");
}
break;
case AVAuthorizationStatusAuthorized:
{
dispatch_async(dispatch_get_main_queue(), ^{
if (authorizedBlock) {
authorizedBlock();
}
});
NSLog(@"用戶授予應(yīng)用訪問捕獲設(shè)備的權(quán)限:AVAuthorizationStatusAuthorized");
}
break;
default:
break;
}
}
在進(jìn)入相機(jī)拍攝界面之前锭魔,調(diào)用上述方法,只有授權(quán)使用相機(jī)時(shí)回調(diào)authorizedBlock
進(jìn)入相機(jī)界面:
[AVCaptureTools getAuthorizationStatus:^{
if (@available(iOS 10.2, *)) {
//使用 AVCapturePhotoOutput 拍照
UINavigationController *nav = [[UINavigationController alloc]initWithRootViewController:[[AVCaptureViewController alloc]init]];
self.window.rootViewController = nav;
} else {
//使用 AVCaptureStillImageOutput 拍照
UINavigationController *nav = [[UINavigationController alloc]initWithRootViewController:[[AVCaptureLowVersionViewController alloc]init]];
self.window.rootViewController = nav;
}
}];
2路呜、發(fā)現(xiàn)設(shè)備
2.1迷捧、AVCaptureDeviceDiscoverySession
在 iPhone 7plus 及以后某些 iPhone 上织咧,采用了后置雙攝像頭配置:一個(gè)廣角鏡頭和一個(gè)長(zhǎng)焦鏡頭,這兩個(gè)鏡頭可以合并為一個(gè)單一采集設(shè)備一起工作漠秋。在iOS 10
及以后的 版本中使用 AVCaptureDeviceDiscoverySession 查詢可用AVCaptureDevice
笙蒙。使用這個(gè)類可以找到所有匹配特定設(shè)備類型deviceTypes
(如麥克風(fēng)或廣角相機(jī))、支持用于捕獲的媒體類型(如音頻庆锦、視頻或兩者)和相機(jī)位置(前或后)的可用AVCaptureDevice
捅位。
使用下述類方法創(chuàng)建一個(gè)AVCaptureDeviceDiscoverySession
,用于查找具有指定標(biāo)準(zhǔn)的設(shè)備:
+ (instancetype)discoverySessionWithDeviceTypes:(NSArray<AVCaptureDeviceType> *)deviceTypes mediaType:(AVMediaType)mediaType position:(AVCaptureDevicePosition)position;
- 參數(shù)
NSArray<AVCaptureDeviceType> *deviceTypes
:要搜索的設(shè)備類型列表搂抒,例如 麥克風(fēng)AVCaptureDeviceTypeBuiltInMicrophone
和相機(jī)AVCaptureDeviceTypeBuiltInWideAngleCamera
艇搀。這個(gè)數(shù)組必須至少包含一個(gè)有效的AVCaptureDeviceType
值。
創(chuàng)建AVCaptureDeviceDiscoverySession
后求晶,讀取其設(shè)備數(shù)組devices
以檢查匹配的設(shè)備并選擇一個(gè)可用的AVCaptureDevice
焰雕。
@property(nonatomic, readonly) NSArray<AVCaptureDevice *> *devices;
這個(gè)數(shù)組只包含當(dāng)前可用的AVCaptureDevice
(在讀取屬性時(shí)),并且滿足使用+ discoverySessionWithDeviceTypes:mediaType:position: initializer
創(chuàng)建設(shè)備發(fā)現(xiàn)會(huì)話時(shí)指定的條件誉帅。
在 iOS 11.0 及更高版本中淀散,這個(gè)數(shù)組的順序與用于創(chuàng)建發(fā)現(xiàn)會(huì)話的
deviceTypes
參數(shù)的順序相匹配,因此可以快速選擇匹配首選類型的設(shè)備(請(qǐng)參閱帶有發(fā)現(xiàn)會(huì)話的排序和篩選設(shè)備)蚜锨。在較老的iOS版本中档插,搜索整個(gè)數(shù)組以找到首選設(shè)備。
2.1.1亚再、 AVCaptureDeviceType
設(shè)備類型AVCaptureDeviceType是使用typedef
修飾的標(biāo)識(shí)符郭膛,提供各種設(shè)備類型,與+ defaultDeviceWithDeviceType:mediaType:position:
方法和AVCaptureDeviceDiscoverySession
類一起使用氛悬。
設(shè)備類型AVCaptureDeviceType
|
描述 |
---|---|
AVCaptureDeviceTypeBuiltInMicrophone |
一個(gè)內(nèi)置的麥克風(fēng) |
AVCaptureDeviceTypeBuiltInWideAngleCamera |
內(nèi)置廣角相機(jī),這些裝置適用于一般用途则剃。 |
AVCaptureDeviceTypeBuiltInTelephotoCamera |
內(nèi)置長(zhǎng)焦相機(jī),比廣角相機(jī)的焦距長(zhǎng)如捅。這種類型只是將窄角設(shè)備與配備兩種類型的攝像機(jī)的硬件上的寬角設(shè)備區(qū)分開來棍现。要確定攝像機(jī)設(shè)備的實(shí)際焦距,可以檢查AVCaptureDevice 的format 數(shù)組中的AVCaptureDeviceFormat 對(duì)象镜遣。 |
AVCaptureDeviceTypeBuiltInDualCamera |
廣角相機(jī)和長(zhǎng)焦相機(jī)的組合己肮,創(chuàng)建了一個(gè)拍照,錄像的AVCaptureDevice 悲关。具有和深度捕捉谎僻,增強(qiáng)變焦和雙圖像捕捉功能。 |
AVCaptureDeviceTypeBuiltInTrueDepthCamera |
相機(jī)和其他傳感器的組合寓辱,創(chuàng)建了一個(gè)捕捉設(shè)備艘绍,能夠拍照、視頻和深度捕捉秫筏。 |
AVCaptureDeviceTypeBuiltInDuoCamera |
iOS 10.2 之后添加自動(dòng)變焦功能诱鞠,該值功能被AVCaptureDeviceTypeBuiltInDualCamera 替代 |
2.1.2挎挖、 AVCaptureDevicePosition
相機(jī)鏡頭位置AVCaptureDevicePosition是個(gè)枚舉類型:
值 | 描述 |
---|---|
AVCaptureDevicePositionUnspecified |
AVCaptureDevice 相對(duì)于系統(tǒng)硬件的位置未指定。 |
AVCaptureDevicePositionBack |
后置鏡頭 |
AVCaptureDevicePositionFront |
前置鏡頭 |
2.2般甲、獲取指定設(shè)備
2.2.1肋乍、多個(gè)篩選條件獲取一個(gè)默認(rèn)設(shè)備
+ (AVCaptureDevice *)defaultDeviceWithDeviceType:(AVCaptureDeviceType)deviceType mediaType:(AVMediaType)mediaType position:(AVCaptureDevicePosition)position;
返回指定設(shè)備類型鹅颊、媒體類型和位置的默認(rèn)設(shè)備敷存;如果當(dāng)前沒有可用設(shè)備滿足指定條件,則為nil堪伍。使用該方法可以輕松地為指定場(chǎng)景選擇系統(tǒng)默認(rèn)AVCaptureDevice
锚烦,例如,要在支持的硬件上獲得雙攝像頭帝雇,并返回到標(biāo)準(zhǔn)廣角攝像頭涮俄;
- (AVCaptureDevice *)defaultCamera {
AVCaptureDevice *device;
if (@available(iOS 10.0, *)) {
device = [AVCaptureDevice defaultDeviceWithDeviceType: AVCaptureDeviceTypeBuiltInDuoCamera
mediaType: AVMediaTypeVideo
position: AVCaptureDevicePositionBack];
} else {
// Fallback on earlier versions
}
if (device != nil) {
return device;
}
if (@available(iOS 10.0, *)) {
device = [AVCaptureDevice defaultDeviceWithDeviceType: AVCaptureDeviceTypeBuiltInWideAngleCamera
mediaType: AVMediaTypeVideo
position: AVCaptureDevicePositionBack];
} else {
// Fallback on earlier versions
}
if (device != nil) {
return device;
}
return nil;
}
2.2.2、給定ID的一個(gè)設(shè)備
+ (AVCaptureDevice *)deviceWithUniqueID:(NSString *)deviceUniqueID;
返回具有給定ID的設(shè)備尸闸。
2.2.3彻亲、給定媒體類型AVMediaType
的一個(gè)設(shè)備
+ (AVCaptureDevice *)defaultDeviceWithMediaType:(AVMediaType)mediaType;
返回指定媒體類型AVMediaType
的默認(rèn)設(shè)備。
注意:使用該方法請(qǐng)求攝像機(jī)
AVMediaTypeVideo
時(shí)吮廉,返回的總是AVCaptureDeviceTypeBuiltInWideAngleCamera
設(shè)備類型苞尝。要使用其他設(shè)備類型,使用+ defaultDeviceWithDeviceType:mediaType:position:
方法宦芦。
2.2.4宙址、返回一組設(shè)備
//返回系統(tǒng)上可用捕獲設(shè)備的數(shù)組。已經(jīng)被蘋果使用AVCaptureDeviceDiscoverySession替代
+ (NSArray<AVCaptureDevice *> *)devices;
//返回給定媒體類型的設(shè)備數(shù)組调卑。已經(jīng)被蘋果使用AVCaptureDeviceDiscoverySession替代
+ (NSArray<AVCaptureDevice *> *)devicesWithMediaType:(AVMediaType)mediaType;
2.3抡砂、通知
通知 | 描述 |
---|---|
AVCaptureDeviceWasConnectedNotification |
當(dāng)新設(shè)備可用時(shí)發(fā)送一個(gè)通知,通知對(duì)象是AVCaptureDevice 實(shí)例恬涧,表示已可用的設(shè)備注益。 |
AVCaptureDeviceWasDisconnectedNotification |
當(dāng)現(xiàn)有設(shè)備不可用時(shí)發(fā)送一個(gè)通知,通知對(duì)象是AVCaptureDevice 實(shí)例溯捆,表示不可用的設(shè)備丑搔。 |
2.4、例子
我們以獲取mediaType
為AVMediaTypeVideo
的后置鏡頭為例:
- (void)getTheAVCaptureDevice
{
if (@available(iOS 10.2, *)) {
NSArray<AVCaptureDeviceType> *deviceTypes = @[AVCaptureDeviceTypeBuiltInWideAngleCamera, AVCaptureDeviceTypeBuiltInDualCamera];//設(shè)備類型:廣角鏡頭现使、雙鏡頭
AVCaptureDeviceDiscoverySession *sessionDiscovery = [AVCaptureDeviceDiscoverySession discoverySessionWithDeviceTypes:deviceTypes mediaType:AVMediaTypeVideo position:AVCaptureDevicePositionBack];
NSArray<AVCaptureDevice *> *devices = sessionDiscovery.devices;//當(dāng)前可用的AVCaptureDevice集合
__block AVCaptureDevice *newVideoDevice = nil;
//遍歷所有可用的AVCaptureDevice低匙,獲取 后置雙鏡頭
[devices enumerateObjectsUsingBlock:^(AVCaptureDevice * _Nonnull device, NSUInteger idx, BOOL * _Nonnull stop) {
if ( device.position == AVCaptureDevicePositionBack && [device.deviceType isEqualToString:AVCaptureDeviceTypeBuiltInDualCamera] ) {
newVideoDevice = device;
* stop = YES;
}
}];
if (!newVideoDevice){
//如果后置雙鏡頭獲取失敗,則獲取廣角鏡頭
[devices enumerateObjectsUsingBlock:^(AVCaptureDevice * _Nonnull device, NSUInteger idx, BOOL * _Nonnull stop) {
if ( device.position == AVCaptureDevicePositionBack) {
newVideoDevice = device;
* stop = YES;
}
}];
}
} else {
//獲取指定mediaType類型的AVCaptureDevice集合
NSArray<AVCaptureDevice *> *devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
__block AVCaptureDevice *newVideoDevice = nil;
//遍歷所有可用的AVCaptureDevice碳锈,獲取后置鏡頭
[devices enumerateObjectsUsingBlock:^(AVCaptureDevice * _Nonnull device, NSUInteger idx, BOOL * _Nonnull stop) {
if ( device.position == AVCaptureDevicePositionBack) {
newVideoDevice = device;
* stop = YES;
}
}];
}
}
我們可以看到顽冶,針對(duì)不同版本的 iOS 系統(tǒng),蘋果提供了兩種方法獲取指定的AVCaptureDevice
:在適配 iOS 10 以后的版本中售碳,我們可以使用AVCaptureDeviceDiscoverySession
獲取后置雙鏡頭强重!但是在另一種方法中绞呈,我們無法使用雙鏡頭,只能獲取一個(gè)默認(rèn)的廣角鏡頭间景。
3佃声、配置設(shè)備
3.1、鎖定設(shè)備
AVCaptureDevice
在改變某些參數(shù)前必須先鎖定倘要,直到改變結(jié)束才能解鎖:
//在修改AVCaptureDevice相關(guān)屬性之前圾亏,必須調(diào)用下述方法上鎖;當(dāng)這個(gè)方法成功地鎖定設(shè)備進(jìn)行配置時(shí)封拧,它返回YES志鹃;如果沒有獲得鎖,則為NO泽西。
- (BOOL)lockForConfiguration:(NSError * _Nullable *)outError;
//在修改AVCaptureDevice相關(guān)屬性完成后曹铃,還需要調(diào)用下述方法解鎖,允許其他應(yīng)用程序進(jìn)行更改捧杉。
- (void)unlockForConfiguration;
如果要求設(shè)備屬性保持不變陕见,可以持有一個(gè)鎖而不釋放它。然而味抖,不必要地持有設(shè)備鎖可能會(huì)降低共享設(shè)備的其他應(yīng)用程序的捕獲質(zhì)量评甜。
在iOS中,直接設(shè)置AVCaptureDevice
的activeFormat
屬性非竿,會(huì)導(dǎo)致AVCaptureSession
的預(yù)設(shè)值sessionPreset
更改為AVCaptureSessionPresetInputPriority
蜕着。更改AVCaptureSession
時(shí),當(dāng)調(diào)用它的startRunning
方法 或 更改它的結(jié)構(gòu)(如添加红柱、刪除輸入和輸出)后調(diào)用-commitConfiguration
方法時(shí)承匣,AVCaptureSession
不再自動(dòng)配置捕獲格式。但是在 Mac OS 中锤悄,在進(jìn)行更改之后韧骗,AVCaptureSession
仍然可以自動(dòng)配置捕獲格式activeFormat
。
為了防止 Mac OS 中捕捉格式activeFormat
的自動(dòng)更改零聚,需要執(zhí)行以下步驟:
- 1袍暴、調(diào)用
AVCaptureDevice
的- lockForConfiguration:
方法鎖定設(shè)備。 - 2隶症、更改
AVCaptureDevice
的activeFormat
屬性政模。 - 3、調(diào)用
AVCaptureSession
的startRunning
方法 - 4蚂会、調(diào)用
AVCaptureDevice
的- unlockForConfiguration
解鎖設(shè)備淋样。
為了防止 在修改 Mac OS 中的AVCaptureSession
的結(jié)構(gòu)后自動(dòng)更改activeFormat
:
- 1、調(diào)用
AVCaptureDevice
的- lockForConfiguration:
方法鎖定設(shè)備胁住。 - 2趁猴、調(diào)用
AVCaptureSession
的- beginConfiguration
方法刊咳,修改它的結(jié)構(gòu); - 3儡司、調(diào)用
AVCaptureSession
的- commitConfiguration
方法娱挨,提交修改; - 4捕犬、調(diào)用
AVCaptureDevice
的- unlockForConfiguration
解鎖設(shè)備跷坝。
3.2、一些設(shè)備參數(shù)
屬性 | 類型 | 描述 |
---|---|---|
inUseByAnotherApplication |
BOOL |
指示設(shè)備是否被其他應(yīng)用程序占用或听。 |
suspended |
BOOL |
指示設(shè)備是否掛起探孝。一些設(shè)備由于參數(shù)設(shè)置不允許數(shù)據(jù)捕獲;例如誉裆,當(dāng)iSight的隱私虹膜關(guān)閉時(shí),isSuspended 會(huì)返回YES缸濒,對(duì)于筆記本上的iSight攝像機(jī)足丢,或者對(duì)于筆記本顯示關(guān)閉時(shí)的內(nèi)部iSight攝像機(jī),issuspend會(huì)返回YES庇配。 |
linkedDevices |
NSArray<AVCaptureDevice *> |
一組AVCaptureDevice 對(duì)象斩跌,表示外接設(shè)備。例如捞慌,對(duì)于外部iSight攝像機(jī)耀鸦,數(shù)組包含一個(gè)AVCaptureDevice 實(shí)例,表示外部iSight麥克風(fēng)啸澡。 |
transportType |
int32_t |
AVCaptureDevice 的傳輸類型(USB袖订、PCI等)。 |
inputSources |
NSArray<AVCaptureDeviceInputSource *> |
AVCaptureDevice 支持的輸入源的AVCaptureDeviceInputSource 對(duì)象數(shù)組嗅虏。 有些設(shè)備可以從多個(gè)數(shù)據(jù)源之一(例如洛姑,同一音頻設(shè)備上的不同輸入插孔)捕獲數(shù)據(jù)。 |
activeInputSource |
AVCaptureDeviceInputSource |
當(dāng)前活躍的輸入源皮服。要設(shè)置該屬性楞艾,需要先調(diào)用- lockForConfiguration: 方法鎖定設(shè)備;否則將拋出異常NSGenericException 龄广;如果傳遞的format 在formats 中不存在硫眯,調(diào)用-setActiveInputSource: 拋出異常NSInvalidArgumentException 。 |
3.3择同、輸入源AVCaptureDeviceInputSource
AVCaptureDeviceInputSource是捕獲設(shè)備AVCaptureDevice
上的輸入源两入。
AVCaptureDevice
對(duì)象可以從inputSources
數(shù)組中選擇一個(gè)作為輸入源,表示設(shè)備的不同的互斥輸入奠衔。例如谆刨,音頻捕獲設(shè)備可能具有ADAT光學(xué)和模擬輸入源;視頻捕獲設(shè)備可能有HDMI輸入源或組件輸入源塘娶。
屬性 | 類型 | 描述 |
---|---|---|
inputSourceID |
NSString |
輸入源ID;在指定AVCaptureDevice 對(duì)象的輸入源中痊夭,ID是唯一的刁岸。 |
localizedName |
NSString |
輸入源的本地化名稱;可以使用此屬性在用戶界面中顯示AVCaptureDevice 輸入源的名稱她我。 |
4虹曙、檢查設(shè)備特征
屬性 | 類型 | 描述 |
---|---|---|
connected |
BOOL |
表示AVCaptureDevice 實(shí)例當(dāng)前是否已連接,是否可用番舆。但是冬骚,當(dāng)這個(gè)屬性的值對(duì)于給定的AVCaptureDevice 實(shí)例變成NO時(shí),它就不會(huì)再變成YES咒钟。如果相同的物理設(shè)備再次對(duì)系統(tǒng)可用糙臼,它將使用AVCaptureDevice 的新實(shí)例表示。 |
position |
AVCaptureDevicePosition |
表示設(shè)備AVCaptureDevice 的物理位置禾怠。 |
modelID |
NSString |
設(shè)備的型號(hào)ID返奉。該值是同一型號(hào)的所有設(shè)備的唯一標(biāo)識(shí)符,該值是跨設(shè)備連接和斷開連接以及跨不同系統(tǒng)的持久值吗氏。例如芽偏,內(nèi)置在兩個(gè)相同iPhone機(jī)型上的攝像頭的型號(hào)ID將是相同的,盡管它們是不同的物理設(shè)備弦讽。 |
localizedName |
NSString |
一個(gè)本地可讀的AVCaptureDevice 設(shè)備名稱污尉;可以使用該值在用戶界面中顯示AVCaptureDevice 設(shè)備設(shè)備的名稱。 |
uniqueID |
NSString |
AVCaptureDevice 唯一ID往产,它可以跨設(shè)備連接和斷開連接被碗、應(yīng)用程序重新啟動(dòng)和系統(tǒng)重新啟動(dòng)在一個(gè)系統(tǒng)上持續(xù)存在∥嫫耄可以存儲(chǔ)該值蛮放,以便將來收回或跟蹤特定設(shè)備的狀態(tài)。 |
lensAperture |
float |
鏡片隔膜的尺寸奠宜,表示透鏡光圈的大小(f號(hào))包颁。是個(gè)只讀屬性,該值不變压真。 |
deviceType |
AVCaptureDeviceType |
設(shè)備類型娩嚼,如內(nèi)置麥克風(fēng)或廣角攝像機(jī)。 |
manufacturer |
NSString |
設(shè)備制造商滴肿。對(duì)于所有蘋果設(shè)備來說岳悟,這一屬性值都是“Apple Inc.”;來自第三方制造商的設(shè)備可能不被識(shí)別,此時(shí)該值值為空字符串贵少。 |
//返回一個(gè)布爾值呵俏,表示AVCaptureDevice是否為指定AVMediaType提供媒體。
- (BOOL)hasMediaType:(AVMediaType)mediaType;
//返回一個(gè)布爾值滔灶,表示AVCaptureDevice是否可以使用 指定sessionPreset的會(huì)話AVCaptureSession普碎。
- (BOOL)supportsAVCaptureSessionPreset:(AVCaptureSessionPreset)preset;
5、管理格式
5.1录平、捕獲格式AVCaptureDeviceFormat
AVCaptureDeviceFormat 對(duì)象詳細(xì)描述了特定捕獲模式的視頻麻车、圖像或音頻參數(shù)等,提供一組可用于配置AVCaptureDevice
的媒體格式與設(shè)置斗这,如視頻分辨率和幀速率动猬。
5.2、設(shè)備支持的捕獲格式
@property(nonatomic, readonly) NSArray<AVCaptureDeviceFormat *> *formats;
該屬性提供了AVCaptureDevice
支持的捕獲格式表箭,如果需要訪問AVCaptureSession
預(yù)設(shè)中未包含的設(shè)置赁咙,可以將activeFormat
屬性設(shè)置為該數(shù)組中的任何格式。
5.3燃逻、當(dāng)前捕獲格式
@property(nonatomic, retain) AVCaptureDeviceFormat *activeFormat;
該屬性提供了AVCaptureDevice
的當(dāng)前活動(dòng)媒體數(shù)據(jù)格式序目;可以使用此屬性獲取或設(shè)置當(dāng)前活動(dòng)的設(shè)備格式。
在iOS中伯襟,通常在AVCaptureSession
對(duì)象上設(shè)置sessionPreset
來配置圖像或視頻捕獲,并使用共享的AVAudioSession
對(duì)象來配置音頻捕獲握童;在使用sessionPreset
時(shí)姆怪,AVCaptureSession
會(huì)自動(dòng)控制AVCaptureDevice
的活動(dòng)格式activeFormat
。然而澡绩,在AVCaptureSession
的設(shè)置中稽揭,有些專門的捕獲選項(xiàng)(比如高幀率)是不可用的;對(duì)于這些選項(xiàng)肥卡,需要設(shè)置AVCaptureDevice
的活動(dòng)格式activeFormat
溪掀,這樣做將關(guān)聯(lián)的AVCaptureSession
的sessionPreset
更改為AVCaptureSessionPresetInputPriority
。
注意:試圖將activeFormat
設(shè)置為formats
數(shù)組中不存在的格式步鉴,會(huì)拋出NSInvalidArgumentException
揪胃。
在更改此屬性的值之前,必須調(diào)用-lockForConfiguration:
以獲得對(duì)設(shè)備配置屬性的訪問權(quán)氛琢,否則喊递,設(shè)置此屬性的值將引發(fā)異常;完成設(shè)備配置后阳似,調(diào)用-unlockForConfiguration
釋放鎖并允許其他設(shè)備配置設(shè)置骚勘。還必須在調(diào)用AVCaptureSession
的-startRunning
方法之前調(diào)用-lockForConfiguration:
,或AVCaptureSession
的sessionPreset
將覆蓋AVCaptureDevice
的活動(dòng)格式activeFormat
。
5.4俏讹、當(dāng)前深度捕獲格式
@property(nonatomic, retain) AVCaptureDeviceFormat *activeDepthDataFormat;
該屬性提供了AVCaptureDevice
的當(dāng)前活動(dòng)深度數(shù)據(jù)格式当宴。
當(dāng)使用AVCaptureDepthDataOutput
類捕獲深度信息時(shí),或者使用AVCapturePhotoOutput
類在照片旁邊啟用捕獲深度映射時(shí)泽疆,捕獲輸出自動(dòng)使用與其活動(dòng)照片/視頻捕獲格式相關(guān)聯(lián)的深度數(shù)據(jù)格式户矢。如果需要更改深度捕獲格式,需要設(shè)置此屬性的值于微。
深度數(shù)據(jù)捕獲要求視頻/照片數(shù)據(jù)的兼容捕獲格式逗嫡,如果將此屬性設(shè)置為當(dāng)前activeFormat
對(duì)象AVCaptureDeviceFormat
的supporteddepthdataformat
數(shù)組中沒有列出的捕獲格式,將會(huì)引發(fā)異常株依。
不能直接設(shè)置深度數(shù)據(jù)捕獲的幀速率:深度數(shù)據(jù)幀速率與設(shè)備的activeVideoMinFrameDuration
和activeVideoMaxFrameDuration
值是同步的驱证,可以等于設(shè)備當(dāng)前的幀速率,如果設(shè)備不能以足夠快的速度生成深度數(shù)據(jù)恋腕,則可以降低抹锄。深度數(shù)據(jù)捕獲可能會(huì)增加系統(tǒng)負(fù)載,從而降低視頻幀速率以實(shí)現(xiàn)熱可持續(xù)性荠藤。
在更改此屬性的值之前伙单,必須調(diào)用-lockForConfiguration:
以獲得對(duì)設(shè)備配置屬性的訪問權(quán),否則哈肖,設(shè)置此屬性的值將引發(fā)異常吻育;完成設(shè)備配置后,調(diào)用-unlockForConfiguration
釋放鎖并允許其他設(shè)備配置設(shè)置淤井。還必須在調(diào)用AVCaptureSession
的-startRunning
方法之前調(diào)用-lockForConfiguration:
布疼,或AVCaptureSession
的sessionPreset
將覆蓋AVCaptureDevice
的活動(dòng)格式activeFormat
。
6币狠、焦點(diǎn)設(shè)置
鏡頭焦點(diǎn)與焦距的區(qū)別:
焦點(diǎn) 是透鏡(或曲面鏡)將光線會(huì)聚后所形成的點(diǎn),因光線會(huì)聚成一點(diǎn)可將物燒焦游两。
焦距 是焦點(diǎn)到面鏡的中心點(diǎn)之間的距離。鏡頭焦距的長(zhǎng)短決定著拍攝的成像大小漩绵,視場(chǎng)角大小贱案,景深大小和畫面的透視強(qiáng)弱。鏡頭的焦距是鏡頭的一個(gè)非常重要的指標(biāo)止吐。鏡頭焦距的長(zhǎng)短決定了被攝物在成像介質(zhì)(膠片或CCD等)上成像的大小宝踪,也就是相當(dāng)于物和象的比例尺。當(dāng)對(duì)同一距離遠(yuǎn)的同一個(gè)被攝目標(biāo)拍攝時(shí)祟印,鏡頭焦距長(zhǎng)的所成的象大肴沫,鏡頭焦距短的所成的象小。根據(jù)用途的不同蕴忆,照相機(jī)鏡頭的焦距相差非常大颤芬,有短到幾毫米,十幾毫米的,也有長(zhǎng)達(dá)幾米的站蝠。
6.1汰具、對(duì)焦模式
屬性 | 類型 | 描述 |
---|---|---|
focusMode |
AVCaptureFocusMode |
設(shè)備的對(duì)焦模式。在更改此屬性的值之前菱魔,必須調(diào)用-lockForConfiguration: 以鎖定AVCaptureDevice 留荔;否則,設(shè)置此屬性的值會(huì)引發(fā)異常澜倦。完成配置設(shè)備后聚蝶,請(qǐng)調(diào)用-unlockForConfiguration 以釋放鎖定并允許其他設(shè)備配置設(shè)置。 |
focusPointOfInterestSupported |
BOOL |
指示設(shè)備是否支持焦點(diǎn)藻治。 |
adjustingFocus |
BOOL |
指示設(shè)備當(dāng)前是否正在調(diào)整其焦點(diǎn)設(shè)置碘勉。 |
AVCaptureFocusMode 用于指定捕獲設(shè)備的焦點(diǎn)模式的枚舉。
枚舉值 | 描述 |
---|---|
AVCaptureFocusModeLocked |
焦點(diǎn)被鎖定桩卵。 |
AVCaptureFocusModeAutoFocus |
設(shè)備會(huì)自動(dòng)調(diào)整焦距一次验靡,然后將焦點(diǎn)模式更改為AVCaptureFocusModeLocked 。 |
AVCaptureFocusModeContinuousAutoFocus |
AVCaptureDevice 持續(xù)監(jiān)視焦點(diǎn)并在必要時(shí)自動(dòng)聚焦雏节。 |
當(dāng)設(shè)備支持焦點(diǎn)胜嗓,設(shè)置對(duì)焦模式時(shí),我們需要調(diào)用- (BOOL)isFocusModeSupported:(AVCaptureFocusMode)focusMode
方法判斷設(shè)備是否支持給定的焦點(diǎn)模式钩乍。如果支持focusMode
則為YES辞州,否則為NO。
6.2寥粹、焦點(diǎn)位置設(shè)置
@property(nonatomic) CGPoint focusPointOfInterest;
聚焦的中心點(diǎn)孙技; {0,0}
是圖片區(qū)域的左上角,{1,1}
是右下角排作。無論實(shí)際的設(shè)備方向如何,此坐標(biāo)系始終相對(duì)于橫向設(shè)備方向亚情,主頁(yè)按鈕位于右側(cè)妄痪。可以使用AVCaptureVideoPreviewLayer
方法在此坐標(biāo)系和視圖坐標(biāo)之間進(jìn)行轉(zhuǎn)換楞件。
設(shè)置此屬性不會(huì)啟動(dòng)聚焦操作衫生。要將相機(jī)聚焦在中心點(diǎn),首先設(shè)置此屬性的值土浸,然后將focusMode
屬性設(shè)置為AVCaptureFocusModeAutoFocus
或AVCaptureFocusModeContinuousAutoFocus
罪针。
在更改此屬性的值之前,必須調(diào)用-lockForConfiguration:
以鎖定AVCaptureDevice
黄伊;否則泪酱,設(shè)置此屬性的值會(huì)引發(fā)異常。完成配置設(shè)備后,請(qǐng)調(diào)用-unlockForConfiguration
以釋放鎖定并允許其他設(shè)備配置設(shè)置墓阀。
6.3毡惜、自動(dòng)對(duì)焦
屬性 | 類型 | 描述 |
---|---|---|
smoothAutoFocusSupported |
BOOL |
指示設(shè)備是否支持平滑自動(dòng)對(duì)焦。自動(dòng)對(duì)焦模式僅適用于兼容設(shè)備斯撮,如果此屬性的值為NO经伙,則將smoothAutoFocusEnabled 的值設(shè)置為YES會(huì)引發(fā)異常。 |
smoothAutoFocusEnabled |
BOOL |
用于確定是否啟用了平滑自動(dòng)對(duì)焦勿锅;在兼容設(shè)備上帕膜,可以啟用自動(dòng)對(duì)焦模式,使鏡頭移動(dòng)速度更慢溢十。在更改此屬性的值之前垮刹,必須調(diào)用-lockForConfiguration: 以鎖定AVCaptureDevice ;否則茶宵,設(shè)置此屬性的值會(huì)引發(fā)異常危纫。完成配置設(shè)備后,請(qǐng)調(diào)用-unlockForConfiguration 以釋放鎖定并允許其他設(shè)備配置設(shè)置乌庶。 |
6.4种蝶、自動(dòng)對(duì)焦范圍
屬性
AVCaptureAutoFocusRangeRestriction autoFocusRangeRestriction
:
控制自動(dòng)對(duì)焦允許范圍;默認(rèn)情況下瞒大,能夠進(jìn)行硬件聚焦的設(shè)備會(huì)嘗試聚焦在任何距離的對(duì)象上螃征。如果希望主要關(guān)注近物體或遠(yuǎn)物體,請(qǐng)?jiān)O(shè)置范圍限制以提高速度并降低自動(dòng)聚焦的功耗透敌,并減少聚焦模糊的可能性盯滚。
在更改此屬性的值之前,必須調(diào)用-lockForConfiguration:
以鎖定AVCaptureDevice
酗电;否則魄藕,設(shè)置此屬性的值會(huì)引發(fā)異常。完成配置設(shè)備后撵术,請(qǐng)調(diào)用-unlockForConfiguration
以釋放鎖定并允許其他設(shè)備配置設(shè)置背率。屬性
BOOL autoFocusRangeRestrictionSupported
:一個(gè)布爾值,指示設(shè)備是否支持焦距范圍限制嫩与。對(duì)焦范圍限制僅適用于兼容設(shè)備寝姿。 如果此屬性的值為NO,則設(shè)置autoFocusRangeRestriction
會(huì)引發(fā)異常划滋。
AVCaptureAutoFocusRangeRestriction
用于指定捕獲設(shè)備的自動(dòng)聚焦范圍的枚舉:如果您希望主要關(guān)注近物體或遠(yuǎn)物體饵筑,可以使用autoFocusRangeRestriction
屬性為聚焦系統(tǒng)提供提示。 這種方法使自動(dòng)對(duì)焦更快处坪,更節(jié)能根资,并且更不容易出錯(cuò)架专。 限制優(yōu)先于指定范圍內(nèi)的距離聚焦,但如果設(shè)備在該范圍內(nèi)沒有找到焦點(diǎn)嫂冻,則不會(huì)阻止聚焦在別處胶征。
枚舉值 | 描述 |
---|---|
AVCaptureAutoFocusRangeRestrictionNone |
設(shè)備會(huì)嘗試關(guān)注任何范圍內(nèi)的對(duì)象。此值是默認(rèn)值桨仿,是不支持焦點(diǎn)范圍限制的設(shè)備上允許的唯一值睛低。 |
AVCaptureAutoFocusRangeRestrictionNear |
該設(shè)備主要嘗試聚焦在相機(jī)附近的拍攝對(duì)象上。對(duì)于使用AVCaptureMetadataOutput 識(shí)別機(jī)器可讀代碼的應(yīng)用程序服傍,建議使用此值钱雷。 |
AVCaptureAutoFocusRangeRestrictionFar |
該設(shè)備主要嘗試對(duì)焦于遠(yuǎn)離相機(jī)的拍攝對(duì)象。 |
7吹零、鏡頭焦距設(shè)置
7.1罩抗、獲取鏡頭焦距
@property(nonatomic, readonly) float lensPosition;
表示鏡頭的焦距;取值范圍是 0.0~1.0 :0.0是鏡頭可以聚焦的最短距離灿椅,1.0是最遠(yuǎn)的距離套蒂;默認(rèn)值是1.0。
該值只能通過-setFocusModeLockedWithLensPosition:completionHandler:
來設(shè)置茫蛹。
const float AVCaptureLensPositionCurrent
表示當(dāng)前鏡頭位置的特殊常數(shù)操刀。將此值傳遞給-setFocusModeLockedWithLensPosition:completionHandler:
在不更改鏡頭當(dāng)前位置的情況下鎖定焦點(diǎn)(即禁用自動(dòng)對(duì)焦)。
7.2婴洼、焦距是否支持修改
@property(nonatomic, readonly, getter=isLockingFocusWithCustomLensPositionSupported) BOOL lockingFocusWithCustomLensPositionSupported;
指示設(shè)備是否支持將焦點(diǎn)鎖定到特定的鏡頭位置的布爾值骨坑;如果此屬性的值為NO,則使用除AVCaptureLensPositionCurrent
之外的鏡頭位置值調(diào)用-setFocusModeLockedWithLensPosition:completionHandler:
方法會(huì)引發(fā)異常柬采。
7.3欢唾、設(shè)置鏡頭焦距
- (void)setFocusModeLockedWithLensPosition:(float)lensPosition completionHandler:(void (^)(CMTime syncTime))handler;
修改鏡頭焦距為指定值;該方法是設(shè)置鏡頭焦距的唯一路徑粉捻。如果lensPosition
被設(shè)為不支持的值礁遣,這個(gè)方法會(huì)拋出NSInvalidArgumentException
異常。如果調(diào)用該方法前沒有使用lockForConfiguration
鎖定AVCaptureDevice
肩刃,則會(huì)引發(fā)NSGenericException
異常亡脸。
- 第一個(gè)參數(shù)
lensPosition
:鏡頭的焦距; - 第二個(gè)參數(shù)
(void (^)(CMTime syncTime))handler
: 當(dāng)lensPosition
設(shè)置為指定值且屬性focusMode
為AVCaptureFocusModeLocked
時(shí)調(diào)用的塊树酪。 該塊接收與已應(yīng)用所有設(shè)置的第一個(gè)緩沖區(qū)匹配的時(shí)間戳;時(shí)間戳與設(shè)備時(shí)鐘同步大州,因此必須先轉(zhuǎn)換為主時(shí)鐘续语,然后再與AVCaptureVideoDataOutput
實(shí)例傳送的緩沖區(qū)的時(shí)間戳進(jìn)行比較。如果不需要知道操作的完成情況厦画,可以將參數(shù)傳遞nil疮茄。
8滥朱、閃光燈設(shè)置
屬性 | 類型 | 描述 |
---|---|---|
hasFlash |
BOOL |
指示AVCaptureDevice 是否有閃光燈。 |
flashMode |
AVCaptureFlashMode |
當(dāng)前的閃光燈模式力试。在更改此屬性的值之前徙邻,必須調(diào)用-lockForConfiguration: 以鎖定AVCaptureDevice ;否則畸裳,設(shè)置此屬性的值會(huì)引發(fā)異常缰犁。完成配置設(shè)備后,請(qǐng)調(diào)用-unlockForConfiguration 以釋放鎖定并允許其他設(shè)備配置設(shè)置怖糊。 |
flashAvailable |
BOOL |
指示閃光燈當(dāng)前是否可用帅容;例如,如果設(shè)備過熱并需要冷卻伍伤,閃光燈可能會(huì)變得不可用并徘。 |
AVCaptureFlashMode 是指定AVCaptureDevice
的閃光燈模式的枚舉:
枚舉值 | 描述 |
---|---|
AVCaptureFlashModeOff |
捕獲設(shè)備閃光燈始終處于關(guān)閉狀態(tài)。 |
AVCaptureFlashModeOn |
捕獲設(shè)備閃存始終打開扰魂。 |
AVCaptureFlashModeAuto |
捕獲設(shè)備持續(xù)監(jiān)控光照水平麦乞,并在必要時(shí)使用閃光燈。 |
我們可以調(diào)用 - (BOOL)isFlashModeSupported:(AVCaptureFlashMode)flashMode;
方法判斷是否支持指定的閃光模式劝评。
- (void)flashModelButtonClick:(UIButton *)sender
{
dispatch_async( self.sessionQueue, ^{
AVCaptureDevice *device = self.videoDeviceInput.device;
//是否有閃光燈姐直,閃光燈當(dāng)前是否可用:如果設(shè)備過熱并需要冷卻,閃光燈可能會(huì)變得不可用
if (device.hasFlash == NO || device.flashAvailable == NO) {
return ;
}
NSError *error = nil;
if ([device lockForConfiguration:&error] ) {
switch (device.flashMode){
case AVCaptureFlashModeAuto:{
if ([device isFlashModeSupported:AVCaptureFlashModeOn]){
[device setFlashMode:AVCaptureFlashModeOn];
dispatch_async(dispatch_get_main_queue(), ^{
[sender setImage:resourceImage(@"cameraFlash_On") forState:UIControlStateNormal];
});
}
}
break;
case AVCaptureFlashModeOff:{
if ([device isFlashModeSupported:AVCaptureFlashModeAuto]){
[device setFlashMode:AVCaptureFlashModeAuto];
dispatch_async(dispatch_get_main_queue(), ^{
[sender setImage:resourceImage(@"cameraFlash_Auto") forState:UIControlStateNormal];
});
}
}
break;
case AVCaptureFlashModeOn: {
if ([device isFlashModeSupported:AVCaptureFlashModeOff]){
[device setFlashMode:AVCaptureFlashModeOff];
dispatch_async(dispatch_get_main_queue(), ^{
[sender setImage:resourceImage(@"cameraFlash_Off") forState:UIControlStateNormal];
});
}
}
break;
default:
break;
}
[device unlockForConfiguration];
}
else {
NSLog( @"Could not lock device for configuration: %@", error );
}
} );
}
9付翁、手電筒設(shè)置
手電筒是一種光源简肴,例如LED閃光燈,可在設(shè)備上使用百侧,用于照亮捕獲的內(nèi)容或提供一般照明砰识。
屬性 | 類型 | 描述 |
---|---|---|
hasTorch |
BOOL |
反映當(dāng)前設(shè)備是否具有內(nèi)置的手電筒。即使設(shè)備有手電筒佣渴,也可能無法使用辫狼。 因此,在使用之前檢查torchAvailable 屬性的值辛润。 |
torchAvailable |
BOOL |
指示手電筒當(dāng)前是否可供使用膨处。例如,如果設(shè)備過熱并需要冷卻砂竖,則手電筒可能無法使用真椿。 |
torchActive |
BOOL |
指示設(shè)備的手電筒當(dāng)前是否打開。必須在設(shè)備上有一個(gè)手電筒乎澄,并且當(dāng)前可用突硝,然后才能激活它。 |
torchLevel |
float |
獲取當(dāng)前手電筒亮度級(jí)別置济;其值在 0.0 到 1.0 的范圍內(nèi):0.0 表示手電筒已關(guān)閉解恰,1.0 表示理論最大值锋八,如果設(shè)備當(dāng)前過熱,則實(shí)際最大值可能更低护盈。 |
torchMode |
AVCaptureTorchMode |
目前的手電筒模式挟纱;設(shè)置此屬性的值還會(huì)將手電筒級(jí)別設(shè)置為其最大當(dāng)前值。在更改此屬性的值之前腐宋,必須調(diào)用-lockForConfiguration: 以鎖定AVCaptureDevice 紊服;否則,設(shè)置此屬性的值會(huì)引發(fā)異常脏款。完成配置設(shè)備后围苫,請(qǐng)調(diào)用-unlockForConfiguration 以釋放鎖定并允許其他設(shè)備配置設(shè)置。 |
9.1撤师、手電筒模式
AVCaptureTorchMode 指定AVCaptureDevice
的手電筒模式的枚舉:
枚舉值 | 描述 |
---|---|
AVCaptureTorchModeOff |
設(shè)備手電筒始終關(guān)閉剂府。 |
AVCaptureTorchModeOn |
設(shè)備手電筒始終打開。 |
AVCaptureTorchModeAuto |
設(shè)備持續(xù)監(jiān)控光照水平剃盾,并在必要時(shí)使用手電筒腺占。 |
- (BOOL)isTorchModeSupported:(AVCaptureTorchMode)torchMode;
我們必須在修改torchMode
之前調(diào)用上述方法判斷設(shè)備是否支持指定的手電筒模式。
9.2痒谴、設(shè)置手電筒照明級(jí)別
- (BOOL)setTorchModeOnWithLevel:(float)torchLevel error:(NSError * _Nullable *)outError;
我們?cè)O(shè)置手電筒照明級(jí)別衰伯,需要調(diào)用上述方法。要將割炬模式級(jí)別torchLevel
設(shè)置為當(dāng)前可用的最大值积蔚,需要使用常量AVCaptureMaxAvailableTorchLevel
意鲸。
設(shè)置手電筒照明級(jí)別之前需要將手電筒模式torchMode
設(shè)置為AVCaptureTorchModeOn
并將級(jí)別設(shè)置為指定值。 如果設(shè)備不支持AVCaptureTorchModeOn
手電筒模式尽爆,或者如果為torchLevel
指定的值超出了可接受的范圍怎顾,則此方法會(huì)引發(fā)異常。 如果割炬值在可接受范圍內(nèi)但大于當(dāng)前支持的最大值 - 可能是因?yàn)樵O(shè)備過熱 - 此方法只返回NO漱贱。
在更改此屬性的值之前槐雾,必須調(diào)用-lockForConfiguration:
以鎖定AVCaptureDevice
;否則幅狮,設(shè)置此屬性的值會(huì)引發(fā)異常募强。完成配置設(shè)備后,請(qǐng)調(diào)用-unlockForConfiguration
以釋放鎖定并允許其他設(shè)備配置設(shè)置崇摄。
10擎值、縮放設(shè)置
10.1、用于控制圖像的縮放值
@property(nonatomic) CGFloat videoZoomFactor;
該屬性是一個(gè)用于控制AVCaptureDevice
的圖像的裁剪和放大的值逐抑;它是一個(gè)乘數(shù):例如幅恋,值 2.0 會(huì)使圖像主體的大小加倍(并使視野減半)。允許的值范圍從 1.0(完整視野)到活動(dòng)格式AVCaptureDeviceFormat
的屬性videoMaxZoomFactor
值泵肄。
AVCaptureDevice
通過圍繞傳感器捕獲的圖像的中心進(jìn)行裁剪來實(shí)現(xiàn)縮放效果捆交。在低縮放系數(shù)下,裁剪的圖像等于或大于輸出大小腐巢。在較高的縮放系數(shù)下品追,設(shè)備必須將裁剪后的圖像縮放到輸出尺寸,從而導(dǎo)致圖像質(zhì)量下降冯丙∪馔撸活動(dòng)格式AVCaptureDeviceFormat
的videoZoomFactorUpscaleThreshold屬性指示將進(jìn)行放大的因素。
在更改此屬性的值之前胃惜,必須調(diào)用-lockForConfiguration:
以鎖定AVCaptureDevice
泞莉;否則,設(shè)置此屬性的值會(huì)引發(fā)異常船殉。完成配置設(shè)備后鲫趁,請(qǐng)調(diào)用-unlockForConfiguration
以釋放鎖定并允許其他設(shè)備配置設(shè)置。
設(shè)置此屬性的值會(huì)立即跳轉(zhuǎn)到新的縮放系數(shù)利虫;要流暢過渡挨厚,需要使用-rampToVideoZoomFactor:withRate:
方法。
最小縮放值
@property(nonatomic, readonly) CGFloat minAvailableVideoZoomFactor;
當(dāng)前AVCaptureDevice
配置中允許的最小縮放系數(shù)糠惫。在單攝像頭設(shè)備上疫剃,此值始終為 1.0 ;在雙攝像頭設(shè)備上硼讽,如果設(shè)備將深度數(shù)據(jù)傳送到一個(gè)或多個(gè)捕獲輸出巢价,則允許的視頻縮放系數(shù)范圍可能會(huì)發(fā)生變化。
設(shè)置屬性videoZoomFactor
或調(diào)用-rampToVideoZoomFactor:withRate:
方法使值小于 1.0 會(huì)引發(fā)異常固阁。 將視頻縮放系數(shù)設(shè)置為介于 1.0 和最小可用縮放系數(shù)之間的值會(huì)將縮放設(shè)置限制為最小值壤躲。
最大縮放值
@property(nonatomic, readonly) CGFloat maxAvailableVideoZoomFactor;
當(dāng)前AVCaptureDevice
配置中允許的最大縮放系數(shù)。在單攝像頭設(shè)備上您炉,此值始終等于AVCaptureDeviceFormat
的屬性videoMaxZoomFactor
柒爵;在雙攝像頭設(shè)備上,如果設(shè)備將深度數(shù)據(jù)傳送到一個(gè)或多個(gè)捕獲輸出赚爵,則允許的視頻縮放系數(shù)范圍可能會(huì)發(fā)生變化棉胀。
設(shè)置屬性videoZoomFactor
或調(diào)用-rampToVideoZoomFactor:withRate:
方法使其值大于AVCaptureDeviceFormat
的屬性videoMaxZoomFactor
,會(huì)引發(fā)異常冀膝。將視頻縮放系數(shù)設(shè)置為最大可用縮放系數(shù)與設(shè)備格式最大值之間的值會(huì)將縮放設(shè)置限制為最大可用值唁奢。
10.2、流暢過渡到新的縮放值
我們可以使用下述方法實(shí)現(xiàn)從當(dāng)前縮放因子到另一個(gè)縮放因子的流暢過渡:
- (void)rampToVideoZoomFactor:(CGFloat)factor withRate:(float)rate;
在該方法中有兩個(gè)參數(shù):
-
CGFloat factor
: 新的放大系數(shù)窝剖; -
float rate
:轉(zhuǎn)換到新放大系數(shù)的速率麻掸,以每秒 2 的冪表示。
縮放值factor
允許范圍從1.0(完整視野)到活動(dòng)捕獲格式AVCaptureDeviceFormat
指定的屬性videoMaxZoomFactor
值赐纱。
在變化期間脊奋,縮放系數(shù)factor
以指數(shù)速率變化熬北,但這會(huì)產(chǎn)生視覺線性過渡。rate
參數(shù)控制此轉(zhuǎn)換的速度诚隙,與方向無關(guān); 例如讶隐,值 1.0 會(huì)導(dǎo)致縮放因子在放大時(shí)每秒加倍(即,如果指定的因子大于當(dāng)前的videoZoomFactor
)久又,或者如果縮小則每秒減半巫延。
在更改此屬性的值之前,必須調(diào)用-lockForConfiguration:
以鎖定AVCaptureDevice
地消;否則炉峰,設(shè)置此屬性的值會(huì)引發(fā)異常。完成配置設(shè)備后脉执,請(qǐng)調(diào)用-unlockForConfiguration
以釋放鎖定并允許其他設(shè)備配置設(shè)置疼阔。
10.3、結(jié)束縮放
流暢的進(jìn)行縮放需要一定的過渡時(shí)間适瓦,我們可能需要停止該緩慢的過渡竿开,需要調(diào)用下述方法:
- (void)cancelVideoZoomRamp;
該方法能流暢地結(jié)束正在進(jìn)行的縮放而不是突然停止;調(diào)用此方法相當(dāng)于調(diào)用 -rampToVideoZoomFactor:withRate:
的速率rate
為零玻熙。 如果正在進(jìn)行縮放轉(zhuǎn)換否彩,則轉(zhuǎn)換將減慢為停止。
在更改此屬性的值之前嗦随,必須調(diào)用-lockForConfiguration:
以鎖定AVCaptureDevice
列荔;否則,設(shè)置此屬性的值會(huì)引發(fā)異常枚尼。完成配置設(shè)備后贴浙,請(qǐng)調(diào)用-unlockForConfiguration
以釋放鎖定并允許其他設(shè)備配置設(shè)置。
10.4署恍、其它指示參數(shù)
屬性 | 類型 | 描述 |
---|---|---|
rampingVideoZoom |
BOOL |
指示是否正在進(jìn)行縮放轉(zhuǎn)換的布爾值崎溃。使用KVO觀察對(duì)此屬性值的更改,以便在縮放過渡開始或結(jié)束時(shí)得到通知盯质。 |
dualCameraSwitchOverVideoZoomFactor |
CGFloat |
雙攝像頭設(shè)備可以在攝像頭之間自動(dòng)切換的視頻縮放系數(shù)袁串;在該系數(shù)下,來自廣角攝像機(jī)的縮放視野與遠(yuǎn)攝相機(jī)的全視野相匹配呼巷。 當(dāng)videoZoomFactor 設(shè)置達(dá)到或超過此值時(shí)囱修,設(shè)備可以根據(jù)場(chǎng)景條件自動(dòng)選擇哪個(gè)攝像機(jī)提供輸出圖像(或自動(dòng)組合兩者的圖像以創(chuàng)建最終輸出)。對(duì)于低于此值的縮放系數(shù)王悍,設(shè)備始終使用來自廣角攝像機(jī)的圖像破镰。在單攝像頭設(shè)備上,此值始終為1.0。 |
10.5鲜漩、縮放示例
//最小縮放值
- (CGFloat)minZoomFactor
{
CGFloat minZoomFactor = 1.0;
if (@available(iOS 11.0, *)) {
minZoomFactor = self.device.minAvailableVideoZoomFactor;
}
return minZoomFactor;
}
//最大縮放值
- (CGFloat)maxZoomFactor
{
CGFloat maxZoomFactor = self.device.activeFormat.videoMaxZoomFactor;
if (@available(iOS 11.0, *)) {
maxZoomFactor = self.device.maxAvailableVideoZoomFactor;
}
if (maxZoomFactor > 6.0) {
maxZoomFactor = 6.0;
}
return maxZoomFactor;
}
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
{
if ([gestureRecognizer isKindOfClass:[UIPinchGestureRecognizer class]]){
self.slider.minimumValue = self.minZoomFactor;
self.slider.maximumValue = self.maxZoomFactor;
self.currentZoomFactor = self.device.videoZoomFactor;
}
return YES;
}
//縮放手勢(shì)
- (void)zoomChangePinchGestureRecognizerClick:(UIPinchGestureRecognizer *)pinchGestureRecognizer
{
if (pinchGestureRecognizer.state == UIGestureRecognizerStateBegan ||
pinchGestureRecognizer.state == UIGestureRecognizerStateChanged)
{
CGFloat currentZoomFactor = self.currentZoomFactor * pinchGestureRecognizer.scale;
self.slider.hidden = NO;
if (currentZoomFactor < self.maxZoomFactor &&
currentZoomFactor > self.minZoomFactor){
NSError *error = nil;
if ([self.device lockForConfiguration:&error] ) {
self.device.videoZoomFactor = currentZoomFactor;
self.slider.value = self.device.videoZoomFactor;
[self.device unlockForConfiguration];
}
else {
NSLog( @"Could not lock device for configuration: %@", error );
}
}
}
else
{
self.slider.hidden = YES;
}
}
- (void)sliderValueChangeClick:(UISlider *)sender
{
self.slider.hidden = NO;
if (sender.value < self.maxZoomFactor &&
sender.value > self.minZoomFactor){
NSError *error = nil;
if ([self.device lockForConfiguration:&error] ) {
self.device.videoZoomFactor = sender.value;
[self.device unlockForConfiguration];
}
else {
NSLog( @"Could not lock device for configuration: %@", error );
}
}
}
由于篇幅限制源譬,關(guān)于 AVCaptureDevice
的更多知識(shí)在 OC之AVCaptureDevice續(xù)