iOS - 自动调整 CVPixelBufferRef 的大小

4

我正试图根据用户的输入对CMSampleBufferRef进行裁剪和缩放,基于比例ratio,以下代码将CMSampleBufferRef转换为CVImageBufferRef,并使用CVPixelBuffer来根据其字节裁剪内部图像。此过程的目标是获得一个已裁剪和缩放的CVPixelBufferRef以写入视频中。

- (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;
    }
}

除了使用这种方法将其写入视频输出时,会不断收到内存警告之外,一切都很正常。如果保持相同的比例,则没有问题。

- (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");
}

我也尝试了使用CMSampleBufferRefCGContext的不同方法。如果您可以为任何一种方法提供解决方案,我可以给您满分。


我有一个小疑问,我想调整CVpixcelbuffer的大小。这可能吗?我刚刚使用了你的代码,但是没有得到期望的输出。在选项字典中,我已经添加了原始大小和临时大小,我指向了我的期望大小,但是它没有起作用。 - Asta ni enohpi
1个回答

1

尝试在调用-CVPixelBufferLockBaseAddress和-CVPixelBufferUnlockBaseAddress时都使用kCVPixelBufferLock_ReadOnly标志。有时,通过复制像素缓冲区可以解决此问题。只需执行一次分配:

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

接下来,将像素缓冲区中的数据复制到data中

size_t size = height * bytesPerRow;

memcpy(data, baseAddress, size);

然后,使用data。希望这能有所帮助。


但是我需要将我的像素缓冲区写入视频,如何使用“data”来实现呢? - vodkhang
样例代码呢?无论如何,您正在使用CVReturn状态创建像素缓冲区 = CVPixelBufferCreateWithBytes(kCFAllocatorDefault,tempWidth,tempHeight,kCVPixelFormatType_32BGRA,&baseAddress [baseAddressStart],bytesPerRow,MyPixelBufferReleaseCallback,NULL,(CFDictionaryRef)options,&pxbuffer); - Nikita Ivaniushchenko
是的,我正在使用它创建像素缓冲区。我只是不明白你现在建议我应该做什么。 - vodkhang
@nikita,你能帮我解决创建视频时的内存问题吗? - Divyesh Dobariya

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接