需求
由于需求的原因要做到視頻的實時渲染但是并不改變原視頻,也就是說不是針對視頻本身去加濾鏡,所以就一直在網(wǎng)上找方法,網(wǎng)上大神說是要拿到視頻的每一幀圖片進行渲染。接下來就開始動手。

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上面,現(xiàn)在我們要在每一幀的時候去獲取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,現(xiàn)在我們就可以加上濾鏡了。
2.加濾鏡
加濾鏡就簡單用了系統(tǒng)的對比度,亮度之類的具體的大家可自行配置好看的濾鏡。
CIFilter *filter = [CIFilter filterWithName:@"CIColorControls"];
[filter setValue:ciImg forKey:kCIInputImageKey];
[filter setDefaults];
// 修改亮度 -1---1 數(shù)越大越亮
[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];
現(xiàn)在就剩顯示出來了,我們選擇了用opengl進行渲染,用CPU的話會稍微有些卡頓。
3.顯示
初始化glkview,進行配置。然后我們傳入一個經(jīng)過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的方法里,調(diào)用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]];
}