Create AVFoundationSoftLink.{h,mm} to reduce duplicate code
[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 #import "config.h"
27 #import "HEVCUtilitiesCocoa.h"
28
29 #if PLATFORM(COCOA)
30
31 #import "FourCC.h"
32 #import "HEVCUtilities.h"
33 #import "MediaCapabilitiesInfo.h"
34
35 #import "VideoToolboxSoftLink.h"
36 #import <pal/cocoa/AVFoundationSoftLink.h>
37
38 namespace WebCore {
39
40 bool validateHEVCParameters(HEVCParameterSet& parameters, MediaCapabilitiesInfo& info, bool hasAlphaChannel)
41 {
42     CMVideoCodecType codec = kCMVideoCodecType_HEVC;
43     if (hasAlphaChannel) {
44         if (!PAL::AVFoundationLibrary() || !PAL::canLoad_AVFoundation_AVVideoCodecTypeHEVCWithAlpha())
45             return false;
46
47         auto codecCode = FourCC::fromString(AVVideoCodecTypeHEVCWithAlpha);
48         if (!codecCode)
49             return false;
50
51         codec = codecCode.value().value;
52     }
53     OSStatus status = VTSelectAndCreateVideoDecoderInstance(codec, kCFAllocatorDefault, nullptr, nullptr);
54     if (status != noErr)
55         return false;
56
57     if (!canLoad_VideoToolbox_VTCopyHEVCDecoderCapabilitiesDictionary()
58         || !canLoad_VideoToolbox_kVTHEVCDecoderCapability_SupportedProfiles()
59         || !canLoad_VideoToolbox_kVTHEVCDecoderCapability_PerProfileSupport()
60         || !canLoad_VideoToolbox_kVTHEVCDecoderProfileCapability_IsHardwareAccelerated()
61         || !canLoad_VideoToolbox_kVTHEVCDecoderProfileCapability_MaxDecodeLevel()
62         || !canLoad_VideoToolbox_kVTHEVCDecoderProfileCapability_MaxPlaybackLevel())
63         return false;
64
65     RetainPtr<CFDictionaryRef> capabilities = adoptCF(VTCopyHEVCDecoderCapabilitiesDictionary());
66     if (!capabilities)
67         return false;
68
69     auto supportedProfiles = (CFArrayRef)CFDictionaryGetValue(capabilities.get(), kVTHEVCDecoderCapability_SupportedProfiles);
70     if (!supportedProfiles || CFGetTypeID(supportedProfiles) != CFArrayGetTypeID())
71         return false;
72
73     int16_t generalProfileIDC = parameters.generalProfileIDC;
74     auto cfGeneralProfileIDC = adoptCF(CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt16Type, &generalProfileIDC));
75     auto searchRange = CFRangeMake(0, CFArrayGetCount(supportedProfiles));
76     if (!CFArrayContainsValue(supportedProfiles, searchRange, cfGeneralProfileIDC.get()))
77         return false;
78
79     auto perProfileSupport = (CFDictionaryRef)CFDictionaryGetValue(capabilities.get(), kVTHEVCDecoderCapability_PerProfileSupport);
80     if (!perProfileSupport || CFGetTypeID(perProfileSupport) != CFDictionaryGetTypeID())
81         return false;
82
83     auto generalProfileIDCString = String::number(generalProfileIDC).createCFString();
84     auto profileSupport = (CFDictionaryRef)CFDictionaryGetValue(perProfileSupport, generalProfileIDCString.get());
85     if (!profileSupport || CFGetTypeID(profileSupport) != CFDictionaryGetTypeID())
86         return false;
87
88     auto isHardwareAccelerated = (CFBooleanRef)CFDictionaryGetValue(profileSupport, kVTHEVCDecoderProfileCapability_IsHardwareAccelerated);
89     if (isHardwareAccelerated && CFGetTypeID(isHardwareAccelerated) == CFBooleanGetTypeID())
90         info.powerEfficient = CFBooleanGetValue(isHardwareAccelerated);
91
92     auto cfMaxDecodeLevel = (CFNumberRef)CFDictionaryGetValue(profileSupport, kVTHEVCDecoderProfileCapability_MaxDecodeLevel);
93     if (cfMaxDecodeLevel && CFGetTypeID(cfMaxDecodeLevel) == CFNumberGetTypeID()) {
94         int16_t maxDecodeLevel = 0;
95         if (!CFNumberGetValue(cfMaxDecodeLevel, kCFNumberSInt16Type, &maxDecodeLevel))
96             return false;
97
98         if (parameters.generalLevelIDC > maxDecodeLevel)
99             return false;
100
101         info.supported = true;
102     }
103
104     auto cfMaxPlaybackLevel = (CFNumberRef)CFDictionaryGetValue(profileSupport, kVTHEVCDecoderProfileCapability_MaxPlaybackLevel);
105     if (cfMaxPlaybackLevel && CFGetTypeID(cfMaxPlaybackLevel) == CFNumberGetTypeID()) {
106         int16_t maxPlaybackLevel = 0;
107         if (!CFNumberGetValue(cfMaxPlaybackLevel, kCFNumberSInt16Type, &maxPlaybackLevel))
108             return false;
109
110         info.smooth = parameters.generalLevelIDC <= maxPlaybackLevel;
111     }
112
113     return true;
114 }
115
116 }
117
118 #endif // PLATFORM(COCOA)