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#include "codec_component_config.h"
16#include <cinttypes>
17#include <osal_mem.h>
18#include "codec_log_wrapper.h"
19#include "codec_hcb_util.h"
20
21#define CODEC_CONFIG_NAME "media_codec_capabilities"
22
23namespace {
24    constexpr int32_t MASK_NUM_LIMIT = 32;
25    constexpr char NODE_VIDEO_HARDWARE_ENCODERS[] = "VideoHwEncoders";
26    constexpr char NODE_VIDEO_HARDWARE_DECODERS[] = "VideoHwDecoders";
27    constexpr char NODE_VIDEO_SOFTWARE_ENCODERS[] = "VideoSwEncoders";
28    constexpr char NODE_VIDEO_SOFTWARE_DECODERS[] = "VideoSwDecoders";
29    constexpr char NODE_AUDIO_HARDWARE_ENCODERS[] = "AudioHwEncoders";
30    constexpr char NODE_AUDIO_HARDWARE_DECODERS[] = "AudioHwDecoders";
31    constexpr char NODE_AUDIO_SOFTWARE_ENCODERS[] = "AudioSwEncoders";
32    constexpr char NODE_AUDIO_SOFTWARE_DECODERS[] = "AudioSwDecoders";
33
34    constexpr char CODEC_CONFIG_KEY_ROLE[] = "role";
35    constexpr char CODEC_CONFIG_KEY_TYPE[] = "type";
36    constexpr char CODEC_CONFIG_KEY_NAME[] = "name";
37    constexpr char CODEC_CONFIG_KEY_SUPPORT_PROFILES[] = "supportProfiles";
38    constexpr char CODEC_CONFIG_KEY_MAX_INST[] = "maxInst";
39    constexpr char CODEC_CONFIG_KEY_IS_SOFTWARE_CODEC[] = "isSoftwareCodec";
40    constexpr char CODEC_CONFIG_KEY_PROCESS_MODE_MASK[] = "processModeMask";
41    constexpr char CODEC_CONFIG_KEY_CAPS_MASK[] = "capsMask";
42    constexpr char CODEC_CONFIG_KEY_MIN_BITRATE[] = "minBitRate";
43    constexpr char CODEC_CONFIG_KEY_MAX_BITRATE[] = "maxBitRate";
44
45    constexpr char CODEC_CONFIG_KEY_MIN_WIDTH[] = "minWidth";
46    constexpr char CODEC_CONFIG_KEY_MIN_HEIGHT[] = "minHeight";
47    constexpr char CODEC_CONFIG_KEY_MAX_WIDTH[] = "maxWidth";
48    constexpr char CODEC_CONFIG_KEY_MAX_HEIGHT[] = "maxHeight";
49    constexpr char CODEC_CONFIG_KEY_WIDTH_ALIGNMENT[] = "widthAlignment";
50    constexpr char CODEC_CONFIG_KEY_HEIGHT_ALIGNMENT[] = "heightAlignment";
51    constexpr char CODEC_CONFIG_KEY_MIN_BLOCK_COUNT[] = "minBlockCount";
52    constexpr char CODEC_CONFIG_KEY_MAX_BLOCK_COUNT[] = "maxBlockCount";
53    constexpr char CODEC_CONFIG_KEY_MIN_BLOCKS_PER_SECOND[] = "minBlocksPerSecond";
54    constexpr char CODEC_CONFIG_KEY_MAX_BLOCKS_PER_SECOND[] = "maxBlocksPerSecond";
55    constexpr char CODEC_CONFIG_KEY_SUPPORT_PIXEL_FMTS[] = "supportPixelFmts";
56    constexpr char CODEC_CONFIG_KEY_BLOCK_SIZE_WIDTH[] = "blockSizeWidth";
57    constexpr char CODEC_CONFIG_KEY_BLOCK_SIZE_HEIGHT[] = "blockSizeHeight";
58    constexpr char CODEC_CONFIG_KEY_MIN_FRAME_RATE[] = "minFrameRate";
59    constexpr char CODEC_CONFIG_KEY_MAX_FRAME_RATE[] = "maxFrameRate";
60    constexpr char CODEC_CONFIG_KEY_BITE_RATE_MODE[] = "bitRateMode";
61    constexpr char CODEC_CONFIG_KEY_MESURED_FRAME_RATE[] = "measuredFrameRate";
62    constexpr char CODEC_CONFIG_KEY_CAN_SWAP_WIDTH_HEIGHT[] = "canSwapWidthHeight";
63
64    constexpr char CODEC_CONFIG_KEY_IS_SUPPORT_PASSTHROUGH[] = "isSupportPassthrough";
65    constexpr char CODEC_CONFIG_KEY_IS_SUPPORT_LOW_LATENCY[] = "isSupportLowLatency";
66    constexpr char CODEC_CONFIG_KEY_IS_SUPPORT_TSVC[] = "isSupportTSVC";
67    constexpr char CODEC_CONFIG_KEY_IS_SUPPORT_LTR[] = "isSupportLTR";
68    constexpr char CODEC_CONFIG_KEY_MAX_LTR_FRAME_NUM[] = "maxLTRFrameNum";
69    constexpr char CODEC_CONFIG_KEY_IS_SUPPORT_WATERMARK[] = "isSupportWaterMark";
70
71    constexpr char CODEC_CONFIG_KEY_SAMPLE_FORMATS[] = "sampleFormats";
72    constexpr char CODEC_CONFIG_KEY_SAMPLE_RATE[] = "sampleRate";
73    constexpr char CODEC_CONFIG_KEY_CHANNEL_LAYOUTS[] = "channelLayouts";
74    constexpr char CODEC_CONFIG_KEY_CHANNEL_COUNT[] = "channelCount";
75}
76
77using namespace OHOS::HDI::Codec::V3_0;
78namespace OHOS {
79namespace Codec {
80namespace Omx {
81CodecComponentConfig CodecComponentConfig::config_;
82CodecComponentConfig::CodecComponentConfig()
83{
84    node_.name = nullptr;
85    node_.hashValue = 0;
86    node_.attrData = nullptr;
87    node_.parent = nullptr;
88    node_.child = nullptr;
89    node_.sibling = nullptr;
90}
91
92void CodecComponentConfig::Init(const DeviceResourceNode &node)
93{
94    node_ = node;
95    const std::string codecGroupsNodeName[] = { NODE_VIDEO_HARDWARE_ENCODERS, NODE_VIDEO_HARDWARE_DECODERS,
96                                                NODE_VIDEO_SOFTWARE_ENCODERS, NODE_VIDEO_SOFTWARE_DECODERS,
97                                                NODE_AUDIO_HARDWARE_ENCODERS, NODE_AUDIO_HARDWARE_DECODERS,
98                                                NODE_AUDIO_SOFTWARE_ENCODERS, NODE_AUDIO_SOFTWARE_DECODERS };
99    int count = sizeof(codecGroupsNodeName) / sizeof(std::string);
100    for (int index = 0; index < count; index++) {
101        GetGroupCapabilities(codecGroupsNodeName[index]);
102    }
103    CODEC_LOGD("Init Run....capList_.size=%{public}zu", capList_.size());
104}
105
106int32_t CodecComponentConfig::CodecCompCapabilityInit()
107{
108    const struct DeviceResourceNode *rootNode = HdfGetHcsRootNode();
109    if (rootNode == nullptr) {
110        CODEC_LOGE("GetRootNode failed");
111        return HDF_FAILURE;
112    }
113    const struct DeviceResourceNode *codecNode = HcsGetNodeByMatchAttr(rootNode, CODEC_CONFIG_NAME);
114    if (codecNode == nullptr) {
115        CODEC_LOGE("codecNode is nullptr");
116        return HDF_FAILURE;
117    }
118    OHOS::Codec::Omx::CodecComponentConfig::GetInstance()->Init(*codecNode);
119    return HDF_SUCCESS;
120}
121
122CodecComponentConfig *CodecComponentConfig::GetInstance()
123{
124    return &config_;
125}
126
127int32_t CodecComponentConfig::GetComponentNum(int32_t &count)
128{
129    count = static_cast<int32_t>(capList_.size());
130    CODEC_LOGD("enter, count = %{public}d", count);
131    return HDF_SUCCESS;
132}
133
134int32_t CodecComponentConfig::GetComponentCapabilityList(std::vector<CodecCompCapability> &capList, int32_t count)
135{
136    CODEC_LOGD("count[%{public}d], size[%{public}zu]", count, capList_.size());
137    if (count <= 0) {
138        CODEC_LOGE("count[%{public}d] is invalid", count);
139        return HDF_FAILURE;
140    }
141    if (count > static_cast<int32_t>(capList_.size())) {
142        CODEC_LOGW("count[%{public}d] is too large", count);
143        count = static_cast<int32_t>(capList_.size());
144    }
145    auto first = capList_.begin();
146    auto last = capList_.begin() + count;
147    capList.assign(first, last);
148    return HDF_SUCCESS;
149}
150
151int32_t CodecComponentConfig::GetGroupCapabilities(const std::string &nodeName)
152{
153    bool isVideoGroup = true;
154    const struct DeviceResourceNode *codecGroupNode = nullptr;
155    struct DeviceResourceNode *childNode = nullptr;
156    struct DeviceResourceIface *iface = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
157    if ((iface == nullptr) || (iface->GetUint32 == nullptr) ||
158        (iface->GetBool == nullptr) || (iface->GetString == nullptr)) {
159        CODEC_LOGE(" failed, iface or its GetUint32 or GetBool or GetString is nullptr!");
160        return HDF_ERR_INVALID_PARAM;
161    }
162
163    codecGroupNode = iface->GetChildNode(&node_, nodeName.c_str());
164    if (codecGroupNode == nullptr) {
165        CODEC_LOGE("failed to get child node: %{public}s!", nodeName.c_str());
166        return HDF_FAILURE;
167    }
168
169    if (nodeName.find("Video") == std::string::npos) {
170        isVideoGroup = false;
171    }
172
173    DEV_RES_NODE_FOR_EACH_CHILD_NODE(codecGroupNode, childNode)
174    {
175        CodecCompCapability cap;
176        if (GetOneCapability(*iface, *childNode, cap, isVideoGroup) != HDF_SUCCESS) {
177            CODEC_LOGE("GetOneCapability failed, role is %{public}d!", cap.role);
178        }
179        capList_.push_back(cap);
180    }
181
182    return HDF_SUCCESS;
183}
184
185int32_t CodecComponentConfig::GetOneCapability(const struct DeviceResourceIface &iface,
186                                               const struct DeviceResourceNode &childNode,
187                                               CodecCompCapability &cap, bool isVideoGroup)
188{
189    if (iface.GetUint32(&childNode, CODEC_CONFIG_KEY_ROLE, reinterpret_cast<uint32_t *>(&cap.role),
190                        MEDIA_ROLETYPE_INVALID) != HDF_SUCCESS) {
191        cap.role = MEDIA_ROLETYPE_INVALID;
192        CODEC_LOGE("failed to get mime for: %{public}s! Discarded", childNode.name);
193        return HDF_FAILURE;
194    }
195    if (iface.GetUint32(&childNode, CODEC_CONFIG_KEY_TYPE, reinterpret_cast<uint32_t *>(&cap.type), INVALID_TYPE) !=
196        HDF_SUCCESS) {
197        cap.role = MEDIA_ROLETYPE_INVALID;
198        cap.type = INVALID_TYPE;
199        CODEC_LOGE("failed to get type for: %{public}s! Discarded", childNode.name);
200        return HDF_FAILURE;
201    }
202
203    const char *compName = nullptr;
204    if (iface.GetString(&childNode, CODEC_CONFIG_KEY_NAME, &compName, "") != HDF_SUCCESS) {
205        cap.role = MEDIA_ROLETYPE_INVALID;
206        CODEC_LOGE("get attr %{public}s err!", CODEC_CONFIG_KEY_NAME);
207        return HDF_FAILURE;
208    }
209    if (compName == nullptr || strlen(compName) == 0) {
210        cap.role = MEDIA_ROLETYPE_INVALID;
211        CODEC_LOGE("compName is nullptr or empty!");
212        return HDF_FAILURE;
213    }
214    cap.compName = compName;
215
216    cap.isSoftwareCodec = iface.GetBool(&childNode, CODEC_CONFIG_KEY_IS_SOFTWARE_CODEC);
217    cap.canSwapWidthHeight = iface.GetBool(&childNode, CODEC_CONFIG_KEY_CAN_SWAP_WIDTH_HEIGHT);
218
219    if (GetMiscOfCapability(iface, childNode, cap) != HDF_SUCCESS) {
220        cap.role = MEDIA_ROLETYPE_INVALID;
221        CODEC_LOGE("get misc cap  err!");
222        return HDF_FAILURE;
223    }
224    if (isVideoGroup) {
225        if (GetVideoPortCapability(iface, childNode, cap) != HDF_SUCCESS) {
226            cap.role = MEDIA_ROLETYPE_INVALID;
227            CODEC_LOGE("get video port cap  err!");
228            return HDF_FAILURE;
229        }
230    } else {
231        if (GetAudioPortCapability(iface, childNode, cap) != HDF_SUCCESS) {
232            cap.role = MEDIA_ROLETYPE_INVALID;
233            CODEC_LOGE("get audio port cap  err!");
234            return HDF_FAILURE;
235        }
236    }
237
238    return HDF_SUCCESS;
239}
240
241int32_t CodecComponentConfig::GetMiscOfCapability(const struct DeviceResourceIface &iface,
242                                                  const struct DeviceResourceNode &childNode, CodecCompCapability &cap)
243{
244    ConfigUintArrayNodeAttr attr = {CODEC_CONFIG_KEY_SUPPORT_PROFILES, cap.supportProfiles};
245    if (GetUintTableConfig(iface, childNode, attr) != HDF_SUCCESS) {
246        CODEC_LOGE("get uint table config [%{public}s] err!", attr.attrName.c_str());
247        return HDF_FAILURE;
248    }
249
250    if (iface.GetUint32(&childNode, CODEC_CONFIG_KEY_MAX_INST, reinterpret_cast<uint32_t *>(&cap.maxInst), 0) !=
251        HDF_SUCCESS) {
252        CODEC_LOGE("get uint32 config [%{public}s] err!", attr.attrName.c_str());
253        return HDF_FAILURE;
254    }
255    if (GetMaskedConfig(iface, childNode, CODEC_CONFIG_KEY_PROCESS_MODE_MASK,
256                        reinterpret_cast<uint32_t &>(cap.processModeMask)) != HDF_SUCCESS) {
257        CODEC_LOGE("get masked config [%{public}s] err!", attr.attrName.c_str());
258        return HDF_FAILURE;
259    }
260    if (GetMaskedConfig(iface, childNode, CODEC_CONFIG_KEY_CAPS_MASK, static_cast<uint32_t &>(cap.capsMask)) !=
261        HDF_SUCCESS) {
262        CODEC_LOGE("get masked config [%{public}s] err!", attr.attrName.c_str());
263        return HDF_FAILURE;
264    }
265    if (iface.GetUint32(&childNode, CODEC_CONFIG_KEY_MIN_BITRATE, reinterpret_cast<uint32_t *>(&cap.bitRate.min), 0) !=
266        HDF_SUCCESS) {
267        CODEC_LOGE("get uin32 config [%{public}s] err!", attr.attrName.c_str());
268        return HDF_FAILURE;
269    }
270    if (iface.GetUint32(&childNode, CODEC_CONFIG_KEY_MAX_BITRATE, reinterpret_cast<uint32_t *>(&cap.bitRate.max), 0) !=
271        HDF_SUCCESS) {
272        CODEC_LOGE("get uin32 config [%{public}s] err!", attr.attrName.c_str());
273        return HDF_FAILURE;
274    }
275
276    return HDF_SUCCESS;
277}
278
279int32_t CodecComponentConfig::GetUintTableConfig(const struct DeviceResourceIface &iface,
280                                                 const struct DeviceResourceNode &node, ConfigUintArrayNodeAttr &attr)
281{
282    if (attr.attrName.empty()) {
283        CODEC_LOGE("failed, invalid attr!");
284        return HDF_ERR_INVALID_PARAM;
285    }
286
287    int32_t count = iface.GetElemNum(&node, attr.attrName.c_str());
288    if (count < 0) {
289        CODEC_LOGE("%{public}s table size: count[%{public}d] < 0!", attr.attrName.c_str(), count);
290        return HDF_FAILURE;
291    }
292    if (count > 0) {
293        std::unique_ptr<int32_t[]> array = std::make_unique<int32_t[]>(count);
294        iface.GetUint32Array(&node, attr.attrName.c_str(), reinterpret_cast<uint32_t *>(array.get()), count, 0);
295        attr.vec.assign(array.get(), array.get() + count);
296    }
297    return HDF_SUCCESS;
298}
299
300int32_t CodecComponentConfig::GetMaskedConfig(const struct DeviceResourceIface &iface,
301                                              const struct DeviceResourceNode &node, const std::string &attrName,
302                                              uint32_t &mask)
303{
304    int32_t count = iface.GetElemNum(&node, attrName.c_str());
305
306    mask = 0;
307    if (count < 0 || count > MASK_NUM_LIMIT) {
308        CODEC_LOGE("failed, count %{public}d incorrect!", count);
309        return HDF_FAILURE;
310    }
311
312    if (count > 0) {
313        std::unique_ptr<uint32_t[]> values = std::make_unique<uint32_t[]>(count);
314        iface.GetUint32Array(&node, attrName.c_str(), values.get(), count, 0);
315        for (int32_t index = 0; index < count; index++) {
316            mask |= values[index];
317        }
318    }
319
320    return HDF_SUCCESS;
321}
322
323int32_t CodecComponentConfig::GetVideoPortCapability(const struct DeviceResourceIface &iface,
324                                                     const struct DeviceResourceNode &childNode,
325                                                     CodecCompCapability &cap)
326{
327    ConfigUintNodeAttr nodeAttrs[] = {
328        {CODEC_CONFIG_KEY_MIN_WIDTH, cap.port.video.minSize.width, 0},
329        {CODEC_CONFIG_KEY_MIN_HEIGHT, cap.port.video.minSize.height, 0},
330        {CODEC_CONFIG_KEY_MAX_WIDTH, cap.port.video.maxSize.width, 0},
331        {CODEC_CONFIG_KEY_MAX_HEIGHT, cap.port.video.maxSize.height, 0},
332        {CODEC_CONFIG_KEY_WIDTH_ALIGNMENT, cap.port.video.whAlignment.widthAlignment, 0},
333        {CODEC_CONFIG_KEY_HEIGHT_ALIGNMENT, cap.port.video.whAlignment.heightAlignment, 0},
334        {CODEC_CONFIG_KEY_MIN_BLOCK_COUNT, cap.port.video.blockCount.min, 0},
335        {CODEC_CONFIG_KEY_MAX_BLOCK_COUNT, cap.port.video.blockCount.max, 0},
336        {CODEC_CONFIG_KEY_MIN_BLOCKS_PER_SECOND, cap.port.video.blocksPerSecond.min, 0},
337        {CODEC_CONFIG_KEY_MAX_BLOCKS_PER_SECOND, cap.port.video.blocksPerSecond.max, 0},
338        {CODEC_CONFIG_KEY_BLOCK_SIZE_WIDTH, cap.port.video.blockSize.width, 0},
339        {CODEC_CONFIG_KEY_BLOCK_SIZE_HEIGHT, cap.port.video.blockSize.height, 0},
340        {CODEC_CONFIG_KEY_MIN_FRAME_RATE, cap.port.video.frameRate.min, 0},
341        {CODEC_CONFIG_KEY_MAX_FRAME_RATE, cap.port.video.frameRate.max, 0}};
342
343    int32_t count = sizeof(nodeAttrs) / sizeof(ConfigUintNodeAttr);
344    for (int32_t i = 0; i < count; i++) {
345        if (iface.GetUint32(&childNode, nodeAttrs[i].attrName.c_str(),
346                            reinterpret_cast<uint32_t *>(&nodeAttrs[i].value),
347                            nodeAttrs[i].defaultValue) != HDF_SUCCESS) {
348            CODEC_LOGE("failed to get %{public}s.%{public}s!", childNode.name, nodeAttrs[i].attrName.c_str());
349            return HDF_FAILURE;
350        }
351    }
352    ConfigUintArrayNodeAttr arrayAttrs[] = {
353        {CODEC_CONFIG_KEY_SUPPORT_PIXEL_FMTS, cap.port.video.supportPixFmts},
354        {CODEC_CONFIG_KEY_BITE_RATE_MODE, reinterpret_cast<std::vector<int32_t> &>(cap.port.video.bitRatemode)},
355        {CODEC_CONFIG_KEY_MESURED_FRAME_RATE, cap.port.video.measuredFrameRate}};
356
357    count = sizeof(arrayAttrs) / sizeof(ConfigUintArrayNodeAttr);
358    for (int32_t i = 0; i < count; i++) {
359        if (GetUintTableConfig(iface, childNode, arrayAttrs[i]) != HDF_SUCCESS) {
360            CODEC_LOGE("failed to get %{public}s.%{public}s!", childNode.name, nodeAttrs[i].attrName.c_str());
361            return HDF_FAILURE;
362        }
363    }
364    cap.port.video.isSupportPassthrough = iface.GetBool(&childNode, CODEC_CONFIG_KEY_IS_SUPPORT_PASSTHROUGH);
365    cap.port.video.isSupportLowLatency = iface.GetBool(&childNode, CODEC_CONFIG_KEY_IS_SUPPORT_LOW_LATENCY);
366    cap.port.video.isSupportTSVC = iface.GetBool(&childNode, CODEC_CONFIG_KEY_IS_SUPPORT_TSVC);
367    cap.port.video.isSupportLTR = iface.GetBool(&childNode, CODEC_CONFIG_KEY_IS_SUPPORT_LTR);
368    if (cap.port.video.isSupportLTR) {
369        if (iface.GetUint32(&childNode, CODEC_CONFIG_KEY_MAX_LTR_FRAME_NUM,
370                            reinterpret_cast<uint32_t *>(&cap.port.video.maxLTRFrameNum), 0) != HDF_SUCCESS) {
371            CODEC_LOGE("failed to get %{public}s maxLTRFrameNum!", childNode.name);
372        }
373    }
374    cap.port.video.isSupportWaterMark = iface.GetBool(&childNode, CODEC_CONFIG_KEY_IS_SUPPORT_WATERMARK);
375    return HDF_SUCCESS;
376}
377
378int32_t CodecComponentConfig::GetAudioPortCapability(const struct DeviceResourceIface &iface,
379                                                     const struct DeviceResourceNode &childNode,
380                                                     CodecCompCapability &cap)
381{
382    ConfigUintArrayNodeAttr arrayAttrs[] = {{CODEC_CONFIG_KEY_SAMPLE_FORMATS, cap.port.audio.sampleFormats},
383                                            {CODEC_CONFIG_KEY_SAMPLE_RATE, cap.port.audio.sampleRate},
384                                            {CODEC_CONFIG_KEY_CHANNEL_LAYOUTS, cap.port.audio.channelLayouts},
385                                            {CODEC_CONFIG_KEY_CHANNEL_COUNT, cap.port.audio.channelCount}};
386
387    int32_t count = sizeof(arrayAttrs) / sizeof(ConfigUintArrayNodeAttr);
388    for (int32_t i = 0; i < count; i++) {
389        if (GetUintTableConfig(iface, childNode, arrayAttrs[i]) != HDF_SUCCESS) {
390            CODEC_LOGE("failed to get %{public}s.%{public}s!", childNode.name, arrayAttrs[i].attrName.c_str());
391            return HDF_FAILURE;
392        }
393    }
394
395    return HDF_SUCCESS;
396}
397}  // namespace Omx
398}  // namespace Codec
399}  // namespace OHOS
400