AVFoundation-07拍攝定制

概述

AVFoundation 是一個(gè)可以用來(lái)使用和創(chuàng)建基于時(shí)間的視聽(tīng)媒體數(shù)據(jù)的框架瑞眼。AVFoundation 的構(gòu)建考慮到了目前的硬件環(huán)境和應(yīng)用程序,其設(shè)計(jì)過(guò)程高度依賴多線程機(jī)制。充分利用了多核硬件的優(yōu)勢(shì)并大量使用block和GCD機(jī)制厢漩,將復(fù)雜的計(jì)算機(jī)進(jìn)程放到了后臺(tái)線程運(yùn)行。會(huì)自動(dòng)提供硬件加速操作,確保在大部分設(shè)備上應(yīng)用程序能以最佳性能運(yùn)行疮胖。該框架就是針對(duì)64位處理器設(shè)計(jì)的,可以發(fā)揮64位處理器的所有優(yōu)勢(shì)闷板。

iOS 媒體環(huán)境.png

切換攝像頭

一般來(lái)說(shuō)iPhone都具有前后兩個(gè)攝像頭澎灸,在做相機(jī)應(yīng)用的時(shí)候一個(gè)基本的需求就是前后攝像頭的切換。在切換相機(jī)的時(shí)候我們需要注意的是我們都需要判斷當(dāng)前設(shè)備支不支持相機(jī)切換遮晚、用戶是否開(kāi)啟了相應(yīng)的權(quán)限性昭、以及設(shè)置的圖片尺寸前后攝像頭是否支持這樣的尺寸。

#pragma mark - 切換攝像頭
- (AVCaptureDevice *)deviceWithPostion:(AVCaptureDevicePosition)position
{
    NSArray *devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
    for (AVCaptureDevice *device in devices) {
        if (device.position == position) {
            return device;
        }
    }
    return nil;
}

- (BOOL)canSwitchCamera
{
    return [[AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo] count] > 1;
}

- (void)switchCamera
{
    if (![self canSwitchCamera]) {
        return;
    }
    
    AVCaptureDevicePosition devicePosition;
    if (self.deviceInput.device.position == AVCaptureDevicePositionBack) {
        devicePosition = AVCaptureDevicePositionFront;
    }else {
        devicePosition = AVCaptureDevicePositionBack;
    }
    
    [self.captureSession beginConfiguration];
    [self.captureSession removeInput:_deviceInput];
    NSError *error;
    AVCaptureDevice *device = [self deviceWithPostion:devicePosition];
    self.deviceInput = [AVCaptureDeviceInput deviceInputWithDevice:device error:&error];
    if (!self.deviceInput) {
        [self.captureSession commitConfiguration];
        return;
    }
    [self.captureSession addInput:self.deviceInput];
    [self.captureSession commitConfiguration];
}
調(diào)整焦距

iOS設(shè)備大多都支持基于給定的興趣點(diǎn)設(shè)置對(duì)焦县遣,我們只需要傳入一個(gè)位置糜颠,系統(tǒng)就會(huì)自動(dòng)在當(dāng)前位置進(jìn)行對(duì)焦。 需要注意的是萧求,定要先設(shè)置位置其兴,再設(shè)置曝光模式。需要注意的是夸政,要先設(shè)置位置元旬,再設(shè)置對(duì)焦模式。這里的 CGPoint 取值范圍是取景框左上角(0,0)到取景框右下角(1法绵,1)之間箕速。

#pragma mark - 自動(dòng)對(duì)焦
- (void)autoFocus
{
    if (!self.deviceInput.device) {
        return;
    }
    
    if ([self.deviceInput.device isFocusModeSupported:AVCaptureFocusModeAutoFocus]) {
        NSError *error;
        if ([self.deviceInput.device lockForConfiguration:&error]) {
            self.deviceInput.device.focusMode = AVCaptureFocusModeAutoFocus;
            [self.deviceInput.device unlockForConfiguration];
        }
    }
}

#pragma mark - 調(diào)整焦距
- (BOOL)canTapFoucus
{
    return [self.deviceInput.device isFocusPointOfInterestSupported];
}

- (void)focusAtPoint:(CGPoint)point
{
    if (![self canTapFoucus]) {
        return;
    }
    
    if ([self.deviceInput.device isFocusModeSupported:AVCaptureFocusModeAutoFocus]) {
        NSError *error;
        if ([self.deviceInput.device lockForConfiguration:&error]) {
            self.deviceInput.device.focusPointOfInterest = point;
            self.deviceInput.device.focusMode = AVCaptureFocusModeAutoFocus;
            [self.deviceInput.device unlockForConfiguration];
        }
    }
}

曝光

iOS設(shè)備大多都支持基于給定的興趣點(diǎn)設(shè)置曝光數(shù)據(jù),我們只需要傳入一個(gè)位置朋譬,系統(tǒng)就會(huì)自動(dòng)在當(dāng)前位置進(jìn)行曝光盐茎。 需要注意的是,定要先設(shè)置位置徙赢,再設(shè)置曝光模式字柠。這里的 CGPoint 取值范圍是取景框左上角(0,0)到取景框右下角(1狡赐,1)之間窑业。

#pragma mark - 曝光
- (BOOL)canTapExpose
{
    return [self.deviceInput.device isExposurePointOfInterestSupported];
}

- (void)exposeAtPoint:(CGPoint)point
{
    if (![self canTapExpose]) {
        return;
    }
    
    if ([self.deviceInput.device isExposureModeSupported:AVCaptureExposureModeAutoExpose]) {
        NSError *error;
        if ([self.deviceInput.device lockForConfiguration:&error]) {
            self.deviceInput.device.exposurePointOfInterest = point;
            self.deviceInput.device.exposureMode = AVCaptureExposureModeAutoExpose;
            [self.deviceInput.device unlockForConfiguration];
        }
    }
}

閃光燈

閃光燈的使用比較簡(jiǎn)單,有以下幾個(gè)模式:AVCaptureFlashModeOff 枕屉、AVCaptureFlashModeOn常柄、AVCaptureFlashModeAuto。

#pragma mark - 閃光燈
- (BOOL)haveFlash
{
    return [self.deviceInput.device hasFlash];
}

- (AVCaptureFlashMode)currentFlashMode
{
    return self.deviceInput.device.flashMode;
}

- (void)setFlashModel:(AVCaptureFlashMode)flashModel
{
    if (self.deviceInput.device.flashMode == flashModel) {
        return;
    }
    
    if ([self.deviceInput.device isFlashModeSupported:flashModel]) {
        NSError *error;
        if ([self.deviceInput.device lockForConfiguration:&error]) {
            self.deviceInput.device.flashMode = flashModel;
            [self.deviceInput.device unlockForConfiguration];
        }
    }
}

手電筒

手電筒的使用比較簡(jiǎn)單搀擂,有以下幾個(gè)模式:AVCaptureTorchModeOff西潘,AVCaptureTorchModeOn,AVCaptureTorchModeAuto 哨颂。

#pragma mark - 手電筒
- (BOOL)haveTorch
{
    return [self.deviceInput.device hasTorch];
}

- (AVCaptureTorchMode)currentTorchMode
{
    return self.deviceInput.device.torchMode;
}

- (void)setTorchModel:(AVCaptureTorchMode)torchModel
{
    if (self.deviceInput.device.torchMode == torchModel) {
        return;
    }
    
    if ([self.deviceInput.device isTorchModeSupported:torchModel]) {
        NSError *error;
        if ([self.deviceInput.device lockForConfiguration:&error]) {
            self.deviceInput.device.torchMode = torchModel;
            [self.deviceInput.device unlockForConfiguration];
        }
    }
}

- (void)setTorchLevel:(float)torchLevel
{
    if ([self.deviceInput.device isTorchActive]) {
        NSError *error;
        if ([self.deviceInput.device lockForConfiguration:&error]) {
            [self.deviceInput.device setTorchModeOnWithLevel:torchLevel error:&error];
            [self.deviceInput.device unlockForConfiguration];
        }
    }
}

保存圖片

使用ALAssetsLibrary喷市,我們可以很方便地將照片或視頻寫入用戶的資源庫(kù)中。在使用的時(shí)候需要注意用戶權(quán)限的控制威恼。

#pragma mark - 保存圖片
- (void)writeImageToPhotosAlbum:(UIImage *)image
{
    ALAssetsLibrary *assetsLib = [[ALAssetsLibrary alloc] init];
    [assetsLib writeImageToSavedPhotosAlbum:image.CGImage
                                orientation:(NSInteger)image.imageOrientation
                            completionBlock:^(NSURL *assetURL, NSError *error) {
        NSLog(@"%@", assetURL);
    }];
}

視頻縮放

縮放的屬性是videoMaxZoomFactor品姓,它的最小值是1.0(不進(jìn)行縮放),最大值由videoMaxZoomFactor確定箫措。

#pragma mark - 視頻縮放
- (BOOL)videoCanZoom
{
    return self.deviceInput.device.activeFormat.videoMaxZoomFactor > 1.0f;
}

- (float)videoMaxZoomFactor
{
    return MIN(self.deviceInput.device.activeFormat.videoMaxZoomFactor, 4.0f);
}

- (void)setVideoZoomFactor:(float)factor
{
    if (self.deviceInput.device.isRampingVideoZoom) {
        return;
    }
    
    NSError *error;
    if ([self.deviceInput.device lockForConfiguration:&error]) {
        self.deviceInput.device.videoZoomFactor = pow([self videoMaxZoomFactor], factor);
        [self.deviceInput.device unlockForConfiguration];
    }
}

- (void)rampZoomToFactor:(float)factor
{
    if (self.deviceInput.device.isRampingVideoZoom) {
        return;
    }

    NSError *error;
    if ([self.deviceInput.device lockForConfiguration:&error]) {
        [self.deviceInput.device rampToVideoZoomFactor:pow([self videoMaxZoomFactor], factor) withRate:1.0f];
        [self.deviceInput.device unlockForConfiguration];
    }
}

CoreVideo渲染

為什么要用快速紋理上傳腹备,相比OpenGLES快速紋理上傳大大加快了紋理上傳的速度。這也是GPUImage中為什么優(yōu)先使用快速紋理上傳的原因斤蔓。在閱讀GPUImage源碼的時(shí)候你可以看到這樣的注釋:// Note: the fast texture caches speed up 640x480 frame reads from 9.6 ms to 3.1 ms on iPhone 4S
詳見(jiàn)框架中的 GPUImageRawDataOutput.m 文件

- (void)setupOpenGLTextureCache
{
    CVReturn statuts = CVOpenGLESTextureCacheCreate(kCFAllocatorDefault,
                                                    NULL,
                                                    _context,
                                                    NULL,
                                                    &_openGLESTextureCache);
    if (statuts != kCVReturnSuccess) {
        exit(0);
    }
}

#pragma mark - GLTexture
- (void)genTetureFromImage:(CVImageBufferRef)imageRef
{
    CVOpenGLESTextureCacheCreateTextureFromImage(kCFAllocatorDefault,
                                                _openGLESTextureCache,
                                                imageRef,
                                                NULL,
                                                GL_TEXTURE_2D,
                                                GL_RGBA,
                                                (GLsizei)CVPixelBufferGetWidth(imageRef),
                                                (GLsizei)CVPixelBufferGetHeight(imageRef),
                                                GL_BGRA,
                                                GL_UNSIGNED_BYTE,
                                                0,
                                                &_openGLESTexture);

    glBindTexture(GL_TEXTURE_2D, CVOpenGLESTextureGetName(_openGLESTexture));
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glUniform1i(glGetUniformLocation(_program, "image"), 0);

    if (_openGLESTexture) {
        CFRelease(_openGLESTexture);
        _openGLESTexture = NULL;
        CVOpenGLESTextureCacheFlush(_openGLESTextureCache, 0);
    }
}

在這里不再介紹如何實(shí)時(shí)渲染相機(jī)視頻馏谨,當(dāng)前在本文的例子中完成了相機(jī)視頻的實(shí)時(shí)渲染,具體請(qǐng)參考之前的文章或本文的相關(guān)示例附迷。

參考

AVFoundation開(kāi)發(fā)秘籍:實(shí)踐掌握iOS & OSX應(yīng)用的視聽(tīng)處理技術(shù)

源碼地址:AVFoundation開(kāi)發(fā) https://github.com/QinminiOS/AVFoundation

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末惧互,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子喇伯,更是在濱河造成了極大的恐慌喊儡,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,185評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件稻据,死亡現(xiàn)場(chǎng)離奇詭異艾猜,居然都是意外死亡买喧,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,652評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門匆赃,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)淤毛,“玉大人,你說(shuō)我怎么就攤上這事算柳〉偷” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 163,524評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵瞬项,是天一觀的道長(zhǎng)蔗蹋。 經(jīng)常有香客問(wèn)我,道長(zhǎng)囱淋,這世上最難降的妖魔是什么猪杭? 我笑而不...
    開(kāi)封第一講書人閱讀 58,339評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮妥衣,結(jié)果婚禮上皂吮,老公的妹妹穿的比我還像新娘。我一直安慰自己税手,他們只是感情好蜂筹,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,387評(píng)論 6 391
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著冈止,像睡著了一般。 火紅的嫁衣襯著肌膚如雪候齿。 梳的紋絲不亂的頭發(fā)上熙暴,一...
    開(kāi)封第一講書人閱讀 51,287評(píng)論 1 301
  • 那天,我揣著相機(jī)與錄音慌盯,去河邊找鬼周霉。 笑死,一個(gè)胖子當(dāng)著我的面吹牛亚皂,可吹牛的內(nèi)容都是我干的俱箱。 我是一名探鬼主播,決...
    沈念sama閱讀 40,130評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼灭必,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼狞谱!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起禁漓,我...
    開(kāi)封第一講書人閱讀 38,985評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后炫欺,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體蚓炬,經(jīng)...
    沈念sama閱讀 45,420評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,617評(píng)論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了叭莫。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蹈集。...
    茶點(diǎn)故事閱讀 39,779評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖雇初,靈堂內(nèi)的尸體忽然破棺而出拢肆,到底是詐尸還是另有隱情,我是刑警寧澤抵皱,帶...
    沈念sama閱讀 35,477評(píng)論 5 345
  • 正文 年R本政府宣布善榛,位于F島的核電站,受9級(jí)特大地震影響呻畸,放射性物質(zhì)發(fā)生泄漏移盆。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,088評(píng)論 3 328
  • 文/蒙蒙 一伤为、第九天 我趴在偏房一處隱蔽的房頂上張望咒循。 院中可真熱鬧,春花似錦绞愚、人聲如沸叙甸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,716評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)裆蒸。三九已至,卻和暖如春糖驴,著一層夾襖步出監(jiān)牢的瞬間僚祷,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 32,857評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工贮缕, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留辙谜,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,876評(píng)論 2 370
  • 正文 我出身青樓感昼,卻偏偏與公主長(zhǎng)得像装哆,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子定嗓,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,700評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • 索尼黑卡RX100設(shè)置與后期詳解(歡迎指正與補(bǔ)充)一蜕琴、拍照1、影像尺寸分20M宵溅、10M奸绷、5 M,這里不是指文件大小...
    justin_pan閱讀 1,489評(píng)論 1 5
  • public classCamera.Parametersextends Objectjava.lang.Obje...
    冉冉升起的小太陽(yáng)閱讀 10,906評(píng)論 0 7
  • iOS 蘋果官方Demo合集 字?jǐn)?shù)10517閱讀21059評(píng)論18喜歡144 其實(shí), 開(kāi)發(fā)了這么久, 不得不說(shuō), ...
    bingo居然被占了閱讀 10,140評(píng)論 2 31
  • 晚飯后层玲,村里兩老頭聚在一起号醉,一邊吧啦著水煙反症,一邊興高采烈地講著昨天的事情。 “唉呀畔派,昨天回家后铅碍,我頭都有點(diǎn)暈了” ...
    聽(tīng)雨軒清秋閱讀 202評(píng)論 5 2
  • 人總是很能注意到自己生活中所遇到的不如意胞谈,特別是心情不好情緒低落的時(shí)候,在一個(gè)人的世界遇到的小小不如意都可以放大很...
    天外來(lái)客人閱讀 249評(píng)論 0 0