美文网首页
libyuv NV12镜像

libyuv NV12镜像

作者: Leoeoo | 来源:发表于2021-06-29 16:48 被阅读0次

从CMSampleBufferRef中取出NV12数据,转换为i420,对i420数据做镜像,然后把镜像的i420转换为NV12,再把NV12包装成CVPixelBufferRef。

+ (CVPixelBufferRef)mirrorSampleBuffler:(CMSampleBufferRef)sampleBufRef {
    //CVPixelBufferRef是CVImageBufferRef的别名,两者操作几乎一致。
    //获取CMSampleBuffer的图像地址
    CVImageBufferRef pixelBuffer = CMSampleBufferGetImageBuffer(sampleBufRef);
    if (!pixelBuffer) {
        return nil;
    }
    //表示开始操作数据
    CVPixelBufferLockBaseAddress(pixelBuffer, 0);
    //图像宽度(像素)
    size_t buffer_width = CVPixelBufferGetWidth(pixelBuffer);
    //图像高度(像素)
    size_t buffer_height = CVPixelBufferGetHeight(pixelBuffer);
    //获取CVImageBufferRef中的y数据
    uint8_t *src_y_frame = (unsigned char *)CVPixelBufferGetBaseAddressOfPlane(pixelBuffer, 0);
    //获取CMVImageBufferRef中的uv数据
    uint8_t *src_uv_frame =(unsigned char *) CVPixelBufferGetBaseAddressOfPlane(pixelBuffer, 1);
    //y stride
    size_t plane1_stride = CVPixelBufferGetBytesPerRowOfPlane(pixelBuffer, 0);
    //uv stride
    size_t plane2_stride = CVPixelBufferGetBytesPerRowOfPlane(pixelBuffer, 1);
    //y height
    size_t plane1_height = CVPixelBufferGetHeightOfPlane(pixelBuffer, 0);
    //uv height
    size_t plane2_height = CVPixelBufferGetHeightOfPlane(pixelBuffer, 1);
    //y_size
    size_t plane1_size = plane1_stride * plane1_height;
    //uv_size
    size_t plane2_size = plane2_stride * plane2_height;
    //yuv_size(内存空间)
    size_t frame_size = plane1_size + plane2_size;

    // 1.NV12转换为I420
    // 开辟buffer_frame大小的内存空间用于存放转换好的i420数据
    uint8* buffer_y = (unsigned char *)malloc(frame_size);
    uint8* buffer_u = buffer_y + plane1_size;
    uint8* buffer_v = buffer_u + plane1_size / 4;

    libyuv::NV12ToI420(/*const uint8 *src_y*/ src_y_frame,
                       /*int src_stride_y*/ (int)plane1_stride,
                       /*const uint8 *src_uv*/ src_uv_frame,
                       /*int src_stride_uv*/ (int)plane2_stride,
                       /*uint8 *dst_y*/ buffer_y,
                       /*int dst_stride_y*/ (int)plane1_stride,
                       /*uint8 *dst_u*/ buffer_u,
                       /*int dst_stride_u*/ (int)plane1_stride >> 1,
                       /*uint8 *dst_v*/ buffer_v,
                       /*int dst_stride_v*/ (int)plane1_stride >> 1,
                       /*int width*/ (int)buffer_width,
                       /*int height*/ (int)buffer_height);
    
    CVPixelBufferUnlockBaseAddress(pixelBuffer, 0);
    
    uint8* mirror_y = (unsigned char *)malloc(frame_size);
    uint8* mirror_u = mirror_y + plane1_size;
    uint8* mirror_v = mirror_u + plane1_size / 4;
    
    libyuv::I420Mirror(/*const uint8* src_y*/buffer_y,
                       /*int src_stride_y*/(int)plane1_stride,
                       /*const uint8* src_u*/buffer_u,
                       /*int src_stride_u*/(int)plane1_stride >> 1,
                       /*const uint8* src_v*/buffer_v,
                       /*int src_stride_v*/(int)plane1_stride >> 1,
                       /*uint8* dst_y*/mirror_y,
                       /*int dst_stride_y*/(int)plane1_stride,
                       /*uint8* dst_u*/mirror_u,
                       /*int dst_stride_u*/(int)plane1_stride >> 1,
                       /*uint8* dst_v*/mirror_v,
                       /*int dst_stride_v*/(int)plane1_stride >> 1,
                       /*int width*/(int)buffer_width,
                       /*int height*/(int)buffer_height);
    
    free(buffer_y);
    
    uint8 *nv12_y = (uint8 *)malloc(frame_size);
    uint8* nv12_uv = nv12_y + plane1_stride * plane1_height;
    
    libyuv::I420ToNV12(/*const uint8 *src_y*/ mirror_y,
                       /*int src_stride_y*/ (int)plane1_stride,
                       /*const uint8 *src_u*/ mirror_u,
                       /*int src_stride_u*/ (int)plane1_stride >> 1,
                       /*const uint8 *src_v*/ mirror_v,
                       /*int src_stride_v*/ (int)plane1_stride >> 1,
                       /*uint8 *dst_y*/ nv12_y,
                       /*int dst_stride_y*/ (int)plane1_stride,
                       /*uint8 *dst_uv*/ nv12_uv,
                       /*int dst_stride_uv*/ (int)plane1_stride,
                       /*int width*/ (int)buffer_width,
                       /*int height*/ (int)buffer_height);
    
    free(mirror_y);
    
    // 4.NV12转换为CVPixelBufferRef
    NSDictionary *pixelAttributes = @{(id)kCVPixelBufferIOSurfacePropertiesKey : @{}};
    CVPixelBufferRef dstPixelBuffer = NULL;
    CVReturn result = CVPixelBufferCreate(kCFAllocatorDefault,
                                          buffer_width, buffer_height, kCVPixelFormatType_420YpCbCr8BiPlanarFullRange,
                                          (__bridge CFDictionaryRef)pixelAttributes, &dstPixelBuffer);

    CVPixelBufferLockBaseAddress(dstPixelBuffer, 0);
    uint8_t *yDstPlane = (uint8*)CVPixelBufferGetBaseAddressOfPlane(dstPixelBuffer, 0);
    memcpy(yDstPlane, nv12_y, plane1_size);
    uint8_t *uvDstPlane = (uint8*)CVPixelBufferGetBaseAddressOfPlane(dstPixelBuffer, 1);
    memcpy(uvDstPlane, nv12_uv, plane2_size);
    if (result != kCVReturnSuccess) {
        NSLog(@"Unable to create cvpixelbuffer %d", result);
    }
    CVPixelBufferUnlockBaseAddress(dstPixelBuffer, 0);
    free(nv12_y);

    return dstPixelBuffer;
}

相关文章

网友评论

      本文标题:libyuv NV12镜像

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