android gpuimage 直播,1小时学会:最简单的iOS直播推流(四)如何使用GPUImage,如何美颜...
最簡(jiǎn)單的iOS 推流代碼,視頻捕獲,軟編碼(faac,x264),硬編碼(aac,h264),美顏,flv編碼,rtmp協(xié)議,陸續(xù)更新代碼解析,你想學(xué)的知識(shí)這里都有,愿意懂直播技術(shù)的同學(xué)快來看!!
上一篇文章介紹了如何使用系統(tǒng)方法捕獲視頻數(shù)據(jù),但是更多的時(shí)候,為了使用美顏濾鏡,我們會(huì)選擇GPUImage來獲取視頻數(shù)據(jù)。
GPUImage是一個(gè)可以為錄制視頻添加實(shí)時(shí)濾鏡的一個(gè)著名第三方庫。
該框架大概原理是,使用OpenGL著色器對(duì)視頻圖像進(jìn)行顏色處理,然后存到frameBuffer,之后可以對(duì)此數(shù)據(jù)再次處理。重復(fù)上述過程,即可達(dá)到多重濾鏡效果。
具體實(shí)現(xiàn)不細(xì)說,這里簡(jiǎn)要介紹一下GPUImage的使用,如何美顏,如何獲取音視頻數(shù)據(jù)。
使用GPUImage
GPUImage的主要代碼在 AWGPUImageAVCapture 這個(gè)類中。
初始化AWAVCaptureManager對(duì)象時(shí)將captureType設(shè)為AWAVCaptureTypeGPUImage,就會(huì)自動(dòng)調(diào)用AWGPUImageAVCapture類來捕獲視頻數(shù)據(jù)。
代碼在 onInit 方法中:
-(void)onInit{
//攝像頭初始化
// AWGPUImageVideoCamera 繼承自 GPUImageVideoCamera。繼承是為了獲取音頻數(shù)據(jù),原代碼中,默認(rèn)情況下音頻數(shù)據(jù)發(fā)送給了 audioEncodingTarget。
// 這個(gè)東西一看類型是GPUImageMovieWriter,應(yīng)該是文件寫入功能。果斷覆蓋掉processAudioSampleBuffer方法,拿到音頻數(shù)據(jù)后自己處理。
// 音頻就這樣可以了,GPUImage主要工作還是在視頻處理這里。
// 設(shè)置預(yù)覽分辨率 self.captureSessionPreset是根據(jù)AWVideoConfig的設(shè)置,獲取的分辨率。設(shè)置前置、后置攝像頭。
_videoCamera = [[AWGPUImageVideoCamera alloc] initWithSessionPreset:self.captureSessionPreset cameraPosition:AVCaptureDevicePositionFront];
//開啟捕獲聲音
[_videoCamera addAudioInputsAndOutputs];
//設(shè)置輸出圖像方向,可用于橫屏推流。
_videoCamera.outputImageOrientation = UIInterfaceOrientationPortrait;
//鏡像策略,這里這樣設(shè)置是最自然的。跟系統(tǒng)相機(jī)默認(rèn)一樣。
_videoCamera.horizontallyMirrorRearFacingCamera = NO;
_videoCamera.horizontallyMirrorFrontFacingCamera = YES;
//設(shè)置預(yù)覽view
_gpuImageView = [[GPUImageView alloc] initWithFrame:self.preview.bounds];
[self.preview addSubview:_gpuImageView];
//初始化美顏濾鏡
_beautifyFilter = [[GPUImageBeautifyFilter alloc] init];
//相機(jī)獲取視頻數(shù)據(jù)輸出至美顏濾鏡
[_videoCamera addTarget:_beautifyFilter];
//美顏后輸出至預(yù)覽
[_beautifyFilter addTarget:_gpuImageView];
// 到這里我們已經(jīng)能夠打開相機(jī)并預(yù)覽了。
// 因?yàn)橐屏?#xff0c;除了預(yù)覽之外,我們還要截取到視頻數(shù)據(jù)。這就需要使用GPUImage中的GPUImageRawDataOutput,它能將美顏后的數(shù)據(jù)輸出,便于我們處理后發(fā)送出去。
// AWGPUImageAVCaptureDataHandler繼承自GPUImageRawDataOutput,從 newFrameReadyAtTime 方法中就可以獲取到美顏后輸出的數(shù)據(jù)。
// 輸出的圖片格式為BGRA。
_dataHandler = [[AWGPUImageAVCaptureDataHandler alloc] initWithImageSize:CGSizeMake(self.videoConfig.width, self.videoConfig.height) resultsInBGRAFormat:YES capture:self];
[_beautifyFilter addTarget:_dataHandler];
// 令A(yù)WGPUImageAVCaptureDataHandler實(shí)現(xiàn)AWGPUImageVideoCameraDelegate協(xié)議,并且讓camera的awAudioDelegate指向_dataHandler對(duì)象。
// 將音頻數(shù)據(jù)轉(zhuǎn)到_dataHandler中處理。然后音視頻數(shù)據(jù)就可以都在_dataHandler中處理了。
_videoCamera.awAudioDelegate = _dataHandler;
//開始捕獲視頻
[self.videoCamera startCameraCapture];
//修改幀率
[self updateFps:self.videoConfig.fps];
}
AWGPUImageAVCaptureDataHandler中音視頻處理方法:
// 獲取到音頻數(shù)據(jù),通過sendAudioSampleBuffer發(fā)送出去
-(void)processAudioSample:(CMSampleBufferRef)sampleBuffer{
if(!self.capture || !self.capture.isCapturing){
return;
}
[self.capture sendAudioSampleBuffer:sampleBuffer];
}
// 獲取到視頻數(shù)據(jù),轉(zhuǎn)換格式后,使用sendVideoYuvData 發(fā)送出去。
-(void)newFrameReadyAtTime:(CMTime)frameTime atIndex:(NSInteger)textureIndex{
[super newFrameReadyAtTime:frameTime atIndex:textureIndex];
if(!self.capture || !self.capture.isCapturing){
return;
}
// GPUImage獲取到的數(shù)據(jù)是BGRA格式。
// 而各種編碼器最適合編碼的格式還是yuv(NV12格式)。
// 所以在此將BGRA格式的視頻數(shù)據(jù)轉(zhuǎn)成yuv格式。(后面會(huì)介紹yuv和pcm格式)
// 將bgra轉(zhuǎn)為yuv
int width = imageSize.width;
int height = imageSize.height;
int w_x_h = width * height;
// 1幀yuv數(shù)據(jù)長(zhǎng)度為 寬x高 * 3 / 2
int yuv_len = w_x_h * 3 / 2;
uint8_t *yuv_bytes = malloc(yuv_len);
//使用libyuv庫,做格式轉(zhuǎn)換。libyuv中的格式都是大端(高位存高位,低位存低位),而iOS設(shè)備是小端(高位存低位,低位存高位),小端為BGRA,則大端為ARGB,所以這里使用ARGBToNV12。
//self.rawBytesForImage就是美顏后的圖片數(shù)據(jù),格式是BGRA。
//關(guān)于大端小端,請(qǐng)自行baidu。
//NV12格式介紹請(qǐng)看下一篇文章:[1小時(shí)學(xué)會(huì):最簡(jiǎn)單的iOS直播推流(五)yuv、pcm數(shù)據(jù)的介紹和獲取](http://www.jianshu.com/p/d5489a8fe2a9)
[self lockFramebufferForReading];
ARGBToNV12(self.rawBytesForImage, width * 4, yuv_bytes, width, yuv_bytes + w_x_h, width, width, height);
[self unlockFramebufferAfterReading];
NSData *yuvData = [NSData dataWithBytesNoCopy:yuv_bytes length:yuv_len];
//將獲取到的yuv420數(shù)據(jù)發(fā)送出去
[self.capture sendVideoYuvData:yuvData];
}
至此,已經(jīng)成功使用GPUImage獲取視頻,美顏,格式轉(zhuǎn)換,準(zhǔn)備發(fā)送數(shù)據(jù)。還是很簡(jiǎn)單的。
我們現(xiàn)在能夠使用2種方法來獲取音頻數(shù)據(jù),接下來會(huì)介紹音視頻編碼相關(guān)內(nèi)容。
文章列表
總結(jié)
以上是生活随笔為你收集整理的android gpuimage 直播,1小时学会:最简单的iOS直播推流(四)如何使用GPUImage,如何美颜...的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 基于SpringBoot+Vue打造实验
- 下一篇: AmbientOcclusion(AO)