1 /*
2  * Copyright (c) 2022-2023 Shenzhen Kaihong DID 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 #include "codec_config_parser.h"
17 #include <osal_mem.h>
18 #include <securec.h>
19 #include <OMX_IVCommon.h>
20 #include "codec_log_wrapper.h"
21 
22 #ifdef __ARCH64__
23 #define MASK_NUM_LIMIT  64
24 #else
25 #define MASK_NUM_LIMIT  32
26 #endif
27 
GetGroupCapabilitiesNumber(const struct DeviceResourceNode * node,const char * nodeName,int32_t * num)28 static int32_t GetGroupCapabilitiesNumber(const struct DeviceResourceNode *node,
29     const char *nodeName, int32_t *num)
30 {
31     if (node == NULL || nodeName == NULL || num == NULL) {
32         CODEC_LOGE("failed for codec %{public}s, invalid param!", nodeName);
33         return HDF_ERR_INVALID_PARAM;
34     }
35 
36     int32_t result = 0;
37     *num = result;
38     const struct DeviceResourceNode *codecGroupNode = NULL;
39     struct DeviceResourceNode *childNode = NULL;
40     struct DeviceResourceIface *iface = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
41     if (iface == NULL) {
42         CODEC_LOGE("failed, iface NULL!");
43         return HDF_FAILURE;
44     }
45 
46     codecGroupNode = iface->GetChildNode(node, nodeName);
47     if (codecGroupNode == NULL) {
48         CODEC_LOGE("failed to get child node %{public}s!", nodeName);
49         return HDF_FAILURE;
50     }
51     DEV_RES_NODE_FOR_EACH_CHILD_NODE(codecGroupNode, childNode) {
52         result++;
53     }
54     *num = result;
55 
56     return HDF_SUCCESS;
57 }
58 
GetUintTableConfig(const struct DeviceResourceIface * iface,const struct DeviceResourceNode * node,ConfigUintArrayNodeAttr * attr)59 static int32_t GetUintTableConfig(const struct DeviceResourceIface *iface,
60     const struct DeviceResourceNode *node, ConfigUintArrayNodeAttr *attr)
61 {
62     if (iface == NULL || node == NULL || attr == NULL) {
63         CODEC_LOGE("invalid param!");
64         return HDF_ERR_INVALID_PARAM;
65     }
66     if (attr->array == NULL || attr->attrName == NULL) {
67         CODEC_LOGE("invalid attr!");
68         return HDF_ERR_INVALID_PARAM;
69     }
70 
71     int32_t count = iface->GetElemNum(node, attr->attrName);
72     if (count < 0 || count >= attr->length) {
73         CODEC_LOGE("%{public}s table size: %{public}d incorrect or exceed max size %{public}d!", attr->attrName,
74             count, attr->length - 1);
75         return HDF_FAILURE;
76     }
77 
78     if (count > 0) {
79         iface->GetUint32Array(node, attr->attrName, (uint32_t *)attr->array, count, 0);
80     }
81     attr->array[count] = attr->endValue;
82 
83     return HDF_SUCCESS;
84 }
85 
GetMaskedConfig(const struct DeviceResourceIface * iface,const struct DeviceResourceNode * node,const char * attrName,uint32_t * mask)86 static int32_t GetMaskedConfig(const struct DeviceResourceIface *iface,
87     const struct DeviceResourceNode *node, const char *attrName, uint32_t *mask)
88 {
89     if (iface == NULL || node == NULL || attrName == NULL || mask == NULL) {
90         CODEC_LOGE("invalid param!");
91         return HDF_ERR_INVALID_PARAM;
92     }
93 
94     uint32_t *values = NULL;
95     int32_t count = iface->GetElemNum(node, attrName);
96 
97     *mask = 0;
98     if (count < 0 || count > MASK_NUM_LIMIT) {
99         CODEC_LOGE("count %{public}d incorrect!", count);
100         return HDF_FAILURE;
101     }
102 
103     if (count > 0) {
104         values = (uint32_t *)OsalMemAlloc(sizeof(uint32_t) * count);
105         if (values == NULL) {
106             CODEC_LOGE("failed to allocate mem for %{public}s!", attrName);
107             return HDF_FAILURE;
108         }
109         iface->GetUint32Array(node, attrName, values, count, 0);
110         for (int32_t index = 0; index < count; index++) {
111             *mask |= values[index];
112         }
113         OsalMemFree(values);
114     }
115 
116     return HDF_SUCCESS;
117 }
118 
GetVideoPortCapability(const struct DeviceResourceIface * iface,const struct DeviceResourceNode * childNode,CodecCompCapability * cap)119 static int32_t GetVideoPortCapability(const struct DeviceResourceIface *iface,
120     const struct DeviceResourceNode *childNode, CodecCompCapability *cap)
121 {
122     if (iface == NULL || childNode == NULL || cap == NULL) {
123         CODEC_LOGE("invalid param!");
124         return HDF_ERR_INVALID_PARAM;
125     }
126 
127     ConfigUintNodeAttr nodeAttrs[] = {
128         {CODEC_CONFIG_KEY_MIN_WIDTH,             (uint32_t*)&cap->port.video.minSize.width,               0},
129         {CODEC_CONFIG_KEY_MIN_HEIGHT,            (uint32_t*)&cap->port.video.minSize.height,              0},
130         {CODEC_CONFIG_KEY_MAX_WIDTH,             (uint32_t*)&cap->port.video.maxSize.width,               0},
131         {CODEC_CONFIG_KEY_MAX_HEIGHT,            (uint32_t*)&cap->port.video.maxSize.height,              0},
132         {CODEC_CONFIG_KEY_WIDTH_ALIGNMENT,       (uint32_t*)&cap->port.video.whAlignment.widthAlignment,  0},
133         {CODEC_CONFIG_KEY_HEIGHT_ALIGNMENT,      (uint32_t*)&cap->port.video.whAlignment.heightAlignment, 0},
134         {CODEC_CONFIG_KEY_MIN_BLOCK_COUNT,       (uint32_t*)&cap->port.video.blockCount.min,              0},
135         {CODEC_CONFIG_KEY_MAX_BLOCK_COUNT,       (uint32_t*)&cap->port.video.blockCount.max,              0},
136         {CODEC_CONFIG_KEY_MIN_BLOCKS_PER_SECOND, (uint32_t*)&cap->port.video.blocksPerSecond.min,         0},
137         {CODEC_CONFIG_KEY_MAX_BLOCKS_PER_SECOND, (uint32_t*)&cap->port.video.blocksPerSecond.max,         0},
138         {CODEC_CONFIG_KEY_BLOCK_SIZE_WIDTH,      (uint32_t*)&cap->port.video.blockSize.width,             0},
139         {CODEC_CONFIG_KEY_BLOCK_SIZE_HEIGHT,     (uint32_t*)&cap->port.video.blockSize.height,            0},
140         {CODEC_CONFIG_KEY_MIN_FRAME_RATE,        (uint32_t *)&cap->port.video.frameRate.min,              0},
141         {CODEC_CONFIG_KEY_MAX_FRAME_RATE,        (uint32_t *)&cap->port.video.frameRate.max,              0}
142     };
143 
144     int32_t count = sizeof(nodeAttrs) / sizeof(ConfigUintNodeAttr);
145     for (int32_t i = 0; i < count; i++) {
146         if (iface->GetUint32(childNode, nodeAttrs[i].attrName, nodeAttrs[i].valueAddr,
147             nodeAttrs[i].defaultValue) != HDF_SUCCESS) {
148             CODEC_LOGE("failed to get %{public}s.%{public}s!", childNode->name, nodeAttrs[i].attrName);
149             return HDF_FAILURE;
150         }
151     }
152 
153     ConfigUintArrayNodeAttr arrayAttrs[] = {
154         {CODEC_CONFIG_KEY_SUPPORT_PIXEL_FMTS, cap->port.video.supportPixFmts, PIX_FORMAT_NUM, OMX_COLOR_FormatUnused},
155         {CODEC_CONFIG_KEY_BITE_RATE_MODE, (int32_t *)cap->port.video.bitRatemode, BIT_RATE_MODE_NUM,
156          BIT_RATE_MODE_INVALID},
157         {CODEC_CONFIG_KEY_MESURED_FRAME_RATE, cap->port.video.measuredFrameRate, MEASURED_FRAME_RATE_NUM, 0}
158     };
159 
160     count = sizeof(arrayAttrs) / sizeof(ConfigUintArrayNodeAttr);
161     for (int32_t i = 0; i < count; i++) {
162         if (GetUintTableConfig(iface, childNode, &arrayAttrs[i]) != HDF_SUCCESS) {
163             CODEC_LOGE("failed to get %{public}s.%{public}s!", childNode->name, nodeAttrs[i].attrName);
164             return HDF_FAILURE;
165         }
166     }
167     return HDF_SUCCESS;
168 }
169 
GetAudioPortCapability(const struct DeviceResourceIface * iface,const struct DeviceResourceNode * childNode,CodecCompCapability * cap)170 static int32_t GetAudioPortCapability(const struct DeviceResourceIface *iface,
171     const struct DeviceResourceNode *childNode, CodecCompCapability *cap)
172 {
173     if (iface == NULL || childNode == NULL || cap == NULL) {
174         CODEC_LOGE("invalid param!");
175         return HDF_ERR_INVALID_PARAM;
176     }
177 
178     ConfigUintArrayNodeAttr arrayAttrs[] = {
179         {CODEC_CONFIG_KEY_SAMPLE_FORMATS,  cap->port.audio.sampleFormats,  SAMPLE_FMT_NUM,  AUDIO_SAMPLE_FMT_INVALID},
180         {CODEC_CONFIG_KEY_SAMPLE_RATE,     cap->port.audio.sampleRate,     SAMPLE_RATE_NUM, AUD_SAMPLE_RATE_INVALID},
181         {CODEC_CONFIG_KEY_CHANNEL_LAYOUTS, cap->port.audio.channelLayouts, CHANNEL_NUM,     -1},
182         {CODEC_CONFIG_KEY_CHANNEL_COUNT,   cap->port.audio.channelCount,   CHANNEL_NUM,     -1}
183     };
184 
185     int32_t count = sizeof(arrayAttrs) / sizeof(ConfigUintArrayNodeAttr);
186     for (int32_t i = 0; i < count; i++) {
187         if (GetUintTableConfig(iface, childNode, &arrayAttrs[i]) != HDF_SUCCESS) {
188             CODEC_LOGE("failed to get %{public}s.%{public}s!", childNode->name, arrayAttrs[i].attrName);
189             return HDF_FAILURE;
190         }
191     }
192 
193     return HDF_SUCCESS;
194 }
195 
GetMiscOfCapability(const struct DeviceResourceIface * iface,const struct DeviceResourceNode * childNode,CodecCompCapability * cap)196 static int32_t GetMiscOfCapability(const struct DeviceResourceIface *iface,
197     const struct DeviceResourceNode *childNode, CodecCompCapability *cap)
198 {
199     if (iface == NULL || childNode == NULL || cap == NULL) {
200         CODEC_LOGE("invalid param!");
201         return HDF_ERR_INVALID_PARAM;
202     }
203 
204     ConfigUintArrayNodeAttr attr = {CODEC_CONFIG_KEY_SUPPORT_PROFILES,
205         cap->supportProfiles, PROFILE_NUM, INVALID_PROFILE};
206     if (GetUintTableConfig(iface, childNode, &attr) != HDF_SUCCESS) {
207         return HDF_FAILURE;
208     }
209     if (iface->GetUint32(childNode, CODEC_CONFIG_KEY_MAX_INST, (uint32_t*)&cap->maxInst, 0) != HDF_SUCCESS) {
210         return HDF_FAILURE;
211     }
212     if (GetMaskedConfig(iface, childNode, CODEC_CONFIG_KEY_PROCESS_MODE_MASK,
213         (uint32_t *)&cap->processModeMask) != HDF_SUCCESS) {
214         return HDF_FAILURE;
215     }
216     if (GetMaskedConfig(iface, childNode, CODEC_CONFIG_KEY_CAPS_MASK, &cap->capsMask) != HDF_SUCCESS) {
217         return HDF_FAILURE;
218     }
219     if (iface->GetUint32(childNode, CODEC_CONFIG_KEY_MIN_BITRATE, (uint32_t*)&(cap->bitRate.min), 0) != HDF_SUCCESS) {
220         return HDF_FAILURE;
221     }
222     if (iface->GetUint32(childNode, CODEC_CONFIG_KEY_MAX_BITRATE, (uint32_t*)&(cap->bitRate.max), 0) != HDF_SUCCESS) {
223         return HDF_FAILURE;
224     }
225 
226     return HDF_SUCCESS;
227 }
228 
GetOneCapability(const struct DeviceResourceIface * iface,const struct DeviceResourceNode * childNode,CodecCompCapability * cap,bool isVideoGroup)229 static int32_t GetOneCapability(const struct DeviceResourceIface *iface,
230     const struct DeviceResourceNode *childNode, CodecCompCapability *cap, bool isVideoGroup)
231 {
232     if (iface == NULL || childNode == NULL || cap == NULL) {
233         CODEC_LOGE("invalid param!");
234         return HDF_ERR_INVALID_PARAM;
235     }
236 
237     if (iface->GetUint32(childNode, CODEC_CONFIG_KEY_ROLE,
238         (uint32_t*)&cap->role, MEDIA_ROLETYPE_INVALID) != HDF_SUCCESS) {
239         cap->role = MEDIA_ROLETYPE_INVALID;
240         CODEC_LOGE("failed to get mime for: %{public}s! Discarded", childNode->name);
241         return HDF_FAILURE;
242     }
243 
244     if (iface->GetUint32(childNode, CODEC_CONFIG_KEY_TYPE, (uint32_t*)&cap->type, INVALID_TYPE) != HDF_SUCCESS) {
245         cap->role = MEDIA_ROLETYPE_INVALID;
246         cap->type = INVALID_TYPE;
247         CODEC_LOGE("failed to get type for: %{public}s! Discarded", childNode->name);
248         return HDF_FAILURE;
249     }
250 
251     const char *compName = NULL;
252     if (iface->GetString(childNode, CODEC_CONFIG_KEY_NAME, &compName, "") != HDF_SUCCESS) {
253         cap->role = MEDIA_ROLETYPE_INVALID;
254         return HDF_FAILURE;
255     }
256     if (compName == NULL || strlen(compName) >= NAME_LENGTH || strlen(compName) == 0) {
257         cap->role = MEDIA_ROLETYPE_INVALID;
258         return HDF_FAILURE;
259     }
260     int32_t ret = strcpy_s(cap->compName, NAME_LENGTH, compName);
261     if (ret != EOK) {
262         CODEC_LOGE("strcpy_s is failed, error code: %{public}d!", ret);
263         return HDF_FAILURE;
264     }
265     cap->isSoftwareCodec = iface->GetBool(childNode, CODEC_CONFIG_KEY_IS_SOFTWARE_CODEC);
266     cap->canSwapWidthHeight = iface->GetBool(childNode, CODEC_CONFIG_KEY_CAN_SWAP_WIDTH_HEIGHT);
267 
268     if (GetMiscOfCapability(iface, childNode, cap) != HDF_SUCCESS) {
269         cap->role = MEDIA_ROLETYPE_INVALID;
270         return HDF_FAILURE;
271     }
272 
273     if (isVideoGroup) {
274         if (GetVideoPortCapability(iface, childNode, cap) != HDF_SUCCESS) {
275             cap->role = MEDIA_ROLETYPE_INVALID;
276             return HDF_FAILURE;
277         }
278     } else {
279         if (GetAudioPortCapability(iface, childNode, cap) != HDF_SUCCESS) {
280             cap->role = MEDIA_ROLETYPE_INVALID;
281             return HDF_FAILURE;
282         }
283     }
284 
285     return HDF_SUCCESS;
286 }
287 
GetGroupCapabilities(const struct DeviceResourceNode * node,const char * nodeName,CodecCapablityGroup * capsGroup)288 static int32_t GetGroupCapabilities(const struct DeviceResourceNode *node,
289     const char *nodeName, CodecCapablityGroup *capsGroup)
290 {
291     if (node == NULL || nodeName == NULL || capsGroup == NULL) {
292         CODEC_LOGE("invalid param!");
293         return HDF_ERR_INVALID_PARAM;
294     }
295 
296     CodecCompCapability *cap = NULL;
297     int32_t index = 0;
298     bool isVideoGroup = true;
299     const struct DeviceResourceNode *codecGroupNode = NULL;
300     struct DeviceResourceNode *childNode = NULL;
301     struct DeviceResourceIface *iface = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
302     if (iface == NULL) {
303         CODEC_LOGE("iface NULL!");
304         return HDF_ERR_INVALID_PARAM;
305     }
306 
307     codecGroupNode = iface->GetChildNode(node, nodeName);
308     if (codecGroupNode == NULL) {
309         CODEC_LOGE("failed to get child node: %{public}s!", nodeName);
310         return HDF_FAILURE;
311     }
312 
313     if (strstr(nodeName, "Video") == NULL) {
314         isVideoGroup = false;
315     }
316     DEV_RES_NODE_FOR_EACH_CHILD_NODE(codecGroupNode, childNode) {
317         cap = &(capsGroup->capablitis[index++]);
318         if (cap == NULL) {
319             continue;
320         }
321         if (GetOneCapability(iface, childNode, cap, isVideoGroup) != HDF_SUCCESS) {
322             CODEC_LOGE("GetOneCapability failed, role is %{public}d!", cap->role);
323         }
324     }
325 
326     return HDF_SUCCESS;
327 }
328 
LoadCodecCapabilityFromHcs(const struct DeviceResourceNode * node,CodecCapablites * caps)329 int32_t LoadCodecCapabilityFromHcs(const struct DeviceResourceNode *node, CodecCapablites *caps)
330 {
331     if (node == NULL || caps == NULL) {
332         CODEC_LOGE("invalid param!");
333         return HDF_ERR_INVALID_PARAM;
334     }
335     CodecCapablityGroup *codecCapGroup = NULL;
336     int32_t index;
337     int32_t codecNum = 0;
338 
339     char *codecGroupsNodeName[] = {
340         NODE_VIDEO_HARDWARE_ENCODERS, NODE_VIDEO_HARDWARE_DECODERS, NODE_VIDEO_SOFTWARE_ENCODERS,
341         NODE_VIDEO_SOFTWARE_DECODERS, NODE_AUDIO_HARDWARE_ENCODERS, NODE_AUDIO_HARDWARE_DECODERS,
342         NODE_AUDIO_SOFTWARE_ENCODERS, NODE_AUDIO_SOFTWARE_DECODERS
343     };
344     CodecCapablityGroup *codecCapGroups[] = {
345         &(caps->videoHwEncoderGroup), &(caps->videoHwDecoderGroup),
346         &(caps->videoSwEncoderGroup), &(caps->videoSwDecoderGroup),
347         &(caps->audioHwEncoderGroup), &(caps->audioHwDecoderGroup),
348         &(caps->audioSwEncoderGroup), &(caps->audioSwDecoderGroup)
349     };
350 
351     for (index = 0; index < CODEC_CAPABLITY_GROUP_NUM; index++) {
352         if (GetGroupCapabilitiesNumber(node, codecGroupsNodeName[index], &codecNum) == HDF_SUCCESS) {
353             codecCapGroup = codecCapGroups[index];
354             if (codecNum > 0) {
355                 codecCapGroup->num = codecNum;
356                 codecCapGroup->capablitis
357                     = (CodecCompCapability *)OsalMemAlloc(sizeof(CodecCompCapability) * codecNum);
358             } else {
359                 codecCapGroup->capablitis = NULL;
360                 codecCapGroup->num = 0;
361             }
362             if (codecNum > 0 && codecCapGroup->capablitis == NULL) {
363                 codecCapGroup->num = 0;
364                 CODEC_LOGE("MemAlloc for capability group failed!");
365                 return HDF_FAILURE;
366             }
367             caps->total += codecCapGroup->num;
368         }
369     }
370 
371     for (index = 0; index < CODEC_CAPABLITY_GROUP_NUM; index++) {
372         if (GetGroupCapabilities(node, codecGroupsNodeName[index], codecCapGroups[index]) != HDF_SUCCESS) {
373             CODEC_LOGE("GetGroupCapabilities failed index: %{public}d!", index);
374             return HDF_FAILURE;
375         }
376     }
377     caps->inited = true;
378     return HDF_SUCCESS;
379 }
380 
ClearCapabilityGroup(CodecCapablites * caps)381 int32_t ClearCapabilityGroup(CodecCapablites *caps)
382 {
383     if (caps == NULL) {
384         CODEC_LOGE("invalid param!");
385         return HDF_ERR_INVALID_PARAM;
386     }
387 
388     int32_t index;
389     CodecCapablityGroup *codecCapGroup = NULL;
390     CodecCapablityGroup *codecCapGroups[] = {
391         &(caps->videoHwEncoderGroup), &(caps->videoHwDecoderGroup),
392         &(caps->videoSwEncoderGroup), &(caps->videoSwDecoderGroup),
393         &(caps->audioHwEncoderGroup), &(caps->audioHwDecoderGroup),
394         &(caps->audioSwEncoderGroup), &(caps->audioSwDecoderGroup)
395     };
396     for (index = 0; index < CODEC_CAPABLITY_GROUP_NUM; index++) {
397         codecCapGroup = codecCapGroups[index];
398         if (codecCapGroup->capablitis != NULL) {
399             OsalMemFree(codecCapGroup->capablitis);
400             codecCapGroup->num = 0;
401             codecCapGroup->capablitis = NULL;
402         }
403     }
404     caps->inited = false;
405     caps->total = 0;
406     return HDF_SUCCESS;
407 }
408