【问题标题】:AVFoundation: add text to the CMSampleBufferRef video frameAVFoundation:将文本添加到 CMSampleBufferRef 视频帧
【发布时间】:2014-03-12 07:30:30
【问题描述】:

我正在使用 AVFoundation 构建一个应用程序。

就在我打电话给[assetWriterInput appendSampleBuffer:sampleBuffer] 之前 - (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection-方法。

我在样本缓冲区中操作像素(使用像素缓冲区来应用效果)。

但客户希望我在帧上也添加文本(时间戳和帧计数器),但我还没有找到方法。

我尝试将样本缓冲区转换为图像,在图像上应用文本,然后将图像转换回样本缓冲区,但随后

CMSampleBufferDataIsReady(sampleBuffer)

失败。

这是我的 UIImage 类别方法:

 +  (UIImage *) imageFromSampleBuffer:(CMSampleBufferRef) sampleBuffer
    {
    CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);

    CVPixelBufferLockBaseAddress(imageBuffer,0);

    uint8_t *baseAddress = (uint8_t *)CVPixelBufferGetBaseAddress(imageBuffer);
    size_t bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer);
    size_t width = CVPixelBufferGetWidth(imageBuffer);
    size_t height = CVPixelBufferGetHeight(imageBuffer);


    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    CGContextRef newContext = CGBitmapContextCreate(baseAddress, width, height, 8, bytesPerRow, colorSpace, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst);

    CGImageRef newImage = CGBitmapContextCreateImage(newContext);

    CGContextRelease(newContext);
    CGColorSpaceRelease(colorSpace);

    UIImage *newUIImage = [UIImage imageWithCGImage:newImage];

    CFRelease(newImage);

    return newUIImage;
    }

 - (CMSampleBufferRef) cmSampleBuffer
    {
        CGImageRef image = self.CGImage;

        NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
                                 [NSNumber numberWithBool:YES], kCVPixelBufferCGImageCompatibilityKey,
                                 [NSNumber numberWithBool:YES], kCVPixelBufferCGBitmapContextCompatibilityKey,
                                 nil];
        CVPixelBufferRef pxbuffer = NULL;

        CVReturn status = CVPixelBufferCreate(kCFAllocatorDefault,
                                              self.size.width,
                                              self.size.height,
                                              kCVPixelFormatType_32ARGB,
                                              (__bridge CFDictionaryRef) options,
                                              &pxbuffer);
        NSParameterAssert(status == kCVReturnSuccess && pxbuffer != NULL);

        CVPixelBufferLockBaseAddress(pxbuffer, 0);
        void *pxdata = CVPixelBufferGetBaseAddress(pxbuffer);
        NSParameterAssert(pxdata != NULL);

        CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateDeviceRGB();
        CGContextRef context = CGBitmapContextCreate(pxdata, self.size.width,
                                                     self.size.height, 8, 4*self.size.width, rgbColorSpace,
                                                     kCGImageAlphaNoneSkipFirst);
        NSParameterAssert(context);
        CGContextConcatCTM(context, CGAffineTransformMakeRotation(0));
        CGContextDrawImage(context, CGRectMake(0, 0, CGImageGetWidth(image),
                                               CGImageGetHeight(image)), image);
        CGColorSpaceRelease(rgbColorSpace);
        CGContextRelease(context);
        CVPixelBufferUnlockBaseAddress(pxbuffer, 0);
        CMVideoFormatDescriptionRef videoInfo = NULL;
        CMSampleBufferRef sampleBuffer = NULL;
        CMSampleBufferCreateForImageBuffer(kCFAllocatorDefault,
                                           pxbuffer, true, NULL, NULL, videoInfo, NULL, &sampleBuffer);
        return sampleBuffer;
    }

有什么想法吗?

编辑:

我用 Tony 的回答更改了我的代码。 (谢谢!) 此代码有效:

CVPixelBufferRef pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);

    CVPixelBufferLockBaseAddress( pixelBuffer, 0 );

    EAGLContext *eaglContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
    CIContext *ciContext = [CIContext contextWithEAGLContext:eaglContext options:@{kCIContextWorkingColorSpace : [NSNull null]} ];

    UIFont *font = [UIFont fontWithName:@"Helvetica" size:40];
    NSDictionary *attributes = @{NSFontAttributeName: font,
                                 NSForegroundColorAttributeName: [UIColor lightTextColor]};

    UIImage *img = [UIImage imageFromText:@"01 - 13/02/2014 15:18:21:654" withAttributes:attributes];
    CIImage *filteredImage = [[CIImage alloc] initWithCGImage:img.CGImage];

    [ciContext render:filteredImage toCVPixelBuffer:pixelBuffer bounds:[filteredImage extent] colorSpace:CGColorSpaceCreateDeviceRGB()];

    CVPixelBufferUnlockBaseAddress(pixelBuffer, 0);

【问题讨论】:

  • 有点随机,但你介意分享你的 UIImage 来源 *img = [UIImage imageFromText:@"01 - 13/02/2014 15:18:21:654" withAttributes:attributes];
  • @chrisallick 见这里:stackoverflow.com/questions/2765537/…
  • 您找到在 CMSampleBuffer 上添加文本的解决方案了吗?

标签: ios avfoundation video-capture


【解决方案1】:

你应该参考苹果的CIFunHouse示例,你可以使用这个api直接绘制到缓冲区

-(void)render:(CIImage *)image toCVPixelBuffer:(CVPixelBufferRef)buffer bounds:(CGRect)r colorSpace:(CGColorSpaceRef)cs

你可以在这里下载它WWDC2013

创建上下文

_eaglContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
_ciContext = [CIContext contextWithEAGLContext:_eaglContext options:@{kCIContextWorkingColorSpace : [NSNull null]} ];

现在渲染图像

CVPixelBufferRef renderedOutputPixelBuffer = NULL;
OSStatus err = CVPixelBufferPoolCreatePixelBuffer(nil, self.pixelBufferAdaptor.pixelBufferPool, &renderedOutputPixelBuffer);
[_ciContext render:filteredImage toCVPixelBuffer:renderedOutputPixelBuffer bounds:[filteredImage extent]

【讨论】:

  • 这很好用,只有透明图像在黑盒子里。知道为什么吗? :)
  • @JoriDor 你知道它为什么是黑色的吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-03-29
  • 2016-05-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-24
  • 2011-10-29
相关资源
最近更新 更多