我可以在iPhone12上获得PHAsset / AVAsset是hdr video / dolby vision吗?

问题描述

我想添加HDR图标以表明某些资产是HDR,但是如果这是来自iphone12的HDR视频记录,我无法获取任何信息来检查视频

解决方法

+ (BOOL)isHDRVideo:(AVAsset *)avasset {
    if (!avasset) {
        return NO;
    }
    __block BOOL isHDRVideo = NO;
    [avasset.tracks enumerateObjectsUsingBlock:^(AVAssetTrack * _Nonnull obj,NSUInteger idx,BOOL * _Nonnull stopTracks) {
        [obj.formatDescriptions enumerateObjectsUsingBlock:^(id  _Nonnull obj,BOOL * _Nonnull stopFormatDescriptions) {
            CMFormatDescriptionRef desc = (__bridge  CMVideoFormatDescriptionRef)obj;
            NSDictionary *dic = (__bridge NSDictionary *)CMFormatDescriptionGetExtensions(desc);
            NSString *imageBufferColorPrimaries = dic[(__bridge  id)kCVImageBufferColorPrimariesKey];
            if ([imageBufferColorPrimaries isEqualToString:(__bridge  id)kCVImageBufferColorPrimaries_ITU_R_2020]) {
                *stopFormatDescriptions = YES;
                *stopTracks = YES;
                isHDRVideo = YES;
            }
        }];
    }];
    
    return isHDRVideo;
}
,

更好的方法是使用 avasset.tracks(withMediaCharacteristic: .containsHDRVideo) 要么 simpleVideo.tracks.forEach{$0.hasMediaCharacteristic(.containsHDRVideo)}

,

这篇文章对我很有帮助,所以我觉得我必须分享我的发现,以便为未来的读者提供一种快速的方法。

可以扩展 AVAssetTrack 以移动所有定义 CMFormatDescription 的逻辑:


public extension AVAssetTrack {
  var isHDRVideo: Bool {
    guard
      self.mediaType == .video,// If is not a video track is not HDR
      let cmFormatDescription = self.formatDescriptions.map { $0 as!  CMFormatDescription }.first,// Safely get the description
      let transferFunction = CMFormatDescriptionGetExtension(
        cmFormatDescription,extensionKey: kCVImageBufferTransferFunctionKey),// It can be nil,which will make the as! CFString fail
    else { return false }

    return [
      kCVImageBufferTransferFunction_ITU_R_2020,kCVImageBufferTransferFunction_ITU_R_2100_HLG,kCVImageBufferTransferFunction_SMPTE_ST_2084_PQ
    ].contains(transferFunction as! CFString)
  }
}

然后假设您有一个名为 AVAssetasset,您可以这样做:

asset.tracks(withMediaType: .video).map { $0.isHDRVideo }

并在此基础上构建您的逻辑。