首页 文章

为AVCaptureSession设置自定义AVFrameRateRange

提问于
浏览
4

我试图用AVCaptureSession每秒拍摄5张照片,我不确定我理解AVFrameRange的含义 . 目前我有一些设置设备的代码:

AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];

并尝试将 activeVideoMinFrameDurationactiveVideoMaxFrameDuration 设置为自定义值 CMTimeMake(1, 5) . Apple告诉我,我只能使用他们提供的AVFrameRanges之一 .

当我对它们进行NSLog时,我得到(2,30),(2,60)和(2,24) . 我首先想知道这意味着什么?这是相机运行的帧速率还是捕获帧的间隔(即我正在尝试做的事情)?

如果不是,我该怎样做才能在sampleBufferDelegate方法上每秒保存5帧?目前它给了我每一个帧,因为每次有一个帧时都会调用该方法,所以我只需要一些指针来说明我每秒只能抓5个 .

2 回答

  • 5

    这是我们使用的工作代码,它将帧速率设置为每秒5帧 .

    如果在使用此代码时测量对CaptureOutput的调用,则可以看到相机帧每200毫秒调用一次(即每秒5帧) . (我们只是对此进行了测试以确认 . )

    更改desiredFrameRate以获取其他相机帧速率 .

    - (void)attemptToConfigure5FPS
    {
        NSError *error;
        if (![self lockForConfiguration:&error]) {
            NSLog(@"Could not lock device %@ for configuration: %@", self, error);
            return;
        }
    
        AVCaptureDeviceFormat *format = self.activeFormat;
        double epsilon = 0.00000001;
    
        int desiredFrameRate = 5;
    
        for (AVFrameRateRange *range in format.videoSupportedFrameRateRanges) {
    
                if (range.minFrameRate <= (desiredFrameRate + epsilon) &&
                range.maxFrameRate >= (desiredFrameRate - epsilon)) {
    
                self.activeVideoMaxFrameDuration = (CMTime){
                    .value = 1,
                    .timescale = desiredFrameRate,
                    .flags = kCMTimeFlags_Valid,
                    .epoch = 0,
                };
                self.activeVideoMinFrameDuration = (CMTime){
                    .value = 1,
                    .timescale = desiredFrameRate,
                    .flags = kCMTimeFlags_Valid,
                    .epoch = 0,
                };           
                break;
            }
        }
    
        [self unlockForConfiguration];
    }
    
  • 2

    选择自定义帧速率的代码如下所示 - 添加了对Apple RosyWriter的检查以验证当前格式是否支持选择的FPS

    - (void)configureCamera:(AVCaptureDevice *)videoDevice withFrameRate:(int)desiredFrameRate
    {
        BOOL isFPSSupported = NO;
        AVCaptureDeviceFormat *currentFormat = [videoDevice activeFormat];
        for ( AVFrameRateRange *range in currentFormat.videoSupportedFrameRateRanges ) {
            if ( range.maxFrameRate >= desiredFrameRate && range.minFrameRate <= desiredFrameRate )        {
                isFPSSupported = YES;
                break;
            }
        }
    
        if( isFPSSupported ) {
            if ( [videoDevice lockForConfiguration:NULL] ) {
                videoDevice.activeVideoMaxFrameDuration = CMTimeMake( 1, desiredFrameRate );
                videoDevice.activeVideoMinFrameDuration = CMTimeMake( 1, desiredFrameRate );
                [videoDevice unlockForConfiguration];
            }
        }
    }
    

    如果当前格式( activeFormat )不支持您选择的FPS,请使用以下代码更改 activeFormat ,然后选择FPS . 需要获得格式尺寸以满足您的需求 .

    - (void)configureCamera:(AVCaptureDevice *)device withFrameRate:(int)desiredFrameRate
    {
        AVCaptureDeviceFormat *desiredFormat = nil;
        for ( AVCaptureDeviceFormat *format in [device formats] ) {
            for ( AVFrameRateRange *range in format.videoSupportedFrameRateRanges ) {
                if ( range.maxFrameRate >= desiredFrameRate && range.minFrameRate <= desiredFrameRate ) {
                    desiredFormat = format;
                    goto desiredFormatFound;
                }
            }
        }
    
        desiredFormatFound:
        if ( desiredFormat ) {
            if ( [device lockForConfiguration:NULL] == YES ) {
                device.activeFormat = desiredFormat ;
                device.activeVideoMinFrameDuration = CMTimeMake ( 1, desiredFrameRate );
                device.activeVideoMaxFrameDuration = CMTimeMake ( 1, desiredFrameRate );
                [device unlockForConfiguration];
            }
        }
    }
    

    注意:不建议使用 AVCaptureConnection videoMinFrameDuration 来设置FPS .

相关问题