0

您好我正在使用 PBJVision 做一些视频处理 iOS。当设置为双倍默认帧速率 24 fps -> 48 fps。我收到以下错误:

2015-10-16 15:02:48.929 RecordGram[2425:515618] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[AVCaptureVideoDevice setActiveVideoMinFrameDuration:] - the passed activeFrameDuration 1:48 is not supported by the device.  Use -activeFormat.videoSupportedFrameRateRanges to discover valid ranges.'

这是发生错误的 PBJVision 的方法。我突出显示了错误所在的行。请注意,该方法supportsVideoFrameRate:返回 true。

// framerate

- (void)setVideoFrameRate:(NSInteger)videoFrameRate
{
if (![self supportsVideoFrameRate:videoFrameRate]) {
    DLog(@"frame rate range not supported for current device format");
    return;
}

BOOL isRecording = _flags.recording;
if (isRecording) {
    [self pauseVideoCapture];
}

CMTime fps = CMTimeMake(1, (int32_t)videoFrameRate);

if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_6_1) {

    AVCaptureDevice *videoDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
    AVCaptureDeviceFormat *supportingFormat = nil;
    int32_t maxWidth = 0;

    NSArray *formats = [videoDevice formats];
    for (AVCaptureDeviceFormat *format in formats) {
        NSArray *videoSupportedFrameRateRanges = format.videoSupportedFrameRateRanges;
        for (AVFrameRateRange *range in videoSupportedFrameRateRanges) {

            CMFormatDescriptionRef desc = format.formatDescription;
            CMVideoDimensions dimensions = CMVideoFormatDescriptionGetDimensions(desc);
            int32_t width = dimensions.width;
            if (range.minFrameRate <= videoFrameRate && videoFrameRate <= range.maxFrameRate && width >= maxWidth) {
                supportingFormat = format;
                maxWidth = width;
            }

        }
    }

    if (supportingFormat) {
        NSError *error = nil;
        if ([_currentDevice lockForConfiguration:&error]) {
            _currentDevice.activeVideoMinFrameDuration = fps; <<<<<<======ERROR IS HERE, THIS LINE IS WHERE THE ERROR OCCURS
            _currentDevice.activeVideoMaxFrameDuration = fps;
            _videoFrameRate = videoFrameRate;
            [_currentDevice unlockForConfiguration];
        } else if (error) {
            DLog(@"error locking device for frame rate change (%@)", error);
        }
    }

    [self _enqueueBlockOnMainQueue:^{
        if ([_delegate respondsToSelector:@selector(visionDidChangeVideoFormatAndFrameRate:)])
            [_delegate visionDidChangeVideoFormatAndFrameRate:self];
    }];

} else {

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
    AVCaptureConnection *connection = [_currentOutput connectionWithMediaType:AVMediaTypeVideo];
    if (connection.isVideoMaxFrameDurationSupported) {
        connection.videoMaxFrameDuration = fps;
    } else {
        DLog(@"failed to set frame rate");
    }

    if (connection.isVideoMinFrameDurationSupported) {
        connection.videoMinFrameDuration = fps;
        _videoFrameRate = videoFrameRate;
    } else {
        DLog(@"failed to set frame rate");
    }

    [self _enqueueBlockOnMainQueue:^{
        if ([_delegate respondsToSelector:@selector(visionDidChangeVideoFormatAndFrameRate:)])
            [_delegate visionDidChangeVideoFormatAndFrameRate:self];
    }];
#pragma clang diagnostic pop

}

if (isRecording) {
    [self resumeVideoCapture];
}
}

这是supportsVideoFrameRate:方法

- (BOOL)supportsVideoFrameRate:(NSInteger)videoFrameRate
{
if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_6_1) {
    AVCaptureDevice *videoDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];

    NSArray *formats = [videoDevice formats];
    for (AVCaptureDeviceFormat *format in formats) {
        NSArray *videoSupportedFrameRateRanges = [format videoSupportedFrameRateRanges];
        for (AVFrameRateRange *frameRateRange in videoSupportedFrameRateRanges) {
            if ( (frameRateRange.minFrameRate <= videoFrameRate) && (videoFrameRate <= frameRateRange.maxFrameRate) ) {
                return YES;
            }
        }
    }

} else {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
    AVCaptureConnection *connection = [_currentOutput connectionWithMediaType:AVMediaTypeVideo];
    return (connection.isVideoMaxFrameDurationSupported && connection.isVideoMinFrameDurationSupported);
#pragma clang diagnostic pop
}

return NO;
}

有人有什么想法吗?

4

1 回答 1

0

这里的问题是“活动设备”或“活动格式”不是 PBJVision 的代码正在检查的内容。它正在检查所有格式和默认设备...

因此,面部摄像头不支持 48 fps。简单检查:

RGLog(@"default video frame rate = %ld", (long)[vision videoFrameRate]);
bool supportsDouble = [vision supportsVideoFrameRate:2*[vision videoFrameRate]];
bool supportsQuad = [vision supportsVideoFrameRate:4*[vision videoFrameRate]];
bool supportsHalf = [vision supportsVideoFrameRate:[vision videoFrameRate]/2];
bool supportsQuarter = [vision supportsVideoFrameRate:[vision videoFrameRate]/4];
RGLog(@"x2 = %d, x4 = %d, /2 = %d, /4 = %d", supportsDouble, supportsQuad, supportsHalf, supportsQuarter);

哪些日志

2015-10-16 15:32:24.279 RecordGram[2436:519667] default video frame rate = 24
2015-10-16 15:32:24.280 RecordGram[2436:519667] x2 = 0, x4 = 0, /2 = 1, /4 = 1

更改supportsVideoFrameRate:方法后查看_currentDevice而不是[AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo]

- (BOOL)supportsVideoFrameRate:(NSInteger)videoFrameRate
{
if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_6_1) {
    AVCaptureDevice *videoDevice = _currentDevice//[AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];

    NSArray *formats = [videoDevice formats];
    for (AVCaptureDeviceFormat *format in formats) {
        NSArray *videoSupportedFrameRateRanges = [format videoSupportedFrameRateRanges];
        for (AVFrameRateRange *frameRateRange in videoSupportedFrameRateRanges) {
            if ( (frameRateRange.minFrameRate <= videoFrameRate) && (videoFrameRate <= frameRateRange.maxFrameRate) ) {
                return YES;
            }
        }
    }

} else {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
    AVCaptureConnection *connection = [_currentOutput connectionWithMediaType:AVMediaTypeVideo];
    return (connection.isVideoMaxFrameDurationSupported && connection.isVideoMinFrameDurationSupported);
#pragma clang diagnostic pop
}

return NO;
}
于 2015-10-16T19:41:23.713 回答