音视频从入门到放弃

libyuv 进行nv12 pixelBuffer 转 i420

2020-03-05  本文已影响0人  yxibng

参考 demo

转为 i420 pixelBuffer

+ (CVPixelBufferRef)convertToI420FromNv12:(CVPixelBufferRef)pixelBuffer
{
    if (!pixelBuffer) {
        return NULL;
    }
    CVPixelBufferRetain(pixelBuffer);
    CVPixelBufferLockBaseAddress(pixelBuffer, 0);

    size_t pixelWidth = CVPixelBufferGetWidth(pixelBuffer);
    size_t pixelHeight = CVPixelBufferGetHeight(pixelBuffer);

    uint8_t *y_frame = (uint8_t *)CVPixelBufferGetBaseAddressOfPlane(pixelBuffer, 0);
    uint8_t *uv_frame = (uint8_t *)CVPixelBufferGetBaseAddressOfPlane(pixelBuffer, 1);

    int src_stride_y = (int)CVPixelBufferGetBytesPerRowOfPlane(pixelBuffer, 0);
    int src_stride_uv = (int)CVPixelBufferGetBytesPerRowOfPlane(pixelBuffer, 1);

    //create i420 buffer
    NSDictionary *att = @{(NSString *)kCVPixelBufferIOSurfacePropertiesKey : @{} };

    CVPixelBufferRef i420Buffer;
    CVPixelBufferCreate(kCFAllocatorDefault, pixelWidth, pixelHeight, kCVPixelFormatType_420YpCbCr8Planar, (__bridge CFDictionaryRef _Nullable)att, &i420Buffer);
    if (!i420Buffer) {
        //create error
        CVPixelBufferUnlockBaseAddress(pixelBuffer, 0);
        CVPixelBufferRelease(pixelBuffer);
        return NULL;
    }

    CVPixelBufferLockBaseAddress(i420Buffer, 0);
    //kCVPixelFormatType_420YpCbCr8Planar 是三平面
    int dst_stride_y = (int)CVPixelBufferGetBytesPerRowOfPlane(i420Buffer, 0);
    int dst_stride_u = (int)CVPixelBufferGetBytesPerRowOfPlane(i420Buffer, 1);
    int dst_stride_v = (int)CVPixelBufferGetBytesPerRowOfPlane(i420Buffer, 2);

    uint8_t *i420_y = (uint8_t *)CVPixelBufferGetBaseAddressOfPlane(i420Buffer, 0);
    uint8_t *i420_u = (uint8_t *)CVPixelBufferGetBaseAddressOfPlane(i420Buffer, 1);
    uint8_t *i420_v = (uint8_t *)CVPixelBufferGetBaseAddressOfPlane(i420Buffer, 2);


    int ret = libyuv::NV12ToI420(y_frame, src_stride_y,
                                 uv_frame, src_stride_uv,
                                 i420_y, dst_stride_y,
                                 i420_u, dst_stride_u,
                                 i420_v, dst_stride_v,
                                 (int)pixelWidth, (int)pixelHeight);
    CVPixelBufferUnlockBaseAddress(pixelBuffer, 0);
    CVPixelBufferRelease(pixelBuffer);

    if (ret != 0) {
        CVPixelBufferUnlockBaseAddress(i420Buffer, 0);
        CVPixelBufferRelease(i420Buffer);
        return NULL;
    }

    CVPixelBufferUnlockBaseAddress(i420Buffer, 0);
    return (CVPixelBufferRef)CFAutorelease(i420Buffer);
}



转为 i420 data

typedef struct {
    uint8_t *y_frame;
    uint8_t *u_frame;
    uint8_t *v_frame;
    
    int width;
    int height;
    
    int stride_y;
    int stride_u;
    int stride_v;
} I420Buffer;

+ (void)convertToI420Buffer:(I420Buffer *)i420Buffer nv12PixelBuffer:(CVPixelBufferRef)pixelBuffer
{
    if (!i420Buffer || !pixelBuffer) {
        return;
    }
    
    CVPixelBufferRetain(pixelBuffer);
    CVPixelBufferLockBaseAddress(pixelBuffer, 0);

    size_t pixelWidth = CVPixelBufferGetWidth(pixelBuffer);
    size_t pixelHeight = CVPixelBufferGetHeight(pixelBuffer);
    
    uint8_t *y_frame = (uint8_t *)CVPixelBufferGetBaseAddressOfPlane(pixelBuffer, 0);
    uint8_t *uv_frame = (uint8_t *)CVPixelBufferGetBaseAddressOfPlane(pixelBuffer, 1);
    int src_stride_y = (int)CVPixelBufferGetBytesPerRowOfPlane(pixelBuffer, 0);
    int src_stride_uv = (int)CVPixelBufferGetBytesPerRowOfPlane(pixelBuffer, 1);
    
    
    uint8_t *i420_y = (uint8_t *)malloc(pixelWidth * pixelHeight * 1.5);
    uint8_t *i420_u = i420_y + pixelWidth * pixelHeight;
    uint8_t *i420_v = i420_u + pixelWidth * pixelHeight / 4;
    
    int dst_stride_y = (int)pixelWidth;
    int dst_stride_u = (int)pixelWidth / 2;
    int dst_stride_v = (int)pixelWidth / 2;
    

   int ret = libyuv::NV12ToI420(y_frame,src_stride_y,
                       uv_frame, src_stride_uv,
                       i420_y, dst_stride_y,
                       i420_u, dst_stride_u,
                       i420_v, dst_stride_v,
                       (int)pixelWidth, (int)pixelHeight);
    
    assert(ret == 0);
    
    CVPixelBufferUnlockBaseAddress(pixelBuffer, 0);
    CVPixelBufferRelease(pixelBuffer);
    
    I420Buffer buffer = {0};
    buffer.y_frame = i420_y;
    buffer.u_frame = i420_u;
    buffer.v_frame = i420_v;
    
    buffer.stride_y = dst_stride_y;
    buffer.stride_u = dst_stride_u;
    buffer.stride_v = dst_stride_v;
    
    buffer.width = pixelWidth;
    buffer.height = pixelHeight;
    
    *i420Buffer = buffer;
}

上一篇 下一篇

猜你喜欢

热点阅读