1/* 2 * Copyright (c) 2022 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 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 "native_buffer_inner.h" 17 18#include <cinttypes> 19#include "surface_type.h" 20#include "buffer_log.h" 21#include "native_window.h" 22#include "surface_buffer_impl.h" 23#include "metadata_helper.h" 24 25using namespace OHOS; 26using namespace HDI::Display::Graphic::Common::V1_0; 27static std::unordered_map<OH_NativeBuffer_ColorSpace, CM_ColorSpaceType> NATIVE_COLORSPACE_TO_HDI_MAP = { 28 {OH_COLORSPACE_NONE, CM_COLORSPACE_NONE}, 29 {OH_COLORSPACE_BT601_EBU_FULL, CM_BT601_EBU_FULL}, 30 {OH_COLORSPACE_BT601_SMPTE_C_FULL, CM_BT601_SMPTE_C_FULL}, 31 {OH_COLORSPACE_BT709_FULL, CM_BT709_FULL}, 32 {OH_COLORSPACE_BT2020_HLG_FULL, CM_BT2020_HLG_FULL}, 33 {OH_COLORSPACE_BT2020_PQ_FULL, CM_BT2020_PQ_FULL}, 34 {OH_COLORSPACE_BT601_EBU_LIMIT, CM_BT601_EBU_LIMIT}, 35 {OH_COLORSPACE_BT601_SMPTE_C_LIMIT, CM_BT601_SMPTE_C_LIMIT}, 36 {OH_COLORSPACE_BT709_LIMIT, CM_BT709_LIMIT}, 37 {OH_COLORSPACE_BT2020_HLG_LIMIT, CM_BT2020_HLG_LIMIT}, 38 {OH_COLORSPACE_BT2020_PQ_LIMIT, CM_BT2020_PQ_LIMIT}, 39 {OH_COLORSPACE_SRGB_FULL, CM_SRGB_FULL}, 40 {OH_COLORSPACE_P3_FULL, CM_P3_FULL}, 41 {OH_COLORSPACE_P3_HLG_FULL, CM_P3_HLG_FULL}, 42 {OH_COLORSPACE_P3_PQ_FULL, CM_P3_PQ_FULL}, 43 {OH_COLORSPACE_ADOBERGB_FULL, CM_ADOBERGB_FULL}, 44 {OH_COLORSPACE_SRGB_LIMIT, CM_SRGB_LIMIT}, 45 {OH_COLORSPACE_P3_LIMIT, CM_P3_LIMIT}, 46 {OH_COLORSPACE_P3_HLG_LIMIT, CM_P3_HLG_LIMIT}, 47 {OH_COLORSPACE_P3_PQ_LIMIT, CM_P3_PQ_LIMIT}, 48 {OH_COLORSPACE_ADOBERGB_LIMIT, CM_ADOBERGB_LIMIT}, 49 {OH_COLORSPACE_LINEAR_SRGB, CM_LINEAR_SRGB}, 50 {OH_COLORSPACE_LINEAR_BT709, CM_LINEAR_BT709}, 51 {OH_COLORSPACE_LINEAR_P3, CM_LINEAR_P3}, 52 {OH_COLORSPACE_LINEAR_BT2020, CM_LINEAR_BT2020}, 53 {OH_COLORSPACE_DISPLAY_SRGB, CM_DISPLAY_SRGB}, 54 {OH_COLORSPACE_DISPLAY_P3_SRGB, CM_DISPLAY_P3_SRGB}, 55 {OH_COLORSPACE_DISPLAY_P3_HLG, CM_DISPLAY_P3_HLG}, 56 {OH_COLORSPACE_DISPLAY_P3_PQ, CM_DISPLAY_P3_PQ}, 57 {OH_COLORSPACE_DISPLAY_BT2020_SRGB, CM_DISPLAY_BT2020_SRGB}, 58 {OH_COLORSPACE_DISPLAY_BT2020_HLG, CM_DISPLAY_BT2020_HLG}, 59 {OH_COLORSPACE_DISPLAY_BT2020_PQ, CM_DISPLAY_BT2020_PQ} 60}; 61 62static std::unordered_map<OH_NativeBuffer_MetadataType, CM_HDR_Metadata_Type> NATIVE_METADATATYPE_TO_HDI_MAP = { 63 {OH_VIDEO_HDR_HLG, CM_VIDEO_HLG}, 64 {OH_VIDEO_HDR_HDR10, CM_VIDEO_HDR10}, 65 {OH_VIDEO_HDR_VIVID, CM_VIDEO_HDR_VIVID}, 66}; 67 68static OH_NativeBuffer* OH_NativeBufferFromSurfaceBuffer(SurfaceBuffer* buffer) 69{ 70 if (buffer == nullptr) { 71 return nullptr; 72 } 73 return buffer->SurfaceBufferToNativeBuffer(); 74} 75 76static SurfaceBuffer* OH_NativeBufferToSurfaceBuffer(OH_NativeBuffer *buffer) 77{ 78 return SurfaceBuffer::NativeBufferToSurfaceBuffer(buffer); 79} 80 81static const SurfaceBuffer* OH_NativeBufferToSurfaceBuffer(const OH_NativeBuffer *buffer) 82{ 83 return SurfaceBuffer::NativeBufferToSurfaceBuffer(buffer); 84} 85 86OH_NativeBuffer* OH_NativeBuffer_Alloc(const OH_NativeBuffer_Config* config) 87{ 88 if (config == nullptr) { 89 return nullptr; 90 } 91 BufferRequestConfig bfConfig = {}; 92 bfConfig.width = config->width; 93 bfConfig.height = config->height; 94 bfConfig.strideAlignment = 0x8; // set 0x8 as default value to alloc SurfaceBufferImpl 95 bfConfig.format = config->format; // PixelFormat 96 bfConfig.usage = config->usage; 97 bfConfig.timeout = 0; 98 bfConfig.colorGamut = GraphicColorGamut::GRAPHIC_COLOR_GAMUT_SRGB; 99 bfConfig.transform = GraphicTransformType::GRAPHIC_ROTATE_NONE; 100 sptr<SurfaceBuffer> bufferImpl = new SurfaceBufferImpl(); 101 GSError ret = bufferImpl->Alloc(bfConfig); 102 if (ret != OHOS::SURFACE_ERROR_OK) { 103 BLOGE("Alloc failed ret: %{public}d, config info: width[%{public}d, height[%{public}d," 104 "format[%{public}d], usage[%{public}d]", ret, config->width, config->height, 105 config->format, config->usage); 106 return nullptr; 107 } 108 109 OH_NativeBuffer* buffer = OH_NativeBufferFromSurfaceBuffer(bufferImpl); 110 int32_t err = OH_NativeBuffer_Reference(buffer); 111 if (err != OHOS::SURFACE_ERROR_OK) { 112 BLOGE("NativeBufferReference failed, err: %{public}d.", err); 113 return nullptr; 114 } 115 return buffer; 116} 117 118int32_t OH_NativeBuffer_Reference(OH_NativeBuffer *buffer) 119{ 120 if (buffer == nullptr) { 121 return OHOS::GSERROR_INVALID_ARGUMENTS; 122 } 123 OHOS::RefBase *ref = reinterpret_cast<OHOS::RefBase *>(buffer); 124 ref->IncStrongRef(ref); 125 return OHOS::SURFACE_ERROR_OK; 126} 127 128int32_t OH_NativeBuffer_Unreference(OH_NativeBuffer *buffer) 129{ 130 if (buffer == nullptr) { 131 return OHOS::GSERROR_INVALID_ARGUMENTS; 132 } 133 OHOS::RefBase *ref = reinterpret_cast<OHOS::RefBase *>(buffer); 134 ref->DecStrongRef(ref); 135 return OHOS::SURFACE_ERROR_OK; 136} 137 138void OH_NativeBuffer_GetConfig(OH_NativeBuffer *buffer, OH_NativeBuffer_Config* config) 139{ 140 if (buffer == nullptr || config == nullptr) { 141 return; 142 } 143 const SurfaceBuffer* sbuffer = OH_NativeBufferToSurfaceBuffer(buffer); 144 config->width = sbuffer->GetWidth(); 145 config->height = sbuffer->GetHeight(); 146 config->format = sbuffer->GetFormat(); 147 config->usage = sbuffer->GetUsage(); 148 config->stride = sbuffer->GetStride(); 149} 150 151int32_t OH_NativeBuffer_Map(OH_NativeBuffer *buffer, void **virAddr) 152{ 153 if (buffer == nullptr || virAddr == nullptr) { 154 return OHOS::SURFACE_ERROR_INVALID_PARAM; 155 } 156 SurfaceBuffer* sbuffer = OH_NativeBufferToSurfaceBuffer(buffer); 157 int32_t ret = sbuffer->Map(); 158 if (ret == OHOS::SURFACE_ERROR_OK) { 159 *virAddr = sbuffer->GetVirAddr(); 160 } else { 161 BLOGE("Map failed, ret:%{public}d", ret); 162 ret = OHOS::SURFACE_ERROR_UNKOWN; 163 } 164 return ret; 165} 166 167int32_t OH_NativeBuffer_Unmap(OH_NativeBuffer *buffer) 168{ 169 if (buffer == nullptr) { 170 return OHOS::SURFACE_ERROR_INVALID_PARAM; 171 } 172 SurfaceBuffer* sbuffer = OH_NativeBufferToSurfaceBuffer(buffer); 173 int32_t ret = sbuffer->Unmap(); 174 if (ret != OHOS::SURFACE_ERROR_OK) { 175 BLOGE("Unmap failed, ret:%{public}d", ret); 176 ret = OHOS::SURFACE_ERROR_UNKOWN; 177 } 178 return ret; 179} 180 181uint32_t OH_NativeBuffer_GetSeqNum(OH_NativeBuffer *buffer) 182{ 183 if (buffer == nullptr) { 184 return UINT_MAX; 185 } 186 const SurfaceBuffer* sbuffer = OH_NativeBufferToSurfaceBuffer(buffer); 187 return sbuffer->GetSeqNum(); 188} 189 190const BufferHandle* OH_NativeBuffer_GetBufferHandle(const OH_NativeBuffer *buffer) 191{ 192 if (buffer == nullptr) { 193 return nullptr; 194 } 195 const SurfaceBuffer* sbuffer = OH_NativeBufferToSurfaceBuffer(buffer); 196 return sbuffer->GetBufferHandle(); 197} 198 199void OH_NativeBuffer_GetNativeBufferConfig(const OH_NativeBuffer *buffer, OH_NativeBuffer_Config* config) 200{ 201 if (buffer == nullptr || config == nullptr) { 202 return; 203 } 204 const SurfaceBuffer* sbuffer = OH_NativeBufferToSurfaceBuffer(buffer); 205 config->width = sbuffer->GetWidth(); 206 config->height = sbuffer->GetHeight(); 207 config->format = sbuffer->GetFormat(); 208 config->usage = sbuffer->GetUsage(); 209 config->stride = sbuffer->GetStride(); 210} 211 212OH_NativeBuffer* OH_NativeBufferFromNativeWindowBuffer(OHNativeWindowBuffer* nativeWindowBuffer) 213{ 214 if (nativeWindowBuffer == nullptr) { 215 return nullptr; 216 } 217 OH_NativeBuffer* buffer = OH_NativeBufferFromSurfaceBuffer(nativeWindowBuffer->sfbuffer); 218 return buffer; 219} 220 221int32_t OH_NativeBuffer_SetColorSpace(OH_NativeBuffer *buffer, OH_NativeBuffer_ColorSpace colorSpace) 222{ 223 if (buffer == nullptr || NATIVE_COLORSPACE_TO_HDI_MAP.find(colorSpace) == NATIVE_COLORSPACE_TO_HDI_MAP.end()) { 224 return OHOS::SURFACE_ERROR_INVALID_PARAM; 225 } 226 sptr<SurfaceBuffer> sbuffer = OH_NativeBufferToSurfaceBuffer(buffer); 227 GSError ret = MetadataHelper::SetColorSpaceType(sbuffer, NATIVE_COLORSPACE_TO_HDI_MAP[colorSpace]); 228 if (ret == OHOS::GSERROR_HDI_ERROR) { 229 return OHOS::SURFACE_ERROR_NOT_SUPPORT; 230 } else if (ret != OHOS::SURFACE_ERROR_OK) { 231 return OHOS::SURFACE_ERROR_UNKOWN; 232 } 233 return OHOS::SURFACE_ERROR_OK; 234} 235 236int32_t OH_NativeBuffer_MapPlanes(OH_NativeBuffer *buffer, void **virAddr, OH_NativeBuffer_Planes *outPlanes) 237{ 238 if (buffer == nullptr || virAddr == nullptr || outPlanes == nullptr) { 239 return OHOS::SURFACE_ERROR_INVALID_PARAM; 240 } 241 sptr<SurfaceBuffer> sbuffer = OH_NativeBufferToSurfaceBuffer(buffer); 242 int32_t ret = sbuffer->Map(); 243 if (ret == OHOS::SURFACE_ERROR_OK) { 244 *virAddr = sbuffer->GetVirAddr(); 245 } else { 246 BLOGE("Map failed, %{public}d", ret); 247 return ret; 248 } 249 OH_NativeBuffer_Planes *planes = nullptr; 250 GSError retVal = sbuffer->GetPlanesInfo(reinterpret_cast<void**>(&planes)); 251 if (retVal != OHOS::SURFACE_ERROR_OK) { 252 BLOGE("GetPlanesInfo failed, retVal:%{public}d", retVal); 253 return retVal; 254 } 255 outPlanes->planeCount = planes->planeCount; 256 for (uint32_t i = 0; i < planes->planeCount && i < 4; i++) { // 4: max plane count 257 outPlanes->planes[i].offset = planes->planes[i].offset; 258 outPlanes->planes[i].rowStride = planes->planes[i].rowStride; 259 outPlanes->planes[i].columnStride = planes->planes[i].columnStride; 260 } 261 return OHOS::SURFACE_ERROR_OK; 262} 263 264int32_t OH_NativeBuffer_FromNativeWindowBuffer(OHNativeWindowBuffer *nativeWindowBuffer, OH_NativeBuffer **buffer) 265{ 266 if (nativeWindowBuffer == nullptr || buffer == nullptr) { 267 return OHOS::SURFACE_ERROR_INVALID_PARAM; 268 } 269 *buffer = OH_NativeBufferFromSurfaceBuffer(nativeWindowBuffer->sfbuffer); 270 if (*buffer == nullptr) { 271 BLOGE("get sfbuffer is nullptr"); 272 return OHOS::GSERROR_INVALID_OPERATING; 273 } 274 return OHOS::SURFACE_ERROR_OK; 275} 276 277int32_t OH_NativeBuffer_GetColorSpace(OH_NativeBuffer *buffer, OH_NativeBuffer_ColorSpace *colorSpace) 278{ 279 if (buffer == nullptr || colorSpace == nullptr) { 280 return OHOS::SURFACE_ERROR_INVALID_PARAM; 281 } 282 sptr<SurfaceBuffer> sbuffer = OH_NativeBufferToSurfaceBuffer(buffer); 283 OHOS::HDI::Display::Graphic::Common::V1_0::CM_ColorSpaceType colorSpaceType; 284 GSError ret = MetadataHelper::GetColorSpaceType(sbuffer, colorSpaceType); 285 if (ret == OHOS::GSERROR_HDI_ERROR) { 286 return OHOS::SURFACE_ERROR_NOT_SUPPORT; 287 } else if (ret != OHOS::SURFACE_ERROR_OK) { 288 BLOGE("GetColorSpaceType failed!, retVal:%{public}d", ret); 289 return OHOS::SURFACE_ERROR_UNKOWN; 290 } 291 auto it = std::find_if(NATIVE_COLORSPACE_TO_HDI_MAP.begin(), NATIVE_COLORSPACE_TO_HDI_MAP.end(), 292 [colorSpaceType](const std::pair<OH_NativeBuffer_ColorSpace, CM_ColorSpaceType>& element) { 293 return element.second == colorSpaceType; 294 }); 295 if (it != NATIVE_COLORSPACE_TO_HDI_MAP.end()) { 296 *colorSpace = it->first; 297 return OHOS::SURFACE_ERROR_OK; 298 } 299 BLOGE("the colorSpace does not support it."); 300 return OHOS::SURFACE_ERROR_UNKOWN; 301} 302 303int32_t OH_NativeBuffer_SetMetadataValue(OH_NativeBuffer *buffer, OH_NativeBuffer_MetadataKey metadataKey, 304 int32_t size, uint8_t *metadata) 305{ 306 if (buffer == nullptr || metadata == nullptr || size <= 0) { 307 return OHOS::SURFACE_ERROR_INVALID_PARAM; 308 } 309 sptr<SurfaceBuffer> sbuffer = OH_NativeBufferToSurfaceBuffer(buffer); 310 GSError ret = GSERROR_OK; 311 std::vector<uint8_t> mD(metadata, metadata + size); 312 if (metadataKey == OH_HDR_DYNAMIC_METADATA) { 313 ret = MetadataHelper::SetHDRDynamicMetadata(sbuffer, mD); 314 } else if (metadataKey == OH_HDR_STATIC_METADATA) { 315 ret = MetadataHelper::SetHDRStaticMetadata(sbuffer, mD); 316 } else if (metadataKey == OH_HDR_METADATA_TYPE) { 317 OH_NativeBuffer_MetadataType hdrMetadataType = static_cast<OH_NativeBuffer_MetadataType>(*metadata); 318 ret = MetadataHelper::SetHDRMetadataType(sbuffer, NATIVE_METADATATYPE_TO_HDI_MAP[hdrMetadataType]); 319 } else { 320 BLOGE("the metadataKey does not support it."); 321 return OHOS::SURFACE_ERROR_UNKOWN; 322 } 323 if (ret == OHOS::GSERROR_HDI_ERROR) { 324 return OHOS::SURFACE_ERROR_NOT_SUPPORT; 325 } else if (ret != OHOS::SURFACE_ERROR_OK) { 326 BLOGE("SetHDRMetadata failed!, retVal:%{public}d", ret); 327 return OHOS::SURFACE_ERROR_UNKOWN; 328 } 329 return OHOS::SURFACE_ERROR_OK; 330} 331 332static GSError OH_NativeBuffer_GetMatedataValueType(sptr<SurfaceBuffer> sbuffer, int32_t *size, uint8_t **metadata) 333{ 334 CM_HDR_Metadata_Type hdrMetadataType = CM_METADATA_NONE; 335 GSError ret = MetadataHelper::GetHDRMetadataType(sbuffer, hdrMetadataType); 336 if (ret == OHOS::GSERROR_HDI_ERROR) { 337 return OHOS::SURFACE_ERROR_NOT_SUPPORT; 338 } else if (ret != OHOS::SURFACE_ERROR_OK) { 339 BLOGE("GetHDRMetadataType failed!, ret: %{public}d", ret); 340 return OHOS::SURFACE_ERROR_UNKOWN; 341 } 342 auto it = std::find_if(NATIVE_METADATATYPE_TO_HDI_MAP.begin(), NATIVE_METADATATYPE_TO_HDI_MAP.end(), 343 [hdrMetadataType](const std::pair<OH_NativeBuffer_MetadataType, CM_HDR_Metadata_Type>& element) { 344 return element.second == hdrMetadataType; 345 }); 346 if (it != NATIVE_METADATATYPE_TO_HDI_MAP.end()) { 347 *size = sizeof(OH_NativeBuffer_MetadataType); 348 *metadata = new uint8_t[*size]; 349 errno_t err = memcpy_s(*metadata, *size, &(it->first), *size); 350 if (err != 0) { 351 delete[] *metadata; 352 *metadata = nullptr; 353 BLOGE("memcpy_s failed!, ret: %{public}d", err); 354 return OHOS::SURFACE_ERROR_UNKOWN; 355 } 356 return OHOS::SURFACE_ERROR_OK; 357 } 358 BLOGE("the hdrMetadataType does not support it."); 359 return OHOS::SURFACE_ERROR_NOT_SUPPORT; 360} 361 362int32_t OH_NativeBuffer_GetMetadataValue(OH_NativeBuffer *buffer, OH_NativeBuffer_MetadataKey metadataKey, 363 int32_t *size, uint8_t **metadata) 364{ 365 if (buffer == nullptr || metadata == nullptr || size == nullptr) { 366 return OHOS::SURFACE_ERROR_INVALID_PARAM; 367 } 368 sptr<SurfaceBuffer> sbuffer = OH_NativeBufferToSurfaceBuffer(buffer); 369 GSError ret = GSERROR_OK; 370 std::vector<uint8_t> mD; 371 if (metadataKey == OH_HDR_DYNAMIC_METADATA) { 372 ret = MetadataHelper::GetHDRDynamicMetadata(sbuffer, mD); 373 } else if (metadataKey == OH_HDR_STATIC_METADATA) { 374 ret = MetadataHelper::GetHDRStaticMetadata(sbuffer, mD); 375 } else if (metadataKey == OH_HDR_METADATA_TYPE) { 376 ret = OH_NativeBuffer_GetMatedataValueType(sbuffer, size, metadata); 377 return ret; 378 } else { 379 BLOGE("the metadataKey does not support it."); 380 return OHOS::SURFACE_ERROR_UNKOWN; 381 } 382 if (ret == OHOS::GSERROR_HDI_ERROR) { 383 return OHOS::SURFACE_ERROR_NOT_SUPPORT; 384 } else if (ret != OHOS::SURFACE_ERROR_OK) { 385 BLOGE("SetHDRSMetadata failed!, ret: %{public}d", ret); 386 return OHOS::SURFACE_ERROR_UNKOWN; 387 } 388 *size = mD.size(); 389 if (mD.empty()) { 390 BLOGE("Metadata is empty!"); 391 return OHOS::SURFACE_ERROR_UNKOWN; 392 } 393 *metadata = new uint8_t[mD.size()]; 394 errno_t err = memcpy_s(*metadata, mD.size(), &mD[0], mD.size()); 395 if (err != 0) { 396 delete[] *metadata; 397 *metadata = nullptr; 398 BLOGE("memcpy_s failed!, ret: %{public}d", err); 399 return OHOS::SURFACE_ERROR_UNKOWN; 400 } 401 return OHOS::SURFACE_ERROR_OK; 402}