4

I am trying to crop and scale a CMSampleBufferRef based on user's inputs, on ratio, the below code takes a CMSampleBufferRef, convert it into a CVImageBufferRef and use CVPixelBuffer to crop the internal image based on its bytes. The goal of this process is to have a cropped and scaled CVPixelBufferRef to write to the video

- (CVPixelBufferRef)modifyImage:(CMSampleBufferRef) sampleBuffer {
    @synchronized (self) {
        CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer); 
        // Lock the image buffer
        CVPixelBufferLockBaseAddress(imageBuffer,0); 

        // Get information about the image
        uint8_t *baseAddress = (uint8_t *)CVPixelBufferGetBaseAddress(imageBuffer); 
        size_t bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer); 
        size_t width = CVPixelBufferGetWidth(imageBuffer); 
        size_t height = CVPixelBufferGetHeight(imageBuffer); 

        CVPixelBufferRef pxbuffer;
        NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
                                 [NSNumber numberWithBool:YES], kCVPixelBufferCGImageCompatibilityKey,
                                 [NSNumber numberWithBool:YES], kCVPixelBufferCGBitmapContextCompatibilityKey,  
                                 [NSNumber numberWithInt:720], kCVPixelBufferWidthKey, 
                                 [NSNumber numberWithInt:1280], kCVPixelBufferHeightKey,
                                 nil];
        NSInteger tempWidth = (NSInteger) (width / ratio);
        NSInteger tempHeight = (NSInteger) (height / ratio);

        NSInteger baseAddressStart = 100 + 100 * bytesPerRow;
        CVReturn status = CVPixelBufferCreateWithBytes(kCFAllocatorDefault, tempWidth, tempHeight, kCVPixelFormatType_32BGRA, &baseAddress[baseAddressStart], bytesPerRow, MyPixelBufferReleaseCallback, NULL, (CFDictionaryRef)options, &pxbuffer);

        if (status != 0) {
            CKLog(@"%d", status);
            return NULL;
        }

        CVPixelBufferUnlockBaseAddress(imageBuffer,0);

        return pxbuffer;
    }
}

It all works fine, except that when I am trying to write it into the video's ouput using this method, it keeps receiving memory warning. It is fine if I keep the same ratio

- (void)writeBufferFrame:(CMSampleBufferRef)sampleBuffer pixelBuffer:(CVPixelBufferRef)pixelBuffer {
    CMTime lastSampleTime = CMSampleBufferGetPresentationTimeStamp(sampleBuffer);    

    if(self.videoWriter.status != AVAssetWriterStatusWriting)
    {
        CKLog(@"%d", self.videoWriter.status);
        [self.videoWriter startWriting];
        [self.videoWriter startSessionAtSourceTime:lastSampleTime];
    }

    CVPixelBufferRef pxbuffer = [self modifyImage:sampleBuffer];
    BOOL success = [self.avAdaptor appendPixelBuffer:pxbuffer withPresentationTime:lastSampleTime];
    if (!success)
        NSLog(@"Warning:  Unable to write buffer to video");
}

I also tried with different approaches using CMSampleBufferRef and CGContext. If you can provide a solution for any approach here, I can give you the full score

Community
  • 1
  • 1
vodkhang
  • 18,639
  • 11
  • 76
  • 110
  • Small doubt i just want to resize CVpixcelbuffer . which is possible ? i just used your code . but couln't get it expected o/p.in option dic i have added original size and temp size i have pointed my expecetd size but which is not worked – Vasu Ashok Dec 08 '14 at 06:24

1 Answers1

1

Try to use kCVPixelBufferLock_ReadOnly flag in both calls to -CVPixelBufferLockBaseAddress and -CVPixelBufferUnlockBaseAddress. And sometimes this issue can be solved by copying pixel buffer. Perform allocating once:

unsigned char *data = (unsigned char*)malloc(ySize * sizeof(unsigned char));

After that, copy data from pixelBuffer to data

size_t size = height * bytesPerRow;

memcpy(data, baseAddress, size);

After that, use data. Hope, that will help.

Community
  • 1
  • 1
Nikita Ivaniushchenko
  • 1,425
  • 11
  • 11
  • But I need to write my pixelBuffer to the video, how can I do that with `data`? – vodkhang Dec 22 '11 at 02:15
  • What abput sample code? Anyway, you're creating pixel buffer with CVReturn status = CVPixelBufferCreateWithBytes(kCFAllocatorDefault, tempWidth, tempHeight, kCVPixelFormatType_32BGRA, &baseAddress[baseAddressStart], bytesPerRow, MyPixelBufferReleaseCallback, NULL, (CFDictionaryRef)options, &pxbuffer); – Nikita Ivaniushchenko Dec 22 '11 at 06:32
  • Yeah, I am creating a pixel buffer with that. I just don't get your suggestion over what I should do now – vodkhang Dec 23 '11 at 03:03
  • @nikita Can you help me regarding the problem of memory while creating a video .. – Divyesh Dobariya Sep 26 '14 at 10:48