AVFoundation - 捕捉設(shè)備: AVCaptureDevice

AVCaptureDevice是相機(jī)硬件的接口,用于配置底層硬件的屬性,這些底層硬件包括前后置攝像頭、麥克風(fēng)、閃光燈等。

驗(yàn)證授權(quán)

1. 請求用戶授權(quán)指定的媒體類型

為保護(hù)用戶隱私,應(yīng)用在使用相機(jī)或者麥克風(fēng)時(shí),總是需要用戶授權(quán)才能正常使用。當(dāng)應(yīng)用第一次需要權(quán)限的媒體類型創(chuàng)建任何AVCaptureDeviceInput對象時(shí),系統(tǒng)會(huì)自動(dòng)顯示一個(gè)alert以請求用戶授權(quán)。在被授予任何訪問權(quán)限之前,任何AVMediaType類型的AVCaptureDevice都將關(guān)閉靜默音頻樣本或黑色視頻幀。
調(diào)用下面方法,可以讓應(yīng)用直接獲取用戶授權(quán),而不是需要等到創(chuàng)建AVCaptureDeviceInput對象時(shí),系統(tǒng)自動(dòng)顯示一個(gè)alert以請求用戶授權(quán)。

+ (void)requestAccessForMediaType:(AVMediaType)mediaType completionHandler:(void (^)(BOOL granted))handler

該方法有兩個(gè)參數(shù):

  • 第一個(gè)參數(shù)mediaType: 媒體類型常量,可以是AVMediaTypeVideo和AVMediaTypeAudio,如果沒有提供媒體類型或提供其他的媒體類型,都將拋出異常
  • 第二個(gè)參數(shù)(void (^)(BOOL granted))handler: 獲得用戶相應(yīng)后調(diào)用的塊,如果用戶授予使用硬件的權(quán)限,則granted返回YES,否則返回NO.注意塊回調(diào)可能在任意線程,如果需要處理UI,需要切回主線程。
    如果調(diào)用該方法之前,已經(jīng)顯示alert以請求用戶授權(quán),不管用戶同意或者拒絕授權(quán),該方法的回調(diào)都會(huì)立即放回用戶曾經(jīng)的授權(quán)結(jié)果,而不會(huì)再次顯示一個(gè)alert請求用戶授權(quán)。

應(yīng)用程序必須在配置信息info.plist中提供使用NSCameraUsageDescription或NSMicrophoneUsageDescription信息的解釋。iOS在最初請求用戶許可時(shí)顯示了這個(gè)解釋,然后在設(shè)置應(yīng)用程序中顯示。在沒有使用說明的情況下啟動(dòng)AVCaptureSession會(huì)引發(fā)異常。

2. 獲取制定媒體類型的授權(quán)狀態(tài)

為了獲悉應(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)限

授權(quán)狀態(tài)AVAuthorizationStatus

  • AVAuthorizationStatusNotDetermined: 用戶尚未授權(quán)
  • AVAuthorizationStatusRestricted:不允許用戶訪問媒體捕獲設(shè)備,用戶不能改變客戶機(jī)的狀態(tài),可能由于活躍的限制,如家長控制,這個(gè)狀態(tài)通常是看不到的,用于發(fā)現(xiàn)設(shè)備的類方法不會(huì)返回用戶被限制訪問的設(shè)備。
  • AVAuthorizationStatusDenied:用戶已經(jīng)明確拒絕了應(yīng)用訪問捕獲設(shè)備
  • AVAuthorizationStatusAuthorized: 用戶授予應(yīng)用訪問捕獲設(shè)備的權(quán)限

媒體類型AVMediaType

  • AVMediaTypeVideo: 指定視頻
  • AVMediaTypeAudio: 指定音頻
  • AVMediaTypeText: 指定文本
  • AVMediaTypeClosedCaption: 指定閉路內(nèi)容
  • AVMediaTypeSubtitle: 指定字幕
  • AVMediaTypeTimecode: 指定一個(gè)時(shí)間代碼
  • AVMediaTypeMetadata: 指定元數(shù)據(jù)
  • AVMediaTypeMuxed: 指定混合媒體
  • AVMediaTypeMetadataObject
  • AVMediaTypeDepthData

通知

  • AVCaptureDeviceWasConnectedNotification
    當(dāng)新設(shè)備可用時(shí)發(fā)送一個(gè)通知,通知對象是AVCaptureDevice實(shí)例,表示已可用的設(shè)備。
  • AVCaptureDeviceWasDisconnectedNotification
    當(dāng)現(xiàn)有設(shè)備不可用時(shí)發(fā)送一個(gè)通知,通知對象是AVCaptureDevice實(shí)例,表示不可用的設(shè)備。

閃光燈

在光線不足的情況下,需要開啟屏幕的閃光燈來進(jìn)行補(bǔ)光,便于鏡頭可以捕捉更好的場景,拍攝出好的照片和視頻

  • iOS 10之前閃光燈設(shè)置
   AVCaptureDevice *device = nil;
   NSArray *inputs = self.session.inputs;
   for (AVCaptureDeviceInput *input in inputs) {
       if ([device.deviceType isEqual:AVMediaTypeVideo]) {
           device = input.device;
       }
   }
   NSError *errorProperty = nil;
   if ([device hasFlash]) {
       if ([device isFlashAvailable]) {
           if ([device isFlashModeSupported:AVCaptureFlashModeOn]) {
               BOOL result = NO;
               result = [device lockForConfiguration:&errorProperty];
               if (result) {
                   [device setFlashMode:AVCaptureFlashModeOn];
               }else {
                   NSLog(@"ERROR : CONFIGURATION CAPTURE DEVICE FLASH FAILURE, ERROR CODE:%ld", (long)errorProperty.code);
               }
               [device unlockForConfiguration];
           }else{
               NSLog(@"ERROR : FLASH IS UNAVAILABLE BECAUSE THE DEVCICE OVERHEATS");
           }
       }else {
           NSLog(@"ERROR : SOFTWARE DEVICE HAVE NO FLASH");
       }
   }
  • iOS 10之后閃光燈設(shè)置
    NSArray *outputs = self.session.outputs;
    for (AVCaptureOutput *output in outputs) {
        if ([output isMemberOfClass:[AVCapturePhotoOutput class]]) {
            AVCapturePhotoOutput *photoOutput = (AVCapturePhotoOutput *)output;
            BOOL flashSupported = [[photoOutput supportedFlashModes] containsObject:@(AVCaptureFlashModeAuto)];
            if (flashSupported) {
                AVCapturePhotoSettings *photoSettings = photoOutput.photoSettingsForSceneMonitoring;
                photoSettings.flashMode = AVCaptureFlashModeAuto;
            }else {
                NSLog(@"ERROR : PHOTOOUTPUT CAN NOT SUPPORT AVCAPTUREMODE TYPE");
            }
        }
    }
  • 閃光燈類型
    AVCaptureFlashModeOff  = 0,//閃光燈關(guān)閉
    AVCaptureFlashModeOn   = 1,//閃光燈開啟
    AVCaptureFlashModeAuto = 2,//閃光燈自動(dòng)

手電筒

在光線不是很暗的情況下我們可以用手機(jī)的LED燈當(dāng)作手電筒使用。

    AVCaptureDevice *device = nil;
    NSArray *inputs = self.session.inputs;
    for (AVCaptureDeviceInput *input in inputs) {
        if ([device.deviceType isEqual:AVMediaTypeVideo]) {
            device = input.device;
        }
    }
    NSError *error = nil;
    if ([device hasTorch]) {
        if ([device isTorchAvailable]) {
            if ([device isTorchModeSupported:AVCaptureTorchModeOn]) {
                BOOL result = NO;
                result = [device lockForConfiguration:&error];
                if (result) {
                    [device setTorchMode:AVCaptureTorchModeOn];
                }else {
                    NSLog(@"ERROR : CONFIGURATION DEVICE TORCH FAIL AND ERROR CODE %ld", (long)error.code);
                }
                error = nil;
                // Torch light
                result = [device setTorchModeOnWithLevel:0.5 error:&error];
                if (!result) {
                    NSLog(@"ERROR : DEVICE SET TORCH FAILURE AND ERROR CODE %ld", error.code);
                }
                [device unlockForConfiguration];
            }else {
                NSLog(@"ERROR : DEVICE CAN NO SUPPORT TORCH");
            }
        }else {
            NSLog(@"ERROR : SOFTHARE DEVICE TORCH IS UNAVAILABLE BECAUSE OVERHEATS");
        }
    }else {
        NSLog(@"ERROR : SOFFHARE DEVICE HAS NO TORCH");
    }

手電筒模式類型

   AVCaptureTorchModeOff  = 0,//關(guān)閉
   AVCaptureTorchModeOn   = 1,//打開
   AVCaptureTorchModeAuto = 2,//自動(dòng)

聚焦

- (void)focusAtPoint:(CGPoint)point {
    AVCaptureDevice *device = [self activeCamera];
    
    if (device.isFocusPointOfInterestSupported && [device isFocusModeSupported:AVCaptureFocusModeAutoFocus]) {
        NSError *error;
        // 鎖定設(shè)備準(zhǔn)備配置,如果獲得了鎖
        if ([device lockForConfiguration:&error]) {
            // 將focusPointOfInterest屬性設(shè)置CGPoint
            device.focusPointOfInterest = point;
            
            device.focusMode = AVCaptureFocusModeAutoFocus;
            
            // 釋放該鎖定
            [device unlockForConfiguration];
        } else {
            if ([self.delegate respondsToSelector:@selector(deviceConfigurationFailedWithError:)]) {
                [self.delegate deviceConfigurationFailedWithError:error];
            }
        }
    }
}
  • 聚焦類型
   AVCaptureFocusModeLocked              = 0,//鎖定當(dāng)前鏡頭位置
   AVCaptureFocusModeAutoFocus           = 1,//鏡頭自動(dòng)調(diào)焦
   AVCaptureFocusModeContinuousAutoFocus = 2,//鏡頭連續(xù)自動(dòng)調(diào)焦

曝光

- (void)exposeAtPoint:(CGPoint)point {
    AVCaptureDevice *device = [self activeCamera];
    
    if (device.isExposurePointOfInterestSupported && [device isExposureModeSupported:AVCaptureExposureModeContinuousAutoExposure]) {
        NSError *error;
        
        if ([device lockForConfiguration:&error]) {
            device.exposurePointOfInterest = point;
            device.exposureMode = AVCaptureExposureModeContinuousAutoExposure;
            
            [device unlockForConfiguration];
        } else {
            if ([self.delegate respondsToSelector:@selector(deviceConfigurationFailedWithError:)]) {
                [self.delegate deviceConfigurationFailedWithError:error];
            }
        }
    }
}
  • 曝光設(shè)置類型
    AVCaptureExposureModeLocked                            = 0,//鎖定
    AVCaptureExposureModeAutoExpose                        = 1,//自動(dòng)對焦
    AVCaptureExposureModeContinuousAutoExposure            = 2,//實(shí)現(xiàn)連續(xù)自動(dòng)對焦

白平衡

  • 類型設(shè)置白平衡
    AVCaptureDevice *device = nil;
    NSArray *inputs = self.session.inputs;
    for (AVCaptureDeviceInput *input in inputs) {
        if ([device.deviceType isEqual:AVMediaTypeVideo]) {
            device = input.device;
        }
    }
    if ([device isWhiteBalanceModeSupported:AVCaptureWhiteBalanceModeAutoWhiteBalance]) {
        NSError *error;
        if ([device lockForConfiguration:&error]) {
            [device setWhiteBalanceMode:AVCaptureWhiteBalanceModeAutoWhiteBalance];
        }
        [device unlockForConfiguration];
    }

白平衡類型

    AVCaptureWhiteBalanceModeLocked                     = 0,
    AVCaptureWhiteBalanceModeAutoWhiteBalance           = 1,
    AVCaptureWhiteBalanceModeContinuousAutoWhiteBalance = 2,
  • RGB設(shè)置白平衡
    AVCaptureDevice *device = nil;
    NSArray *inputs = self.session.inputs;
    for (AVCaptureDeviceInput *input in inputs) {
        if ([device.deviceType isEqual:AVMediaTypeVideo]) {
            device = input.device;
        }
    }
    float maxWhiteBalance = device.maxWhiteBalanceGain;
    float redGain =  MIN(2.0, maxWhiteBalance);
    float greenGain = MIN(2.0, maxWhiteBalance);
    float blueGain = MIN(2.0, maxWhiteBalance);
    AVCaptureWhiteBalanceGains whiteBalanceGains = {
        redGain,
        greenGain,
        blueGain
    };
    
    [device setWhiteBalanceModeLockedWithDeviceWhiteBalanceGains:whiteBalanceGains completionHandler:nil];
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容