//初始化输入,输出的类型
-(void)initCapureSession{
//创建AVCaptureDevice的视频设备对象
AVCaptureDevice* videoDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
NSError* error;
//创建视频输入端对象
AVCaptureDeviceInput* input = [AVCaptureDeviceInput deviceInputWithDevice:videoDevice error:&error];
if (error) {
NSLog(@"创建输入端失败,%@",error);
return;
}
//创建功能会话对象
self.captureSession = [[AVCaptureSession alloc] init];
//设置会话输出的视频分辨率
[self.captureSession setSessionPreset:AVCaptureSessionPreset1280x720];
//添加输入端
if (![self.captureSession canAddInput:input]) {
NSLog(@"输入端添加失败");
return;
}
[self.captureSession addInput:input];
//显示摄像头捕捉到的数据
AVCaptureVideoPreviewLayer* layer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:self.captureSession];
layer.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height - 100);
[self.view.layer addSublayer:layer];
//创建输出端
AVCaptureVideoDataOutput *videoDataOutput = [[AVCaptureVideoDataOutput alloc] init];
NSString* key = (NSString*)kCVPixelBufferPixelFormatTypeKey;
NSNumber* value = [NSNumber
numberWithUnsignedInt:kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange];
NSDictionary* videoSettings = [NSDictionary
dictionaryWithObject:value forKey:key];
[videoDataOutput setVideoSettings:videoSettings];
//会话对象添加输出端
if ([self.captureSession canAddOutput:videoDataOutput]) {
[self.captureSession addOutput:videoDataOutput];
self.videoDataOutput = videoDataOutput;
//创建输出调用的队列
dispatch_queue_t videoDataOutputQueue = dispatch_queue_create("videoDataOutputQueue", DISPATCH_QUEUE_SERIAL);
self.videoDataOutputQueue = videoDataOutputQueue;
//设置代理和调用的队列
[self.videoDataOutput setSampleBufferDelegate:self queue:videoDataOutputQueue];
//设置延时丢帧
self.videoDataOutput.alwaysDiscardsLateVideoFrames = NO;
}
}
#pragma mark - AVCaptureVideoDataOutputSampleBufferDelegate
- (void)captureOutput:(AVCaptureOutput *)output didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection {
NSLog(@"did get %@",output);
NSData *data22 = [self convertVideoSmapleBufferToYuvData:sampleBuffer];
[self.h264Tool addFrame:sampleBuffer];
}
// CMSampleBufferRef代表一帧图像,调用苹果提供的api可以获取具体的yuv的数据
-(NSData *) convertVideoSmapleBufferToYuvData:(CMSampleBufferRef) videoSample{
// 获取yuv数据
// 通过CMSampleBufferGetImageBuffer方法,获得CVImageBufferRef。
// 这里面就包含了yuv420(NV12)数据的指针
CVImageBufferRef pixelBuffer = CMSampleBufferGetImageBuffer(videoSample);
//表示开始操作数据
CVPixelBufferLockBaseAddress(pixelBuffer, 0);
//图像宽度(像素)
size_t pixelWidth = CVPixelBufferGetWidth(pixelBuffer);
//图像高度(像素)
size_t pixelHeight = CVPixelBufferGetHeight(pixelBuffer);
//yuv中的y所占字节数
size_t y_size = pixelWidth * pixelHeight;
//yuv中的uv所占的字节数
size_t uv_size = y_size / 2;
uint8_t *yuv_frame = malloc(uv_size + y_size);
//获取CVImageBufferRef中的y数据
uint8_t *y_frame = CVPixelBufferGetBaseAddressOfPlane(pixelBuffer, 0);
memcpy(yuv_frame, y_frame, y_size);
//获取CMVImageBufferRef中的uv数据
uint8_t *uv_frame = CVPixelBufferGetBaseAddressOfPlane(pixelBuffer, 1);
memcpy(yuv_frame + y_size, uv_frame, uv_size);
CVPixelBufferUnlockBaseAddress(pixelBuffer, 0);
uint8_t *I420 = malloc(uv_size + y_size);
NSString *path = [self getHomePath];
const char *resultCString = NULL;
if ([path canBeConvertedToEncoding:NSUTF8StringEncoding]) {
resultCString = [path cStringUsingEncoding:NSUTF8StringEncoding];
}
NSString *path2 = [self getHome2Path];
const char *resultCString2 = NULL;
if ([path2 canBeConvertedToEncoding:NSUTF8StringEncoding]) {
resultCString2 = [path2 cStringUsingEncoding:NSUTF8StringEncoding];
}
dispatch_sync(dispatch_get_main_queue(), ^{
func(yuv_frame, I420,pixelWidth,pixelHeight,resultCString,resultCString2);
func5(yuv_frame, I420,pixelWidth,pixelHeight,resultCString,resultCString2);
});
//返回数据
return [NSData dataWithBytesNoCopy:yuv_frame length:y_size + uv_size];
}
// nv12 写入本地
void func0(uint8_t *NV12, uint8_t *I420,size_t pixelWidth,size_t pixelHeight,const char *resultCString,const char *resultCString2){
NSLog(@"start");
int len = (int)pixelHeight * pixelWidth + pixelHeight * pixelWidth / 2;
FILE* fpyuv = fopen(resultCString, "wb");
for (int i = 0; i < len; i ++) {
fwrite(NV12, 1, 1, fpyuv);
NV12 ++;
}
fclose(fpyuv);
free(NV12);
NSLog(@"end");
}
// nv12 转 yuv 并写入本地
void func(uint8_t *NV12, uint8_t *I420,size_t pixelWidth,size_t pixelHeight,const char *resultCString,const char *resultCString2){
unsigned char *ybuf = (unsigned char *)malloc(pixelHeight * pixelWidth);
unsigned char *ubuf = (unsigned char *)malloc((pixelHeight/2) * (pixelWidth/2));
unsigned char *vbuf = (unsigned char *)malloc((pixelHeight/2) * (pixelWidth/2));
unsigned char *y = ybuf;
unsigned char *u = ubuf;
unsigned char *v = vbuf;
int len = (int)pixelHeight * pixelWidth + pixelHeight * pixelWidth / 2;
FILE* fpyuv = fopen(resultCString, "wb");
for (int i = 0; i < len; i ++) {
if (i < (pixelWidth * pixelHeight)) { //yyyyy
*y = *NV12;
y++;
}
else{//uvuvuv
if (i % 2 == 0) {//uuuuu
*u = *NV12;
u ++;
}else{//vvvvv
*v = *NV12;
v ++;
}
}
NV12 ++;
}
fwrite(ybuf, 1, pixelWidth*pixelHeight, fpyuv);
fwrite(ubuf, 1, pixelWidth*pixelHeight/4, fpyuv);
fwrite(vbuf, 1, pixelWidth*pixelHeight/4, fpyuv);
fclose(fpyuv);
free(ybuf);
free(ubuf);
free(vbuf);
}
// 从本地文件获取yuv的数据 并实现180度的翻转 并写入本地
void func2(uint8_t *NV12, uint8_t *I420,size_t pixelWidth,size_t pixelHeight,const char *resultCString,const char *resultCString2){
unsigned char *ybuf = (unsigned char *)malloc(pixelHeight * pixelWidth);
unsigned char *ubuf = (unsigned char *)malloc((pixelHeight/2) * (pixelWidth/2));
unsigned char *vbuf = (unsigned char *)malloc((pixelHeight/2) * (pixelWidth/2));
unsigned char *y = ybuf;
unsigned char *u = ubuf;
unsigned char *v = vbuf;
FILE* fpyuv = fopen(resultCString, "rb");
FILE* fpyuv2 = fopen(resultCString2, "wb");
uint8_t* yuvbuf = malloc(pixelHeight * pixelWidth * 3 / 2);
fread(yuvbuf, pixelWidth*pixelHeight * 3 / 2, 1, fpyuv);
fclose(fpyuv);
// y
for (int i = pixelHeight -1; i >= 0; i --) {
for (int j = pixelWidth - 1; j >= 0; j--) {
*(y++) = *(yuvbuf +(i*pixelWidth + j));
}
}
//U
uint8_t* uheader = yuvbuf + pixelWidth*pixelHeight;
for (int i = pixelHeight/2 - 1; i >= 0; i--){
for (int j = pixelWidth/2-1 ; j >= 0; j--){
*(u++) = *(uheader +(i*pixelWidth/2 + j));
}
}
//v
uint8_t* vheader = uheader + pixelWidth*pixelHeight/4;
for (int i = pixelHeight/2 - 1; i >= 0; i--){
for (int j = pixelWidth/2-1 ; j >= 0; j--){
*(v++) = *(vheader +(i*pixelWidth/2 + j));
}
}
fwrite(ybuf, 1, pixelWidth*pixelHeight, fpyuv2);
fwrite(ubuf, 1, pixelWidth*pixelHeight/4, fpyuv2);
fwrite(vbuf, 1, pixelWidth*pixelHeight/4, fpyuv2);
fclose(fpyuv2);
free(ybuf);
free(ubuf);
free(vbuf);
}
// 从本地文件获取yuv的数据 并实现逆时针90度的翻转 并写入本地
void func3(uint8_t *NV12, uint8_t *I420,size_t pixelWidth,size_t pixelHeight,const char *resultCString,const char *resultCString2){
unsigned char *ybuf = (unsigned char *)malloc(pixelHeight * pixelWidth);
unsigned char *ubuf = (unsigned char *)malloc((pixelHeight/2) * (pixelWidth/2));
unsigned char *vbuf = (unsigned char *)malloc((pixelHeight/2) * (pixelWidth/2));
unsigned char *y = ybuf;
unsigned char *u = ubuf;
unsigned char *v = vbuf;
FILE* fpyuv = fopen(resultCString, "rb");
FILE* fpyuv2 = fopen(resultCString2, "wb");
uint8_t* yuvbuf = malloc(pixelHeight * pixelWidth * 3 / 2);
fread(yuvbuf, pixelWidth*pixelHeight * 3 / 2, 1, fpyuv);
fclose(fpyuv);
for (int i = 0; i < pixelWidth; i ++) {
for (int j = pixelHeight - 1; j >= 0; j --) {
*(y++) = *(yuvbuf +(j*pixelWidth +i));
}
}
uint8_t* uheader = yuvbuf + pixelWidth*pixelHeight;
for (int i = 0; i < pixelWidth/2; i ++) {
for (int j = pixelHeight/2 - 1; j >= 0; j --) {
*(u++) = *(uheader +(j*pixelWidth/2 + i));
}
}
uint8_t* vheader = uheader + pixelWidth*pixelHeight/4;
for (int i = 0; i < pixelWidth/2; i ++) {
for (int j = pixelHeight/2 - 1; j >= 0; j --) {
*(v++) = *(vheader +(j*pixelWidth/2 + i));
}
}
fwrite(ybuf, 1, pixelWidth*pixelHeight, fpyuv2);
fwrite(ubuf, 1, pixelWidth*pixelHeight/4, fpyuv2);
fwrite(vbuf, 1, pixelWidth*pixelHeight/4, fpyuv2);
fclose(fpyuv2);
free(ybuf);
free(ubuf);
free(vbuf);
}
// 从本地文件获取yuv的数据 并实现顺时针90度的翻转 并写入本地
void func4(uint8_t *NV12, uint8_t *I420,size_t pixelWidth,size_t pixelHeight,const char *resultCString,const char *resultCString2){
unsigned char *ybuf = (unsigned char *)malloc(pixelHeight * pixelWidth);
unsigned char *ubuf = (unsigned char *)malloc((pixelHeight/2) * (pixelWidth/2));
unsigned char *vbuf = (unsigned char *)malloc((pixelHeight/2) * (pixelWidth/2));
unsigned char *y = ybuf;
unsigned char *u = ubuf;
unsigned char *v = vbuf;
FILE* fpyuv = fopen(resultCString, "rb");
FILE* fpyuv2 = fopen(resultCString2, "wb");
uint8_t* yuvbuf = malloc(pixelHeight * pixelWidth * 3 / 2);
fread(yuvbuf, pixelWidth*pixelHeight * 3 / 2, 1, fpyuv);
fclose(fpyuv);
for (int i = pixelWidth - 1; i >= 0; i --) {
for (int j = 0; j < pixelHeight; j ++) {
*(y++) = *(yuvbuf +(j*pixelWidth +i));
}
}
uint8_t* uheader = yuvbuf + pixelWidth*pixelHeight;
for (int i = pixelWidth/2 - 1; i >= 0; i --) {
for (int j = 0; j < pixelHeight/2; j ++) {
*(u++) = *(uheader +(j*pixelWidth/2 +i));
}
}
uint8_t* vheader = uheader + pixelWidth*pixelHeight/4;
for (int i = pixelWidth/2 - 1; i >= 0; i --) {
for (int j = 0; j < pixelHeight/2; j ++) {
*(v++) = *(vheader +(j*pixelWidth/2 +i));
}
}
fwrite(ybuf, 1, pixelWidth*pixelHeight, fpyuv2);
fwrite(ubuf, 1, pixelWidth*pixelHeight/4, fpyuv2);
fwrite(vbuf, 1, pixelWidth*pixelHeight/4, fpyuv2);
fclose(fpyuv2);
free(ybuf);
free(ubuf);
free(vbuf);
}
// 从本地文件获取yuv的数据 制作水平方向的镜像 并写入本地
void func5(uint8_t *NV12, uint8_t *I420,size_t pixelWidth,size_t pixelHeight,const char *resultCString,const char *resultCString2){
unsigned char *ybuf = (unsigned char *)malloc(pixelHeight * pixelWidth);
unsigned char *ubuf = (unsigned char *)malloc((pixelHeight/2) * (pixelWidth/2));
unsigned char *vbuf = (unsigned char *)malloc((pixelHeight/2) * (pixelWidth/2));
unsigned char *y = ybuf;
unsigned char *u = ubuf;
unsigned char *v = vbuf;
FILE* fpyuv = fopen(resultCString, "rb");
FILE* fpyuv2 = fopen(resultCString2, "wb");
uint8_t* yuvbuf = malloc(pixelHeight * pixelWidth * 3 / 2);
fread(yuvbuf, pixelWidth*pixelHeight * 3 / 2, 1, fpyuv);
fclose(fpyuv);
for (int i = 0; i < pixelHeight - 1; i ++) {
for (int j = pixelWidth - 1; j >= 0; j --) {
*(y++) = *(yuvbuf +(i*pixelWidth +j));
}
}
uint8_t* uheader = yuvbuf + pixelWidth*pixelHeight;
for (int i = 0; i < pixelHeight/2 - 1; i ++) {
for (int j = pixelWidth/2 - 1; j >= 0; j --) {
*(u++) = *(uheader +(i*pixelWidth/2 +j));
}
}
uint8_t* vheader = uheader + pixelWidth*pixelHeight/4;
for (int i = 0; i < pixelHeight/2 - 1; i ++) {
for (int j = pixelWidth/2 - 1; j >= 0; j --) {
*(v++) = *(vheader +(i*pixelWidth/2 +j));
}
}
fwrite(ybuf, 1, pixelWidth*pixelHeight, fpyuv2);
fwrite(ubuf, 1, pixelWidth*pixelHeight/4, fpyuv2);
fwrite(vbuf, 1, pixelWidth*pixelHeight/4, fpyuv2);
fclose(fpyuv2);
free(ybuf);
free(ubuf);
free(vbuf);
}
- (NSString *)getHomePath{
NSString *path = NSHomeDirectory();
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docDir = [paths objectAtIndex:0];
return [NSString stringWithFormat:@"%@/outforyuv420p_new_new.yuv",docDir];
}
- (NSString *)getHome2Path{
NSString *path = NSHomeDirectory();
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docDir = [paths objectAtIndex:0];
return [NSString stringWithFormat:@"%@/outforyuv420p_new_new_rala.yuv",docDir];
}
网友评论