ios objective-c video opengl-es glkit

Crear CVPixelBuffer desde YUV con IOSurface respaldado



objective-c video (2)

Lo descubrí y fue bastante trivial. Aquí está el código completo a continuación. El único problema es que recibo un BSXPCMessage received error for message: Connection interrupted y demora un tiempo para que se muestre el video.

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);

Olvidé agregar el código para intercalar los dos planos U y V, pero eso no debería ser tan malo.

Así que estoy obteniendo datos de YUV sin procesar en 3 arrays separados de una devolución de llamada de red (aplicación de voip). Por lo que entiendo, no se pueden crear memorias intermedias de píxeles respaldadas por CVPixelBufferCreateWithPlanarBytes con CVPixelBufferCreateWithPlanarBytes acuerdo con aquí

Importante: No puede usar CVPixelBufferCreateWithBytes () o CVPixelBufferCreateWithPlanarBytes () con kCVPixelBufferIOSurfacePropertiesKey. Llamar a CVPixelBufferCreateWithBytes () o CVPixelBufferCreateWithPlanarBytes () dará como resultado CVPixelBuffers que no están respaldados por IOSurface.

Entonces, tiene que crearlo con CVPixelBufferCreate , pero ¿cómo transfiere los datos de la devolución de llamada al CVPixelBufferRef que crea?

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

No estoy seguro de qué hacer después aquí? Eventualmente quiero convertir esto en un CIImage que luego puedo usar mi GLKView para renderizar el video. ¿Cómo la gente "pone" los datos en los buffers desde cuando los creaste?


Tenía una pregunta similar y aquí está lo que tengo en SWIFT 2.0 con información que recibí de respuestas a otras preguntas o enlaces.

func generatePixelBufferFromYUV2(inout yuvFrame: YUVFrame) -> CVPixelBufferRef? { var uIndex: Int var vIndex: Int var uvDataIndex: Int var pixelBuffer: CVPixelBufferRef? = nil var err: CVReturn; if (m_pixelBuffer == nil) { err = CVPixelBufferCreate(kCFAllocatorDefault, yuvFrame.width, yuvFrame.height, kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange, nil, &pixelBuffer) if (err != 0) { NSLog("Error at CVPixelBufferCreate %d", err) return nil } } if (pixelBuffer != nil) { CVPixelBufferLockBaseAddress(pixelBuffer!, 0) let yBaseAddress = CVPixelBufferGetBaseAddressOfPlane(pixelBuffer!, 0) if (yBaseAddress != nil) { let yData = UnsafeMutablePointer<UInt8>(yBaseAddress) let yDataPtr = UnsafePointer<UInt8>(yuvFrame.luma.bytes) // Y-plane data memcpy(yData, yDataPtr, yuvFrame.luma.length) } let uvBaseAddress = CVPixelBufferGetBaseAddressOfPlane(m_pixelBuffer!, 1) if (uvBaseAddress != nil) { let uvData = UnsafeMutablePointer<UInt8>(uvBaseAddress) let pUPointer = UnsafePointer<UInt8>(yuvFrame.chromaB.bytes) let pVPointer = UnsafePointer<UInt8>(yuvFrame.chromaR.bytes) // For the uv data, we need to interleave them as uvuvuvuv.... let iuvRow = (yuvFrame.chromaB.length*2/yuvFrame.width) let iHalfWidth = yuvFrame.width/2 for i in 0..<iuvRow { for j in 0..<(iHalfWidth) { // UV data for original frame. Just interleave them. uvDataIndex = i*iHalfWidth+j uIndex = (i*yuvFrame.width) + (j*2) vIndex = uIndex + 1 uvData[uIndex] = pUPointer[uvDataIndex] uvData[vIndex] = pVPointer[uvDataIndex] } } } CVPixelBufferUnlockBaseAddress(pixelBuffer!, 0) } return pixelBuffer }

Nota: yuvFrame es una estructura con búferes de plan y, uy v, y ancho y alto. Además, tengo el CFDictionary? parámetro en CVPixelBufferCreate (...) establecido en nil. Si le doy el atributo IOSurface, fallará y se quejará de que no está respaldado por IOSurface o error -6683.

Visite estos enlaces para obtener más información: Este enlace es sobre intercalación UV: Cómo convertir de YUV a CIImage para iOS

y pregunta relacionada: CVOpenGLESTextureCacheCreateTextureFromImage devuelve el error 6683