ios - 在录制视频时将动态文本渲染到 CVPixelBufferRef 上

标签 ios objective-c avfoundation core-image core-video

我正在使用 AVCaptureVideoDataOutputAVCaptureAudioDataOutput 录制视频和音频,并在 captureOutput:didOutputSampleBuffer:fromConnection: 委托(delegate)方法中,我想将文本绘制到我从视频连接接收到的每个单独的样本缓冲区上。文本几乎每帧都会发生变化(这是一个秒表标签),我希望将其记录在捕获的视频数据之上。

到目前为止,这是我能想到的:

//1.
CVPixelBufferRef pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);

//2.   
UIImage *textImage = [self createTextImage];
CIImage *maskImage = [CIImage imageWithCGImage:textImage.CGImage];

//3.
CVPixelBufferLockBaseAddress(pixelBuffer, 0); 
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
NSDictionary *options = [NSDictionary dictionaryWithObject:(__bridge id)colorSpace forKey:kCIImageColorSpace];
CIImage *inputImage = [CIImage imageWithCVPixelBuffer:pixelBuffer options:options];

//4.
CIFilter *filter = [CIFilter filterWithName:@"CIBlendWithMask"];
[filter setValue:inputImage forKey:@"inputImage"];
[filter setValue:maskImage forKey:@"inputMaskImage"];
CIImage *outputImage = [filter outputImage];
CVPixelBufferUnlockBaseAddress(pixelBuffer, 0);

//5.   
[self.renderContext render:outputImage toCVPixelBuffer:pixelBuffer bounds:[outputImage extent] colorSpace:CGColorSpaceCreateDeviceRGB()];

//6.
[self.pixelBufferAdaptor appendPixelBuffer:pixelBuffer withPresentationTime:timestamp];
  1. 在这里,我获取像素缓冲区,非常简单。
  2. 我使用核心图形将文本写入空白 UIImage(这就是 createTextImage 所做的。我能够验证此步骤是否有效;我将绘制有文本的图像保存到我的照片中。
  3. 我从像素缓冲区创建一个 CGImage。
  4. 我为 CIBlendWithMask 制作了一个 CIFilter,将输入图像设置为从原始像素缓冲区创建的图像,将输入掩码设置为从带有文本的图像制作的 CIImage画在上面。
  5. 最后,我将过滤器输出图像渲染到 pixelBuffer。 CIContext 是预先使用 [CIContext contextWithOptions:nil]; 创建的。
  6. 之后,我使用适当的时间戳将像素缓冲区附加到我的 pixelBufferAdaptor

在录制结束时保存的视频没有明显的变化,即没有在像素缓冲区上绘制 mask 图像。

有人知道我这里哪里出错了吗?几天来我一直坚持这一点,非常感谢任何帮助。

编辑:

- (UIImage *)createTextImage {
    UIGraphicsBeginImageContextWithOptions(CGSizeMake(self.view.bounds.size.width, self.view.bounds.size.height), NO, 1.0);
    NSMutableAttributedString *timeStamp = [[NSMutableAttributedString alloc]initWithString:self.timeLabel.text attributes:@{NSForegroundColorAttributeName:self.timeLabel.textColor, NSFontAttributeName: self.timeLabel.font}];
    NSMutableAttributedString *countDownString = [[NSMutableAttributedString alloc]initWithString:self.cDownLabel.text attributes:@{NSForegroundColorAttributeName:self.cDownLabel.textColor, NSFontAttributeName:self.cDownLabel.font}];
    [timeStamp drawAtPoint:self.timeLabel.center];
    [countDownString drawAtPoint:self.view.center];
    UIImage *blank = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return blank;
}

最佳答案

你想像下面这样吗? enter image description here

而不是使用 CIBlendWithMask,你应该使用 CISourceOverCompositing,试试这个:

//4.
CIFilter *filter = [CIFilter filterWithName:@"CISourceOverCompositing"];
[filter setValue:maskImage forKey:kCIInputImageKey];
[filter setValue:inputImage forKey:kCIInputBackgroundImageKey];
CIImage *outputImage = [filter outputImage];

关于ios - 在录制视频时将动态文本渲染到 CVPixelBufferRef 上,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30609241/

相关文章:

ios - 如何删除现有记录并在核心数据中添加新数据

iOS - 仅使 subview 可点击

swift - 如何快速裁剪所选区域的视频帧大小?

ios 9 AVCaptureDevice 设置焦点

ios - UIActionSheet 在 iOS7 中缺少背景

iOS - UISlider 滑动时显示多个值

iphone - 从 iPhone 获取时区/国家

ios - UIImagePickerController 不是全屏

ios - 无法在我的 iPhone 应用程序中显示 playhaven 全屏广告

ios - swift 3 : Rerecord video through AVFoundation