iOS直播技術(shù)_前提準(zhǔn)備

這里我們要研究直播技術(shù)首先需要對AVFoundation熟悉掌握

AVFoundation拍照和錄制視頻

AVFoundation中提供了很多現(xiàn)成的播放器和錄音機,但是事實上它還有更加底層的內(nèi)容可以供開發(fā)者使用。因為AVFoundation中抽了很多和底層輸入、輸出設(shè)備打交道的類,依靠這些類開發(fā)人員面對的不再是封裝好的音頻播放器AVAudioPlayer、錄音機(AVAudioRecorder)、視頻(包括音頻)播放器AVPlayer,而是輸入設(shè)備(例如麥克風(fēng)、攝像頭)、輸出設(shè)備(圖片、視頻)等。首先了解一下使用AVFoundation做拍照和視頻錄制開發(fā)用到的相關(guān)類:

AVCaptureSession:媒體(音、視頻)捕獲會話,負(fù)責(zé)把捕獲的音視頻數(shù)據(jù)輸出到輸出設(shè)備中。一個AVCaptureSession可以有多個輸入輸出:

AVCaptureDevice:輸入設(shè)備,包括麥克風(fēng)、攝像頭,通過該對象可以設(shè)置物理設(shè)備的一些屬性(例如相機聚焦、白平衡等)。

AVCaptureDeviceInput:設(shè)備輸入數(shù)據(jù)管理對象,可以根據(jù)AVCaptureDevice創(chuàng)建對應(yīng)的AVCaptureDeviceInput對象,該對象將會被添加到AVCaptureSession中管理。

AVCaptureOutput:輸出數(shù)據(jù)管理對象,用于接收各類輸出數(shù)據(jù),通常使用對應(yīng)的子類AVCaptureAudioDataOutput、AVCaptureStillImageOutput、AVCaptureVideoDataOutput、AVCaptureFileOutput,該對象將會被添加到AVCaptureSession中管理。注意:前面幾個對象的輸出數(shù)據(jù)都是NSData類型,而AVCaptureFileOutput代表數(shù)據(jù)以文件形式輸出,類似的,AVCcaptureFileOutput也不會直接創(chuàng)建使用,通常會使用其子類:AVCaptureAudioFileOutput、AVCaptureMovieFileOutput。當(dāng)把一個輸入或者輸出添加到AVCaptureSession之后AVCaptureSession就會在所有相符的輸入、輸出設(shè)備之間建立連接(AVCaptionConnection):

AVCaptureVideoPreviewLayer:相機拍攝預(yù)覽圖層,是CALayer的子類,使用該對象可以實時查看拍照或視頻錄制效果,創(chuàng)建該對象需要指定對應(yīng)的AVCaptureSession對象。

使用AVFoundation拍照和錄制視頻的一般步驟如下:

創(chuàng)建AVCaptureSession對象。

使用AVCaptureDevice的靜態(tài)方法獲得需要使用的設(shè)備,例如拍照和錄像就需要獲得攝像頭設(shè)備,錄音就要獲得麥克風(fēng)設(shè)備。

利用輸入設(shè)備AVCaptureDevice初始化AVCaptureDeviceInput對象。

初始化輸出數(shù)據(jù)管理對象,如果要拍照就初始化AVCaptureStillImageOutput對象;如果拍攝視頻就初始化AVCaptureMovieFileOutput對象。

將數(shù)據(jù)輸入對象AVCaptureDeviceInput、數(shù)據(jù)輸出對象AVCaptureOutput添加到媒體會話管理對象AVCaptureSession中。

創(chuàng)建視頻預(yù)覽圖層AVCaptureVideoPreviewLayer并指定媒體會話,添加圖層到顯示容器中,調(diào)用AVCaptureSession的startRuning方法開始捕獲。

將捕獲的音頻或視頻數(shù)據(jù)輸出到指定文件。

#import"ViewController.h"

#define WIDTH [UIScreen mainScreen].bounds.size.width

#define HEIGHT [UIScreen mainScreen].bounds.size.height

@interfaceViewController()

@property(nonatomic,strong)AVCaptureSession *session;

@property(nonatomic,strong)AVCaptureVideoPreviewLayer *preViewLayer;

@end

@implementationViewController{

AVCaptureConnection *_videoConnection;//輸入輸出建立連接

AVCaptureConnection *_audioConnection;

}

- (void)viewDidLoad {? ?

?[superviewDidLoad];? ?

?[selfinitView];

// Do any additional setup after loading the view, typically from a nib.

}

-(void)initView{

//初始化會話

NSError* error =nil;

self.session= [[AVCaptureSession alloc] init];//? ? ???

self.session.sessionPreset= AVCaptureSessionPresetMedium;

//設(shè)置攝像頭

AVCaptureDevice * device = [selfcameraWithPosition:AVCaptureDevicePositionFront];

//獲取輸入設(shè)備

AVCaptureDeviceInput * input = [AVCaptureDeviceInput deviceInputWithDevice:device error:&error];

if(error) {

NSLog(@"%@",error);? ??

}

//添加輸入設(shè)備

if([_session canAddInput:input]) {? ? ? ??

[self.sessionaddInput:input];? ?

?}

//獲取輸出設(shè)備

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

dispatch_queue_tqueue = dispatch_queue_create("myQueue",NULL);? ?

?[output setSampleBufferDelegate:selfqueue:queue];? ??

output.videoSettings= [NSDictionarydictionaryWithObject:[NSNumbernumberWithInt:kCVPixelFormatType_420YpCbCr8BiPlanarFullRange] forKey:(NSString*)kCVPixelBufferPixelFormatTypeKey];? ?

?output.alwaysDiscardsLateVideoFrames=YES; ??

[selfstartRuning];

//添加輸出設(shè)備

if([self.sessioncanAddOutput:output]) {? ? ? ?

?[self.sessionaddOutput:output];? ?

?}

//創(chuàng)建瀏覽層,用于展示

self.preViewLayer= [[AVCaptureVideoPreviewLayer alloc] initWithSession:self.session];

self.preViewLayer.frame= CGRectMake(0,0, WIDTH,500);

self.preViewLayer.videoGravity= AVLayerVideoGravityResizeAspectFill;

//填充模式

[self.view.layeraddSublayer:self.preViewLayer];

//_videoConnection = [output connectionWithMediaType:AVMediaTypeVideo];

}

-(void)startRuning{? ?

?[self.sessionstartRunning];

}

// 選擇是前攝像頭還是后攝像頭

- (AVCaptureDevice *)cameraWithPosition:(AVCaptureDevicePosition) position {

NSArray*devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];

for(AVCaptureDevice *device in devices) {

if([device position] == position) {returndevice;? ? ? ?

?}? ??

}return?nil;

}

// 關(guān)鍵方法,捕獲攝像頭每一幀的畫面并編碼

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

if(connection == _videoConnection) {//? ? ? ??

[_manager264 encoderToH264:sampleBuffer];

}

if(connection == _audioConnection) {NSLog(@"yy");? ??

}

}

@end

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

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

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