iOS 从摄像头获取YUV420SP数据

该博客介绍了如何在iOS中从摄像头获取YUV420SP格式的数据,包括引入AVFoundation和AssetsLibrary库,遵循AVCaptureVideoDataOutputSampleBufferDelegate代理,设置Session和分辨率,以及在代理方法中处理获取到的YUV420SP数据,以供OpenGL ES显示。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

需要引入两个库

#import <AVFoundation/AVFoundation.h>

#import <AssetsLibrary/AssetsLibrary.h>


所在类需遵守AVCaptureVideoDataOutputSampleBufferDelegate代理


设置Session

<span style="font-size:18px;">- (void)setSession
{
    _captureInput = [[AVCaptureDeviceInput alloc]initWithDevice:[self getFrontCameraDevice] error:nil];
    AVCaptureVideoDataOutput *captureOutput = [[AVCaptureVideoDataOutput alloc]
                                               init];
    captureOutput.alwaysDiscardsLateVideoFrames = YES;
    
    dispatch_queue_t queue;
    queue = dispatch_queue_create("cameraQueue", NULL);
    [captureOutput setSampleBufferDelegate:self queue:queue];
    NSString* key = (NSString*)kCVPixelBufferPixelFormatTypeKey;
    NSNumber* value = [NSNumber
                       numberWithUnsignedInt:kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange];
    NSDictionary* videoSettings = [NSDictionary
                                   dictionaryWithObject:value forKey:key];
    [captureOutput setVideoSettings:videoSettings];
    self.captureSession = [[AVCaptureSession alloc] init];
    [self.captureSession addInput:_captureInput];
    [self.captureSession addOutput:captureOutput];
    [self.captureSession setSessionPreset:AVCaptureSessionPreset640x480];
    
}</span>

NSNumber* value = [NSNumber numberWithUnsignedInt:kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange];

表示设置摄像头返回的数据类型为YUV420SP类型

[self.captureSessionsetSessionPreset:AVCaptureSessionPreset640x480];

设置分辨率

<span style="font-size:18px;">/**
 *  获取前置摄像头
 *
 *  @return 摄像头设备
 */
- (AVCaptureDevice *)getFrontCameraDevice{
    NSArray *cameras= [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
    for (AVCaptureDevice *camera in cameras) {
        if ([camera position] == AVCaptureDevicePositionFront) {
            return camera;
        }
    }
    return nil;
}</span>

AVCaptureVideoDataOutputSampleBufferDelegate代理中的操作


<span style="font-size:18px;">#pragma mark AVCaptureSession - delegate
- (void)captureOutput:(AVCaptureOutput *)captureOutput
didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer
       fromConnection:(AVCaptureConnection *)connection {
    CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
    
    // Lock the base address of the pixel buffer
    CVPixelBufferLockBaseAddress(imageBuffer, 0);
    CMTime pts = CMSampleBufferGetPresentationTimeStamp(sampleBuffer);
    CMTime duration = CMSampleBufferGetDuration(sampleBuffer);
    // Get the number of bytes per row for the plane pixel buffer
    void *imageAddress = CVPixelBufferGetBaseAddressOfPlane(imageBuffer, 0);
    
    size_t width = CVPixelBufferGetWidth(imageBuffer);
    size_t height = CVPixelBufferGetHeight(imageBuffer);
    
    
    Byte *buf = malloc(width * height * 3/ 2);
    memcpy(buf, imageAddress, width * height);
    size_t a = width * height;
    size_t b = width * height * 5 / 4;
    for (NSInteger i = 0; i < width * height/ 2; i ++) {
        memcpy(buf + a, imageAddress + width * height + i , 1);
        a++;
        i++;
        memcpy(buf + b, imageAddress + width * height + i, 1);
        b++;
        
    }
    CVPixelBufferUnlockBaseAddress(imageBuffer,0);
}</span>


将YUV420SP的数据重新排列为YUV420P


    Byte *buf = malloc(width * height *3/ 2);

    memcpy(buf, imageAddress, width * height);

    size_t a = width * height;

    size_t b = width * height * 5 / 4;

    for (NSInteger i =0; i < width * height/ 2; i ++) {

        memcpy(buf + a, imageAddress + width * height + i ,1);

        a++;

        i++;

        memcpy(buf + b, imageAddress + width * height + i,1);

        b++;

        

    }

buf中的数据就是YUV420P的数据可以供OpenGL ES显示





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值