从YUV创建CVPixelBuffer并支持IOSurface

cvu*_*cvu 8 video opengl-es objective-c ios glkit

所以我从网络回调(voip app)获得3个独立阵列中的原始YUV数据.根据我的理解,你不能CVPixelBufferCreateWithPlanarBytes根据这里创建IOSurface支持的像素缓冲区

重要提示:您不能将CVPixelBufferCreateWithBytes()或CVPixelBufferCreateWithPlanarBytes()与kCVPixelBufferIOSurfacePropertiesKey一起使用.调用CVPixelBufferCreateWithBytes()或CVPixelBufferCreateWithPlanarBytes()将导致CVPixelBuffers不是IOSurface支持的

因此,您必须创建它CVPixelBufferCreate,但是如何将数据从回调传输回CVPixelBufferRef您创建的?

- (void)videoCallBack(uint8_t *yPlane, uint8_t *uPlane, uint8_t *vPlane, size_t width, size_t height, size_t stride yStride,
                      size_t uStride, size_t vStride)
    NSDictionary *pixelAttributes = @{(id)kCVPixelBufferIOSurfacePropertiesKey : @{}};
    CVPixelBufferRef pixelBuffer = NULL;
    CVReturn result = CVPixelBufferCreate(kCFAllocatorDefault,
                                          width,
                                          height,
                                          kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange,
                                          (__bridge CFDictionaryRef)(pixelAttributes),
                                          &pixelBuffer);
Run Code Online (Sandbox Code Playgroud)

我不确定之后该做什么?最终我想把它变成一个CIImage,然后我可以使用我的GLKView来渲染视频.人们如何在创建数据时将数据"放入"缓冲区?

cvu*_*cvu 8

我想出来了,这是相当微不足道的.以下是完整的代码.唯一的问题是,我得到了BSXPCMessage received error for message: Connection interrupted一个,视频显示需要一段时间.

NSDictionary *pixelAttributes = @{(id)kCVPixelBufferIOSurfacePropertiesKey : @{}};
CVPixelBufferRef pixelBuffer = NULL;
CVReturn result = CVPixelBufferCreate(kCFAllocatorDefault,
                                      width,
                                      height,
                                      kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange,
                                      (__bridge CFDictionaryRef)(pixelAttributes),
                                      &pixelBuffer);

CVPixelBufferLockBaseAddress(pixelBuffer, 0);
uint8_t *yDestPlane = CVPixelBufferGetBaseAddressOfPlane(pixelBuffer, 0);
memcpy(yDestPlane, yPlane, width * height);
uint8_t *uvDestPlane = CVPixelBufferGetBaseAddressOfPlane(pixelBuffer, 1);
memcpy(uvDestPlane, uvPlane, numberOfElementsForChroma);
CVPixelBufferUnlockBaseAddress(pixelBuffer, 0);

if (result != kCVReturnSuccess) {
    DDLogWarn(@"Unable to create cvpixelbuffer %d", result);
}

CIImage *coreImage = [CIImage imageWithCVPixelBuffer:pixelBuffer]; //success!
CVPixelBufferRelease(pixelBuffer);
Run Code Online (Sandbox Code Playgroud)

我忘了添加代码来交错两个U和V平面,但这不应该太糟糕.