【滤镜】CVPixelBufferRef处理成黑屏+水印

 注意点:

1、resultPixelBuffer属性set方法写法

2、uiElement懒加载方式,以及在init方法中进行预懒加载

3、GPUImageAlphaBlend的用法,disableSecondFrameCheck,这样只是在需要更新水印的时候检查更新就不会调用很多次

4、注意GPUImageUIElement的这种写法

        __unsafe_unretained GPUImageUIElement *weakOverlay = uiElement;

        [filter disableSecondFrameCheck];//这样只是在需要更新水印的时候检查更新就不会调用很多次

        runAsynchronouslyOnVideoProcessingQueue(^{

            [weakOverlay update];

        });

@interface VideoProcessingManager ()
@property (nonatomic, strong) NSMutableArray *filterArray;

@property (nonatomic, strong) MFPixelBufferHelper *pixelBufferHelper;

@property (nonatomic, assign) CVPixelBufferRef resultPixelBuffer;

@property (nonatomic, strong) GPUImageUIElement *uiElement;

@end

@implementation VideoProcessingManager

- (instancetype)init {
    self = [super init];
    if (self) {
        dispatch_async(dispatch_get_main_queue(), ^{
            // 这里是放到主线程预缓存水印
            GPUImageUIElement *tmp = self.uiElement;
            
        });
    }
    return self;
}

#pragma mark - CapturerManagerDelegate
- (CVPixelBufferRef)processFrame:(CVPixelBufferRef)pixelBuffer {
    CVPixelBufferRef outputPixelBuffer = pixelBuffer;
    if (!self.resultPixelBuffer) {
       CVPixelBufferRef pixelBuffer = [self renderByGPUImage:outputPixelBuffer];
       self.resultPixelBuffer = pixelBuffer;
       CVPixelBufferRelease(pixelBuffer);
    }
    outputPixelBuffer = self.resultPixelBuffer;
    return outputPixelBuffer;
}

- (void)setResultPixelBuffer:(CVPixelBufferRef)resultPixelBuffer {
    if (_resultPixelBuffer &&
        resultPixelBuffer &&
        CFEqual(resultPixelBuffer, _resultPixelBuffer)) {
        return;
    }
    if (resultPixelBuffer) {
        CVPixelBufferRetain(resultPixelBuffer);
    }
    if (_resultPixelBuffer) {
        CVPixelBufferRelease(_resultPixelBuffer);
    }
    _resultPixelBuffer = resultPixelBuffer;
}


- (MFPixelBufferHelper *)pixelBufferHelper {
    if (!_pixelBufferHelper) {
        EAGLContext *context = [[GPUImageContext sharedImageProcessingContext] context];
        _pixelBufferHelper = [[MFPixelBufferHelper alloc] initWithContext:context];
    }
    return _pixelBufferHelper;
}

- (CVPixelBufferRef)renderByGPUImage:(CVPixelBufferRef)pixelBuffer {
    
    CVPixelBufferRetain(pixelBuffer);
    __block CVPixelBufferRef output = nil;
    __weak typeof(self) weakSelf = self;
    runSynchronouslyOnVideoProcessingQueue(^{
        [GPUImageContext useImageProcessingContext];
        
        // (1)
        GLuint textureID = [weakSelf.pixelBufferHelper convertYUVPixelBufferToTexture:pixelBuffer];
        CGSize size = CGSizeMake(CVPixelBufferGetWidth(pixelBuffer),
                                 CVPixelBufferGetHeight(pixelBuffer));

        [GPUImageContext setActiveShaderProgram:nil];
        // (2)
        GPUImageTextureInput *textureInput = [[GPUImageTextureInput alloc] initWithTexture:textureID size:size];
//        GPUImageSmoothToonFilter *filter = [[GPUImageSmoothToonFilter alloc] init];
//        [textureInput addTarget:filter];

        GPUImageBrightnessFilter *brightNessFilter = [[GPUImageBrightnessFilter alloc] init];
        brightNessFilter.brightness = -1;
        [textureInput addTarget:brightNessFilter];
        
        /**/


        //创建滤镜
        GPUImageUIElement *uiElement = self.uiElement;

        GPUImageAlphaBlendFilter *filter = [[GPUImageAlphaBlendFilter alloc] init];

        filter.mix = 1.0;
//        [textureInput addTarget:filter];
        [brightNessFilter addTarget:filter];
        [uiElement addTarget:filter];
        /**/

        GPUImageTextureOutput *textureOutput = [[GPUImageTextureOutput alloc] init];
//        [filter addTarget:textureOutput];
//
        [filter addTarget:textureOutput];
        
        /**/
        __unsafe_unretained GPUImageUIElement *weakOverlay = uiElement;

        [filter disableSecondFrameCheck];//这样只是在需要更新水印的时候检查更新就不会调用很多次

        runAsynchronouslyOnVideoProcessingQueue(^{

            [weakOverlay update];

        });

        /**/
        [textureInput processTextureWithFrameTime:kCMTimeZero];

        // (3)
        output = [weakSelf.pixelBufferHelper convertTextureToPixelBuffer:textureOutput.texture
                                                         textureSize:size];

        [textureOutput doneWithTexture];

        glDeleteTextures(1, &textureID);
    });
    CVPixelBufferRelease(pixelBuffer);
    return output;
}

- (GPUImageUIElement *)uiElement {
    if (!_uiElement) {
        
        CGSize size = [UIScreen mainScreen].bounds.size;
        //添加时间戳水印和图片水印
        
        UIView *contentView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, size.width, size.height)];
        
        
        UIImageView *imageV = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, size.width, size.height)];
//        imageV.backgroundColor = [UIColor cyanColor];
        imageV.image = [UIImage imageNamed:@"QQ.png" inBundle:[NSBundle bundleForClass:self.class] compatibleWithTraitCollection:nil];
        [contentView addSubview:imageV];
        
        NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
        
        [formatter setDateFormat:@"yyyy年MM月dd日hh:mm:ss"];
        
        NSDate *currentDate = [NSDate date];
        
        NSString *timeString = [formatter stringFromDate:currentDate];
        
        UILabel *timestampLabel = [[UILabel alloc] initWithFrame:CGRectMake(contentView.frame.size.width * 0.5 - 80, 200, 160, 60)];
        
        timestampLabel.text = timeString;
        
        timestampLabel.textColor = [UIColor redColor];
        
        [contentView addSubview:timestampLabel];
        
        
        //创建水印图形
        
        GPUImageUIElement *uiElement = [[GPUImageUIElement alloc] initWithView:contentView];
        _uiElement = uiElement;
    }
    return _uiElement;
}

@end

MFPixelBufferHelper 见:【CVPixelBufferRef】添加滤镜的方法_allanGold的博客-CSDN博客

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值