美文网首页音视频从入门到放弃
libyuv 进行nv12 pixelBuffer 转 i420

libyuv 进行nv12 pixelBuffer 转 i420

作者: yxibng | 来源:发表于2020-03-05 09:43 被阅读0次

参考 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;
}

相关文章

网友评论

    本文标题:libyuv 进行nv12 pixelBuffer 转 i420

    本文链接:https://www.haomeiwen.com/subject/imktrhtx.html