Unreviewed, rolling out r244627.
[WebKit-https.git] / Source / WebCore / platform / graphics / cocoa / HEVCUtilitiesCocoa.mm
1 /*
2  * Copyright (C) 2018 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "HEVCUtilitiesCocoa.h"
28
29 #if PLATFORM(COCOA)
30
31 #include "FourCC.h"
32 #include "HEVCUtilities.h"
33 #include "MediaCapabilitiesInfo.h"
34
35 #include "VideoToolboxSoftLink.h"
36
37 SOFT_LINK_FRAMEWORK_OPTIONAL(AVFoundation)
38 SOFT_LINK_CONSTANT_MAY_FAIL(AVFoundation, AVVideoCodecTypeHEVCWithAlpha, NSString *)
39
40 namespace WebCore {
41
42 bool validateHEVCParameters(HEVCParameterSet& parameters, MediaCapabilitiesInfo& info, bool hasAlphaChannel)
43 {
44     CMVideoCodecType codec = kCMVideoCodecType_HEVC;
45     if (hasAlphaChannel) {
46         if (!AVFoundationLibrary() || !canLoadAVVideoCodecTypeHEVCWithAlpha())
47             return false;
48
49         auto codecCode = FourCC::fromString(getAVVideoCodecTypeHEVCWithAlpha());
50         if (!codecCode)
51             return false;
52
53         codec = codecCode.value().value;
54     }
55     OSStatus status = VTSelectAndCreateVideoDecoderInstance(codec, kCFAllocatorDefault, nullptr, nullptr);
56     if (status != noErr)
57         return false;
58
59     if (!canLoad_VideoToolbox_VTCopyHEVCDecoderCapabilitiesDictionary()
60         || !canLoad_VideoToolbox_kVTHEVCDecoderCapability_SupportedProfiles()
61         || !canLoad_VideoToolbox_kVTHEVCDecoderCapability_PerProfileSupport()
62         || !canLoad_VideoToolbox_kVTHEVCDecoderProfileCapability_IsHardwareAccelerated()
63         || !canLoad_VideoToolbox_kVTHEVCDecoderProfileCapability_MaxDecodeLevel()
64         || !canLoad_VideoToolbox_kVTHEVCDecoderProfileCapability_MaxPlaybackLevel())
65         return false;
66
67     RetainPtr<CFDictionaryRef> capabilities = adoptCF(VTCopyHEVCDecoderCapabilitiesDictionary());
68     if (!capabilities)
69         return false;
70
71     auto supportedProfiles = (CFArrayRef)CFDictionaryGetValue(capabilities.get(), kVTHEVCDecoderCapability_SupportedProfiles);
72     if (!supportedProfiles || CFGetTypeID(supportedProfiles) != CFArrayGetTypeID())
73         return false;
74
75     int16_t generalProfileIDC = parameters.generalProfileIDC;
76     auto cfGeneralProfileIDC = adoptCF(CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt16Type, &generalProfileIDC));
77     auto searchRange = CFRangeMake(0, CFArrayGetCount(supportedProfiles));
78     if (!CFArrayContainsValue(supportedProfiles, searchRange, cfGeneralProfileIDC.get()))
79         return false;
80
81     auto perProfileSupport = (CFDictionaryRef)CFDictionaryGetValue(capabilities.get(), kVTHEVCDecoderCapability_PerProfileSupport);
82     if (!perProfileSupport || CFGetTypeID(perProfileSupport) != CFDictionaryGetTypeID())
83         return false;
84
85     auto generalProfileIDCString = String::number(generalProfileIDC).createCFString();
86     auto profileSupport = (CFDictionaryRef)CFDictionaryGetValue(perProfileSupport, generalProfileIDCString.get());
87     if (!profileSupport || CFGetTypeID(profileSupport) != CFDictionaryGetTypeID())
88         return false;
89
90     auto isHardwareAccelerated = (CFBooleanRef)CFDictionaryGetValue(profileSupport, kVTHEVCDecoderProfileCapability_IsHardwareAccelerated);
91     if (isHardwareAccelerated && CFGetTypeID(isHardwareAccelerated) == CFBooleanGetTypeID())
92         info.powerEfficient = CFBooleanGetValue(isHardwareAccelerated);
93
94     auto cfMaxDecodeLevel = (CFNumberRef)CFDictionaryGetValue(profileSupport, kVTHEVCDecoderProfileCapability_MaxDecodeLevel);
95     if (cfMaxDecodeLevel && CFGetTypeID(cfMaxDecodeLevel) == CFNumberGetTypeID()) {
96         int16_t maxDecodeLevel = 0;
97         if (!CFNumberGetValue(cfMaxDecodeLevel, kCFNumberSInt16Type, &maxDecodeLevel))
98             return false;
99
100         if (parameters.generalLevelIDC > maxDecodeLevel)
101             return false;
102
103         info.supported = true;
104     }
105
106     auto cfMaxPlaybackLevel = (CFNumberRef)CFDictionaryGetValue(profileSupport, kVTHEVCDecoderProfileCapability_MaxPlaybackLevel);
107     if (cfMaxPlaybackLevel && CFGetTypeID(cfMaxPlaybackLevel) == CFNumberGetTypeID()) {
108         int16_t maxPlaybackLevel = 0;
109         if (!CFNumberGetValue(cfMaxPlaybackLevel, kCFNumberSInt16Type, &maxPlaybackLevel))
110             return false;
111
112         info.smooth = parameters.generalLevelIDC <= maxPlaybackLevel;
113     }
114
115     return true;
116 }
117
118 }
119
120 #endif // PLATFORM(COCOA)