• 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];
        }];
        
    }
  • 相关阅读:
    EOS概念理解总结
    boost asio one client one thread
    EOS 数据签名与公匙验证代码用例
    EOS 智能合约编写(一)
    EOS多节点同步代码分析
    EOS 用户权限相关命令
    EOS 多主机多节点配置终极命令
    EOS多主机多节点环境配置
    ubuntu命令错误集
    java多线程中的调度策略
  • 原文地址:https://www.cnblogs.com/madaha/p/9810654.html
Copyright © 2020-2023  润新知