AV Foundation ⑮ 使用高帧率捕捉

AVFoundation 中关于高帧率的支持

    在 高帧率捕捉是开发者在一些场景中希望使用的技术。苹果公司并没有单独推出这一个功能,而是通过 AV Foundation 框架为这个功能给出了强大的支撑。

  • 捕捉: 支持每秒 60 帧 (fps) 的完整 720p(1280 x 720 像素)分辨率,包括视频稳定和支持启动 droppable P-frames (H.264 编码的特性 ),即使在较慢和较旧的硬件上也可以流畅地播放电影。
  • 播放: AVPlayer 已经支持以多种播放帧率播放资源内容,增强了对慢速和快速播放的音频支持,AVPlayerItem 有一个 audioTimePitchAlgorithm 可以允许以较慢或较快的速度设置算法。
  • 编辑:全面支持可变组合成中执行缩放编辑。
  • 导出:AV Foundation 提供了保存原始帧率的功能,所以 60 fps 影片可以被导出,或者将电影转换为任意较慢的帧速率,例如每秒 30 帧。

高帧率捕捉概述

    使用高帧率捕捉的首先要获取到设备的最高质量格式,找到它相关的帧时长,之后手动设置捕捉设备的格式和帧时长。AVCaptureDeviceFormat 类确定设备的捕获能力。此类具有返回支持的媒体类型、帧速率、视野、最大缩放系数、是否支持视频稳定等的方法,其具有一个 videoSupportedFrameRateRanges 属性,包含了一个 AVFrameRateRange 对象数组,其中带有格式所支持的最小帧率、最大帧率和时长信息。

支持高帧率捕捉

由于查找设备最大帧率的过程较为麻烦,通过给 AVCaptureDevice 添加分类的方法来实现,开启高帧率率捕捉的功能:

  1. 新增分类声明两个方法 - (BOOL)supportsHighFrameRateCapture 判断当前设备是否支持高帧率捕捉和 - (BOOL)enableMaxFrameRateCapture;开启高帧率捕捉
  2. 实现 findHighestQualityOfService 遍历所有的捕捉设备的支持 formats,并对每一个元素获取相应的 codeType,这里筛选出 kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange 格式,接着遍历 AVFrameRateRange 对象数组,获取最大的 AVFrameRateRange,最终找到提供的最高的format 和帧率并将其存储起来。
  3. 实现 supportsHighFrameRateCapture,若最大帧率大于 30 fps,则支持高帧率;
  4. 实现 enableMaxFrameRateCapture,修改捕捉设备的 format 、最小帧时长 activeVideoMinFrameDuration 和最大帧时长activeVideoMaxFrameDuration

@interface AVCaptureDevice (QualityOfService)

- (BOOL)supportsHighFrameRateCapture;
- (BOOL)enableMaxFrameRateCapture;

@end
const void* kMaxFormat = &kMaxFormat;
const void* kMaxFrameRateRange = &kMaxFrameRateRange;
@implementation AVCaptureDevice (QualityOfService)

- (void)setMaxFormat:(AVCaptureDeviceFormat *)maxFormat{
    objc_setAssociatedObject(self, kMaxFormat, maxFormat, OBJC_ASSOCIATION_RETAIN);
}

- (AVCaptureDeviceFormat *)maxFormat{
    return objc_getAssociatedObject(self, &kMaxFormat);
}

- (void)setMaxFrameRateRange:(AVFrameRateRange*)maxFrameRateRange{
    objc_setAssociatedObject(self, kMaxFrameRateRange, maxFrameRateRange, OBJC_ASSOCIATION_RETAIN);
}

- (AVFrameRateRange *)maxFrameRateRange{
    return objc_getAssociatedObject(self, &kMaxFrameRateRange);
}

- (BOOL)supportsHighFrameRateCapture {
    if (![self hasMediaType:AVMediaTypeVideo]) {                            // 1
        return NO;
    }
    return [self isHighFrameRate];              // 2
}

- (BOOL)enableMaxFrameRateCapture{

    if (![self isHighFrameRate]) {                                             // 1
        
        return NO;
    }

    if ([self lockForConfiguration:nil]) {                                // 2

        CMTime minFrameDuration = [self maxFrameRateRange].minFrameDuration;

        self.activeFormat = [self maxFormat];                                     // 3
        self.activeVideoMinFrameDuration = minFrameDuration;                // 4
        self.activeVideoMaxFrameDuration = minFrameDuration;

        [self unlockForConfiguration];
        return YES;
    }
    return NO;
}

- (void)findHighestQualityOfService {

    AVCaptureDeviceFormat *maxFormat = nil;
    AVFrameRateRange *maxFrameRateRange = nil;

    for (AVCaptureDeviceFormat *format in self.formats) {

        FourCharCode codecType =                                           
            CMVideoFormatDescriptionGetCodecType(format.formatDescription);

        if (codecType == kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange) { 

            NSArray *frameRateRanges = format.videoSupportedFrameRateRanges;

            for (AVFrameRateRange *range in frameRateRanges) {              
                if (range.maxFrameRate > maxFrameRateRange.maxFrameRate) {
                    maxFormat = format;
                    maxFrameRateRange = range;
                }
            }
        }
    }

    [self setMaxFormat:maxFormat];
    [self setMaxFrameRateRange:maxFrameRateRange];


}

- (BOOL)isHighFrameRate {
    AVFrameRateRange *frameRateRange = [self maxFrameRateRange]
    if(!frameRateRange){
       [self findHighestQualityOfService];
    }
    return [self maxFrameRateRange].maxFrameRate > 30.0f;
}

@end

你可能感兴趣的:(AV Foundation ⑮ 使用高帧率捕捉)