Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/platform/graphics/cocoa/VP9UtilitiesCocoa.mm

    r264476 r265167  
    3030
    3131#import "FourCC.h"
     32#import "LibWebRTCProvider.h"
    3233#import "MediaCapabilitiesInfo.h"
    3334#import "PlatformScreen.h"
     
    9798}
    9899
    99 bool validateVPParameters(VPCodecConfigurationRecord& codecConfiguration, MediaCapabilitiesInfo& info, const VideoConfiguration& videoConfiguration)
    100 {
    101     OSStatus status = VTSelectAndCreateVideoDecoderInstance(kCMVideoCodecType_VP9, kCFAllocatorDefault, nullptr, nullptr);
    102     if (status != noErr)
    103         return false;
    104 
    105     // VideoConfiguration and VPCodecConfigurationRecord can have conflicting values for HDR properties. If so, reject.
    106     if (videoConfiguration.transferFunction) {
    107         // Note: Transfer Characteristics are defined by ISO/IEC 23091-2:2019.
    108         if (*videoConfiguration.transferFunction == TransferFunction::SRGB && codecConfiguration.transferCharacteristics > 15)
    109             return false;
    110         if (*videoConfiguration.transferFunction == TransferFunction::PQ && codecConfiguration.transferCharacteristics != 16)
    111             return false;
    112         if (*videoConfiguration.transferFunction == TransferFunction::HLG && codecConfiguration.transferCharacteristics != 18)
    113             return false;
    114     }
    115 
    116     if (videoConfiguration.colorGamut) {
    117         if (*videoConfiguration.colorGamut == ColorGamut::Rec2020 && codecConfiguration.colorPrimaries != 9)
    118             return false;
    119     }
    120 
    121     if (canLoad_VideoToolbox_VTIsHardwareDecodeSupported() && VTIsHardwareDecodeSupported(kCMVideoCodecType_VP9) && !hardwareVP9DecoderDisabledForTesting) {
    122         info.powerEfficient = true;
    123 
    124         // HW VP9 Decoder supports Profile 0 & 2:
    125         if (!codecConfiguration.profile && codecConfiguration.profile != 2)
    126             return false;
    127 
    128         // HW VP9 Decoder supports up to Level 6:
    129         if (codecConfiguration.level > VPConfigurationLevel::Level_6)
    130             return false;
    131 
    132         // HW VP9 Decoder supports 8 or 10 bit color:
    133         if (codecConfiguration.bitDepth > 10)
    134             return false;
    135 
    136         // HW VP9 Decoder suports only 420 chroma subsampling:
    137         if (codecConfiguration.chromaSubsampling > VPConfigurationChromaSubsampling::Subsampling_420_Colocated)
    138             return false;
    139 
    140         // HW VP9 Decoder does not support alpha channel:
    141         if (videoConfiguration.alphaChannel && *videoConfiguration.alphaChannel)
    142             return false;
    143 
    144         // HW VP9 Decoder can support up to 4K @ 120 or 8K @ 30
    145         auto resolution = resolutionCategory({ (float)videoConfiguration.width, (float)videoConfiguration.height });
    146         if (resolution > ResolutionCategory::R_8K)
    147             return false;
    148         if (resolution == ResolutionCategory::R_8K && videoConfiguration.framerate > 30)
    149             info.smooth = false;
    150         else if (resolution <= ResolutionCategory::R_4K && videoConfiguration.framerate > 120)
    151             info.smooth = false;
    152         else
    153             info.smooth = true;
    154 
    155         return true;
    156     }
    157 
    158     // SW VP9 Decoder has much more variable capabilities depending on CPU characteristics.
    159     // FIXME: Add a lookup table for device-to-capabilities. For now, assume that the SW VP9
    160     // decoder can support 4K @ 30.
    161     if (videoConfiguration.height <= 1080 && videoConfiguration.framerate > 60)
    162         info.smooth = false;
    163     if (videoConfiguration.height <= 2160 && videoConfiguration.framerate > 30)
    164         info.smooth = false;
    165     else
    166         info.smooth = true;
     100void registerWebKitVP9Decoder()
     101{
     102    LibWebRTCProvider::registerWebKitVP9Decoder();
     103}
     104
     105void registerSupplementalVP9Decoder()
     106{
     107    if (!VideoToolboxLibrary(true))
     108        return;
     109
     110    if (canLoad_VideoToolbox_VTRegisterSupplementalVideoDecoderIfAvailable())
     111        softLink_VideoToolbox_VTRegisterSupplementalVideoDecoderIfAvailable(kCMVideoCodecType_VP9);
     112}
     113
     114bool isVP9DecoderAvailable()
     115{
     116    if (!VideoToolboxLibrary(true))
     117        return false;
     118    return noErr == VTSelectAndCreateVideoDecoderInstance(kCMVideoCodecType_VP9, kCFAllocatorDefault, nullptr, nullptr);
     119}
     120
     121bool isVPCodecConfigurationRecordSupported(VPCodecConfigurationRecord& codecConfiguration)
     122{
     123    if (!isVP9DecoderAvailable())
     124        return false;
     125
     126    // HW & SW VP9 Decoders support Profile 0 & 2:
     127    if (codecConfiguration.profile && codecConfiguration.profile != 2)
     128        return false;
     129
     130    // HW & SW VP9 Decoders support only 420 chroma subsampling:
     131    if (codecConfiguration.chromaSubsampling > VPConfigurationChromaSubsampling::Subsampling_420_Colocated)
     132        return false;
     133
     134    // HW & SW VP9 Decoders support 8 or 10 bit color:
     135    if (codecConfiguration.bitDepth > 10)
     136        return false;
     137
     138    // HW & SW VP9 Decoders support up to Level 6:
     139    if (codecConfiguration.level > VPConfigurationLevel::Level_6)
     140        return false;
     141
     142    // Hardware decoders are always available.
     143    if (canLoad_VideoToolbox_VTIsHardwareDecodeSupported() && VTIsHardwareDecodeSupported(kCMVideoCodecType_VP9) && !hardwareVP9DecoderDisabledForTesting)
     144        return true;
    167145
    168146    // For wall-powered devices, always report VP9 as supported, even if not powerEfficient.
    169     if (!systemHasBattery()) {
    170         info.supported = true;
    171         return true;
    172     }
     147    if (!systemHasBattery())
     148        return true;
    173149
    174150    // For battery-powered devices, always report VP9 as supported when running on AC power,
    175151    // but only on battery when there is an attached screen whose resolution is large enough
    176152    // to support 4K video.
    177     if (systemHasAC()) {
    178         info.supported = true;
    179         return true;
    180     }
     153    if (systemHasAC())
     154        return true;
    181155
    182156    bool has4kScreen = false;
     
    194168    }
    195169
    196     if (!has4kScreen) {
    197         info.supported = false;
    198         return false;
    199     }
    200 
     170    return has4kScreen;
     171}
     172
     173bool validateVPParameters(VPCodecConfigurationRecord& codecConfiguration, MediaCapabilitiesInfo& info, const VideoConfiguration& videoConfiguration)
     174{
     175    if (!isVPCodecConfigurationRecordSupported(codecConfiguration))
     176        return false;
     177
     178    // VideoConfiguration and VPCodecConfigurationRecord can have conflicting values for HDR properties. If so, reject.
     179    if (videoConfiguration.transferFunction) {
     180        // Note: Transfer Characteristics are defined by ISO/IEC 23091-2:2019.
     181        if (*videoConfiguration.transferFunction == TransferFunction::SRGB && codecConfiguration.transferCharacteristics > 15)
     182            return false;
     183        if (*videoConfiguration.transferFunction == TransferFunction::PQ && codecConfiguration.transferCharacteristics != 16)
     184            return false;
     185        if (*videoConfiguration.transferFunction == TransferFunction::HLG && codecConfiguration.transferCharacteristics != 18)
     186            return false;
     187    }
     188
     189    if (videoConfiguration.colorGamut) {
     190        if (*videoConfiguration.colorGamut == ColorGamut::Rec2020 && codecConfiguration.colorPrimaries != 9)
     191            return false;
     192    }
     193
     194    if (canLoad_VideoToolbox_VTIsHardwareDecodeSupported() && VTIsHardwareDecodeSupported(kCMVideoCodecType_VP9) && !hardwareVP9DecoderDisabledForTesting) {
     195        // HW VP9 Decoder does not support alpha channel:
     196        if (videoConfiguration.alphaChannel && *videoConfiguration.alphaChannel)
     197            return false;
     198
     199        // HW VP9 Decoder can support up to 4K @ 120 or 8K @ 30
     200        auto resolution = resolutionCategory({ (float)videoConfiguration.width, (float)videoConfiguration.height });
     201        if (resolution > ResolutionCategory::R_8K)
     202            return false;
     203        if (resolution == ResolutionCategory::R_8K && videoConfiguration.framerate > 30)
     204            info.smooth = false;
     205        else if (resolution <= ResolutionCategory::R_4K && videoConfiguration.framerate > 120)
     206            info.smooth = false;
     207        else
     208            info.smooth = true;
     209
     210        info.powerEfficient = true;
     211        info.supported = true;
     212        return true;
     213    }
     214
     215    info.powerEfficient = false;
     216
     217    // SW VP9 Decoder has much more variable capabilities depending on CPU characteristics.
     218    // FIXME: Add a lookup table for device-to-capabilities. For now, assume that the SW VP9
     219    // decoder can support 4K @ 30.
     220    if (videoConfiguration.height <= 1080 && videoConfiguration.framerate > 60)
     221        info.smooth = false;
     222    if (videoConfiguration.height <= 2160 && videoConfiguration.framerate > 30)
     223        info.smooth = false;
     224    else
     225        info.smooth = true;
     226
     227    // For wall-powered devices, always report VP9 as supported, even if not powerEfficient.
     228    if (!systemHasBattery()) {
     229        info.supported = true;
     230        return true;
     231    }
     232
     233    // For battery-powered devices, always report VP9 as supported when running on AC power,
     234    // but only on battery when there is an attached screen whose resolution is large enough
     235    // to support 4K video.
     236    if (systemHasAC()) {
     237        info.supported = true;
     238        return true;
     239    }
     240
     241    bool has4kScreen = false;
     242
     243    if (screenSizeAndScaleForTesting) {
     244        auto screenSize = FloatSize(screenSizeAndScaleForTesting->width, screenSizeAndScaleForTesting->height).scaled(screenSizeAndScaleForTesting->scale);
     245        has4kScreen = resolutionCategory(screenSize) >= ResolutionCategory::R_4K;
     246    } else {
     247        for (auto& screenData : getScreenProperties().screenDataMap.values()) {
     248            if (resolutionCategory(screenData.screenRect.size().scaled(screenData.scaleFactor)) >= ResolutionCategory::R_4K) {
     249                has4kScreen = true;
     250                break;
     251            }
     252        }
     253    }
     254
     255    if (!has4kScreen)
     256        return false;
     257
     258    info.supported = true;
    201259    return true;
    202260}
Note: See TracChangeset for help on using the changeset viewer.