zoukankan      html  css  js  c++  java
  • 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];
        }];
        
    }
  • 相关阅读:
    学习算法和刷题的思路指南
    提交包到iTunes Connect时构建版本“正在处理”后直接消失的问题
    对网络通讯的一些学习和总结
    iOS开发 dispatch_block_t 简单的实现不带参数的回调函数
    app刚开始启动时(即:appdelegate文件中)可以写的几个功能
    拷贝项目时,自己总结的一些小事项
    iOS开发中遇到的一些问题以及解决办法总结
    宝库~iOS开发笔试题
    GCD 之线程死锁
    iOS开发之旅之懒加载
  • 原文地址:https://www.cnblogs.com/madaha/p/9810654.html
Copyright © 2011-2022 走看看