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