2017-05-05 563 views
0

我需要轉換YUV幀到CVPixelBuffer我從OTVideoFrame如何YUV幀(從OTVideoFrame)轉換爲CVPixelBuffer

該類提供平面的,其中包含三個元素爲y中的視頻幀的陣列得到,u,v每幀索引號爲0,1,2

@屬性(非原子,保留)NSPointerArray *平面

和所述視頻幀的format

@屬性(非原子,保留)OTVideoFormat *格式

包含框架的屬性,如寬度,高度,bytesPerRow等

我需要過濾器添加到我收到的OTVideoFrame形式的形象,我已經嘗試過這些問題的答案:

這兩個環節上有在Objective-C中的解決方案,但我想迅速做到這一點。第二個鏈接中的答案之一很快,但它缺少一些關於結構的信息,答案提到了這個結構。

,我收到的格式是NV12

這是我一直在努力做的到現在,但我不知道如何下一步繼續: -

/** 
* Calcualte the size of each plane from OTVideoFrame. 
* 
* @param frame The frame to render. 
* @return tuple containing three elements for size of each plane 
*/ 
fileprivate func calculatePlaneSize(forFrame frame: OTVideoFrame) 
     -> (ySize: Int, uSize: Int, vSize: Int){ 
      guard let frameFormat = frame.format 
       else { 
        return (0, 0 ,0) 
      } 
      let baseSize = Int(frameFormat.imageWidth * frameFormat.imageHeight) * MemoryLayout<GLubyte>.size 
      return (baseSize, baseSize/4, baseSize/4) 
    } 

/** 
* Renders a frame to the video renderer. 
* 
* @param frame The frame to render. 
*/ 
func renderVideoFrame(_ frame: OTVideoFrame) { 


    let planeSize = calculatePlaneSize(forFrame: frame) 
    let yPlane = UnsafeMutablePointer<GLubyte>.allocate(capacity: planeSize.ySize) 
    let uPlane = UnsafeMutablePointer<GLubyte>.allocate(capacity: planeSize.uSize) 
    let vPlane = UnsafeMutablePointer<GLubyte>.allocate(capacity: planeSize.vSize) 

    memcpy(yPlane, frame.planes?.pointer(at: 0), planeSize.ySize) 
    memcpy(uPlane, frame.planes?.pointer(at: 1), planeSize.uSize) 
    memcpy(vPlane, frame.planes?.pointer(at: 2), planeSize.vSize) 

    let yStride = frame.format!.bytesPerRow.object(at: 0) as! Int 
    // multiply chroma strides by 2 as bytesPerRow represents 2x2 subsample 
    let uStride = frame.format!.bytesPerRow.object(at: 1) as! Int 
    let vStride = frame.format!.bytesPerRow.object(at: 2) as! Int 

    let width = frame.format!.imageWidth 
    let height = frame.format!.imageHeight 

    var pixelBuffer: CVPixelBuffer? = nil 
    var err: CVReturn; 


    err = CVPixelBufferCreate(kCFAllocatorDefault, Int(width), Int(height), kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange, nil, &pixelBuffer) 
    if (err != 0) { 
     NSLog("Error at CVPixelBufferCreate %d", err) 
     fatalError() 
    } 

} 

從以指導這兩個鏈接我試圖創建像素緩衝區,但我被困每次在這一點上,因爲在此之後,Objective-C代碼的轉換不是類似於我們在斯威夫特3.

回答

0

下面是我工作(我有 採取你的功能,並改變了一下):

func createPixelBufferWithVideoFrame(_ frame: OTVideoFrame) -> CVPixelBuffer? { 
    if let fLock = frameLock { 
     fLock.lock() 

     let planeSize = calculatePlaneSize(forFrame: frame) 

     let yPlane = UnsafeMutablePointer<GLubyte>.allocate(capacity: planeSize.ySize) 
     let uPlane = UnsafeMutablePointer<GLubyte>.allocate(capacity: planeSize.uSize) 
     let vPlane = UnsafeMutablePointer<GLubyte>.allocate(capacity: planeSize.vSize) 

     memcpy(yPlane, frame.planes?.pointer(at: 0), planeSize.ySize) 
     memcpy(uPlane, frame.planes?.pointer(at: 1), planeSize.uSize) 
     memcpy(vPlane, frame.planes?.pointer(at: 2), planeSize.vSize) 

     let width = frame.format!.imageWidth 
     let height = frame.format!.imageHeight 

     var pixelBuffer: CVPixelBuffer? = nil 
     var err: CVReturn; 

     err = CVPixelBufferCreate(kCFAllocatorDefault, Int(width), Int(height), kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange, nil, &pixelBuffer) 
     if (err != 0) { 
      NSLog("Error at CVPixelBufferCreate %d", err) 
      return nil 
     } 

     if let pixelBuffer = pixelBuffer { 
      CVPixelBufferLockBaseAddress(pixelBuffer, .readOnly) 
      let yPlaneTo = CVPixelBufferGetBaseAddressOfPlane(pixelBuffer, 0) 
      memcpy(yPlaneTo, yPlane, planeSize.ySize) 

      let uvRow: Int = planeSize.uSize*2/Int(width) 

      let halfWidth: Int = Int(width)/2 

      if let uPlaneTo = CVPixelBufferGetBaseAddressOfPlane(pixelBuffer, 1) { 
       let uvPlaneTo = uPlaneTo.bindMemory(to: GLubyte.self, capacity: Int(uvRow*halfWidth*2)) 

       for i in 0..<uvRow { 
        for j in 0..<halfWidth { 
         let dataIndex: Int = Int(i) * Int(halfWidth) + Int(j) 
         let uIndex: Int = (i * Int(width)) + Int(j) * 2 
         let vIndex: Int = uIndex + 1 

         uvPlaneTo[uIndex] = uPlane[dataIndex] 
         uvPlaneTo[vIndex] = vPlane[dataIndex] 

        } 
       } 

      } 

     } 

     fLock.unlock() 

     return pixelBuffer 
    } 
    return nil 
}