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
28static 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
59static 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
86static 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
119static 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
170static 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
196static 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
229static 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
288static 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
329int32_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
381int32_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