• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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