1 /*
2  * Copyright (c) 2021-2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #define HST_LOG_TAG "Compatible_Check"
17 
18 #include "pipeline/core/compatible_check.h"
19 #include <algorithm>
20 #include <functional>
21 #include <map>
22 #include "foundation/log.h"
23 #include "plugin/common/plugin_attr_desc.h"
24 
25 namespace OHOS {
26 namespace Media {
27 namespace Pipeline {
28 static constexpr uint8_t ALLOW_FIXED = 1 << 0;
29 static constexpr uint8_t ALLOW_INTERVAL = 1 << 1;
30 static constexpr uint8_t ALLOW_DISCRETE = 1 << 2;
31 
IsFixedAllowed(uint8_t flags)32 static inline bool IsFixedAllowed(uint8_t flags)
33 {
34     return ALLOW_FIXED & flags;
35 }
36 
IsIntervalAllowed(uint8_t flags)37 static inline bool IsIntervalAllowed(uint8_t flags)
38 {
39     return ALLOW_INTERVAL & flags;
40 }
41 
IsDiscreteAllowed(uint8_t flags)42 static inline bool IsDiscreteAllowed(uint8_t flags)
43 {
44     return ALLOW_DISCRETE & flags;
45 }
46 
47 template<typename T>
48 bool CapabilityValueCheck(CapabilityID key, std::pair<const Plugin::ValueType&, const Plugin::ValueType&> inVals,
49                           uint8_t flags, std::function<int(T,T)> cmpFunc, Plugin::ValueType& outValue);
50 
51 template <typename T>
FixInvalDiscCapValCheck(CapabilityID key,const Plugin::ValueType & val1,const Plugin::ValueType & val2,Plugin::ValueType & outValue)52 bool FixInvalDiscCapValCheck(CapabilityID key, const Plugin::ValueType& val1, const Plugin::ValueType& val2,
53                              Plugin::ValueType& outValue)
54 {
55     return CapabilityValueCheck<T>(key, {val1, val2}, ALLOW_FIXED | ALLOW_INTERVAL | ALLOW_DISCRETE,
56         [](T a, T b) {
57         return a - b;
58         }, outValue);
59 }
60 
61 template <typename T, typename U>
FixDiscCapValCheck(CapabilityID key,const Plugin::ValueType & val1,const Plugin::ValueType & val2,Plugin::ValueType & outValue)62 bool FixDiscCapValCheck(CapabilityID key, const Plugin::ValueType& val1, const Plugin::ValueType& val2,
63                         Plugin::ValueType& outValue)
64 {
65     return CapabilityValueCheck<T>(key, {val1, val2}, ALLOW_FIXED | ALLOW_DISCRETE, [](T a, T b) {
66         return static_cast<U>(a) - static_cast<U>(b);
67     }, outValue);
68 }
69 
70 static std::vector<CapabilityID> g_allCapabilityId = {
71     CapabilityID::AUDIO_SAMPLE_RATE, // 0
72     CapabilityID::AUDIO_CHANNELS, // 1
73     CapabilityID::AUDIO_CHANNEL_LAYOUT, // 2
74     CapabilityID::AUDIO_SAMPLE_FORMAT, // 3
75     CapabilityID::AUDIO_MPEG_VERSION, // 4
76     CapabilityID::AUDIO_MPEG_LAYER, // 5
77     CapabilityID::AUDIO_AAC_PROFILE, // 6
78     CapabilityID::AUDIO_AAC_LEVEL, // 7
79     CapabilityID::AUDIO_AAC_STREAM_FORMAT, // 8
80     CapabilityID::VIDEO_PIXEL_FORMAT, // 9
81     CapabilityID::VIDEO_BIT_STREAM_FORMAT, // 10
82     CapabilityID::MEDIA_BITRATE, // 11
83 };
84 
85 template <typename T>
86 bool ExtractFixedCap(const Plugin::ValueType& value, Plugin::ValueType& fixedValue);
87 static std::map<CapabilityID, std::function<bool(const Plugin::ValueType&, Plugin::ValueType&)>> g_capExtrMap = {
88     {g_allCapabilityId[0], ExtractFixedCap<uint32_t>}, // 0
89     {g_allCapabilityId[1], ExtractFixedCap<uint32_t>}, // 1
90     {g_allCapabilityId[2], ExtractFixedCap<Plugin::AudioChannelLayout>}, // 2
91     {g_allCapabilityId[3], ExtractFixedCap<Plugin::AudioSampleFormat>}, // 3
92     {g_allCapabilityId[4], ExtractFixedCap<uint32_t>}, // 4
93     {g_allCapabilityId[5], ExtractFixedCap<uint32_t>}, // 5
94     {g_allCapabilityId[6], ExtractFixedCap<Plugin::AudioAacProfile>}, // 6
95     {g_allCapabilityId[7], ExtractFixedCap<uint32_t>}, // 7
96     {g_allCapabilityId[8], ExtractFixedCap<Plugin::AudioAacStreamFormat>}, // 8
97     {g_allCapabilityId[9], ExtractFixedCap<Plugin::VideoPixelFormat>}, // 9
98     {g_allCapabilityId[10], ExtractFixedCap<Plugin::VideoBitStreamFormat>}, // 10
99     {g_allCapabilityId[11], ExtractFixedCap<int64_t>}, // 11
100 };
101 using CheckFunc = std::function<bool(Capability::Key key, const Plugin::ValueType& val1, const Plugin::ValueType& val2,
102         Plugin::ValueType& outValue)>;
103 static std::map<CapabilityID, CheckFunc> g_capabilityValueCheckMap = {
104     {g_allCapabilityId[0], FixInvalDiscCapValCheck<uint32_t>}, // 0
105     {g_allCapabilityId[1], FixInvalDiscCapValCheck<uint32_t>}, // 1
106     {g_allCapabilityId[2], FixDiscCapValCheck<Plugin::AudioChannelLayout, uint64_t>}, // 2
107     {g_allCapabilityId[3], FixDiscCapValCheck<Plugin::AudioSampleFormat, uint8_t>}, // 3
108     {g_allCapabilityId[4], FixInvalDiscCapValCheck<uint32_t>}, // 4
109     {g_allCapabilityId[5], FixInvalDiscCapValCheck<uint32_t>}, // 5
110     {g_allCapabilityId[6], FixDiscCapValCheck<Plugin::AudioAacProfile, uint8_t>}, // 6
111     {g_allCapabilityId[7], FixInvalDiscCapValCheck<uint32_t>}, // 7
112     {g_allCapabilityId[8], FixDiscCapValCheck<Plugin::AudioAacStreamFormat, uint8_t>}, // 8
113     {g_allCapabilityId[9], FixDiscCapValCheck<Plugin::VideoPixelFormat, uint32_t>}, // 9
114     {g_allCapabilityId[10], FixDiscCapValCheck<Plugin::VideoBitStreamFormat, uint32_t>}, // 10
115     {g_allCapabilityId[11], FixInvalDiscCapValCheck<int64_t>}, // 11
116 };
117 
118 
StringEqIgnoreCase(const std::string & s1,const std::string & s2)119 static bool StringEqIgnoreCase(const std::string& s1, const std::string& s2)
120 {
121     if (s1.length() == s2.length()) {
122         return std::equal(s1.begin(), s1.end(), s2.begin(), [](char a, char b) { return tolower(a) == tolower(b); });
123     }
124     return false;
125 }
126 
IsSubsetMime(const std::string & subset,const std::string & universe)127 bool IsSubsetMime(const std::string& subset, const std::string& universe)
128 {
129     size_t devLinePosInMeta = subset.find_first_of('/');
130     if (devLinePosInMeta == 0 || devLinePosInMeta == std::string::npos) {
131         MEDIA_LOG_E("wrong format of subset mime, must be xx/xxx");
132         return false;
133     }
134 
135     if (universe == "*") {
136         return true;
137     }
138 
139     size_t devLinePosInCap = universe.find_first_of('/');
140     if (devLinePosInCap == 0 || devLinePosInCap == std::string::npos) {
141         MEDIA_LOG_E("wrong format of universe mime, must be * or xx/* or xx/xxx");
142         return false;
143     }
144 
145     // if media type is not the same, return false
146     if (!StringEqIgnoreCase(subset.substr(0, devLinePosInMeta), universe.substr(0, devLinePosInCap))) {
147         return false;
148     }
149     // if media type of capability is like audio/* video/* image/* etc. always return true
150     if (universe.substr(devLinePosInCap + 1) == "*") {
151         return true;
152     }
153     // left mime string compare
154     if (!StringEqIgnoreCase(universe.substr(devLinePosInCap + 1), subset.substr(devLinePosInMeta + 1))) {
155         return false;
156     }
157     return true;
158 }
159 
160 template <typename T>
Max(T val1,T val2,std::function<int (T,T)> compareFunc)161 T Max(T val1, T val2, std::function<int(T, T)> compareFunc)
162 {
163     if (compareFunc(val1, val2) >= 0) {
164         return val1;
165     }
166     return val2;
167 }
168 
169 template <typename T>
Min(T val1,T val2,std::function<int (T,T)> compareFunc)170 T Min(T val1, T val2, std::function<int(T, T)> compareFunc)
171 {
172     if (compareFunc(val1, val2) <= 0) {
173         return val1;
174     }
175     return val2;
176 }
177 
178 template <typename T>
FFCapabilityCheck(const Plugin::FixedCapability<T> & v1,const Plugin::FixedCapability<T> & v2,std::function<int (T,T)> & cmpFunc,Plugin::ValueType & outValue)179 bool FFCapabilityCheck(const Plugin::FixedCapability<T>& v1, const Plugin::FixedCapability<T>& v2,
180                        std::function<int(T,T)>& cmpFunc, Plugin::ValueType& outValue)
181 {
182     if (cmpFunc(v1, v2) == 0) {
183         outValue = v1;
184         return true;
185     }
186     return false;
187 }
188 
189 template <typename T>
FICapabilityCheck(const Plugin::FixedCapability<T> & v1,const Plugin::IntervalCapability<T> & v2,const std::function<int (T,T)> & cmpFunc,Plugin::ValueType & outValue)190 bool FICapabilityCheck(const Plugin::FixedCapability<T>& v1, const Plugin::IntervalCapability<T>& v2,
191                        const std::function<int(T,T)>& cmpFunc, Plugin::ValueType& outValue)
192 {
193     T max = Max(v2.first, v2.second, cmpFunc);
194     T min = Min(v2.first, v2.second, cmpFunc);
195     if (cmpFunc(v1, min) >= 0 && cmpFunc(v1, max) <= 0) {
196         outValue = v1;
197         return true;
198     }
199     return false;
200 }
201 
202 template <typename T>
FDCapabilityCheck(const Plugin::FixedCapability<T> & v1,const Plugin::DiscreteCapability<T> & v2,const std::function<int (T,T)> & cmpFunc,Plugin::ValueType & outValue)203 bool FDCapabilityCheck(const Plugin::FixedCapability<T>& v1, const Plugin::DiscreteCapability<T>& v2,
204                        const std::function<int(T,T)>& cmpFunc, Plugin::ValueType& outValue)
205 {
206     if (std::any_of(v2.begin(), v2.end(), [&v1, &cmpFunc](const T& tmp){return cmpFunc(tmp, v1) == 0;})) {
207         outValue = v1;
208         return true;
209     }
210     return false;
211 }
212 
213 template <typename T>
IICapabilityCheck(const Plugin::IntervalCapability<T> & v1,const Plugin::IntervalCapability<T> & v2,const std::function<int (T,T)> & cmpFunc,Plugin::ValueType & outValue)214 bool IICapabilityCheck(const Plugin::IntervalCapability<T>& v1, const Plugin::IntervalCapability<T>& v2,
215                        const std::function<int(T,T)>& cmpFunc, Plugin::ValueType& outValue)
216 {
217     T max1 = Max(v1.first, v1.second, cmpFunc);
218     T min1 = Min(v1.first, v1.second, cmpFunc);
219     T max2 = Max(v2.first, v2.second, cmpFunc);
220     T min2 = Min(v2.first, v2.second, cmpFunc);
221     T tmpMin = Max(min1, min2, cmpFunc);
222     T tmpMax = Min(max1, max2, cmpFunc);
223     auto compRes = cmpFunc(tmpMin, tmpMax);
224     if (compRes > 0) {
225         return false;
226     } else if (compRes == 0) {
227         outValue = Plugin::FixedCapability<T>(tmpMin);
228     } else {
229         outValue = Plugin::IntervalCapability<T>(tmpMin, tmpMax);
230     }
231     return true;
232 }
233 
234 template <typename T>
IDCapabilityCheck(const Plugin::IntervalCapability<T> & v1,const Plugin::DiscreteCapability<T> & v2,const std::function<int (T,T)> & cmpFunc,Plugin::ValueType & outValue)235 bool IDCapabilityCheck(const Plugin::IntervalCapability<T>& v1, const Plugin::DiscreteCapability<T>& v2,
236                        const std::function<int(T,T)>& cmpFunc, Plugin::ValueType& outValue)
237 {
238     Plugin::DiscreteCapability<T> tmpOut;
239     for (const auto& oneValue : v2) {
240         if (cmpFunc(oneValue, v1.first) >= 0 && cmpFunc(oneValue, v1.second) <= 0) {
241             tmpOut.emplace_back(oneValue);
242         }
243     }
244     if (tmpOut.empty()) {
245         return false;
246     }
247     if (tmpOut.size() == 1) {
248         outValue = Plugin::FixedCapability<T>(tmpOut[0]);
249     } else {
250         outValue = Plugin::DiscreteCapability<T>(tmpOut);
251     }
252     return true;
253 }
254 
255 template <typename T>
DDCapabilityCheck(const Plugin::DiscreteCapability<T> & v1,const Plugin::DiscreteCapability<T> & v2,const std::function<int (T,T)> & cmpFunc,Plugin::ValueType & outValue)256 bool DDCapabilityCheck(const Plugin::DiscreteCapability<T>& v1, const Plugin::DiscreteCapability<T>& v2,
257                        const std::function<int(T,T)>& cmpFunc, Plugin::ValueType& outValue)
258 {
259     Plugin::DiscreteCapability<T> tmpOut;
260     for (const auto& cap1 : v1) {
261         if (std::any_of(v2.begin(), v2.end(), [&cap1, &cmpFunc](const T& tmp){return cmpFunc(cap1, tmp) == 0;})) {
262             tmpOut.emplace_back(cap1);
263         }
264     }
265     if (tmpOut.empty()) {
266         return false;
267     }
268     if (tmpOut.size() == 1) {
269         outValue = Plugin::FixedCapability<T>(tmpOut[0]);
270     } else {
271         outValue = Plugin::DiscreteCapability<T>(tmpOut);
272     }
273     return true;
274 }
275 
LogOutIncorrectType(CapabilityID key,uint8_t flags)276 void LogOutIncorrectType(CapabilityID key, uint8_t flags)
277 {
278     if (Plugin::HasTagInfo(static_cast<Tag>(key))) {
279         const auto& tuple = Plugin::g_tagInfoMap.at(static_cast<Tag>(key));
280         const auto& typeName = std::get<2>(tuple); // secondary
281         MEDIA_LOG_E("type of " PUBLIC_LOG_S " should be"
282         " " PUBLIC_LOG_S "(" PUBLIC_LOG_C ")"
283         " or Interval<" PUBLIC_LOG_S ">(" PUBLIC_LOG_C ")"
284         " or Discrete<" PUBLIC_LOG_S ">(" PUBLIC_LOG_C ")",
285         std::get<0>(tuple),
286         typeName, IsFixedAllowed(flags)? 'o': 'x',
287         typeName, IsFixedAllowed(flags)? 'o': 'x',
288         typeName, IsFixedAllowed(flags)? 'o': 'x');
289     } else {
290         MEDIA_LOG_E("capability " PUBLIC_LOG_D32 "is not in the map, may be update the map?", key);
291     }
292 }
293 
294 template <typename T>
FixedNumericalCapabilityCheck(CapabilityID key,const T & value2,const Plugin::ValueType & value1,uint8_t flags,std::function<int (T,T)> cmpFunc,Plugin::ValueType & outValue)295 bool FixedNumericalCapabilityCheck(CapabilityID key, const T& value2, const Plugin::ValueType& value1,
296                                    uint8_t flags, std::function<int(T, T)> cmpFunc, Plugin::ValueType& outValue)
297 {
298     if (Plugin::Any::IsSameTypeWith<T>(value1)) {
299         return FFCapabilityCheck(value2, Plugin::AnyCast<T>(value1), cmpFunc, outValue);
300     }
301     if (IsIntervalAllowed(flags) && Plugin::Any::IsSameTypeWith<Plugin::IntervalCapability<T>>(value1)) {
302         return FICapabilityCheck(value2, Plugin::AnyCast<Plugin::IntervalCapability<T>>(value1), cmpFunc, outValue);
303     }
304     if (IsDiscreteAllowed(flags) && Plugin::Any::IsSameTypeWith<Plugin::DiscreteCapability<T>>(value1)) {
305         return FDCapabilityCheck(value2, Plugin::AnyCast<Plugin::DiscreteCapability<T>>(value1), cmpFunc, outValue);
306     }
307     LogOutIncorrectType(key, flags);
308     return false;
309 }
310 
311 template <typename T>
IntervalNumericalCapabilityCheck(CapabilityID key,const Plugin::IntervalCapability<T> & value2,const Plugin::ValueType & value1,uint8_t flags,std::function<int (T,T)> cmpFunc,Plugin::ValueType & outValue)312 bool IntervalNumericalCapabilityCheck(CapabilityID key, const Plugin::IntervalCapability<T>& value2,
313     const Plugin::ValueType& value1, uint8_t flags, std::function<int(T, T)> cmpFunc, Plugin::ValueType& outValue)
314 {
315     if (IsFixedAllowed(flags) && Plugin::Any::IsSameTypeWith<T>(value1)) {
316         return FICapabilityCheck(Plugin::AnyCast<T>(value1), value2, cmpFunc, outValue);
317     }
318     if (Plugin::Any::IsSameTypeWith<Plugin::IntervalCapability<T>>(value1)) {
319         return IICapabilityCheck(Plugin::AnyCast<Plugin::IntervalCapability<T>>(value1), value2, cmpFunc, outValue);
320     }
321     if (IsDiscreteAllowed(flags) && Plugin::Any::IsSameTypeWith<Plugin::DiscreteCapability<T>>(value1)) {
322         return IDCapabilityCheck(value2, Plugin::AnyCast<Plugin::DiscreteCapability<T>>(value1), cmpFunc, outValue);
323     }
324     LogOutIncorrectType(key, flags);
325     return false;
326 }
327 
328 template <typename T>
DiscreteNumericalCapabilityCheck(CapabilityID key,const Plugin::DiscreteCapability<T> & value2,const Plugin::ValueType & value1,uint8_t flags,std::function<int (T,T)> cmpFunc,Plugin::ValueType & outValue)329 bool DiscreteNumericalCapabilityCheck(CapabilityID key, const Plugin::DiscreteCapability<T>& value2,
330     const Plugin::ValueType& value1, uint8_t flags, std::function<int(T, T)> cmpFunc, Plugin::ValueType& outValue)
331 {
332     if (IsFixedAllowed(flags) && Plugin::Any::IsSameTypeWith<T>(value1)) {
333         return FDCapabilityCheck(Plugin::AnyCast<T>(value1), value2, cmpFunc, outValue);
334     }
335     if (IsIntervalAllowed(flags) && Plugin::Any::IsSameTypeWith<Plugin::IntervalCapability<T>>(value1)) {
336         return IDCapabilityCheck(Plugin::AnyCast<Plugin::IntervalCapability<T>>(value1), value2, cmpFunc, outValue);
337     }
338     if (Plugin::Any::IsSameTypeWith<Plugin::DiscreteCapability<T>>(value1)) {
339         return DDCapabilityCheck(Plugin::AnyCast<Plugin::DiscreteCapability<T>>(value1), value2, cmpFunc, outValue);
340     }
341     LogOutIncorrectType(key, flags);
342     return false;
343 }
344 
345 template<typename T>
CapabilityValueCheck(CapabilityID key,std::pair<const Plugin::ValueType &,const Plugin::ValueType &> inVals,uint8_t flags,std::function<int (T,T)> cmpFunc,Plugin::ValueType & outValue)346 bool CapabilityValueCheck(CapabilityID key, std::pair<const Plugin::ValueType&, const Plugin::ValueType&> inVals,
347                           uint8_t flags, std::function<int(T,T)> cmpFunc, Plugin::ValueType& outValue)
348 {
349     if (IsFixedAllowed(flags) && Plugin::Any::IsSameTypeWith<Plugin::FixedCapability<T>>(inVals.first)) {
350         return FixedNumericalCapabilityCheck<T>(key,
351             Plugin::AnyCast<Plugin::FixedCapability<T>>(inVals.first), inVals.second, flags, cmpFunc,outValue);
352     }
353     if (IsIntervalAllowed(flags) && Plugin::Any::IsSameTypeWith<Plugin::IntervalCapability<T>>(inVals.first)) {
354         return IntervalNumericalCapabilityCheck(key,
355             Plugin::AnyCast<Plugin::IntervalCapability<T>>(inVals.first), inVals.second, flags, cmpFunc, outValue);
356     }
357     if (IsDiscreteAllowed(flags) && Plugin::Any::IsSameTypeWith<Plugin::DiscreteCapability<T>>(inVals.first)) {
358         return DiscreteNumericalCapabilityCheck(key,
359             Plugin::AnyCast<Plugin::DiscreteCapability<T>>(inVals.first), inVals.second, flags, cmpFunc, outValue);
360     }
361     LogOutIncorrectType(key, flags);
362     return false;
363 }
364 
MergeCapabilityKeys(const Capability & originCap,const Capability & otherCap,Capability & resCap)365 bool MergeCapabilityKeys(const Capability& originCap, const Capability& otherCap, Capability& resCap)
366 {
367     resCap.keys.clear();
368     for (const auto& pairKey : originCap.keys) {
369         auto oIte = otherCap.keys.find(pairKey.first);
370         if (oIte == otherCap.keys.end()) {
371             // if key is not in otherCap, then put into resCap
372             resCap.keys.insert(pairKey);
373             continue;
374         }
375         // if key is in otherCap, calculate the intersections
376         if (g_capabilityValueCheckMap.count(pairKey.first) == 0) {
377             MEDIA_LOG_W("capability " PUBLIC_LOG_S " cannot be applied, may be update the check map?",
378                         Plugin::Tag2String(static_cast<Plugin::Tag>(pairKey.first)));
379             continue;
380         }
381         Plugin::ValueType tmp;
382         if (g_capabilityValueCheckMap.at(pairKey.first)(pairKey.first, pairKey.second, oIte->second, tmp)) {
383             resCap.keys[pairKey.first] = tmp;
384         } else {
385             //  if no intersections return false
386             resCap.keys.clear();
387             MEDIA_LOG_W("No intersections, originCap.mime: " PUBLIC_LOG_S ", tag: " PUBLIC_LOG_S,
388                         originCap.mime.c_str(), Plugin::Tag2String(static_cast<Plugin::Tag>(pairKey.first)));
389             return false;
390         }
391     }
392     // if key is otherCap but not in originCap, put into resCap
393     for (const auto& pairKey : otherCap.keys) {
394         if (resCap.keys.count(pairKey.first) == 0) {
395             resCap.keys.insert(pairKey);
396         }
397     }
398     return true;
399 }
400 
MergeCapability(const Capability & originCap,const Capability & otherCap,Capability & resCap)401 bool MergeCapability(const Capability& originCap, const Capability& otherCap, Capability& resCap)
402 {
403     resCap.mime.clear();
404     resCap.keys.clear();
405     if (!IsSubsetMime(originCap.mime, otherCap.mime)) {
406         return false;
407     }
408     if (!MergeCapabilityKeys(originCap, otherCap, resCap)) {
409         return false;
410     }
411     resCap.mime = originCap.mime;
412     return true;
413 }
414 
ApplyCapabilitySet(const Capability & originCap,const CapabilitySet & capabilitySet,Capability & resCap)415 bool ApplyCapabilitySet(const Capability& originCap, const CapabilitySet& capabilitySet, Capability& resCap)
416 {
417     Capability tmp;
418     for (const auto& cap : capabilitySet) {
419         if (MergeCapability(originCap, cap, resCap)) {
420             return true;
421         }
422     }
423     return false;
424 }
425 
426 template <typename T>
ExtractFixedCap(const Plugin::ValueType & value,Plugin::ValueType & fixedValue)427 bool ExtractFixedCap(const Plugin::ValueType& value, Plugin::ValueType& fixedValue)
428 {
429     if (Plugin::Any::IsSameTypeWith<Plugin::FixedCapability<T>>(value)) {
430         fixedValue = Plugin::AnyCast<Plugin::FixedCapability<T>>(value);
431         return true;
432     } else if (Plugin::Any::IsSameTypeWith<Plugin::IntervalCapability<T>>(value)) {
433         auto tmp = Plugin::AnyCast<Plugin::IntervalCapability<T>>(value);
434         fixedValue = tmp.first;
435         return true;
436     } else if (Plugin::Any::IsSameTypeWith<Plugin::DiscreteCapability<T>>(value)) {
437         auto tmp = Plugin::AnyCast<Plugin::DiscreteCapability<T>>(value);
438         if (!tmp.empty()) {
439             fixedValue = tmp[0];
440             return true;
441         }
442     }
443     return false;
444 }
445 
MetaToCapability(const Plugin::Meta & meta)446 std::shared_ptr<Capability> MetaToCapability(const Plugin::Meta& meta)
447 {
448     auto ret = std::make_shared<Capability>();
449     std::string mime;
450     if (meta.Get<Plugin::Tag::MIME>(mime)) {
451         ret->mime = mime;
452     }
453     for (const auto& key : g_allCapabilityId) {
454         Plugin::ValueType tmp;
455         if (meta.GetData(static_cast<Plugin::Tag>(key), tmp)) {
456             ret->keys[key] = tmp;
457         }
458     }
459     return ret;
460 }
461 
MergeMetaWithCapability(const Plugin::Meta & meta,const Capability & cap,Plugin::Meta & resMeta)462 bool MergeMetaWithCapability(const Plugin::Meta& meta, const Capability& cap, Plugin::Meta& resMeta)
463 {
464     resMeta.Clear();
465     // change meta into capability firstly
466     Capability metaCap;
467     metaCap.mime = cap.mime;
468     for (const auto& key : g_allCapabilityId) {
469         Plugin::ValueType tmp;
470         if (meta.GetData(static_cast<Plugin::Tag>(key), tmp)) {
471             metaCap.keys[key] = tmp;
472         }
473     }
474     Capability resCap;
475     if (!MergeCapability(metaCap, cap, resCap)) {
476         return false;
477     }
478     // merge capability
479     resMeta = meta;
480     resMeta.Set<Plugin::Tag::MIME>(cap.mime);
481     for (const auto& oneCap : resCap.keys) {
482         if (g_capExtrMap.count(oneCap.first) == 0) {
483             continue;
484         }
485         auto func = g_capExtrMap[oneCap.first];
486         Plugin::ValueType tmp;
487         if (func(oneCap.second, tmp)) {
488             resMeta.SetData(static_cast<Plugin::Tag>(oneCap.first), tmp);
489         }
490     }
491     return true;
492 }
493 } // namespace Pipeline
494 } // namespace Media
495 } // namespace OHOS
496