注意点:
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博客