1小時學會:最簡單的iOS直播推流(四)如何使用GPUImage,如何美顏

最簡單的iOS 推流代碼,視頻捕獲,軟編碼(faac,x264),硬編碼(aac,h264),美顏,flv編碼,rtmp協議,陸續更新代碼解析,你想學的知識這裏都有,願意懂直播技術的同窗快來看!!git

源代碼:https://github.com/hardman/AWLivegithub

上一篇文章介紹瞭如何使用系統方法捕獲視頻數據,可是更多的時候,爲了使用美顏濾鏡,咱們會選擇GPUImage來獲取視頻數據。算法

GPUImage是一個能夠爲錄製視頻添加實時濾鏡的一個著名第三方庫。bash

該框架大概原理是,使用OpenGL着色器對視頻圖像進行顏色處理,而後存到frameBuffer,以後能夠對此數據再次處理。重複上述過程,便可達到多重濾鏡效果。架構

具體實現不細說,這裏簡要介紹一下GPUImage的使用,如何美顏,如何獲取音視頻數據。框架

使用GPUImage

GPUImage的主要代碼在 AWGPUImageAVCapture 這個類中。ide

初始化AWAVCaptureManager對象時將captureType設爲AWAVCaptureTypeGPUImage,就會自動調用AWGPUImageAVCapture類來捕獲視頻數據。post

代碼在 onInit 方法中:學習

-(void)onInit{
    //攝像頭初始化
    // AWGPUImageVideoCamera 繼承自 GPUImageVideoCamera。繼承是爲了獲取音頻數據,原代碼中,默認狀況下音頻數據發送給了 audioEncodingTarget。
    // 這個東西一看類型是GPUImageMovieWriter,應該是文件寫入功能。果斷覆蓋掉processAudioSampleBuffer方法,拿到音頻數據後本身處理。
    // 音頻就這樣能夠了,GPUImage主要工做仍是在視頻處理這裏。
    // 設置預覽分辨率 self.captureSessionPreset是根據AWVideoConfig的設置,獲取的分辨率。設置前置、後置攝像頭。
    _videoCamera = [[AWGPUImageVideoCamera alloc] initWithSessionPreset:self.captureSessionPreset cameraPosition:AVCaptureDevicePositionFront];

    //開啓捕獲聲音
    [_videoCamera addAudioInputsAndOutputs];

    //設置輸出圖像方向,可用於橫屏推流。
    _videoCamera.outputImageOrientation = UIInterfaceOrientationPortrait;

    //鏡像策略,這裏這樣設置是最天然的。跟系統相機默認同樣。
    _videoCamera.horizontallyMirrorRearFacingCamera = NO;
    _videoCamera.horizontallyMirrorFrontFacingCamera = YES;
    
    //設置預覽view
    _gpuImageView = [[GPUImageView alloc] initWithFrame:self.preview.bounds];
    [self.preview addSubview:_gpuImageView];
    
    //初始化美顏濾鏡
    _beautifyFilter = [[GPUImageBeautifyFilter alloc] init];

    //相機獲取視頻數據輸出至美顏濾鏡
    [_videoCamera addTarget:_beautifyFilter];
    
    //美顏後輸出至預覽
    [_beautifyFilter addTarget:_gpuImageView];
    
    // 到這裏咱們已經可以打開相機並預覽了。
    // 由於要推流,除了預覽以外,咱們還要截取到視頻數據。這就須要使用GPUImage中的GPUImageRawDataOutput,它能將美顏後的數據輸出,便於咱們處理後發送出去。
    // AWGPUImageAVCaptureDataHandler繼承自GPUImageRawDataOutput,從 newFrameReadyAtTime 方法中就能夠獲取到美顏後輸出的數據。
    // 輸出的圖片格式爲BGRA。
    _dataHandler = [[AWGPUImageAVCaptureDataHandler alloc] initWithImageSize:CGSizeMake(self.videoConfig.width, self.videoConfig.height) resultsInBGRAFormat:YES capture:self];
    [_beautifyFilter addTarget:_dataHandler];

    // 令AWGPUImageAVCaptureDataHandler實現AWGPUImageVideoCameraDelegate協議,而且讓camera的awAudioDelegate指向_dataHandler對象。
    // 將音頻數據轉到_dataHandler中處理。而後音視頻數據就能夠都在_dataHandler中處理了。
    _videoCamera.awAudioDelegate = _dataHandler;
    
    //開始捕獲視頻
    [self.videoCamera startCameraCapture];
    
    //修改幀率
    [self updateFps:self.videoConfig.fps];
}
複製代碼

美顏濾鏡使用的是:https://github.com/Guikunzhi/BeautifyFaceDemo 感謝Guikunzhi的分享。想了解美顏詳細算法的同窗,能夠自行學習。ui

AWGPUImageAVCaptureDataHandler中音視頻處理方法:

// 獲取到音頻數據,經過sendAudioSampleBuffer發送出去
-(void)processAudioSample:(CMSampleBufferRef)sampleBuffer{
    if(!self.capture || !self.capture.isCapturing){
        return;
    }
    [self.capture sendAudioSampleBuffer:sampleBuffer];
}

// 獲取到視頻數據,轉換格式後,使用sendVideoYuvData 發送出去。
-(void)newFrameReadyAtTime:(CMTime)frameTime atIndex:(NSInteger)textureIndex{
    [super newFrameReadyAtTime:frameTime atIndex:textureIndex];
    if(!self.capture || !self.capture.isCapturing){
        return;
    }
    // GPUImage獲取到的數據是BGRA格式。
    // 而各類編碼器最適合編碼的格式仍是yuv(NV12格式)。
    // 因此在此將BGRA格式的視頻數據轉成yuv格式。(後面會介紹yuv和pcm格式)
    // 將bgra轉爲yuv
    int width = imageSize.width;
    int height = imageSize.height;
    int w_x_h = width * height;
    // 1幀yuv數據長度爲 寬x高 * 3 / 2
    int yuv_len = w_x_h * 3 / 2;
    
    uint8_t *yuv_bytes = malloc(yuv_len);
    
    //使用libyuv庫,作格式轉換。libyuv中的格式都是大端(高位存高位,低位存低位),而iOS設備是小端(高位存低位,低位存高位),小端爲BGRA,則大端爲ARGB,因此這裏使用ARGBToNV12。
    //self.rawBytesForImage就是美顏後的圖片數據,格式是BGRA。
    //關於大端小端,請自行baidu。
    //NV12格式介紹請看下一篇文章:[1小時學會:最簡單的iOS直播推流(五)yuv、pcm數據的介紹和獲取](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數據發送出去
    [self.capture sendVideoYuvData:yuvData];
}
複製代碼

至此,已經成功使用GPUImage獲取視頻,美顏,格式轉換,準備發送數據。仍是很簡單的。

咱們如今可以使用2種方法來獲取音頻數據,接下來會介紹音視頻編碼相關內容。

文章列表

  1. 1小時學會:最簡單的iOS直播推流(一)項目介紹
  2. 1小時學會:最簡單的iOS直播推流(二)代碼架構概述
  3. 1小時學會:最簡單的iOS直播推流(三)使用系統接口捕獲音視頻
  4. 1小時學會:最簡單的iOS直播推流(四)如何使用GPUImage,如何美顏
  5. 1小時學會:最簡單的iOS直播推流(五)yuv、pcm數據的介紹和獲取
  6. 1小時學會:最簡單的iOS直播推流(六)h26四、aac、flv介紹
  7. 1小時學會:最簡單的iOS直播推流(七)h264/aac 硬編碼
  8. 1小時學會:最簡單的iOS直播推流(八)h264/aac 軟編碼
  9. 1小時學會:最簡單的iOS直播推流(九)flv 編碼與音視頻時間戳同步
  10. 1小時學會:最簡單的iOS直播推流(十)librtmp使用介紹
  11. 1小時學會:最簡單的iOS直播推流(十一)sps&pps和AudioSpecificConfig介紹(完結)
相關文章
相關標籤/搜索