Create CVPixelBufferRef from CIImage for Writing to File

13,158

UPDATED ANSWER

While my previous method works, I was able to tweak it to simplify the code. It also seems to runs slightly faster.

samplePixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
CVPixelBufferLockBaseAddress(samplePixelBuffer, 0); // NOT SURE IF NEEDED // NO PERFORMANCE IMPROVEMENTS IF REMOVED

NSDictionary *options = [NSDictionary dictionaryWithObject:(__bridge id)rgbColorSpace forKey:kCIImageColorSpace];                
outputImage = [CIImage imageWithCVPixelBuffer:samplePixelBuffer options:options];

//-----------------
// FILTER OUTPUT IMAGE

@autoreleasepool {

    outputImage = [self applyEffectToCIImage:outputImage dict:dict];

}
CVPixelBufferUnlockBaseAddress(samplePixelBuffer, 0); // NOT SURE IF NEEDED // NO PERFORMANCE IMPROVEMENTS IF REMOVED

//-----------------
// RENDER OUTPUT IMAGE BACK TO PIXEL BUFFER

[self.filterContext render:outputImage toCVPixelBuffer:samplePixelBuffer bounds:[outputImage extent] colorSpace:CGColorSpaceCreateDeviceRGB()]; // DOES NOT SEEM TO WORK USING rgbColorSpace

PREVIOUS ANSWER

I just implemented the following to get the pixel buffer from a CIImage. Make sure your pixel formats are consistent otherwise you will have color issues. Also the CFDictionaries are very important. http://allmybrain.com/2011/12/08/rendering-to-a-texture-with-ios-5-texture-cache-api/

CFDictionaryRef empty = CFDictionaryCreate(kCFAllocatorDefault, // EMPTY IOSURFACE DICT
                                           NULL,
                                           NULL,
                                           0,
                                           &kCFTypeDictionaryKeyCallBacks,
                                           &kCFTypeDictionaryValueCallBacks);
CFMutableDictionaryRef attributes = CFDictionaryCreateMutable(kCFAllocatorDefault,
                                                         1,
                                                         &kCFTypeDictionaryKeyCallBacks,
                                                         &kCFTypeDictionaryValueCallBacks);

CFDictionarySetValue(attributes,kCVPixelBufferIOSurfacePropertiesKey,empty);

CVPixelBufferRef pixelBuffer = NULL;
CVReturn status = CVPixelBufferCreate(kCFAllocatorDefault, 
                                      outputImage.extent.size.width, 
                                      outputImage.extent.size.height, 
                                      kCVPixelFormatType_32BGRA, 
                                      attributes, 
                                      &pixelBuffer);

if (status == kCVReturnSuccess && pixelBuffer != NULL) {

    CVPixelBufferLockBaseAddress(pixelBuffer, 0); // NOT SURE IF NEEDED // KEPT JUST IN CASE
    [self.filterContext render:outputImage toCVPixelBuffer:pixelBuffer bounds:[outputImage extent] colorSpace:CGColorSpaceCreateDeviceRGB()];
    CVPixelBufferUnlockBaseAddress(pixelBuffer, 0); // NOT SURE IF NEEDED // KEPT JUST IN CASE

}
Share:
13,158
Andrew
Author by

Andrew

Updated on June 14, 2022

Comments

  • Andrew
    Andrew almost 2 years

    I'm writing a custom Movie Recording app and have implemented AVAssetWriter and AVAssetWriterInputPixelBufferAdaptor for writing frames to a file. In the DataOutputDelegate callback I am trying to apply a CIFilter to the sampleBuffer. First I get a CVPixelBufferRef and then create a CIImage. I then apply the CIIFilter and grab the resulting CIImage:

        CVPixelBufferRef pixelBuffer = (CVPixelBufferRef)CMSampleBufferGetImageBuffer(sampleBuffer);
    
        CIImage *image = [CIImage imageWithCVPixelBuffer:pixelBuffer];
        CIFilter *hueAdjust = [CIFilter filterWithName:@"CIHueAdjust"];
        [hueAdjust setDefaults];
        [hueAdjust setValue: image forKey: @"inputImage"];
        [hueAdjust setValue: [NSNumber numberWithFloat: 2.094]
                     forKey: @"inputAngle"];
    
        CIImage *result = [hueAdjust valueForKey: @"outputImage"];
    
        CVPixelBufferRef newBuffer = //Convert CIImage...
    

    How would I go about converting that CIImage so I can:

        [self.filteredImageWriter appendPixelBuffer:newBuffer withPresentationTime:lastSampleTime];
    
  • Tim Bull
    Tim Bull about 10 years
    This is a very useful answer, however it's missing a critical piece of information for me. What is [self.filterContext... ]. If I understand your code correctly, this is the part that actually renders the CIImage back to the Pixel Buffer which is what I'm looking for. Can you share that function please? Thank you!
  • halileohalilei
    halileohalilei over 6 years
    @TimBull I know it's been a couple of years but for anyone that may see this in the future: self.filteContext is a CIContext object. The render method renders the CIImage to a CVPixelBuffer object: developer.apple.com/documentation/coreimage/cicontext/…
  • user924
    user924 about 6 years
    example in swift?
  • user924
    user924 about 6 years
    @halileohalilei can you provide full example in Swift and hot to get that context? Is it form CIImage?