1 /*
2 * Copyright (C) 2025 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 #define MLOG_TAG "Thumbnail"
16
17 #include "thumbnail_image_framework_utils.h"
18
19 #include <securec.h>
20
21 #include "exif_metadata.h"
22 #include "hdr_type.h"
23 #include "v1_0/buffer_handle_meta_key_type.h"
24
25 #include "medialibrary_errno.h"
26 #include "medialibrary_tracer.h"
27 #include "media_exif.h"
28 #include "media_log.h"
29 #include "thumbnail_const.h"
30
31 using namespace std;
32 using namespace OHOS::HDI::Display::Graphic::Common::V1_0;
33
34 namespace OHOS {
35 namespace Media {
36
37 static constexpr int32_t PLANE_Y = 0;
38 static constexpr int32_t PLANE_U = 1;
39 static constexpr int32_t PLANE_V = 2;
40 static constexpr uint8_t HDR_PIXEL_SIZE = 2;
41 static constexpr uint8_t SDR_PIXEL_SIZE = 1;
42 static const std::map<std::string, int32_t> ORIENTATION_INT_MAP = {
43 {"Top-left", 0},
44 {"Bottom-right", 180},
45 {"Right-top", 90},
46 {"Left-bottom", 270},
47 };
48
IsYuvPixelMap(std::shared_ptr<PixelMap> pixelMap)49 bool ThumbnailImageFrameWorkUtils::IsYuvPixelMap(std::shared_ptr<PixelMap> pixelMap)
50 {
51 CHECK_AND_RETURN_RET_LOG(pixelMap != nullptr, false, "PixelMap is nullptr");
52 PixelFormat format = pixelMap->GetPixelFormat();
53 return format == PixelFormat::NV21 || format == PixelFormat::NV12 ||
54 format == PixelFormat::YCRCB_P010 || format == PixelFormat::YCBCR_P010;
55 }
56
IsSupportCopyPixelMap(std::shared_ptr<PixelMap> pixelMap)57 bool ThumbnailImageFrameWorkUtils::IsSupportCopyPixelMap(std::shared_ptr<PixelMap> pixelMap)
58 {
59 CHECK_AND_RETURN_RET_LOG(pixelMap != nullptr, false, "PixelMap is nullptr");
60 if (!IsYuvPixelMap(pixelMap)) {
61 return true;
62 }
63 PixelFormat format = pixelMap->GetPixelFormat();
64 CHECK_AND_RETURN_RET_LOG(format == PixelFormat::NV21 || format == PixelFormat::NV12, false,
65 "Not support copy pixelMap, format:%{public}d", format);
66 return true;
67 }
68
CopyPictureSource(std::shared_ptr<Picture> picture)69 std::shared_ptr<Picture> ThumbnailImageFrameWorkUtils::CopyPictureSource(std::shared_ptr<Picture> picture)
70 {
71 CHECK_AND_RETURN_RET_LOG(picture != nullptr, nullptr, "Picture is nullptr");
72 MediaLibraryTracer tracer;
73 tracer.Start("CopyPictureSource");
74 auto pixelMap = picture->GetMainPixel();
75 auto gainMap = picture->GetGainmapPixelMap();
76 CHECK_AND_RETURN_RET_LOG(pixelMap != nullptr && gainMap != nullptr, nullptr,
77 "PixelMap or gainMap is nullptr");
78 MEDIA_INFO_LOG("Picture information: pixelMap format:%{public}d isHdr:%{public}d allocatorType:%{public}d, "
79 "gainMap format:%{public}d isHdr:%{public}d allocatorType:%{public}d, size: %{public}d * %{public}d",
80 pixelMap->GetPixelFormat(), pixelMap->IsHdr(), pixelMap->GetAllocatorType(), gainMap->GetPixelFormat(),
81 gainMap->IsHdr(), gainMap->GetAllocatorType(), pixelMap->GetWidth(), pixelMap->GetHeight());
82
83 std::shared_ptr<PixelMap> copyPixelMap = CopyPixelMapSource(pixelMap);
84 CHECK_AND_RETURN_RET_LOG(copyPixelMap != nullptr, nullptr, "Copy pixelMap failed");
85
86 std::shared_ptr<PixelMap> copyGainMap = CopyPixelMapSource(gainMap);
87 CHECK_AND_RETURN_RET_LOG(copyGainMap != nullptr, nullptr, "Copy gainMap failed");
88
89 Size copyGainMapSize = {copyGainMap->GetWidth(), copyGainMap->GetHeight()};
90 auto auxiliaryPicturePtr = AuxiliaryPicture::Create(copyGainMap, AuxiliaryPictureType::GAINMAP, copyGainMapSize);
91 std::shared_ptr<AuxiliaryPicture> auxiliaryPicture = std::move(auxiliaryPicturePtr);
92 CHECK_AND_RETURN_RET_LOG(auxiliaryPicture != nullptr, nullptr, "Create auxiliaryPicture failed");
93
94 auto copySourcePtr = Picture::Create(copyPixelMap);
95 std::shared_ptr<Picture> copySource = std::move(copySourcePtr);
96 copySource->SetAuxiliaryPicture(auxiliaryPicture);
97 return copySource;
98 }
99
CopyPixelMapSource(std::shared_ptr<PixelMap> pixelMap)100 std::shared_ptr<PixelMap> ThumbnailImageFrameWorkUtils::CopyPixelMapSource(std::shared_ptr<PixelMap> pixelMap)
101 {
102 CHECK_AND_RETURN_RET_LOG(IsSupportCopyPixelMap(pixelMap), nullptr, "Not support copy pixelMap");
103 if (IsYuvPixelMap(pixelMap)) {
104 return CopyYuvPixelmap(pixelMap);
105 }
106 return CopyNormalPixelmap(pixelMap);
107 }
108
CopyNormalPixelmap(std::shared_ptr<PixelMap> pixelMap)109 std::shared_ptr<PixelMap> ThumbnailImageFrameWorkUtils::CopyNormalPixelmap(std::shared_ptr<PixelMap> pixelMap)
110 {
111 MediaLibraryTracer tracer;
112 tracer.Start("CopyNormalPixelmap");
113 Media::InitializationOptions pixelMapOpts = {
114 .size = {pixelMap->GetWidth(), pixelMap->GetHeight()},
115 .pixelFormat = pixelMap->GetPixelFormat(),
116 .alphaType = pixelMap->GetAlphaType()
117 };
118 auto copyPixelMapPtr = PixelMap::Create(*pixelMap, pixelMapOpts);
119 std::shared_ptr<PixelMap> copyPixelMap = std::move(copyPixelMapPtr);
120 CHECK_AND_RETURN_RET_LOG(copyPixelMap != nullptr, nullptr, "CopyNormalPixelmap failed");
121 return copyPixelMap;
122 }
123
CopyYuvPixelmap(std::shared_ptr<PixelMap> pixelMap)124 std::shared_ptr<PixelMap> ThumbnailImageFrameWorkUtils::CopyYuvPixelmap(std::shared_ptr<PixelMap> pixelMap)
125 {
126 if (pixelMap->GetAllocatorType() == AllocatorType::DMA_ALLOC) {
127 return CopyYuvPixelmapWithSurfaceBuffer(pixelMap);
128 }
129 return CopyNoSurfaceBufferYuvPixelmap(pixelMap);
130 }
131
CopyYuvPixelmapWithSurfaceBuffer(std::shared_ptr<PixelMap> pixelMap)132 std::shared_ptr<PixelMap> ThumbnailImageFrameWorkUtils::CopyYuvPixelmapWithSurfaceBuffer(
133 std::shared_ptr<PixelMap> pixelMap)
134 {
135 MediaLibraryTracer tracer;
136 tracer.Start("CopyYuvPixelmapWithSurfaceBuffer");
137 CHECK_AND_RETURN_RET_LOG(pixelMap->GetFd() != nullptr, nullptr, "Get fd failed");
138 sptr<SurfaceBuffer> surfaceBuffer = reinterpret_cast<SurfaceBuffer *>(pixelMap->GetFd());
139 CHECK_AND_RETURN_RET_LOG(surfaceBuffer != nullptr, nullptr, "Get surfaceBuffer failed");
140 sptr<SurfaceBuffer> dstSurfaceBuffer = SurfaceBuffer::Create();
141 CHECK_AND_RETURN_RET_LOG(dstSurfaceBuffer != nullptr, nullptr, "Create surfaceBuffer failed");
142
143 BufferRequestConfig requestConfig = {
144 .width = surfaceBuffer->GetWidth(),
145 .height = surfaceBuffer->GetHeight(),
146 .strideAlignment = 0x2,
147 .format = surfaceBuffer->GetFormat(),
148 .usage = surfaceBuffer->GetUsage(),
149 .timeout = 0,
150 };
151 GSError allocRes = dstSurfaceBuffer->Alloc(requestConfig);
152 CHECK_AND_RETURN_RET_LOG(allocRes == 0, nullptr, "Alloc surfaceBuffer failed, err:%{public}d", allocRes);
153 CopySurfaceBufferInfo(surfaceBuffer, dstSurfaceBuffer);
154 int32_t copyRes = memcpy_s(dstSurfaceBuffer->GetVirAddr(), dstSurfaceBuffer->GetSize(),
155 surfaceBuffer->GetVirAddr(), surfaceBuffer->GetSize());
156 CHECK_AND_RETURN_RET_LOG(copyRes == E_OK, nullptr,
157 "Copy surface buffer pixels failed, copyRes %{public}d", copyRes);
158
159 InitializationOptions opts;
160 opts.size.width = pixelMap->GetWidth();
161 opts.size.height = pixelMap->GetHeight();
162 opts.srcPixelFormat = pixelMap->GetPixelFormat();
163 opts.pixelFormat = pixelMap->GetPixelFormat();
164 opts.useDMA = true;
165 std::shared_ptr<PixelMap> copyPixelMap = PixelMap::Create(opts);
166 CHECK_AND_RETURN_RET_LOG(copyPixelMap != nullptr, nullptr, "Create pixelMap failed");
167
168 void* nativeBuffer = dstSurfaceBuffer.GetRefPtr();
169 RefBase *ref = reinterpret_cast<RefBase *>(nativeBuffer);
170 ref->IncStrongRef(ref);
171 copyPixelMap->SetHdrType(pixelMap->GetHdrType());
172 copyPixelMap->InnerSetColorSpace(pixelMap->InnerGetGrColorSpace());
173 copyPixelMap->SetPixelsAddr(dstSurfaceBuffer->GetVirAddr(), dstSurfaceBuffer.GetRefPtr(),
174 dstSurfaceBuffer->GetSize(), AllocatorType::DMA_ALLOC, nullptr);
175 CHECK_AND_RETURN_RET_LOG(SetPixelMapYuvInfo(dstSurfaceBuffer, copyPixelMap, pixelMap->IsHdr()), nullptr,
176 "SetPixelMapYuvInfo failed");
177 return copyPixelMap;
178 }
179
CopyNoSurfaceBufferYuvPixelmap(std::shared_ptr<PixelMap> pixelMap)180 std::shared_ptr<PixelMap> ThumbnailImageFrameWorkUtils::CopyNoSurfaceBufferYuvPixelmap(
181 std::shared_ptr<PixelMap> pixelMap)
182 {
183 MediaLibraryTracer tracer;
184 tracer.Start("CopyNoSurfaceBufferYuvPixelmap");
185 auto startPtr = pixelMap->GetPixels();
186 InitializationOptions opts;
187 opts.size.width = pixelMap->GetWidth();
188 opts.size.height = pixelMap->GetHeight();
189 opts.pixelFormat = pixelMap->GetPixelFormat();
190 std::shared_ptr<PixelMap> copyPixelMap = PixelMap::Create(opts);
191 int32_t copyRes = memcpy_s(copyPixelMap->GetWritablePixels(), pixelMap->GetByteCount(),
192 startPtr, pixelMap->GetByteCount());
193 CHECK_AND_RETURN_RET_LOG(copyRes == E_OK, nullptr,
194 "CopyNoSurfaceBufferYuvPixelmap failed, copyRes:%{public}d", copyRes);
195 sptr<SurfaceBuffer> surfaceBuffer = nullptr;
196 CHECK_AND_RETURN_RET_LOG(SetPixelMapYuvInfo(surfaceBuffer, copyPixelMap, false), nullptr,
197 "SetPixelMapYuvInfo failed");
198 return copyPixelMap;
199 }
200
SetPixelMapYuvInfo(sptr<SurfaceBuffer> & surfaceBuffer,std::shared_ptr<PixelMap> pixelMap,bool isHdr)201 bool ThumbnailImageFrameWorkUtils::SetPixelMapYuvInfo(sptr<SurfaceBuffer> &surfaceBuffer,
202 std::shared_ptr<PixelMap> pixelMap, bool isHdr)
203 {
204 CHECK_AND_RETURN_RET_LOG(pixelMap != nullptr, false, "PixelMap is nullptr");
205 uint8_t ratio = isHdr ? HDR_PIXEL_SIZE : SDR_PIXEL_SIZE;
206 int32_t srcWidth = pixelMap->GetWidth();
207 int32_t srcHeight = pixelMap->GetHeight();
208 YUVDataInfo yuvDataInfo = { .yWidth = srcWidth,
209 .yHeight = srcHeight,
210 .uvWidth = srcWidth / 2,
211 .uvHeight = srcHeight / 2,
212 .yStride = srcWidth,
213 .uvStride = srcWidth,
214 .uvOffset = srcWidth * srcHeight};
215
216 if (surfaceBuffer == nullptr) {
217 pixelMap->SetImageYUVInfo(yuvDataInfo);
218 return true;
219 }
220 OH_NativeBuffer_Planes *planes = nullptr;
221 GSError retVal = surfaceBuffer->GetPlanesInfo(reinterpret_cast<void**>(&planes));
222 if (retVal != OHOS::GSERROR_OK || planes == nullptr) {
223 pixelMap->SetImageYUVInfo(yuvDataInfo);
224 return true;
225 }
226
227 auto format = pixelMap->GetPixelFormat();
228 if (format == PixelFormat::NV12) {
229 yuvDataInfo.yStride = planes->planes[PLANE_Y].columnStride / ratio;
230 yuvDataInfo.uvStride = planes->planes[PLANE_U].columnStride / ratio;
231 yuvDataInfo.yOffset = planes->planes[PLANE_Y].offset / ratio;
232 yuvDataInfo.uvOffset = planes->planes[PLANE_U].offset / ratio;
233 } else if (format == PixelFormat::NV21) {
234 yuvDataInfo.yStride = planes->planes[PLANE_Y].columnStride / ratio;
235 yuvDataInfo.uvStride = planes->planes[PLANE_V].columnStride / ratio;
236 yuvDataInfo.yOffset = planes->planes[PLANE_Y].offset / ratio;
237 yuvDataInfo.uvOffset = planes->planes[PLANE_V].offset / ratio;
238 } else {
239 MEDIA_ERR_LOG("Not support SetImageYUVInfo, format:%{public}d", format);
240 return false;
241 }
242
243 pixelMap->SetImageYUVInfo(yuvDataInfo);
244 return true;
245 }
246
GetPictureOrientation(std::shared_ptr<Picture> picture,int32_t & orientation)247 int32_t ThumbnailImageFrameWorkUtils::GetPictureOrientation(std::shared_ptr<Picture> picture, int32_t &orientation)
248 {
249 CHECK_AND_RETURN_RET_LOG(picture != nullptr, E_ERR, "Picture is nullptr");
250 std::shared_ptr<ExifMetadata> exifMetadata = picture->GetExifMetadata();
251 CHECK_AND_RETURN_RET_LOG(exifMetadata != nullptr, E_ERR, "ExifMetadata is nullptr");
252
253 std::string orientationStr;
254 int32_t err = exifMetadata->GetValue(PHOTO_DATA_IMAGE_ORIENTATION, orientationStr);
255 CHECK_AND_RETURN_RET_LOG(err == E_OK, err, "Get orientation failed, err:%{public}d", err);
256 CHECK_AND_RETURN_RET_LOG(ORIENTATION_INT_MAP.count(orientationStr) != 0, E_ERR, "Orientation is invalid");
257 orientation = ORIENTATION_INT_MAP.at(orientationStr);
258 return E_OK;
259 }
260
CopySurfaceBufferInfo(sptr<SurfaceBuffer> & source,sptr<SurfaceBuffer> & dst)261 void ThumbnailImageFrameWorkUtils::CopySurfaceBufferInfo(sptr<SurfaceBuffer> &source, sptr<SurfaceBuffer> &dst)
262 {
263 MediaLibraryTracer tracer;
264 tracer.Start("CopySurfaceBufferInfo");
265 CHECK_AND_RETURN_LOG(source != nullptr && dst != nullptr,
266 "CopySurfaceBufferInfo failed, source or dst is nullptr");
267 std::vector<uint8_t> hdrMetadataTypeVec;
268 std::vector<uint8_t> colorSpaceInfoVec;
269 std::vector<uint8_t> staticData;
270 std::vector<uint8_t> dynamicData;
271
272 if (source->GetMetadata(ATTRKEY_HDR_METADATA_TYPE, hdrMetadataTypeVec) == GSERROR_OK) {
273 dst->SetMetadata(ATTRKEY_HDR_METADATA_TYPE, hdrMetadataTypeVec);
274 }
275 if (source->GetMetadata(ATTRKEY_COLORSPACE_INFO, colorSpaceInfoVec) == GSERROR_OK) {
276 dst->SetMetadata(ATTRKEY_COLORSPACE_INFO, colorSpaceInfoVec);
277 }
278 if (GetSbStaticMetadata(source, staticData) && (staticData.size() > 0)) {
279 SetSbStaticMetadata(dst, staticData);
280 }
281 if (GetSbDynamicMetadata(source, dynamicData) && (dynamicData.size()) > 0) {
282 SetSbDynamicMetadata(dst, dynamicData);
283 }
284 }
285
GetSbStaticMetadata(const sptr<SurfaceBuffer> & buffer,std::vector<uint8_t> & staticMetadata)286 bool ThumbnailImageFrameWorkUtils::GetSbStaticMetadata(const sptr<SurfaceBuffer> &buffer,
287 std::vector<uint8_t> &staticMetadata)
288 {
289 return buffer->GetMetadata(ATTRKEY_HDR_STATIC_METADATA, staticMetadata) == GSERROR_OK;
290 }
291
GetSbDynamicMetadata(const sptr<SurfaceBuffer> & buffer,std::vector<uint8_t> & dynamicMetadata)292 bool ThumbnailImageFrameWorkUtils::GetSbDynamicMetadata(const sptr<SurfaceBuffer> &buffer,
293 std::vector<uint8_t> &dynamicMetadata)
294 {
295 return buffer->GetMetadata(ATTRKEY_HDR_DYNAMIC_METADATA, dynamicMetadata) == GSERROR_OK;
296 }
297
SetSbStaticMetadata(sptr<SurfaceBuffer> & buffer,const std::vector<uint8_t> & staticMetadata)298 bool ThumbnailImageFrameWorkUtils::SetSbStaticMetadata(sptr<SurfaceBuffer> &buffer,
299 const std::vector<uint8_t> &staticMetadata)
300 {
301 return buffer->SetMetadata(ATTRKEY_HDR_STATIC_METADATA, staticMetadata) == GSERROR_OK;
302 }
303
SetSbDynamicMetadata(sptr<SurfaceBuffer> & buffer,const std::vector<uint8_t> & dynamicMetadata)304 bool ThumbnailImageFrameWorkUtils::SetSbDynamicMetadata(sptr<SurfaceBuffer> &buffer,
305 const std::vector<uint8_t> &dynamicMetadata)
306 {
307 return buffer->SetMetadata(ATTRKEY_HDR_DYNAMIC_METADATA, dynamicMetadata) == GSERROR_OK;
308 }
309 } // namespace Media
310 } // namespace OHOS