2015-08-05 27 views
6

Quindi sto ottenendo dati YUV grezzi in 3 array separati da una richiamata di rete (app VoIP). Da quello che ho capito non è possibile creare buffer di pixel IOSurface sostenuto con CVPixelBufferCreateWithPlanarBytes in base alle hereCreare CVPixelBuffer da YUV con IOSurface supportato

Importante: Non è possibile utilizzare CVPixelBufferCreateWithBytes() o CVPixelBufferCreateWithPlanarBytes() con kCVPixelBufferIOSurfacePropertiesKey. Chiamando CVPixelBufferCreateWithBytes() o CVPixelBufferCreateWithPlanarBytes() si tradurrà in CVPixelBuffers che non sono IOSurface-backed

Così dunque si deve creare con CVPixelBufferCreate, ma come si fa a trasferire i dati dalla chiamata al CVPixelBufferRef che crei?

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

Non so cosa fare dopo? Alla fine voglio trasformare questo in un CIImage che poi posso usare il mio GLKView per renderizzare il video. In che modo le persone "inseriscono" i dati nei buffer da quando li crei?

risposta

7

L'ho capito ed era abbastanza banale. Ecco il codice completo qui sotto. L'unico problema è che ottengo uno BSXPCMessage received error for message: Connection interrupted e ci vuole un po 'prima che il video venga mostrato.

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

Ho dimenticato di aggiungere il codice per interlacciare i due piani U e V, ma che non dovrebbe essere troppo male.

+0

Si prega di fornire il codice per la U e V aerei e numberOfElementsForChroma – JULIIncognito

+0

@JULIIncognito L'uvPlane è solo una serie di uint_8 credo. Questo è molto tempo fa, mi dispiace. numberOfElementsForChroma sarà semplicemente la dimensione fissa di cui hai bisogno. – cvu

+0

@JULIIncognito NumberOfElementsForChroma è uguale alla larghezza * altezza? Perché non funziona. – lilouch

1

Ho avuto una domanda simile ed ecco cosa ho in SWIFT 2.0 con informazioni che ho ottenuto dalle risposte ad altre domande o collegamenti.

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 è una struttura con y, u, v e tamponi piano e larghezza e altezza. Inoltre, ho il CFDictionary? parametro in CVPixelBufferCreate (...) impostato su nil. Se fornisco l'attributo IOSurface, fallirà e si lamenterà che non è supportato da IOSurface o errore -6683.

Visita questi link per ulteriori informazioni: Questo collegamento è di circa interleave UV: How to convert from YUV to CIImage for iOS

e relativa domanda: CVOpenGLESTextureCacheCreateTextureFromImage returns error 6683

+0

ho qualche attività simile da eseguire posso avere un aspetto di YUVFrame Struct e il codice di conversione. Da qui non sono riuscito a ottenere i risultati per la conversione dei puntatori YUV al buffer dei pixel. Grazie –

+0

Il mio codice è un mix di obiettivo-c e SWIFT. La struttura che ho è in obiettivo-c. Consiste di tre NSData e due NSInteger: proprietà (forte, non anatomica) NSData * luma; proprietà (forte, non anatomica) NSData * chromaB; proprietà (forte, non anatomica) NSData * chromaR; proprietà NS Larghezza intera; proprietà NSInterger height; // Le proprietà @ prima di vengono rimosse – mdang