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