Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/xpath/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 如何从vImage_缓冲区转到CVPixelBufferRef_Ios_Vimage - Fatal编程技术网

Ios 如何从vImage_缓冲区转到CVPixelBufferRef

Ios 如何从vImage_缓冲区转到CVPixelBufferRef,ios,vimage,Ios,Vimage,我正在iOS应用程序中录制实时视频。在另一个堆栈溢出中,我发现可以使用vImage\u Buffer处理我的帧 问题是我不知道如何从输出的vImage_缓冲区返回CVPixelBufferRef 以下是另一篇文章中给出的代码: NSInteger cropX0 = 100, cropY0 = 100, cropHeight = 100, cropWidth = 100, outWidth = 480,

我正在iOS应用程序中录制实时视频。在另一个堆栈溢出中,我发现可以使用
vImage\u Buffer
处理我的帧

问题是我不知道如何从输出的
vImage_缓冲区返回
CVPixelBufferRef

以下是另一篇文章中给出的代码:

NSInteger cropX0 = 100,
          cropY0 = 100,
          cropHeight = 100,
          cropWidth = 100,
          outWidth = 480,
          outHeight = 480;

CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);                   
CVPixelBufferLockBaseAddress(imageBuffer,0);
void *baseAddress = CVPixelBufferGetBaseAddress(imageBuffer);
size_t bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer);

vImage_Buffer inBuff;                       
inBuff.height = cropHeight;
inBuff.width = cropWidth;
inBuff.rowBytes = bytesPerRow;

int startpos = cropY0 * bytesPerRow + 4 * cropX0;
inBuff.data = baseAddress + startpos;

unsigned char *outImg = (unsigned char*)malloc(4 * outWidth * outHeight);
vImage_Buffer outBuff = {outImg, outHeight, outWidth, 4 * outWidth};

vImage_Error err = vImageScale_ARGB8888(&inBuff, &outBuff, NULL, 0);
if (err != kvImageNoError) NSLog(@" error %ld", err);
现在我需要将
exputff
转换为
CVPixelBufferRef

我假设我需要使用
vImageBuffer\u CopyToCVPixelBuffer
,但我不确定如何使用

我的第一次尝试失败,访问失败:CVPixelBufferUnlockBaseAddress(imageBuffer,0)

有什么想法吗

NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
    [NSNumber numberWithBool : YES], kCVPixelBufferCGImageCompatibilityKey,
    [NSNumber numberWithBool : YES], kCVPixelBufferCGBitmapContextCompatibilityKey,
    [NSNumber numberWithInt : 480], kCVPixelBufferWidthKey,
    [NSNumber numberWithInt : 480], kCVPixelBufferHeightKey,
    nil];

status = CVPixelBufferCreateWithBytes(kCFAllocatorDefault,
                                      480,
                                      480,
                                      kCVPixelFormatType_32BGRA,
                                      outImg,
                                      bytesPerRow,
                                      NULL,
                                      NULL,
                                      (__bridge CFDictionaryRef)options,
                                      &pixbuffer);
您应该像上面那样生成一个新的
像素缓冲区。

  • 以防万一。。。如果您想在界面中输入裁剪过的实时视频,请使用
    AVPlayerLayer
    AVCaptureVideoPreviewLayer
    和/或其他
    CALayer
    子类,将100x100像素区域的层边界、帧和位置设置为480x480像素区域
问题的
vImage
注释(不同情况可能不同):

  • CVPixelBufferCreateWithBytes
    无法与
    vImageBuffer\u CopyToCVPixelBuffer()
    一起使用,因为需要将
    vImage\u Buffer
    数据复制到“干净”或“空”的
    CVPixelBuffer

  • 无需锁定/解锁-确保您知道何时锁定和何时不锁定像素缓冲区

  • 您的
    inBuff
    vImage\u Buffer
    只需要从像素缓冲区数据初始化,而不是手动初始化(除非您知道如何使用
    CGContext
    s等初始化像素网格)

  • 使用vImageBuffer\u InitWithCVPixelBuffer()
  • vImageScale_argb888
    将整个CVPixel数据缩放为一个较小/较大的矩形。它不会将缓冲区的一部分/裁剪区域缩放到另一个缓冲区

  • 当您使用vImageBuffer\u CopyToCVPixelBuffer()时,
    vImageCVImageFormatRef
    &
    vImage\u CGImageFormat
    需要正确填写

    CGColorSpaceRef dstColorSpace = CGColorSpaceCreateWithName(kCGColorSpaceITUR_709);
    
    vImage_CGImageFormat format = {
        .bitsPerComponent = 16,
        .bitsPerPixel = 64,
        .bitmapInfo = (CGBitmapInfo)kCGImageAlphaPremultipliedLast  |  kCGBitmapByteOrder16Big ,
        .colorSpace = dstColorSpace
    };
    vImageCVImageFormatRef vformat = vImageCVImageFormat_Create(kCVPixelFormatType_4444AYpCbCr16,
                                                                kvImage_ARGBToYpCbCrMatrix_ITU_R_709_2,
                                                                kCVImageBufferChromaLocation_Center,
                                                                format.colorSpace,
                                                                0);
    
    CVReturn status = CVPixelBufferCreate(kCFAllocatorDefault,
                                          480,
                                          480,
                                          kCVPixelFormatType_4444AYpCbCr16,
                                          NULL,
                                          &destBuffer);
    
    NSParameterAssert(status == kCVReturnSuccess && destBuffer != NULL);
    
    err = vImageBuffer_CopyToCVPixelBuffer(&sourceBuffer, &format, destBuffer, vformat, 0, kvImagePrintDiagnosticsToConsole);
    

  • 注意:这些是64位ProRes的设置,Alpha-adjust为32位。

    EXC\u BAD\u访问对应哪个字节块?vImage_Buffer.data或CVPixelBufferRef基址?嗨,伊恩,我怎样才能准确地找到它?在调试器中运行代码。当崩溃时,您应该看到类似“EXC\u BAD\u ACCESS(Code=X,address=ADDR)”的内容。此时,使用调试器查看pixelBuffer和Exputff.data的值。其中一个应该与ADDR相同或接近(这是假设您实际上在CopyToCVPixelBuffer中崩溃,而不是更早;您在崩溃什么函数?)嗯,调试器在vImageBuffer_CopyToCVPixelBuffer中保持,但ADDR实际上是0x0,但所有输入参数都会中断,格式和像素缓冲区与0x0不同。代码是1不要忘记NB,NB,非常NB-内存泄漏城市1。你必须自己释放CG对象(色彩空间等)2。您还必须从缓冲区中释放(无论如何.data)。这些函数都不支持ARC,如果你正在处理许多视频帧,你很快就会陷入停顿。嗨,保罗,你能回答我的SO问题吗(),它与这个答案有关,我不知道如何在swift中实现它。
    CGColorSpaceRef dstColorSpace = CGColorSpaceCreateWithName(kCGColorSpaceITUR_709);
    
    vImage_CGImageFormat format = {
        .bitsPerComponent = 16,
        .bitsPerPixel = 64,
        .bitmapInfo = (CGBitmapInfo)kCGImageAlphaPremultipliedLast  |  kCGBitmapByteOrder16Big ,
        .colorSpace = dstColorSpace
    };
    vImageCVImageFormatRef vformat = vImageCVImageFormat_Create(kCVPixelFormatType_4444AYpCbCr16,
                                                                kvImage_ARGBToYpCbCrMatrix_ITU_R_709_2,
                                                                kCVImageBufferChromaLocation_Center,
                                                                format.colorSpace,
                                                                0);
    
    CVReturn status = CVPixelBufferCreate(kCFAllocatorDefault,
                                          480,
                                          480,
                                          kCVPixelFormatType_4444AYpCbCr16,
                                          NULL,
                                          &destBuffer);
    
    NSParameterAssert(status == kCVReturnSuccess && destBuffer != NULL);
    
    err = vImageBuffer_CopyToCVPixelBuffer(&sourceBuffer, &format, destBuffer, vformat, 0, kvImagePrintDiagnosticsToConsole);