1/*
2 * Copyright (c) 2023 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 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 <array>
17#include "codec_image_config.h"
18#include "codec_log_wrapper.h"
19namespace {
20    constexpr char NODE_IMAGE_HARDWARE_ENCODERS[] = "ImageHwEncoders";
21    constexpr char NODE_IMAGE_HARDWARE_DECODERS[] = "ImageHwDecoders";
22
23    constexpr char CODEC_CONFIG_KEY_ROLE[] = "role";
24    constexpr char CODEC_CONFIG_KEY_TYPE[] = "type";
25    constexpr char CODEC_CONFIG_KEY_NAME[] = "name";
26    constexpr char CODEC_CONFIG_KEY_MAX_SAMPLE[] = "maxSample";
27    constexpr char CODEC_CONFIG_KEY_MAX_WIDTH[] = "maxWidth";
28    constexpr char CODEC_CONFIG_KEY_MAX_HEIGHT[] = "maxHeight";
29    constexpr char CODEC_CONFIG_KEY_MIN_WIDTH[] = "minWidth";
30    constexpr char CODEC_CONFIG_KEY_MIN_HEIGHT[] = "minHeight";
31    constexpr char CODEC_CONFIG_KEY_MAX_INST[] = "maxInst";
32    constexpr char CODEC_CONFIG_KEY_WIDTH_ALIGNMENT[] = "widthAlignment";
33    constexpr char CODEC_CONFIG_KEY_HEIGHT_ALIGNMENT[] = "heightAlignment";
34    constexpr char CODEC_CONFIG_KEY_IS_SOFTWARE_CODEC[] = "isSoftwareCodec";
35    constexpr char CODEC_CONFIG_KEY_SUPPORT_PIXEL_FMTS[] = "supportPixelFmts";
36}
37namespace OHOS {
38namespace HDI {
39namespace Codec {
40namespace Image {
41namespace V2_0 {
42CodecImageConfig CodecImageConfig::config_;
43
44CodecImageConfig::CodecImageConfig()
45{
46    node_.name = nullptr;
47    node_.hashValue = 0;
48    node_.attrData = nullptr;
49    node_.parent = nullptr;
50    node_.child = nullptr;
51    node_.sibling = nullptr;
52}
53
54void CodecImageConfig::Init(const struct DeviceResourceNode &node)
55{
56    node_ = node;
57    const uint32_t count = 2; // encoder and decoder
58    const static std::array<std::string, count> codecGroupsNodeName = {
59        NODE_IMAGE_HARDWARE_ENCODERS,
60        NODE_IMAGE_HARDWARE_DECODERS
61    };
62    for (uint32_t index = 0; index < count; index++) {
63        if (GetGroupCapabilities(codecGroupsNodeName[index]) != HDF_SUCCESS) {
64            continue;
65        }
66    }
67    CODEC_LOGI("Init Run....capList_.size=%{public}zu", capList_.size());
68}
69
70CodecImageConfig *CodecImageConfig::GetInstance()
71{
72    return &config_;
73}
74
75int32_t CodecImageConfig::GetImageCapabilityList(std::vector<CodecImageCapability> &capList)
76{
77    size_t size = capList_.size();
78    CODEC_LOGI("size[%{public}zu]", size);
79    if (size == 0) {
80        return HDF_FAILURE;
81    }
82    auto first = capList_.begin();
83    auto last = capList_.end();
84    capList.assign(first, last);
85    return HDF_SUCCESS;
86}
87
88int32_t CodecImageConfig::GetGroupCapabilities(const std::string &nodeName)
89{
90    const struct DeviceResourceNode *codecGroupNode = nullptr;
91    struct DeviceResourceNode *childNode = nullptr;
92    struct DeviceResourceIface *iface = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
93    CHECK_AND_RETURN_RET_LOG(iface != nullptr, HDF_ERR_INVALID_PARAM, "iface is nullptr");
94
95    codecGroupNode = iface->GetChildNode(&node_, nodeName.c_str());
96    CHECK_AND_RETURN_RET_LOG(codecGroupNode != nullptr, HDF_FAILURE, "failed to get child node: %{public}s!",
97        nodeName.c_str());
98
99    DEV_RES_NODE_FOR_EACH_CHILD_NODE(codecGroupNode, childNode)
100    {
101        CodecImageCapability cap;
102        if (GetOneCapability(*iface, *childNode, cap) != HDF_SUCCESS) {
103            CODEC_LOGE("GetOneCapability failed, name is %{public}s!", cap.name.c_str());
104        }
105        capList_.push_back(cap);
106    }
107
108    return HDF_SUCCESS;
109}
110
111int32_t CodecImageConfig::GetOneCapability(const struct DeviceResourceIface &iface,
112                                           const struct DeviceResourceNode &childNode, CodecImageCapability &cap)
113{
114    const char *name = nullptr;
115    auto ret = iface.GetString(&childNode, CODEC_CONFIG_KEY_NAME, &name, "");
116    CHECK_AND_RETURN_RET_LOG(ret == HDF_SUCCESS, HDF_FAILURE, "get attr %{public}s err!", CODEC_CONFIG_KEY_NAME);
117    CHECK_AND_RETURN_RET_LOG(name != nullptr && strlen(name) != 0, HDF_FAILURE, "compName is nullptr or empty!");
118    cap.name = name;
119
120    if (iface.GetUint32(&childNode, CODEC_CONFIG_KEY_ROLE, reinterpret_cast<uint32_t *>(&cap.role),
121                        CODEC_IMAGE_INVALID) != HDF_SUCCESS) {
122        cap.role = CODEC_IMAGE_INVALID;
123        CODEC_LOGE("failed to get role for: %{public}s! Discarded", childNode.name);
124        return HDF_FAILURE;
125    }
126
127    if (iface.GetUint32(&childNode, CODEC_CONFIG_KEY_TYPE, reinterpret_cast<uint32_t *>(&cap.type),
128                        CODEC_IMAGE_TYPE_INVALID) != HDF_SUCCESS) {
129        cap.role = CODEC_IMAGE_INVALID;
130        cap.type = CODEC_IMAGE_TYPE_INVALID;
131        CODEC_LOGE("failed to get type for: %{public}s! Discarded", childNode.name);
132        return HDF_FAILURE;
133    }
134
135    cap.isSoftwareCodec = iface.GetBool(&childNode, CODEC_CONFIG_KEY_IS_SOFTWARE_CODEC);
136
137    ConfigUintNodeAttr nodeAttrs[] = {
138        {CODEC_CONFIG_KEY_MIN_WIDTH, cap.minWidth, 0},
139        {CODEC_CONFIG_KEY_MIN_HEIGHT, cap.minHeight, 0},
140        {CODEC_CONFIG_KEY_MAX_WIDTH, cap.maxWidth, 0},
141        {CODEC_CONFIG_KEY_MAX_HEIGHT, cap.maxHeight, 0},
142        {CODEC_CONFIG_KEY_MAX_INST, cap.maxInst, 0},
143        {CODEC_CONFIG_KEY_MAX_SAMPLE, cap.maxSample, 0},
144        {CODEC_CONFIG_KEY_WIDTH_ALIGNMENT, cap.widthAlignment, 0},
145        {CODEC_CONFIG_KEY_HEIGHT_ALIGNMENT, cap.heightAlignment, 0}};
146
147    int32_t count = sizeof(nodeAttrs) / sizeof(ConfigUintNodeAttr);
148    for (int32_t i = 0; i < count; i++) {
149        auto err = iface.GetUint32(&childNode, nodeAttrs[i].attrName.c_str(),
150            reinterpret_cast<uint32_t *>(&nodeAttrs[i].value), nodeAttrs[i].defaultValue);
151
152        CHECK_AND_RETURN_RET_LOG(err == HDF_SUCCESS, HDF_FAILURE, "failed to get %{public}s.%{public}s!",
153            childNode.name, nodeAttrs[i].attrName.c_str());
154    }
155
156    ConfigUintArrayNodeAttr attr = {CODEC_CONFIG_KEY_SUPPORT_PIXEL_FMTS, cap.supportPixFmts};
157    ret = GetUintTableConfig(iface, childNode, attr);
158    CHECK_AND_RETURN_RET_LOG(ret == HDF_SUCCESS, HDF_FAILURE, "get uint table config [%{public}s] err!",
159        attr.attrName.c_str());
160
161    return HDF_SUCCESS;
162}
163
164int32_t CodecImageConfig::GetUintTableConfig(const struct DeviceResourceIface &iface,
165    const struct DeviceResourceNode &node, ConfigUintArrayNodeAttr &attr)
166{
167    CHECK_AND_RETURN_RET_LOG(!attr.attrName.empty(), HDF_ERR_INVALID_PARAM, "failed, invalid attr");
168
169    int32_t count = iface.GetElemNum(&node, attr.attrName.c_str());
170    CHECK_AND_RETURN_RET_LOG(count >= 0, HDF_FAILURE, "%{public}s table size: count[%{public}d] < 0!",
171        attr.attrName.c_str(), count);
172
173    if (count > 0) {
174        std::unique_ptr<int32_t[]> array = std::make_unique<int32_t[]>(count);
175        iface.GetUint32Array(&node, attr.attrName.c_str(), reinterpret_cast<uint32_t *>(array.get()), count, 0);
176        attr.vec.assign(array.get(), array.get() + count);
177    }
178    return HDF_SUCCESS;
179}
180} // V2_0
181} // Image
182} // Codec
183} // HDI
184} // OHOS
185