iOS实现系统录屏 RPBroadcastSampleHandler 和 AVAssetWriter 结合使用便可实现,这两个类如何使用这里不做过多说明,文章内容是在已实现录屏功能的情况下如何为视频帧添加水印。
1、初始化方法里添加
#import <Metal/Metal.h>
- (instancetype)init{
if(self = [super init]){
//其它代码.......
UIImage *image = [[UIImage alloc] initWithContentsOfFile:@"水印图片路径"];
_watermarkImage = [CIImage imageWithCGImage:image.CGImage];
id<MTLDevice> metalDevice = MTLCreateSystemDefaultDevice();
CIContext *ciContext = [CIContext contextWithMTLDevice:metalDevice];
_ciContext = ciContext;
}
return self;
}
核心代码:
- (void)processSampleBuffer:(CMSampleBufferRef)sampleBuffer withType:(RPSampleBufferType)sampleBufferType{
if(sampleBufferType == RPSampleBufferTypeVideo){
AVAssetWriterStatus status = self.assetWriter.status;
if (status == AVAssetWriterStatusFailed || status == AVAssetWriterStatusCompleted || status == AVAssetWriterStatusCancelled) {
return;
}
if (status == AVAssetWriterStatusUnknown) {
//初始化起始时间
[self.assetWriter startWriting];
CMTime time = CMSampleBufferGetPresentationTimeStamp(sampleBuffer);
[self.assetWriter startSessionAtSourceTime:time];
[self.videoInput appendSampleBuffer:[self addPortraitWatermarkWithBufferRef:sampleBuffer watermark:self.watermarkImage]];
}
if(status == AVAssetWriterStatusWriting && self.videoInput.isReadyForMoreMediaData){
//添加水印处理
[self.videoInput appendSampleBuffer:[self addPortraitWatermarkWithBufferRef:sampleBuffer watermark:self.watermarkImage]];
}
}
}
//水印渲染到视频帧
- (CMSampleBufferRef)addPortraitWatermarkWithBufferRef:(CMSampleBufferRef)sampleBufferRef
watermark:(CIImage *)watermark{
//核心代码如下:可以按照自己的需求调整水印位置,当前的水印是和屏幕比例相同的图片,并且图片是除了水印部分,其它为透明的图片,所以只需放缩到和视频帧画面大小即可
CVPixelBufferRef curPixelBuffer = CMSampleBufferGetImageBuffer(sampleBufferRef);
CVPixelBufferLockBaseAddress(curPixelBuffer, 0);
CGFloat rrwidth = CVPixelBufferGetWidth(curPixelBuffer);
CIImage *contentImage = [CIImage imageWithCVPixelBuffer:curPixelBuffer];
CGFloat rate = rrwidth / contentImage.extent.size.width;
contentImage = [contentImage imageByApplyingTransform:CGAffineTransformMakeScale(rate, rate)];
CGFloat imageWidth = watermark.extent.size.width;
CGFloat w_rate = rrwidth/imageWidth;
CIImage *tempImage = [watermark imageByApplyingTransform:CGAffineTransformMakeScale(w_rate, w_rate)];
tempImage = [tempImage imageByCompositingOverImage:contentImage];
[_ciContext render:tempImage toCVPixelBuffer:curPixelBuffer];
CVPixelBufferUnlockBaseAddress(curPixelBuffer, 0);
return sampleBufferRef;
}