會話的參數(shù)配置:
1)传睹、設(shè)置分辨率
使用會話上的 preset 來指定圖像的質(zhì)量和分辨率屹培。預(yù)設(shè)是一個常數(shù)轴总,確定了一部分可能的配置中的一個帮非;在某些情況下氧吐,設(shè)計的配置是設(shè)備特有的:
Symbol | Resolution | Comments |
---|---|---|
AVCaptureSessionPresetPhoto | Photo | Full photo resolution.This is not supported for video output. |
AVCaptureSessionPresetHigh | High | Highest recording quality.This varies per device. |
AVCaptureSessionPresetMedium | Medium | Suitable for Wi-Fi sharing.The actual values may change. |
AVCaptureSessionPresetLow | Low | Suitable for 3G sharing.The actual values may change. |
AVCaptureSessionPreset352x288 | 352x288 | CIF |
AVCaptureSessionPreset640x480 | 640x480 | VGA |
AVCaptureSessionPreset1280x720 | 1280x720 | 720p HD. |
AVCaptureSessionPreset1920x1080 | 1920x1080 | 1080P |
AVCaptureSessionPreset3840x2160 | 3840x2160 | UHD or 4K |
AVCaptureSessionPresetiFrame1280x720 | 1280x720 | Specifies capture settings to achieve 1280x720 quality iFrame H.264 video at about 40 Mbits/sec with AAC audio. |
AVCaptureSessionPresetiFrame960x540 | 960x540 | Specifies capture settings to achieve 960x540 quality iFrame H.264 video at about 30 Mbits/sec with AAC audio. |
AVCaptureSessionPresetInputPriority | *** | Specifies that the capture session does not control audio and video output settings. |
設(shè)置圖像的預(yù)設(shè)分辨率
if ([self.session canSetSessionPreset:self.captureSessionPreset]) {
[self.session setSessionPreset:self.captureSessionPreset];
}
如果需要比預(yù)設(shè)情況,更加精細(xì)的水平調(diào)整會話參數(shù)末盔,或者想給一個正在運(yùn)行的會話做些改變筑舅,用 beginConfiguration 和 commitConfiguration 方法。beginConfiguration 和 commitConfiguration 方法確保設(shè)備作為一個群體在變化陨舱,降低狀態(tài)的清晰度或者不協(xié)調(diào)性翠拣。調(diào)用 beginConfiguration 之后,可以添加或者移除輸出游盲,改變 sessionPreset
屬性误墓,或者單獨(dú)配置捕獲輸入或輸出屬性蛮粮。在你調(diào)用 commitConfiguration 之前實際上是沒有變化的,調(diào)用的時候它們才被應(yīng)用到一起优烧。
[session beginConfiguration];
// Remove an existing capture device.
// Add a new capture device.
// Reset the preset.
[session commitConfiguration];
2)蝉揍、切換輸入設(shè)備
一個 AVCaptureDevice 對象抽象出物理捕獲設(shè)備,提供了輸入數(shù)據(jù)(比如音頻或者視頻)給 AVCaptureSession
對象畦娄。例如每個輸入設(shè)備都有一個對象又沾,兩個視頻輸入,一個用于前置攝像頭熙卡,一個用于后置攝像頭杖刷,一個用于麥克風(fēng)的音頻輸入。
使用 AVCaptureDevice
類方法 devices 和 devicesWithMediaType: 可以找出哪一個捕獲設(shè)備當(dāng)前是可用的驳癌。而且如果有必要滑燃,可以找出 iPhone
,iPad
或者 iPod
提供了什么功能(詳情看:Device Capture Settings)颓鲜。雖然可用設(shè)備的列表可能會改變表窘。當(dāng)前輸入設(shè)備可能會變得不可用(如果他們被另一個應(yīng)用程序使用),新的輸入設(shè)備可能成為可用的甜滨,(如果他們被另一個應(yīng)用程序讓出)乐严。應(yīng)該注冊,當(dāng)可用設(shè)備列表改變時接收 AVCaptureDeviceWasConnectedNotification 和 AVCaptureDeviceWasDisconnectedNotification 通知衣摩。
測試是否支持特定設(shè)備的方法昂验,一般為這兩種:
1)、hasMediaType:
2)艾扮、supportsAVCaptureSessionPreset:
NSArray *devices = [AVCaptureDevice devices];
for (AVCaptureDevice *device in devices) {
NSLog(@"Device name: %@", [device localizedName]);
if ([device hasMediaType:AVMediaTypeVideo]) {
if ([device position] == AVCaptureDevicePositionBack) {
NSLog(@"Device position : back");
}
else {
NSLog(@"Device position : front");
}
}
}
不同設(shè)備有不同的功能既琴,一些可能支持不同的聚焦或者閃光模式;一些可能會支持聚焦在一個興趣點(diǎn)泡嘴。
// 如何找到有一個 torch 模式的視頻輸入設(shè)備甫恩,并且支持一個捕捉會話預(yù)設(shè)
NSArray *devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
NSMutableArray *torchDevices = [[NSMutableArray alloc] init];
for (AVCaptureDevice *device in devices) {
[if ([device hasTorch] &&
[device supportsAVCaptureSessionPreset:AVCaptureSessionPreset640x480]) {
[torchDevices addObject:device];
}
}
Switching Between Devices - 切換裝置
有時,你可能想允許用戶在輸入設(shè)備之間進(jìn)行切換磕诊,比如使用前置攝像頭到后置攝像頭的切換填物。為了避免暫停或者卡頓霎终,可以在運(yùn)行時配置一個會話滞磺,但是你應(yīng)該使用 beginConfiguration 和 commitConfiguration 支持你的配置改變:
AVCaptureSession *session = [[AVCaptureSession alloc] init];
[session beginConfiguration];
[session removeInput:frontFacingCameraDeviceInput];
[session addInput:backFacingCameraDeviceInput];
[session commitConfiguration];
當(dāng)最外面的 commitConfiguration 被調(diào)用,所有的改變都是一起做的莱褒。這保證了平穩(wěn)過渡击困。
AVCaptureDevicePositionBack
AVCaptureDevicePositionFront
- (void)changeCaptureDevicePosition:(AVCaptureDevicePosition)captureDevicePosition
newVideoDeviceInput:(AVCaptureDeviceInput *)newVideoDeviceInput
{
[self.session stopRunning];
[self.session beginConfiguration];
// Remove the existing device input first, since using the front and back camera simultaneously is not supported
[self.session removeInput:self.videoDeviceInput];
if ( [self.session canAddInput:newVideoDeviceInput] ) {
[self.session addInput:newVideoDeviceInput];
self.videoDeviceInput = newVideoDeviceInput;
self.videoDevice = newVideoDeviceInput.device;
} else {
if (self.videoDeviceInput) {
[self.session addInput:self.videoDeviceInput];
}
}
AVCaptureSessionPreset preset = self.captureSessionPreset;
if (![self.captureSessionPreset isEqualToString:preset]) {
if ([[self session] canSetSessionPreset:preset]) {
[[self session] setSessionPreset:preset];
self.captureSessionPreset = preset;
}
}
if (self.captureSupportOption & XYCaptureSupportOptionVideo) {
self.videoConnection = [self.videoDataOutPut connectionWithMediaType:AVMediaTypeVideo];
if ([self.videoConnection isVideoStabilizationSupported]) {
self.videoConnection.preferredVideoStabilizationMode = AVCaptureVideoStabilizationModeStandard;
}
[self.videoConnection setVideoOrientation:AVCaptureVideoOrientationLandscapeRight];
if(captureDevicePosition == AVCaptureDevicePositionFront){//mirror the front camera
[self.videoConnection setVideoMirrored:YES];
}else{
[self.videoConnection setVideoMirrored:NO];
}
}
[[self session] commitConfiguration];
[self.session startRunning];
}
Focus Modes - 聚焦模式
有3個聚焦模式:
-
AVCaptureFocusModeLocked :焦點(diǎn)的位置是固定的。
這是很有用的,當(dāng)你想讓用戶組成一個場景阅茶,然后鎖定焦點(diǎn)蛛枚。 -
AVCaptureFocusModeAutoFocus :照相機(jī)做一次掃描聚焦,然后將焦點(diǎn)鎖定脸哀。
這適合于蹦浦,你想要選擇一個特定的項目,即使它不是現(xiàn)場的中心撞蜂,但可以專注于該項目的焦點(diǎn)盲镶。 - AVCaptureFocusModeContinuousAutoFocus 相機(jī)需要不斷的自動對焦。
使用 isFocusModeSupported: 方法來決定設(shè)備是否支持給定的聚焦模式蝌诡,然后使用 focusMode 屬性設(shè)置模式溉贿。
此外,設(shè)備可能支持一個興趣焦點(diǎn)浦旱。使用 focusPointOfInterestSupported 進(jìn)行支持測試宇色。如果支持,使用 focusPointOfInterest 設(shè)置焦點(diǎn)颁湖。傳一個 CGPoing
宣蠕,橫向模式下(就是 home
鍵在右邊)圖片的左上角是 {0, 0}
,右下角是 {1, 1}
甥捺, – 即使設(shè)備是縱向模式也適用植影。
你可以使用 adjustingFocus 屬性來確定設(shè)備是否正在聚焦。當(dāng)設(shè)備開始涎永、停止聚焦時可以使用 key-value observing
觀察,接收通知鹿响。
// 如果改變聚焦模式設(shè)置羡微,可以將其返回到默認(rèn)配置
if ([currentDevice isFocusModeSupported:AVCaptureFocusModeContinuousAutoFocus]) {
CGPoint autofocusPoint = CGPointMake(0.5f, 0.5f);
[currentDevice setFocusPointOfInterest:autofocusPoint];
[currentDevice setFocusMode:AVCaptureFocusModeContinuousAutoFocus];
}
if (context == &CameraAdjustingFocusContext) {
NSLog(@"observeValueForKeyPath CameraAdjustingFocusContext");
AVCaptureDevice *device = (AVCaptureDevice *)object;
if (!device.isAdjustingFocus ) {
// 聚焦完成了
[object removeObserver:self forKeyPath:@"adjustingFocus" context:&CameraAdjustingFocusContext];
if (self.isAutoExposureAndFocusLock && [device isFocusModeSupported:AVCaptureFocusModeLocked]) {
dispatch_async(self.sessionQueue, ^{
BOOL adjustingFocus = [[change objectForKey:NSKeyValueChangeNewKey] isEqualToNumber:[NSNumber numberWithInt:1]];
if (adjustingFocus == NO) {
NSError *error;
if ([device lockForConfiguration:&error]) {
[device setFocusMode:AVCaptureFocusModeLocked];
[device setSubjectAreaChangeMonitoringEnabled:NO];
[device unlockForConfiguration];
dispatch_async(dispatch_get_main_queue(), ^{
if (weakSelf.lockSettingBlock) weakSelf.lockSettingBlock(YES, nil);
});
}
}
});
}else {
dispatch_async(dispatch_get_main_queue(), ^{
if (weakSelf.settingBlock) {
weakSelf.settingBlock(XYCameraSettingTypeAdjustFocus, YES, device.focusPointOfInterest, nil);
}
});
}
}
}
Exposure Modes - 曝光模式
有兩種曝光模式:
- AVCaptureExposureModeContinuousAutoExposure :設(shè)備根據(jù)需要自動調(diào)整曝光等級。
- AVCaptureExposureModeLocked :曝光等級固定在當(dāng)前等級惶我。
使用 isExposureModeSupported: 方法來確定設(shè)備是否支持給定的曝光模式妈倔,然后使用 exposureMode 屬性設(shè)置模式。
此外绸贡,一個設(shè)備支持一個曝光點(diǎn)盯蝴。使用 exposurePointOfInterestSupported 測試支持。如果支持听怕,使用 exposurePointOfInterest 設(shè)置曝光點(diǎn)捧挺。傳一個 CGPoing
,橫向模式下(就是 home
鍵在右邊)圖片的左上角是 {0, 0}
尿瞭,右下角是 {1, 1}
闽烙, – 即使設(shè)備是縱向模式也適用。
可以使用 adjustingExposure 屬性來確定設(shè)備當(dāng)前是否改變它的聚焦設(shè)置声搁。當(dāng)設(shè)備開始黑竞、停止聚焦時可以使用 key-value observing
觀察捕发,接收通知。
// 如果改變曝光設(shè)置很魂,可以將其返回到默認(rèn)配置
if ([currentDevice isExposureModeSupported:AVCaptureExposureModeContinuousAutoExposure]) {
CGPoint exposurePoint = CGPointMake(0.5f, 0.5f);
[currentDevice setExposurePointOfInterest:exposurePoint];
[currentDevice setExposureMode:AVCaptureExposureModeContinuousAutoExposure];
}
if (context == &CameraAdjustingExposureContext) {
NSLog(@"observeValueForKeyPath CameraAdjustingExposureContext");
AVCaptureDevice *device = (AVCaptureDevice *)object;
if (!device.isAdjustingExposure) {
// 鎖定曝光完成了
[object removeObserver:self forKeyPath:@"adjustingExposure" context:&CameraAdjustingExposureContext];
NSLog(@"device.exposureMode == %ld", (long)device.exposureMode);
if (self.isAutoExposureAndFocusLock && [device isExposureModeSupported:AVCaptureExposureModeLocked]) {
dispatch_async(self.sessionQueue, ^{
BOOL adjustingExposure = [[change objectForKey:NSKeyValueChangeNewKey] isEqualToNumber:[NSNumber numberWithInt:1]];
if (adjustingExposure) {
NSError *error;
if ([device lockForConfiguration:&error]) {
[device setExposureMode:AVCaptureExposureModeLocked];
[device unlockForConfiguration];
dispatch_async(dispatch_get_main_queue(), ^{
if (weakSelf.lockSettingBlock) weakSelf.lockSettingBlock(YES, nil);
});
}
}
});
}else {
CGFloat delayTime = 0;
if ([weakSelf isFrontCamera]) {
delayTime = 0.5;
}
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayTime * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
if (weakSelf.settingBlock) {
weakSelf.settingBlock(XYCameraSettingTypeAdjustExposure, YES, device.exposurePointOfInterest, nil);
}
});
}
}
}
Flash Modes - 閃光模式
有3種閃光模式:
- AVCaptureFlashModeOff :閃光燈不會閃扎酷。
- AVCaptureFlashModeOn :閃光燈總是會閃。
- AVCaptureFlashModeAuto :閃光燈取決去周圍的光感環(huán)境遏匆。
使用 hasFlash 來確定設(shè)備是否有閃光燈法挨。如果這個方法返回 YES
,然后使用 isFlashModeSupported: 方法確定設(shè)備是否支持給定的閃光模式拉岁,然后使用 flashMode 屬性設(shè)置模式坷剧。
Torch Mode - 手電筒模式
在手電筒模式下,閃光燈在一個低功率下一直開啟喊暖,以照亮對視頻捕獲惫企。有3個手電筒模式:
- AVCaptureTorchModeOff :總是關(guān)閉。
- AVCaptureTorchModeOn :總是打開陵叽。
- AVCaptureTorchModeAuto :閃光燈根據(jù)需要自動開關(guān)狞尔。
使用 hasTorch 來確定設(shè)備是否有閃光燈。使用 isTorchModeSupported: 方法來確定設(shè)備是否支持給定的閃光模式巩掺,然后使用 torchMode 屬性來設(shè)置模式偏序。
對于一個有手電筒的設(shè)備,只有當(dāng)該設(shè)備與一個運(yùn)行時捕捉會話關(guān)聯(lián)時胖替,才能打開手電筒研儒。
防抖
電影視頻的穩(wěn)定化可用于連接視頻上的操作,這取決于具體的硬件独令。盡管如此端朵,不是所有的源格式和視頻分辨率都被支持。
使用電影視頻穩(wěn)定化也可能會對視頻采集管道引起額外的延遲燃箭。正在使用視頻穩(wěn)定化時冲呢,使用 videoStabilizationEnabled 屬性可以檢測。enablesVideoStabilizationWhenAvailable 屬性允許應(yīng)用程序自動使視頻穩(wěn)定化可用招狸,如果它是被攝像頭支持的話敬拓。由于以上限制,默認(rèn)自動穩(wěn)定化是禁用的裙戏。
White Balance - 白平衡
有兩個白平衡模式:
- AVCaptureWhiteBalanceModeLocked :白平衡模式是固定的乘凸。
- AVCaptureWhiteBalanceModeContinuousAutoWhiteBalance :相機(jī)需要不斷調(diào)整白平衡。
使用 isWhiteBalanceModeSupported: :方法來確定設(shè)備是否支持給定的白平衡模式挽懦,然后使用 whiteBalanceMode 屬性設(shè)置模式翰意。
可以使用 adjustingWhiteBalance 屬性來確定設(shè)備是否正在改變白平衡設(shè)置。當(dāng)設(shè)備開始或者停止改變它的白平衡設(shè)置時,可以使用 key-value observing
觀察屬性冀偶,接收通知醒第。
Setting Device Orientation - 設(shè)置設(shè)備方向
在 AVCaptureConnection
設(shè)置期望的方向,來指定你想要的圖像在 AVCaptureOutput
(AVCaptureMovieFileOutput
进鸠, AVCaptureStillImageOutput
, AVCaptureVideoDataOutput
)中的方向稠曼,為了連接。
使用 AVCaptureConnectionsupportsVideoOrientation
屬性來確定設(shè)備是否支持改變視頻的方向客年,videoOrientation
屬性指定你想要的圖像在輸出端口的方向霞幅。列表4-1顯示了如何設(shè)置方向,為 AVCaptureConnection 設(shè)置 AVCaptureVideoOrientationLandscapeLeft 量瓜。
配置設(shè)備
在設(shè)備上設(shè)置捕獲屬性司恳,必須先使用 lockForConfiguration: 獲得設(shè)備鎖。這樣就避免了在其他應(yīng)用程序中可能與設(shè)置不兼容的更改绍傲。下面的代碼段演示了首先如何通過確定模式是否被支持的方式改變一個設(shè)備上的焦點(diǎn)模式扔傅,然后視圖鎖定設(shè)備重新配置。只有當(dāng)鎖被獲取到烫饼,焦點(diǎn)模式才會被改變猎塞,并且鎖被釋放后立即鎖定。
if ([device isFocusModeSupported:AVCaptureFocusModeLocked]) {
NSError *error = nil;
if ([device lockForConfiguration:&error]) {
device.focusMode = AVCaptureFocusModeLocked;
[device unlockForConfiguration];
}
else {
// Respond to the failure as appropriate.
}
只有在需要設(shè)置設(shè)備屬性保持不變的時候才應(yīng)該使設(shè)備鎖保持杠纵。沒必要的保持設(shè)備鎖荠耽,可能會在其他應(yīng)用程序共享設(shè)備時降低捕獲質(zhì)量。
Use Capture Inputs to Add a Capture Device to a Session - 使用捕獲輸入將捕獲設(shè)備添加到會話中
添加一個捕獲裝置到捕獲會話中比藻,使用 AVCaptureDeviceInput (AVCaptureInput 抽象類的具體子類)的實例铝量。捕獲設(shè)備輸入管理設(shè)備的端口。
NSError *error;
AVCaptureDeviceInput *input =
[AVCaptureDeviceInput deviceInputWithDevice:device error:&error];
if (!input) {
// Handle the error appropriately.
}
使用 addInput: 給會話添加一個輸入银亲。如果合適的話款违,可以使用 canAddInput: 檢查是否有輸入捕獲與現(xiàn)有會話是兼容的。
有關(guān)如果配置一個正在運(yùn)行的會話群凶,更多細(xì)節(jié)請查看 Configuring a Session .
AVCaptureInput
聲明一個或者多個媒體數(shù)據(jù)流。例如哄辣,輸入設(shè)備可以提供音頻和視頻數(shù)據(jù)请梢。輸入提供的每個媒體流都被一個 AVCaptureInputPort 所表示。一個捕獲會話使用 AVCaptureConnection
對象來定義一個 一組 AVCaptureInputPort
對象和一個 AVCaptureOutput
之間的映射力穗。
Use Capture Outputs to Get Output from a Session - 使用捕獲輸出從會話得到輸出
要從捕獲會話得到輸出毅弧,可以添加一個或多個輸出。一個輸出是 AVCaptureOutput 的具體子類的實例当窗。下面幾種使用:
AVCaptureMovieFileOutput 輸出電影文件
AVCaptureVideoDataOutput 如果你想處理被捕獲視頻的幀够坐,例如,創(chuàng)建自己的自定義
view layer
。AVCaptureAudioDataOutput 如果你想處理被捕獲的音頻數(shù)據(jù)。
AVCaptureStillImageOutput 如果你想捕獲有元數(shù)據(jù)的靜態(tài)圖像。
AVCapturePhotoOutput(AVCapturePhoto) 接替AVCaptureStillImageOutput
使用 addOutput: 把輸出添加到捕獲會話中援所。使用 canAddOutput: 檢查是否一個捕獲輸出與現(xiàn)有的會話是兼容的香璃。可以在會話正在運(yùn)行的時候添加和刪除所需的輸出喜喂。
AVCaptureSession *captureSession = [[AVCaptureSession alloc] init];
AVCaptureMovieFileOutput *movieOutput = <#Create and configure a movie output#>;
if ([captureSession canAddOutput:movieOutput]) {
[captureSession addOutput:movieOutput];
}
else {
// Handle the failure.
}