1.YUV转RGB,调用libYUV
- (BOOL)NV12ToRgbaPixelBuffer:(CVPixelBufferRef)pixelBufferNV12 pixelBufferRGBA:(CVPixelBufferRef)pixelBufferRGBA
{
CVPixelBufferLockBaseAddress(pixelBufferNV12, 0);
unsigned char* y = (unsigned char*)CVPixelBufferGetBaseAddressOfPlane(pixelBufferNV12,0);
unsigned char* uv = (unsigned char*)CVPixelBufferGetBaseAddressOfPlane(pixelBufferNV12,1);
CVPixelBufferLockBaseAddress(pixelBufferRGBA, 0);
uint8_t* data = (uint8_t*)CVPixelBufferGetBaseAddress(pixelBufferRGBA);
int32_t width = (int32_t)CVPixelBufferGetWidth(pixelBufferNV12);
int32_t height = (int32_t)CVPixelBufferGetHeight(pixelBufferNV12);
size_t bgraStride = CVPixelBufferGetBytesPerRowOfPlane(pixelBufferRGBA,0);
size_t y_stride = CVPixelBufferGetBytesPerRowOfPlane(pixelBufferNV12,0);
size_t uv_stride = CVPixelBufferGetBytesPerRowOfPlane(pixelBufferNV12, 1);
libyuv::NV12ToARGB(y,
int(y_stride),
uv,
int(uv_stride),
data,
int(bgraStride),
width,
height);
CVPixelBufferUnlockBaseAddress(pixelBufferRGBA, 0);
CVPixelBufferUnlockBaseAddress(pixelBufferNV12, 0);
return true;
}
2.RGB转YUV
- (BOOL)RgbaToNV12PixelBuffer:(CVPixelBufferRef)pixelBufferRGBA pixelBufferYUV:(CVPixelBufferRef)pixelBufferNV12
{
CVPixelBufferLockBaseAddress(pixelBufferNV12, 0);
unsigned char* y = (unsigned char*)CVPixelBufferGetBaseAddressOfPlane(pixelBufferNV12,0);
unsigned char* u = (unsigned char*)CVPixelBufferGetBaseAddressOfPlane(pixelBufferNV12,1);
CVPixelBufferLockBaseAddress(pixelBufferRGBA, 0);
uint8_t* data = (uint8_t*)CVPixelBufferGetBaseAddress(pixelBufferRGBA);
int32_t width = (int32_t)CVPixelBufferGetWidth(pixelBufferNV12);
int32_t height = (int32_t)CVPixelBufferGetHeight(pixelBufferNV12);
unsigned char* v = u + width*height/4;
size_t bgraStride = CVPixelBufferGetBytesPerRowOfPlane(pixelBufferRGBA,0);
// size_t y_stride = CVPixelBufferGetBytesPerRowOfPlane(pixelBufferNV12,0);
// size_t uv_stride = CVPixelBufferGetBytesPerRowOfPlane(pixelBufferNV12, 1);
libyuv::ARGBToI420(data,
(int)bgraStride,
y,
width,
u,
width/2,
v,
width/2,
width,
height);
CVPixelBufferUnlockBaseAddress(pixelBufferRGBA, 0);
CVPixelBufferUnlockBaseAddress(pixelBufferNV12, 0);
return true;
}
3.YUV保存本地
-(BOOL) savePixelBufferYUV:(CVPixelBufferRef)CVPixelBufferYUV
{
int32_t width = (int32_t)CVPixelBufferGetWidth(CVPixelBufferYUV);
int32_t height = (int32_t)CVPixelBufferGetHeight(CVPixelBufferYUV);
CVPixelBufferLockBaseAddress(CVPixelBufferYUV, 0);
unsigned char* y = (unsigned char*)CVPixelBufferGetBaseAddressOfPlane(CVPixelBufferYUV,0);
unsigned char* uv = (unsigned char*)CVPixelBufferGetBaseAddressOfPlane(CVPixelBufferYUV,1);
FILE *VTcaptureFile = NULL;
if (!VTcaptureFile)
{
NSString *path_document = NSHomeDirectory();
NSString *imagePath = [path_document stringByAppendingFormat:@"%@",@"/Documents/previewYUV.yuv"];
// VTcaptureFile = fopen(captureTestName, "aw");
const char * captureTestName = [imagePath UTF8String];
VTcaptureFile = fopen(captureTestName, "aw");
if (!VTcaptureFile)
{
NSLog(@"fopen file error!! \n");
return NO ;
}
fwrite(y, 1, width*height, VTcaptureFile);
fflush(VTcaptureFile);
fwrite(uv, 1, width*height/2, VTcaptureFile);
fflush(VTcaptureFile);
}
CVPixelBufferUnlockBaseAddress(CVPixelBufferYUV, 0);
return YES;
}
4.Creat YUV PixelBuffer
CVPixelBufferRef _pixelBufferYUV = NULL;
const void *keys[] = {
kCVPixelBufferOpenGLCompatibilityKey,
kCVPixelBufferIOSurfacePropertiesKey,
};
const void *values[] = {
(__bridge const void *)([NSNumber numberWithBool:YES]),
(__bridge const void *)([NSDictionary dictionary])
};
OSType bufferPixelFormat = kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange;
CFDictionaryRef optionsDictionary = CFDictionaryCreate(NULL, keys, values, 2, NULL, NULL);
CVReturn err __unused = CVPixelBufferCreate(kCFAllocatorDefault,
encodedWidth,
encodedHeight,
bufferPixelFormat,
optionsDictionary,
&_pixelBufferYUV);
5.NSImage转BGRA CVPixelBuffer
- (CVPixelBufferRef)venusFastImageFromNSImage:(NSImage *)image
{
CVPixelBufferRef buffer = NULL;
size_t width = [image size].width;
size_t height = [image size].height;
size_t bitsPerComponent = 8; // *not* CGImageGetBitsPerComponent(image);
CGColorSpaceRef cs = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
CGBitmapInfo bitmap = kCGImageAlphaNoneSkipFirst;
NSDictionary *dic = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES], kCVPixelBufferCGImageCompatibilityKey, [NSNumber numberWithBool:YES], kCVPixelBufferCGBitmapContextCompatibilityKey, nil];
// create pixel buffer
CVPixelBufferCreate(kCFAllocatorDefault, width, height, k32ARGBPixelFormat, (__bridge CFDictionaryRef)dic, &buffer);
CVPixelBufferLockBaseAddress(buffer, 0);
void *rasterData = CVPixelBufferGetBaseAddress(buffer);
size_t bytesPerRow = CVPixelBufferGetBytesPerRow(buffer);
// context to draw in, set to pixel buffer's address pls 4 align just for venus
CGContextRef ctxt = CGBitmapContextCreate(rasterData, width, height, bitsPerComponent, bytesPerRow, cs, bitmap);
if(ctxt == NULL){
NSLog(@"could not create context");
return NULL;
}
// draw image -> pixelbuffer
NSGraphicsContext *nsctxt = [NSGraphicsContext graphicsContextWithGraphicsPort:ctxt flipped:NO];
[NSGraphicsContext saveGraphicsState];
[NSGraphicsContext setCurrentContext:nsctxt];
[image compositeToPoint:NSMakePoint(0.0, 0.0) operation:NSCompositeCopy];
[NSGraphicsContext restoreGraphicsState];
//reset pixelbuffer -> image
CVPixelBufferUnlockBaseAddress(buffer, 0);
CFRelease(ctxt);
return buffer;
}
6. CVPixelBuffer转NSImage
//后面有空再研究,参考下面链接
// https://gist.github.com/AllanChen/d1478f6794075b82e9458c13b3539006
7.CVPixelBuffer(NV12)保存本地,YUV420和NV12
- (void)SavePixelBufferNV12:(CVPixelBufferRef)pixelBuf{
int yStride = (int)CVPixelBufferGetBytesPerRowOfPlane(pixelBuf,0);
int h = (int)CVPixelBufferGetHeight(pixelBuf);
auto buffer = (unsigned char*) malloc(yStride * h * 1.5);
CVPixelBufferLockBaseAddress(pixelBuf, 0);
if (CVPixelBufferIsPlanar(pixelBuf)) {
unsigned char* src = (unsigned char*) CVPixelBufferGetBaseAddressOfPlane(pixelBuf, 0);
unsigned char* uvsrc = (unsigned char*) CVPixelBufferGetBaseAddressOfPlane(pixelBuf, 1);
unsigned char* dst = buffer;
memcpy(dst, src, yStride * h);
auto d1 = dst + yStride * h;
auto d2 = dst + yStride * h * 5 / 4;
auto len = yStride * h / 4;
for(int i = 0; i < len; i++){
//nv12 --> YUV420
//nv12,uv分量交替存储;YUV420,uv分量分层存储
*d1++ = *uvsrc++;
*d2++ = *uvsrc++;
}
// 420 yuv
{
std::string path = [[NSHomeDirectory() stringByAppendingString:@"/Downloads"] UTF8String];
path += "/";
std::string str = path;
str += "_";
str += std::to_string(h);
str += "x";
str += std::to_string(yStride);
str += "_420.yuv";
FILE* fp = fopen(str.c_str(), "ab+");
if (fp) {
fwrite(buffer, 1, yStride * h * 1.5, fp);
fclose(fp);
}
}
// nv12
{
std::string path = [[NSHomeDirectory() stringByAppendingString:@"/Downloads"] UTF8String];
path += "/";
std::string str = path;
str += "_";
str += std::to_string(h);
str += "x";
str += std::to_string(yStride);
str += "_nv12.yuv";
FILE* fp = fopen(str.c_str(), "ab+");
if (fp) {
fwrite((unsigned char*) CVPixelBufferGetBaseAddressOfPlane(pixelBuf, 0), 1, yStride * h , fp);
fwrite((unsigned char*) CVPixelBufferGetBaseAddressOfPlane(pixelBuf, 1), 1, yStride * h /2, fp);
fclose(fp);
}
}
}
CVPixelBufferUnlockBaseAddress(pixelBuf, 0);
}