【问题标题】:How to create instance of Sample Buffer (CMSampleBufferRef)?如何创建样本缓冲区(CMSampleBufferRef)的实例?
【发布时间】:2016-06-02 14:00:35
【问题描述】:

我尝试写ios相机,我拿了部分代码from apple

- (void)captureOutput:(AVCaptureOutput *)captureOutput
         didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer
         fromConnection:(AVCaptureConnection *)connection
{
    // Create a UIImage from the sample buffer data
    UIImage *image = [self imageFromSampleBuffer:sampleBuffer];

     < Add your code here that uses the image >

}

我需要从程序中的任何位置调用此函数。但是因为它需要创建(CMSampleBufferRef) 的对象类型。怎么做?

我试着写这样的东西:

buf1 = [[CMSampleBufferRef alloc]init] 

但这是错误的方式。

【问题讨论】:

  • 在您的委托方法中,您不需要创建 CMSampleBuffer 的实例。您会获得对现有缓冲区的引用(sampleBuffer 参数)。
  • @stefos 恕我直言,调用方法需要转换成 3 个参数。还是我错了?
  • 这是一个 AVCaptureVideoDataOutputSampleBufferDelegate 方法,在写入新视频帧时调用。您没有显式调用此方法。
  • 正如@Xcoder 所说,您不要调用此方法。您只需使用 [captureOutput setSampleBufferDelegate: self queue:] 将控制器设置为委托。
  • @stefos 谢谢。我会考虑的

标签: ios objective-c camera cmsamplebufferref


【解决方案1】:

这是我目前用于在 swift3 中模拟 CMSampleBuffer 进行单元测试的 sn-p:

fileprivate func getCMSampleBuffer() -> CMSampleBuffer {
    var pixelBuffer : CVPixelBuffer? = nil
    CVPixelBufferCreate(kCFAllocatorDefault, 100, 100, kCVPixelFormatType_32BGRA, nil, &pixelBuffer)

    var info = CMSampleTimingInfo()
    info.presentationTimeStamp = kCMTimeZero
    info.duration = kCMTimeInvalid
    info.decodeTimeStamp = kCMTimeInvalid


    var formatDesc: CMFormatDescription? = nil
    CMVideoFormatDescriptionCreateForImageBuffer(kCFAllocatorDefault, pixelBuffer!, &formatDesc)

    var sampleBuffer: CMSampleBuffer? = nil

    CMSampleBufferCreateReadyWithImageBuffer(kCFAllocatorDefault,
                                             pixelBuffer!,
                                             formatDesc!,
                                             &info,
                                             &sampleBuffer);

    return sampleBuffer!
}

【讨论】:

  • 感谢您的回答。我已经不记得事情的本质了。
【解决方案2】:

@Rotem Tamir's Answer 的 Swift 5 版本

fileprivate func getCMSampleBuffer() -> CMSampleBuffer {
    var pixelBuffer: CVPixelBuffer?
    CVPixelBufferCreate(kCFAllocatorDefault, 100, 100, kCVPixelFormatType_32BGRA, nil, &pixelBuffer)

    var info = CMSampleTimingInfo()
    info.presentationTimeStamp = CMTime.zero
    info.duration = CMTime.invalid
    info.decodeTimeStamp = CMTime.invalid

    var formatDesc: CMFormatDescription?
    CMVideoFormatDescriptionCreateForImageBuffer(allocator: kCFAllocatorDefault,
                                                 imageBuffer: pixelBuffer!,
                                                 formatDescriptionOut: &formatDesc)

    var sampleBuffer: CMSampleBuffer?

    CMSampleBufferCreateReadyWithImageBuffer(allocator: kCFAllocatorDefault,
                                             imageBuffer: pixelBuffer!,
                                             formatDescription: formatDesc!,
                                             sampleTiming: &info,
                                             sampleBufferOut: &sampleBuffer)

    return sampleBuffer!
}

【讨论】:

    【解决方案3】:

    尝试所有这些(可能可行):

    UIImage *image = [self imageFromSampleBuffer:&sampleBuffer];
    UIImage *image = [self imageFromSampleBuffer:(id)sampleBuffer];
    UIImage *image = [self imageFromSampleBuffer:(__bridge CMSampleBufferRef)sampleBuffer];
    UIImage *image = [self imageFromSampleBuffer:(__bridge id)sampleBuffer];
    

    如果这些都不起作用,请创建对 CMSampleBuffer 的 CVImageBuffer 的引用,而不添加上述任何内容来替换 UIImage 方法中的 sampleBuffer:

    CVImageBufferRef cvImageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
    

    如果这不起作用,您可以创建一个单独的方法,将 CMSampleBuffer 转换为 UIImage,如下所示:

    // Create a UIImage from sample buffer data
    - (UIImage *) imageFromSampleBuffer:(CMSampleBufferRef) sampleBuffer
    {
        // Get a CMSampleBuffer's Core Video image buffer for the media data
        CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
        // Lock the base address of the pixel buffer
        CVPixelBufferLockBaseAddress(imageBuffer, 0);
    
        // Get the number of bytes per row for the pixel buffer
        void *baseAddress = CVPixelBufferGetBaseAddress(imageBuffer);
    
        // Get the number of bytes per row for the pixel buffer
        size_t bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer);
        // Get the pixel buffer width and height
        size_t width = CVPixelBufferGetWidth(imageBuffer);
        size_t height = CVPixelBufferGetHeight(imageBuffer);
    
        // Create a device-dependent RGB color space
        CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    
        // Create a bitmap graphics context with the sample buffer data
        CGContextRef context = CGBitmapContextCreate(baseAddress, width, height, 8,
          bytesPerRow, colorSpace, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst);
        // Create a Quartz image from the pixel data in the bitmap graphics context
        CGImageRef quartzImage = CGBitmapContextCreateImage(context);
        // Unlock the pixel buffer
        CVPixelBufferUnlockBaseAddress(imageBuffer,0);
    
        // Free up the context and color space
        CGContextRelease(context);
        CGColorSpaceRelease(colorSpace);
    
        // Create an image object from the Quartz image
        UIImage *image = [UIImage imageWithCGImage:quartzImage];
    
        // Release the Quartz image
        CGImageRelease(quartzImage);
    
        return (image);
    }
    

    此方法有效;事实上,这是我使用的那个。

    【讨论】:

      猜你喜欢
      • 2015-06-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-05-22
      • 1970-01-01
      • 1970-01-01
      • 2018-06-29
      相关资源
      最近更新 更多