直播-數(shù)據(jù)采集

采集數(shù)據(jù)需要使用AVFoundation下的相關API

AVFoundation在相關框架棧中的的位置:

為了捕捉視頻,我們需要這樣幾種類(與其它的子類)。

AVCaptureDevice 代表了輸入設備,例如攝像頭與麥克風。

AVCaptureInput 代表了輸入數(shù)據(jù)源

AVCaptureOutput 代表了輸出數(shù)據(jù)源

AVCaptureSession 用于協(xié)調(diào)輸入與輸出之間的數(shù)據(jù)流

并且還有AVCaptureVideoPreviewLayer提供攝像頭的預覽功能

可以用這樣一幅圖來概述:

實際應用AVFoundation來捕捉視頻流并不復雜。

Talk is Cheap,Show me the Code.

我們用代碼簡單地描述用AVFoundation捕捉視頻的過程,其他捕捉音頻,靜態(tài)圖像的過程也是大同小異的。

1.創(chuàng)建AVCaputureSession。

作為協(xié)調(diào)輸入與輸出的中心,我們第一步需要創(chuàng)建一個Session

AVCaptureSession?*session?=?[[AVCaptureSession?alloc]?init];

2.創(chuàng)建AVCaptureDevice

創(chuàng)建一個AVCaptureDevice代表代表輸入設備。在這里我們制定設備用于攝像。

此方法是獲得前攝像頭的

AVCaptureDevice?*videoDevice?=?[AVCaptureDevice?defaultDeviceWithMediaType:AVMediaTypeVideo];

想要同時獲得前后攝像頭可以使用下面方法

NSArray *videoDevices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];

AVCaptureDevice *frontCamera = [AVCaptureDeviceInput deviceInputWithDevice:videoDevices.firstObject error:nil];

AVCaptureDevice *backCamera =[AVCaptureDeviceInput deviceInputWithDevice:videoDevices.lastObject error:nil];


//初始化攝像頭

self.frontCamera = [AVCaptureDeviceInput deviceInputWithDevice:videoDevices.firstObject error:nil];

self.backCamera =[AVCaptureDeviceInput deviceInputWithDevice:videoDevices.lastObject error:nil];

初始化麥克風

AVCaptureDevice *audioDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeAudio];

3.創(chuàng)建AVCaptureDeviceInput,并添加到Session中

我們需要使用AVCaptureDeviceInput來讓設備添加到session中, AVCaptureDeviceInput負責管理設備端口。我們可以理解它為設備的抽象。一個設備可能可以同時提供視頻和音頻的捕捉。我們可以分別用AVCaptureDeviceInput來代表視頻輸入和音頻輸入。

NSError?*error;

AVCaptureDeviceInput *videoInput = [AVCaptureDeviceInput deviceInputWithDevice:videoDevice error:&error];

AVCaptureDeviceInput *audioInput = [AVCaptureDeviceInput deviceInputWithDevice:audioDevice error:&error];

[session?addInput:input];

4.創(chuàng)建AVCaptureOutput

為了從session中取得數(shù)據(jù),我們需要創(chuàng)建一個AVCaptureOutput

AVCaptureVideoDataOutput *videoDataOutput = [[AVCaptureVideoDataOutput alloc]init];

[videoDataOutput setAlwaysDiscardsLateVideoFrames:YES];

//設置視頻輸出格式

[videoDataOutput setVideoSettings:@{

(__bridge NSString *)kCVPixelBufferPixelFormatTypeKey:@(kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange)

}];

self.captureVideoDataOutput.alwaysDiscardsLateVideoFrames = YES;


這里的kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange是用于設置輸出的YUV,這里先簡單提一下,稍后會有詳細的文章來介紹。

kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange ?//NV12

5.設置output delegate,將output添加至session,在代理方法中分析視頻流

為了分析視頻流,我們需要為output設置delegate,并且指定delegate方法在哪個線程被調(diào)用。需要注意的是,線程必須是串行的,確保視頻幀按序到達。

videoDataOutputQueue?=?dispatch_queue_create("VideoDataOutputQueue",?DISPATCH_QUEUE_SERIAL);

[videoDataOutput?setSampleBufferDelegate:self?queue:videoDataOutputQueue];

[session?addOutput:videoDataOutput];

我們可以在delegate方法中獲得視頻流及音頻流,并進行編碼。

-(void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection{

? ? ? ? ? ? ?if ([self.videoDataOutput isEqual:captureOutput]) {

? ? ? ? ? ? ? ? ? ?//判斷是視頻流

? ? ? ? ? ? ? }else if([self.audioDataOutput isEqual:captureOutput]){

? ? ? ? ? ? ? ? ?//判斷出是音頻流

? ? ? ? ? ? ? }

}

6.設置本機播放

AVCaptureVideoPreviewLayer *previewLayer = [AVCaptureVideoPreviewLayer layerWithSession:self.captureSession];

previewLayer.frame = preview.bounds;

[self.preview.layer addSublayer:self.previewLayer];

7.開始捕捉

[session?startRunning];

通過上面的簡單例子,我么可以看出使用AVFoundation來捕捉視頻流并不是十分復雜。重點是使用的過程需要了解配置的細節(jié),還有性能問題。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

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

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