ios 实时影像回调---分解LFLiveKit

- (void)reloadFilter{
    
    /* 移除所有的下一级滤镜对象 */
    [self.filter removeAllTargets];
    [self.blendFilter removeAllTargets];
    [self.uiElementInput removeAllTargets];
    [self.videoCamera removeAllTargets];
    [self.output removeAllTargets];
    [self.cropfilter removeAllTargets];
    
    if (self.beautyFace) {
        self.output = [[LFGPUImageEmptyFilter alloc] init];
        self.filter = [[LFGPUImageBeautyFilter alloc] init];
        self.beautyFilter = (LFGPUImageBeautyFilter*)self.filter;
    } else {
        self.output = [[LFGPUImageEmptyFilter alloc] init];
        self.filter = [[LFGPUImageEmptyFilter alloc] init];
        self.beautyFilter = nil;
    }
    
    ///< 调节镜像
    [self reloadMirror];
    
    ///< 480*640 比例为4:3  强制转换为16:9
    if([self.configuration.avSessionPreset isEqualToString:AVCaptureSessionPreset640x480]){
        
        /*
         图片宽 = 像素宽 / 分辨率宽
         图片高 = 像素高 / 分辨率高
         
         CropRegion: 在图片内裁剪,宽高按比例默认0.0~1.0,0.0-0.0位于图片左上角

         假设一张图片size=100x100,
         如果横屏裁切后展示的区域是CGRectMake(0, 12.5, 100, 75)
         如果竖屏裁切后的展示区域是CGRectMake(12.5, 0, 75, 100)
         */
        CGRect cropRect = self.configuration.landscape ? CGRectMake(0, 0.125, 1, 0.75) : CGRectMake(0.125, 0, 0.75, 1);
        self.cropfilter = [[GPUImageCropFilter alloc] initWithCropRegion:cropRect];
        [self.videoCamera addTarget:self.cropfilter];
        [self.cropfilter addTarget:self.filter];
    }else{
        
        /*
         将滤镜添加到摄像头
         */
        [self.videoCamera addTarget:self.filter];
    }
    
    /*
     每个处理环节都是从上一个获取图像数据,进行处理后传递给下一个,下游的处理对象被称之为上一步的tatget
     使用 addTarget: 为处理链路添加每个环节的对象
     */
    
    //< 添加水印
    if(self.warterMarkView){
        
        /*
         要理解它的实现原理,需要搞懂GPUImageUIElement和GPUImageAlphaBlendFilter。
         GPUImageUIElement的作用是把一个视图的layer通过CALayer的renderInContext:方法把layer转化为image,
         然后作为OpenGL的纹理传给GPUImageAlphaBlendFilter。
         而GPUImageAlphaBlendFilter则是一个两输入的blend filter,
         第一个输入是摄像头数据,
         第二个输入是刚刚提到的GPUImageUIElement的数据,
         GPUImageAlphaBlendFilter将这两个输入做alpha blend,可以简单的理解为将第二个输入叠加到第一个的上面,
         */
        
        /*
         双重滤镜叠加效果(并联)
         fileter滤镜->blendFilter滤镜->gpuImageView展示
         uiElementInput->blendFilter滤镜->gpuImageView展示
         
         uiElementInput: 只有初始化的水印图片,注释 [self.filter addTarget:self.blendFilter] ,
                         屏幕上只有水印录像没有实时影像
         filter: 实时影像
         */
        [self.filter addTarget:self.blendFilter];
        [self.uiElementInput addTarget:self.blendFilter];
        [self.blendFilter addTarget:self.gpuImageView];
        if(self.saveLocalVideo) [self.blendFilter addTarget:self.movieWriter];
        [self.filter addTarget:self.output];
        [self.uiElementInput update]; // 
    }else{
        [self.filter addTarget:self.output];
        [self.output addTarget:self.gpuImageView];
        if(self.saveLocalVideo) [self.output addTarget:self.movieWriter];
    }
    
    // 设置渲染的区域
    [self.filter forceProcessingAtSize:self.configuration.videoSize];
    [self.output forceProcessingAtSize:self.configuration.videoSize];
    [self.blendFilter forceProcessingAtSize:self.configuration.videoSize];
    [self.uiElementInput forceProcessingAtSize:self.configuration.videoSize];
    
    /*
     为什么要使用output? 在水印判断代码中最后都添加了output的这个target?
     首先filter分为美颜与普通,filter本身并不携带水印,
     其次output也可以省去,那么就需要if和else都调用 setFrameProcessingCompletionBlock
     
     output充当一个汇总,并且初始化的时候是 LFGPUImageEmptyFilter ,并不做二次滤镜效果
     */
    
    //< 输出数据
    __weak typeof(self) _self = self;
    [self.output setFrameProcessingCompletionBlock:^(GPUImageOutput *output, CMTime time) {
        [_self processVideo:output];
    }];
    
}

 

posted on 2018-10-18 15:15  马大哈哈  阅读(663)  评论(0编辑  收藏  举报

导航