ios视频实时渲染

需求

由于需求的原因要做到视频的实时渲染但是并不改变原视频,也就是说不是针对视频本身去加滤镜,所以就一直在网上找方法,网上大神说是要拿到视频的每一帧图片进行渲染。接下来就开始动手。


截图


1.拿到视频每一帧

在AVFoundation框架里有一个类AVPlayerItemVideoOutput,用来获取视频输出的每一帧,具体看代码

AVPlayerItem *item = [AVPlayerItem playerItemWithURL:videoUrl];

_videoOutPut = [[AVPlayerItemVideoOutput alloc] initWithOutputSettings:nil];

_player = [[AVPlayer alloc] initWithPlayerItem:item];

[self.player.currentItem addOutput:_videoOutPut];

上面初始化了一个item和videoOutPut,并且把videoOutPut加到了item上面,现在我们要在每一帧的时候去获取buffer。

CMTime itemTime = [_videoOutPut itemTimeForHostTime:CACurrentMediaTime()];

if ([_videoOutPut hasNewPixelBufferForItemTime:itemTime]) {

CVPixelBufferRef pixelBuffer = [_videoOutPut copyPixelBufferForItemTime:itemTime itemTimeForDisplay:nil];

CIImage *ciImage = [CIImage imageWithCVPixelBuffer:pixelBuffer];

CVBufferRelease(pixelBuffer);

}else{

}

这样我们就获取到了视频每一帧的CIImage,现在我们就可以加上滤镜了。

2.加滤镜

加滤镜就简单用了系统的对比度,亮度之类的具体的大家可自行配置好看的滤镜。

CIFilter *filter = [CIFilter filterWithName:@"CIColorControls"];

[filter setValue:ciImg forKey:kCIInputImageKey];

[filter setDefaults];

// 修改亮度 -1---1 数越大越亮

[filter setValue:@(self.light) forKey:@"inputBrightness"];

// 修改饱和度 0---2

[filter setValue:@(self.saturation) forKey:@"inputSaturation"];

// 修改对比度 0---4

[filter setValue:@(self.contrast) forKey:@"inputContrast"];

CIImage *outputImage = [filter outputImage];

现在就剩显示出来了,我们选择了用opengl进行渲染,用CPU的话会稍微有些卡顿。

3.显示

初始化glkview,进行配置。然后我们传入一个经过CIFilter处理的CIImage就可以渲染出来了。

- (void)initGlkView{

EAGLContext *eaglContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];

_glkView = [[GLKView alloc] initWithFrame:CGRectZero context:eaglContext];

_glkView.delegate = self;

[_glkView bindDrawable];

_glkView.enableSetNeedsDisplay = NO;

[self addSubview:_glkView];

[EAGLContext setCurrentContext:eaglContext];

_imageContext = [CIContext contextWithEAGLContext:eaglContext options:@{kCIContextWorkingColorSpace:[NSNull null]}];

}


在传入CIImage的方法里,调用display方法进行绘制。

- (void)setRenderImg:(CIImage *)renderImg{

_renderImg = renderImg;

[self.glkView display];

}

- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect{

[self.imageContext drawImage:self.renderImg inRect:CGRectMake(0, 0, self.glkView.drawableWidth, self.glkView.drawableHeight) fromRect:[self.renderImg extent]];

}

具体代码地址:https://github.com/zhuyongqing/ZYPlayerView

你可能感兴趣的:(ios视频实时渲染)