2015-08-05 2 views
6

Итак, я получаю сырые данные YUV в 3 отдельных массивах из сетевого обратного вызова (приложение voip). Из того, что я понимаю, что вы не можете создать IOSurface поддержанные пиксельных буферов с CVPixelBufferCreateWithPlanarBytes согласно hereСоздайте CVPixelBuffer из YUV с поддержкой 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); 

Я не уверен, что делать после этого здесь? В конце концов я хочу превратить это в CIImage, который затем я могу использовать свой GLKView для рендеринга видео. Как люди «помещают» данные в буферы, когда вы его создаете?

ответ

7

Я понял, и это было довольно тривиально. Ниже приведен полный код. Только проблема в том, что я получаю 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); 

Я забыл добавить код для чередования двух U и V плоскостей, но это не должно быть слишком плохо.

+0

Пожалуйста, укажите код для самолетов U и V и numberOfElementsForChroma – JULIIncognito

+0

@JULIIncognito uvPlane является просто я думаю, массив uint_8. Это так давно жаль. numberOfElementsForChroma будет только тем фиксированным размером, который вам нужен. – cvu

+0

@JULIIncognito IsOneElementsForChroma такой же ширины * высота? Потому что он не работает. – lilouch

1

У меня был аналогичный вопрос, и вот что я имею в SWIFT 2.0 с информацией, полученной от ответов на другие вопросы или ссылки.

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 
} 

Примечание: yuvFrame представляет собой структуру с буферами y, u и v, а также шириной и высотой. Кроме того, у меня есть CFDictionary? параметр в параметре CVPixelBufferCreate (...) равен нулю. Если я дам атрибут IOSurface, он потерпит неудачу и пожалуется, что это не IOSurface или ошибка -6683.

Посетите эти ссылки для получения дополнительной информации: Эта ссылка о УФ чередовании: How to convert from YUV to CIImage for iOS

и связанный с этим вопрос: CVOpenGLESTextureCacheCreateTextureFromImage returns error 6683

+0

У меня есть аналогичная задача для выполнения, у меня есть сущность YUVFrame Struct и код преобразования. Из-за этого мне не удалось получить результаты для преобразования указателей YUV к буферу пикселей. Спасибо –

+0

Мой код представляет собой сочетание объектива-c & SWIFT. Структура, которая у меня есть, находится в объективе c. Он состоит из трех NSData и двух объектов NSInteger: (сильный, неатомный) NSData * luma; property (strong, nonatomic) NSData * chromaB; свойство (сильное, неатомическое) NSData * chromaR; недвижимость NSInteger ширина; недвижимость NSInteger высота; // Удаленные объекты @ – mdang

Смежные вопросы