1094332d3Sopenharmony_ci/*
2094332d3Sopenharmony_ci * Copyright (c) 2022-2023 Shenzhen Kaihong DID Co., Ltd.
3094332d3Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4094332d3Sopenharmony_ci * you may not use this file except in compliance with the License.
5094332d3Sopenharmony_ci * You may obtain a copy of the License at
6094332d3Sopenharmony_ci *
7094332d3Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8094332d3Sopenharmony_ci *
9094332d3Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10094332d3Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11094332d3Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12094332d3Sopenharmony_ci * See the License for the specific language governing permissions and
13094332d3Sopenharmony_ci * limitations under the License.
14094332d3Sopenharmony_ci */
15094332d3Sopenharmony_ci
16094332d3Sopenharmony_ci#include "codec_config_parser.h"
17094332d3Sopenharmony_ci#include <osal_mem.h>
18094332d3Sopenharmony_ci#include <securec.h>
19094332d3Sopenharmony_ci#include <OMX_IVCommon.h>
20094332d3Sopenharmony_ci#include "codec_log_wrapper.h"
21094332d3Sopenharmony_ci
22094332d3Sopenharmony_ci#ifdef __ARCH64__
23094332d3Sopenharmony_ci#define MASK_NUM_LIMIT  64
24094332d3Sopenharmony_ci#else
25094332d3Sopenharmony_ci#define MASK_NUM_LIMIT  32
26094332d3Sopenharmony_ci#endif
27094332d3Sopenharmony_ci
28094332d3Sopenharmony_cistatic int32_t GetGroupCapabilitiesNumber(const struct DeviceResourceNode *node,
29094332d3Sopenharmony_ci    const char *nodeName, int32_t *num)
30094332d3Sopenharmony_ci{
31094332d3Sopenharmony_ci    if (node == NULL || nodeName == NULL || num == NULL) {
32094332d3Sopenharmony_ci        CODEC_LOGE("failed for codec %{public}s, invalid param!", nodeName);
33094332d3Sopenharmony_ci        return HDF_ERR_INVALID_PARAM;
34094332d3Sopenharmony_ci    }
35094332d3Sopenharmony_ci
36094332d3Sopenharmony_ci    int32_t result = 0;
37094332d3Sopenharmony_ci    *num = result;
38094332d3Sopenharmony_ci    const struct DeviceResourceNode *codecGroupNode = NULL;
39094332d3Sopenharmony_ci    struct DeviceResourceNode *childNode = NULL;
40094332d3Sopenharmony_ci    struct DeviceResourceIface *iface = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
41094332d3Sopenharmony_ci    if (iface == NULL) {
42094332d3Sopenharmony_ci        CODEC_LOGE("failed, iface NULL!");
43094332d3Sopenharmony_ci        return HDF_FAILURE;
44094332d3Sopenharmony_ci    }
45094332d3Sopenharmony_ci
46094332d3Sopenharmony_ci    codecGroupNode = iface->GetChildNode(node, nodeName);
47094332d3Sopenharmony_ci    if (codecGroupNode == NULL) {
48094332d3Sopenharmony_ci        CODEC_LOGE("failed to get child node %{public}s!", nodeName);
49094332d3Sopenharmony_ci        return HDF_FAILURE;
50094332d3Sopenharmony_ci    }
51094332d3Sopenharmony_ci    DEV_RES_NODE_FOR_EACH_CHILD_NODE(codecGroupNode, childNode) {
52094332d3Sopenharmony_ci        result++;
53094332d3Sopenharmony_ci    }
54094332d3Sopenharmony_ci    *num = result;
55094332d3Sopenharmony_ci
56094332d3Sopenharmony_ci    return HDF_SUCCESS;
57094332d3Sopenharmony_ci}
58094332d3Sopenharmony_ci
59094332d3Sopenharmony_cistatic int32_t GetUintTableConfig(const struct DeviceResourceIface *iface,
60094332d3Sopenharmony_ci    const struct DeviceResourceNode *node, ConfigUintArrayNodeAttr *attr)
61094332d3Sopenharmony_ci{
62094332d3Sopenharmony_ci    if (iface == NULL || node == NULL || attr == NULL) {
63094332d3Sopenharmony_ci        CODEC_LOGE("invalid param!");
64094332d3Sopenharmony_ci        return HDF_ERR_INVALID_PARAM;
65094332d3Sopenharmony_ci    }
66094332d3Sopenharmony_ci    if (attr->array == NULL || attr->attrName == NULL) {
67094332d3Sopenharmony_ci        CODEC_LOGE("invalid attr!");
68094332d3Sopenharmony_ci        return HDF_ERR_INVALID_PARAM;
69094332d3Sopenharmony_ci    }
70094332d3Sopenharmony_ci
71094332d3Sopenharmony_ci    int32_t count = iface->GetElemNum(node, attr->attrName);
72094332d3Sopenharmony_ci    if (count < 0 || count >= attr->length) {
73094332d3Sopenharmony_ci        CODEC_LOGE("%{public}s table size: %{public}d incorrect or exceed max size %{public}d!", attr->attrName,
74094332d3Sopenharmony_ci            count, attr->length - 1);
75094332d3Sopenharmony_ci        return HDF_FAILURE;
76094332d3Sopenharmony_ci    }
77094332d3Sopenharmony_ci
78094332d3Sopenharmony_ci    if (count > 0) {
79094332d3Sopenharmony_ci        iface->GetUint32Array(node, attr->attrName, (uint32_t *)attr->array, count, 0);
80094332d3Sopenharmony_ci    }
81094332d3Sopenharmony_ci    attr->array[count] = attr->endValue;
82094332d3Sopenharmony_ci
83094332d3Sopenharmony_ci    return HDF_SUCCESS;
84094332d3Sopenharmony_ci}
85094332d3Sopenharmony_ci
86094332d3Sopenharmony_cistatic int32_t GetMaskedConfig(const struct DeviceResourceIface *iface,
87094332d3Sopenharmony_ci    const struct DeviceResourceNode *node, const char *attrName, uint32_t *mask)
88094332d3Sopenharmony_ci{
89094332d3Sopenharmony_ci    if (iface == NULL || node == NULL || attrName == NULL || mask == NULL) {
90094332d3Sopenharmony_ci        CODEC_LOGE("invalid param!");
91094332d3Sopenharmony_ci        return HDF_ERR_INVALID_PARAM;
92094332d3Sopenharmony_ci    }
93094332d3Sopenharmony_ci
94094332d3Sopenharmony_ci    uint32_t *values = NULL;
95094332d3Sopenharmony_ci    int32_t count = iface->GetElemNum(node, attrName);
96094332d3Sopenharmony_ci
97094332d3Sopenharmony_ci    *mask = 0;
98094332d3Sopenharmony_ci    if (count < 0 || count > MASK_NUM_LIMIT) {
99094332d3Sopenharmony_ci        CODEC_LOGE("count %{public}d incorrect!", count);
100094332d3Sopenharmony_ci        return HDF_FAILURE;
101094332d3Sopenharmony_ci    }
102094332d3Sopenharmony_ci
103094332d3Sopenharmony_ci    if (count > 0) {
104094332d3Sopenharmony_ci        values = (uint32_t *)OsalMemAlloc(sizeof(uint32_t) * count);
105094332d3Sopenharmony_ci        if (values == NULL) {
106094332d3Sopenharmony_ci            CODEC_LOGE("failed to allocate mem for %{public}s!", attrName);
107094332d3Sopenharmony_ci            return HDF_FAILURE;
108094332d3Sopenharmony_ci        }
109094332d3Sopenharmony_ci        iface->GetUint32Array(node, attrName, values, count, 0);
110094332d3Sopenharmony_ci        for (int32_t index = 0; index < count; index++) {
111094332d3Sopenharmony_ci            *mask |= values[index];
112094332d3Sopenharmony_ci        }
113094332d3Sopenharmony_ci        OsalMemFree(values);
114094332d3Sopenharmony_ci    }
115094332d3Sopenharmony_ci
116094332d3Sopenharmony_ci    return HDF_SUCCESS;
117094332d3Sopenharmony_ci}
118094332d3Sopenharmony_ci
119094332d3Sopenharmony_cistatic int32_t GetVideoPortCapability(const struct DeviceResourceIface *iface,
120094332d3Sopenharmony_ci    const struct DeviceResourceNode *childNode, CodecCompCapability *cap)
121094332d3Sopenharmony_ci{
122094332d3Sopenharmony_ci    if (iface == NULL || childNode == NULL || cap == NULL) {
123094332d3Sopenharmony_ci        CODEC_LOGE("invalid param!");
124094332d3Sopenharmony_ci        return HDF_ERR_INVALID_PARAM;
125094332d3Sopenharmony_ci    }
126094332d3Sopenharmony_ci
127094332d3Sopenharmony_ci    ConfigUintNodeAttr nodeAttrs[] = {
128094332d3Sopenharmony_ci        {CODEC_CONFIG_KEY_MIN_WIDTH,             (uint32_t*)&cap->port.video.minSize.width,               0},
129094332d3Sopenharmony_ci        {CODEC_CONFIG_KEY_MIN_HEIGHT,            (uint32_t*)&cap->port.video.minSize.height,              0},
130094332d3Sopenharmony_ci        {CODEC_CONFIG_KEY_MAX_WIDTH,             (uint32_t*)&cap->port.video.maxSize.width,               0},
131094332d3Sopenharmony_ci        {CODEC_CONFIG_KEY_MAX_HEIGHT,            (uint32_t*)&cap->port.video.maxSize.height,              0},
132094332d3Sopenharmony_ci        {CODEC_CONFIG_KEY_WIDTH_ALIGNMENT,       (uint32_t*)&cap->port.video.whAlignment.widthAlignment,  0},
133094332d3Sopenharmony_ci        {CODEC_CONFIG_KEY_HEIGHT_ALIGNMENT,      (uint32_t*)&cap->port.video.whAlignment.heightAlignment, 0},
134094332d3Sopenharmony_ci        {CODEC_CONFIG_KEY_MIN_BLOCK_COUNT,       (uint32_t*)&cap->port.video.blockCount.min,              0},
135094332d3Sopenharmony_ci        {CODEC_CONFIG_KEY_MAX_BLOCK_COUNT,       (uint32_t*)&cap->port.video.blockCount.max,              0},
136094332d3Sopenharmony_ci        {CODEC_CONFIG_KEY_MIN_BLOCKS_PER_SECOND, (uint32_t*)&cap->port.video.blocksPerSecond.min,         0},
137094332d3Sopenharmony_ci        {CODEC_CONFIG_KEY_MAX_BLOCKS_PER_SECOND, (uint32_t*)&cap->port.video.blocksPerSecond.max,         0},
138094332d3Sopenharmony_ci        {CODEC_CONFIG_KEY_BLOCK_SIZE_WIDTH,      (uint32_t*)&cap->port.video.blockSize.width,             0},
139094332d3Sopenharmony_ci        {CODEC_CONFIG_KEY_BLOCK_SIZE_HEIGHT,     (uint32_t*)&cap->port.video.blockSize.height,            0},
140094332d3Sopenharmony_ci        {CODEC_CONFIG_KEY_MIN_FRAME_RATE,        (uint32_t *)&cap->port.video.frameRate.min,              0},
141094332d3Sopenharmony_ci        {CODEC_CONFIG_KEY_MAX_FRAME_RATE,        (uint32_t *)&cap->port.video.frameRate.max,              0}
142094332d3Sopenharmony_ci    };
143094332d3Sopenharmony_ci
144094332d3Sopenharmony_ci    int32_t count = sizeof(nodeAttrs) / sizeof(ConfigUintNodeAttr);
145094332d3Sopenharmony_ci    for (int32_t i = 0; i < count; i++) {
146094332d3Sopenharmony_ci        if (iface->GetUint32(childNode, nodeAttrs[i].attrName, nodeAttrs[i].valueAddr,
147094332d3Sopenharmony_ci            nodeAttrs[i].defaultValue) != HDF_SUCCESS) {
148094332d3Sopenharmony_ci            CODEC_LOGE("failed to get %{public}s.%{public}s!", childNode->name, nodeAttrs[i].attrName);
149094332d3Sopenharmony_ci            return HDF_FAILURE;
150094332d3Sopenharmony_ci        }
151094332d3Sopenharmony_ci    }
152094332d3Sopenharmony_ci
153094332d3Sopenharmony_ci    ConfigUintArrayNodeAttr arrayAttrs[] = {
154094332d3Sopenharmony_ci        {CODEC_CONFIG_KEY_SUPPORT_PIXEL_FMTS, cap->port.video.supportPixFmts, PIX_FORMAT_NUM, OMX_COLOR_FormatUnused},
155094332d3Sopenharmony_ci        {CODEC_CONFIG_KEY_BITE_RATE_MODE, (int32_t *)cap->port.video.bitRatemode, BIT_RATE_MODE_NUM,
156094332d3Sopenharmony_ci         BIT_RATE_MODE_INVALID},
157094332d3Sopenharmony_ci        {CODEC_CONFIG_KEY_MESURED_FRAME_RATE, cap->port.video.measuredFrameRate, MEASURED_FRAME_RATE_NUM, 0}
158094332d3Sopenharmony_ci    };
159094332d3Sopenharmony_ci
160094332d3Sopenharmony_ci    count = sizeof(arrayAttrs) / sizeof(ConfigUintArrayNodeAttr);
161094332d3Sopenharmony_ci    for (int32_t i = 0; i < count; i++) {
162094332d3Sopenharmony_ci        if (GetUintTableConfig(iface, childNode, &arrayAttrs[i]) != HDF_SUCCESS) {
163094332d3Sopenharmony_ci            CODEC_LOGE("failed to get %{public}s.%{public}s!", childNode->name, nodeAttrs[i].attrName);
164094332d3Sopenharmony_ci            return HDF_FAILURE;
165094332d3Sopenharmony_ci        }
166094332d3Sopenharmony_ci    }
167094332d3Sopenharmony_ci    return HDF_SUCCESS;
168094332d3Sopenharmony_ci}
169094332d3Sopenharmony_ci
170094332d3Sopenharmony_cistatic int32_t GetAudioPortCapability(const struct DeviceResourceIface *iface,
171094332d3Sopenharmony_ci    const struct DeviceResourceNode *childNode, CodecCompCapability *cap)
172094332d3Sopenharmony_ci{
173094332d3Sopenharmony_ci    if (iface == NULL || childNode == NULL || cap == NULL) {
174094332d3Sopenharmony_ci        CODEC_LOGE("invalid param!");
175094332d3Sopenharmony_ci        return HDF_ERR_INVALID_PARAM;
176094332d3Sopenharmony_ci    }
177094332d3Sopenharmony_ci
178094332d3Sopenharmony_ci    ConfigUintArrayNodeAttr arrayAttrs[] = {
179094332d3Sopenharmony_ci        {CODEC_CONFIG_KEY_SAMPLE_FORMATS,  cap->port.audio.sampleFormats,  SAMPLE_FMT_NUM,  AUDIO_SAMPLE_FMT_INVALID},
180094332d3Sopenharmony_ci        {CODEC_CONFIG_KEY_SAMPLE_RATE,     cap->port.audio.sampleRate,     SAMPLE_RATE_NUM, AUD_SAMPLE_RATE_INVALID},
181094332d3Sopenharmony_ci        {CODEC_CONFIG_KEY_CHANNEL_LAYOUTS, cap->port.audio.channelLayouts, CHANNEL_NUM,     -1},
182094332d3Sopenharmony_ci        {CODEC_CONFIG_KEY_CHANNEL_COUNT,   cap->port.audio.channelCount,   CHANNEL_NUM,     -1}
183094332d3Sopenharmony_ci    };
184094332d3Sopenharmony_ci
185094332d3Sopenharmony_ci    int32_t count = sizeof(arrayAttrs) / sizeof(ConfigUintArrayNodeAttr);
186094332d3Sopenharmony_ci    for (int32_t i = 0; i < count; i++) {
187094332d3Sopenharmony_ci        if (GetUintTableConfig(iface, childNode, &arrayAttrs[i]) != HDF_SUCCESS) {
188094332d3Sopenharmony_ci            CODEC_LOGE("failed to get %{public}s.%{public}s!", childNode->name, arrayAttrs[i].attrName);
189094332d3Sopenharmony_ci            return HDF_FAILURE;
190094332d3Sopenharmony_ci        }
191094332d3Sopenharmony_ci    }
192094332d3Sopenharmony_ci
193094332d3Sopenharmony_ci    return HDF_SUCCESS;
194094332d3Sopenharmony_ci}
195094332d3Sopenharmony_ci
196094332d3Sopenharmony_cistatic int32_t GetMiscOfCapability(const struct DeviceResourceIface *iface,
197094332d3Sopenharmony_ci    const struct DeviceResourceNode *childNode, CodecCompCapability *cap)
198094332d3Sopenharmony_ci{
199094332d3Sopenharmony_ci    if (iface == NULL || childNode == NULL || cap == NULL) {
200094332d3Sopenharmony_ci        CODEC_LOGE("invalid param!");
201094332d3Sopenharmony_ci        return HDF_ERR_INVALID_PARAM;
202094332d3Sopenharmony_ci    }
203094332d3Sopenharmony_ci
204094332d3Sopenharmony_ci    ConfigUintArrayNodeAttr attr = {CODEC_CONFIG_KEY_SUPPORT_PROFILES,
205094332d3Sopenharmony_ci        cap->supportProfiles, PROFILE_NUM, INVALID_PROFILE};
206094332d3Sopenharmony_ci    if (GetUintTableConfig(iface, childNode, &attr) != HDF_SUCCESS) {
207094332d3Sopenharmony_ci        return HDF_FAILURE;
208094332d3Sopenharmony_ci    }
209094332d3Sopenharmony_ci    if (iface->GetUint32(childNode, CODEC_CONFIG_KEY_MAX_INST, (uint32_t*)&cap->maxInst, 0) != HDF_SUCCESS) {
210094332d3Sopenharmony_ci        return HDF_FAILURE;
211094332d3Sopenharmony_ci    }
212094332d3Sopenharmony_ci    if (GetMaskedConfig(iface, childNode, CODEC_CONFIG_KEY_PROCESS_MODE_MASK,
213094332d3Sopenharmony_ci        (uint32_t *)&cap->processModeMask) != HDF_SUCCESS) {
214094332d3Sopenharmony_ci        return HDF_FAILURE;
215094332d3Sopenharmony_ci    }
216094332d3Sopenharmony_ci    if (GetMaskedConfig(iface, childNode, CODEC_CONFIG_KEY_CAPS_MASK, &cap->capsMask) != HDF_SUCCESS) {
217094332d3Sopenharmony_ci        return HDF_FAILURE;
218094332d3Sopenharmony_ci    }
219094332d3Sopenharmony_ci    if (iface->GetUint32(childNode, CODEC_CONFIG_KEY_MIN_BITRATE, (uint32_t*)&(cap->bitRate.min), 0) != HDF_SUCCESS) {
220094332d3Sopenharmony_ci        return HDF_FAILURE;
221094332d3Sopenharmony_ci    }
222094332d3Sopenharmony_ci    if (iface->GetUint32(childNode, CODEC_CONFIG_KEY_MAX_BITRATE, (uint32_t*)&(cap->bitRate.max), 0) != HDF_SUCCESS) {
223094332d3Sopenharmony_ci        return HDF_FAILURE;
224094332d3Sopenharmony_ci    }
225094332d3Sopenharmony_ci
226094332d3Sopenharmony_ci    return HDF_SUCCESS;
227094332d3Sopenharmony_ci}
228094332d3Sopenharmony_ci
229094332d3Sopenharmony_cistatic int32_t GetOneCapability(const struct DeviceResourceIface *iface,
230094332d3Sopenharmony_ci    const struct DeviceResourceNode *childNode, CodecCompCapability *cap, bool isVideoGroup)
231094332d3Sopenharmony_ci{
232094332d3Sopenharmony_ci    if (iface == NULL || childNode == NULL || cap == NULL) {
233094332d3Sopenharmony_ci        CODEC_LOGE("invalid param!");
234094332d3Sopenharmony_ci        return HDF_ERR_INVALID_PARAM;
235094332d3Sopenharmony_ci    }
236094332d3Sopenharmony_ci
237094332d3Sopenharmony_ci    if (iface->GetUint32(childNode, CODEC_CONFIG_KEY_ROLE,
238094332d3Sopenharmony_ci        (uint32_t*)&cap->role, MEDIA_ROLETYPE_INVALID) != HDF_SUCCESS) {
239094332d3Sopenharmony_ci        cap->role = MEDIA_ROLETYPE_INVALID;
240094332d3Sopenharmony_ci        CODEC_LOGE("failed to get mime for: %{public}s! Discarded", childNode->name);
241094332d3Sopenharmony_ci        return HDF_FAILURE;
242094332d3Sopenharmony_ci    }
243094332d3Sopenharmony_ci
244094332d3Sopenharmony_ci    if (iface->GetUint32(childNode, CODEC_CONFIG_KEY_TYPE, (uint32_t*)&cap->type, INVALID_TYPE) != HDF_SUCCESS) {
245094332d3Sopenharmony_ci        cap->role = MEDIA_ROLETYPE_INVALID;
246094332d3Sopenharmony_ci        cap->type = INVALID_TYPE;
247094332d3Sopenharmony_ci        CODEC_LOGE("failed to get type for: %{public}s! Discarded", childNode->name);
248094332d3Sopenharmony_ci        return HDF_FAILURE;
249094332d3Sopenharmony_ci    }
250094332d3Sopenharmony_ci
251094332d3Sopenharmony_ci    const char *compName = NULL;
252094332d3Sopenharmony_ci    if (iface->GetString(childNode, CODEC_CONFIG_KEY_NAME, &compName, "") != HDF_SUCCESS) {
253094332d3Sopenharmony_ci        cap->role = MEDIA_ROLETYPE_INVALID;
254094332d3Sopenharmony_ci        return HDF_FAILURE;
255094332d3Sopenharmony_ci    }
256094332d3Sopenharmony_ci    if (compName == NULL || strlen(compName) >= NAME_LENGTH || strlen(compName) == 0) {
257094332d3Sopenharmony_ci        cap->role = MEDIA_ROLETYPE_INVALID;
258094332d3Sopenharmony_ci        return HDF_FAILURE;
259094332d3Sopenharmony_ci    }
260094332d3Sopenharmony_ci    int32_t ret = strcpy_s(cap->compName, NAME_LENGTH, compName);
261094332d3Sopenharmony_ci    if (ret != EOK) {
262094332d3Sopenharmony_ci        CODEC_LOGE("strcpy_s is failed, error code: %{public}d!", ret);
263094332d3Sopenharmony_ci        return HDF_FAILURE;
264094332d3Sopenharmony_ci    }
265094332d3Sopenharmony_ci    cap->isSoftwareCodec = iface->GetBool(childNode, CODEC_CONFIG_KEY_IS_SOFTWARE_CODEC);
266094332d3Sopenharmony_ci    cap->canSwapWidthHeight = iface->GetBool(childNode, CODEC_CONFIG_KEY_CAN_SWAP_WIDTH_HEIGHT);
267094332d3Sopenharmony_ci
268094332d3Sopenharmony_ci    if (GetMiscOfCapability(iface, childNode, cap) != HDF_SUCCESS) {
269094332d3Sopenharmony_ci        cap->role = MEDIA_ROLETYPE_INVALID;
270094332d3Sopenharmony_ci        return HDF_FAILURE;
271094332d3Sopenharmony_ci    }
272094332d3Sopenharmony_ci
273094332d3Sopenharmony_ci    if (isVideoGroup) {
274094332d3Sopenharmony_ci        if (GetVideoPortCapability(iface, childNode, cap) != HDF_SUCCESS) {
275094332d3Sopenharmony_ci            cap->role = MEDIA_ROLETYPE_INVALID;
276094332d3Sopenharmony_ci            return HDF_FAILURE;
277094332d3Sopenharmony_ci        }
278094332d3Sopenharmony_ci    } else {
279094332d3Sopenharmony_ci        if (GetAudioPortCapability(iface, childNode, cap) != HDF_SUCCESS) {
280094332d3Sopenharmony_ci            cap->role = MEDIA_ROLETYPE_INVALID;
281094332d3Sopenharmony_ci            return HDF_FAILURE;
282094332d3Sopenharmony_ci        }
283094332d3Sopenharmony_ci    }
284094332d3Sopenharmony_ci
285094332d3Sopenharmony_ci    return HDF_SUCCESS;
286094332d3Sopenharmony_ci}
287094332d3Sopenharmony_ci
288094332d3Sopenharmony_cistatic int32_t GetGroupCapabilities(const struct DeviceResourceNode *node,
289094332d3Sopenharmony_ci    const char *nodeName, CodecCapablityGroup *capsGroup)
290094332d3Sopenharmony_ci{
291094332d3Sopenharmony_ci    if (node == NULL || nodeName == NULL || capsGroup == NULL) {
292094332d3Sopenharmony_ci        CODEC_LOGE("invalid param!");
293094332d3Sopenharmony_ci        return HDF_ERR_INVALID_PARAM;
294094332d3Sopenharmony_ci    }
295094332d3Sopenharmony_ci
296094332d3Sopenharmony_ci    CodecCompCapability *cap = NULL;
297094332d3Sopenharmony_ci    int32_t index = 0;
298094332d3Sopenharmony_ci    bool isVideoGroup = true;
299094332d3Sopenharmony_ci    const struct DeviceResourceNode *codecGroupNode = NULL;
300094332d3Sopenharmony_ci    struct DeviceResourceNode *childNode = NULL;
301094332d3Sopenharmony_ci    struct DeviceResourceIface *iface = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
302094332d3Sopenharmony_ci    if (iface == NULL) {
303094332d3Sopenharmony_ci        CODEC_LOGE("iface NULL!");
304094332d3Sopenharmony_ci        return HDF_ERR_INVALID_PARAM;
305094332d3Sopenharmony_ci    }
306094332d3Sopenharmony_ci
307094332d3Sopenharmony_ci    codecGroupNode = iface->GetChildNode(node, nodeName);
308094332d3Sopenharmony_ci    if (codecGroupNode == NULL) {
309094332d3Sopenharmony_ci        CODEC_LOGE("failed to get child node: %{public}s!", nodeName);
310094332d3Sopenharmony_ci        return HDF_FAILURE;
311094332d3Sopenharmony_ci    }
312094332d3Sopenharmony_ci
313094332d3Sopenharmony_ci    if (strstr(nodeName, "Video") == NULL) {
314094332d3Sopenharmony_ci        isVideoGroup = false;
315094332d3Sopenharmony_ci    }
316094332d3Sopenharmony_ci    DEV_RES_NODE_FOR_EACH_CHILD_NODE(codecGroupNode, childNode) {
317094332d3Sopenharmony_ci        cap = &(capsGroup->capablitis[index++]);
318094332d3Sopenharmony_ci        if (cap == NULL) {
319094332d3Sopenharmony_ci            continue;
320094332d3Sopenharmony_ci        }
321094332d3Sopenharmony_ci        if (GetOneCapability(iface, childNode, cap, isVideoGroup) != HDF_SUCCESS) {
322094332d3Sopenharmony_ci            CODEC_LOGE("GetOneCapability failed, role is %{public}d!", cap->role);
323094332d3Sopenharmony_ci        }
324094332d3Sopenharmony_ci    }
325094332d3Sopenharmony_ci
326094332d3Sopenharmony_ci    return HDF_SUCCESS;
327094332d3Sopenharmony_ci}
328094332d3Sopenharmony_ci
329094332d3Sopenharmony_ciint32_t LoadCodecCapabilityFromHcs(const struct DeviceResourceNode *node, CodecCapablites *caps)
330094332d3Sopenharmony_ci{
331094332d3Sopenharmony_ci    if (node == NULL || caps == NULL) {
332094332d3Sopenharmony_ci        CODEC_LOGE("invalid param!");
333094332d3Sopenharmony_ci        return HDF_ERR_INVALID_PARAM;
334094332d3Sopenharmony_ci    }
335094332d3Sopenharmony_ci    CodecCapablityGroup *codecCapGroup = NULL;
336094332d3Sopenharmony_ci    int32_t index;
337094332d3Sopenharmony_ci    int32_t codecNum = 0;
338094332d3Sopenharmony_ci
339094332d3Sopenharmony_ci    char *codecGroupsNodeName[] = {
340094332d3Sopenharmony_ci        NODE_VIDEO_HARDWARE_ENCODERS, NODE_VIDEO_HARDWARE_DECODERS, NODE_VIDEO_SOFTWARE_ENCODERS,
341094332d3Sopenharmony_ci        NODE_VIDEO_SOFTWARE_DECODERS, NODE_AUDIO_HARDWARE_ENCODERS, NODE_AUDIO_HARDWARE_DECODERS,
342094332d3Sopenharmony_ci        NODE_AUDIO_SOFTWARE_ENCODERS, NODE_AUDIO_SOFTWARE_DECODERS
343094332d3Sopenharmony_ci    };
344094332d3Sopenharmony_ci    CodecCapablityGroup *codecCapGroups[] = {
345094332d3Sopenharmony_ci        &(caps->videoHwEncoderGroup), &(caps->videoHwDecoderGroup),
346094332d3Sopenharmony_ci        &(caps->videoSwEncoderGroup), &(caps->videoSwDecoderGroup),
347094332d3Sopenharmony_ci        &(caps->audioHwEncoderGroup), &(caps->audioHwDecoderGroup),
348094332d3Sopenharmony_ci        &(caps->audioSwEncoderGroup), &(caps->audioSwDecoderGroup)
349094332d3Sopenharmony_ci    };
350094332d3Sopenharmony_ci
351094332d3Sopenharmony_ci    for (index = 0; index < CODEC_CAPABLITY_GROUP_NUM; index++) {
352094332d3Sopenharmony_ci        if (GetGroupCapabilitiesNumber(node, codecGroupsNodeName[index], &codecNum) == HDF_SUCCESS) {
353094332d3Sopenharmony_ci            codecCapGroup = codecCapGroups[index];
354094332d3Sopenharmony_ci            if (codecNum > 0) {
355094332d3Sopenharmony_ci                codecCapGroup->num = codecNum;
356094332d3Sopenharmony_ci                codecCapGroup->capablitis
357094332d3Sopenharmony_ci                    = (CodecCompCapability *)OsalMemAlloc(sizeof(CodecCompCapability) * codecNum);
358094332d3Sopenharmony_ci            } else {
359094332d3Sopenharmony_ci                codecCapGroup->capablitis = NULL;
360094332d3Sopenharmony_ci                codecCapGroup->num = 0;
361094332d3Sopenharmony_ci            }
362094332d3Sopenharmony_ci            if (codecNum > 0 && codecCapGroup->capablitis == NULL) {
363094332d3Sopenharmony_ci                codecCapGroup->num = 0;
364094332d3Sopenharmony_ci                CODEC_LOGE("MemAlloc for capability group failed!");
365094332d3Sopenharmony_ci                return HDF_FAILURE;
366094332d3Sopenharmony_ci            }
367094332d3Sopenharmony_ci            caps->total += codecCapGroup->num;
368094332d3Sopenharmony_ci        }
369094332d3Sopenharmony_ci    }
370094332d3Sopenharmony_ci
371094332d3Sopenharmony_ci    for (index = 0; index < CODEC_CAPABLITY_GROUP_NUM; index++) {
372094332d3Sopenharmony_ci        if (GetGroupCapabilities(node, codecGroupsNodeName[index], codecCapGroups[index]) != HDF_SUCCESS) {
373094332d3Sopenharmony_ci            CODEC_LOGE("GetGroupCapabilities failed index: %{public}d!", index);
374094332d3Sopenharmony_ci            return HDF_FAILURE;
375094332d3Sopenharmony_ci        }
376094332d3Sopenharmony_ci    }
377094332d3Sopenharmony_ci    caps->inited = true;
378094332d3Sopenharmony_ci    return HDF_SUCCESS;
379094332d3Sopenharmony_ci}
380094332d3Sopenharmony_ci
381094332d3Sopenharmony_ciint32_t ClearCapabilityGroup(CodecCapablites *caps)
382094332d3Sopenharmony_ci{
383094332d3Sopenharmony_ci    if (caps == NULL) {
384094332d3Sopenharmony_ci        CODEC_LOGE("invalid param!");
385094332d3Sopenharmony_ci        return HDF_ERR_INVALID_PARAM;
386094332d3Sopenharmony_ci    }
387094332d3Sopenharmony_ci
388094332d3Sopenharmony_ci    int32_t index;
389094332d3Sopenharmony_ci    CodecCapablityGroup *codecCapGroup = NULL;
390094332d3Sopenharmony_ci    CodecCapablityGroup *codecCapGroups[] = {
391094332d3Sopenharmony_ci        &(caps->videoHwEncoderGroup), &(caps->videoHwDecoderGroup),
392094332d3Sopenharmony_ci        &(caps->videoSwEncoderGroup), &(caps->videoSwDecoderGroup),
393094332d3Sopenharmony_ci        &(caps->audioHwEncoderGroup), &(caps->audioHwDecoderGroup),
394094332d3Sopenharmony_ci        &(caps->audioSwEncoderGroup), &(caps->audioSwDecoderGroup)
395094332d3Sopenharmony_ci    };
396094332d3Sopenharmony_ci    for (index = 0; index < CODEC_CAPABLITY_GROUP_NUM; index++) {
397094332d3Sopenharmony_ci        codecCapGroup = codecCapGroups[index];
398094332d3Sopenharmony_ci        if (codecCapGroup->capablitis != NULL) {
399094332d3Sopenharmony_ci            OsalMemFree(codecCapGroup->capablitis);
400094332d3Sopenharmony_ci            codecCapGroup->num = 0;
401094332d3Sopenharmony_ci            codecCapGroup->capablitis = NULL;
402094332d3Sopenharmony_ci        }
403094332d3Sopenharmony_ci    }
404094332d3Sopenharmony_ci    caps->inited = false;
405094332d3Sopenharmony_ci    caps->total = 0;
406094332d3Sopenharmony_ci    return HDF_SUCCESS;
407094332d3Sopenharmony_ci}
408