• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 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 "post_proc.h"
17 
18 #include <memory>
19 #include <unistd.h>
20 
21 #include "basic_transformer.h"
22 #include "image_log.h"
23 #include "image_system_properties.h"
24 #include "image_trace.h"
25 #include "image_type.h"
26 #include "image_utils.h"
27 #include "media_errors.h"
28 #include "memory_manager.h"
29 #include "pixel_convert_adapter.h"
30 #ifndef _WIN32
31 #include "securec.h"
32 #else
33 #include "memory.h"
34 #endif
35 #if !defined(_WIN32) && !defined(_APPLE) && !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)
36 #include <sys/mman.h>
37 #include "ashmem.h"
38 #include "surface_buffer.h"
39 #include "vpe_utils.h"
40 #include "pixel_map_program_manager.h"
41 #ifdef __cplusplus
42 extern "C" {
43 #endif
44 #include "libswscale/swscale.h"
45 #ifdef __cplusplus
46 };
47 #endif
48 #endif
49 
50 #undef LOG_DOMAIN
51 #define LOG_DOMAIN LOG_TAG_DOMAIN_ID_IMAGE
52 
53 #undef LOG_TAG
54 #define LOG_TAG "PostProc"
55 
56 namespace OHOS {
57 namespace Media {
58 using namespace std;
59 constexpr uint32_t NEED_NEXT = 1;
60 constexpr float EPSILON = 1e-6;
61 constexpr uint8_t HALF = 2;
62 constexpr float HALF_F = 2;
63 constexpr int FFMPEG_NUM = 8;
64 constexpr int SLR_CACHE_CAPACITY = 256;
65 
66 #if !defined(_WIN32) && !defined(_APPLE) && !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)
67 static const map<PixelFormat, AVPixelFormat> PIXEL_FORMAT_MAP = {
68     { PixelFormat::ALPHA_8, AVPixelFormat::AV_PIX_FMT_GRAY8 },
69     { PixelFormat::RGB_565, AVPixelFormat::AV_PIX_FMT_RGB565BE },
70     { PixelFormat::RGB_888, AVPixelFormat::AV_PIX_FMT_RGB24 },
71     { PixelFormat::RGBA_8888, AVPixelFormat::AV_PIX_FMT_RGBA },
72     { PixelFormat::ARGB_8888, AVPixelFormat::AV_PIX_FMT_ARGB },
73     { PixelFormat::BGRA_8888, AVPixelFormat::AV_PIX_FMT_BGRA },
74     { PixelFormat::RGBA_F16, AVPixelFormat::AV_PIX_FMT_RGBA64BE },
75 };
76 #endif
77 
DecodePostProc(const DecodeOptions & opts,PixelMap & pixelMap,FinalOutputStep finalOutputStep)78 uint32_t PostProc::DecodePostProc(const DecodeOptions &opts, PixelMap &pixelMap, FinalOutputStep finalOutputStep)
79 {
80     if (opts.cropAndScaleStrategy == CropAndScaleStrategy::SCALE_FIRST && opts.desiredSize.height > 0 &&
81         opts.desiredSize.width > 0) {
82         CHECK_ERROR_RETURN_RET_LOG(!ScalePixelMap(opts.desiredSize, pixelMap), ERR_IMAGE_TRANSFORM,
83             "[PostProc]scale:transform pixelMap failed");
84         CHECK_ERROR_RETURN_RET_LOG(pixelMap.crop(opts.CropRect) != SUCCESS, ERR_IMAGE_TRANSFORM,
85             "[PostProc]crop:transform pixelMap failed");
86     } else {
87         ImageInfo srcImageInfo;
88         pixelMap.GetImageInfo(srcImageInfo);
89         ImageInfo dstImageInfo;
90         GetDstImageInfo(opts, pixelMap, srcImageInfo, dstImageInfo);
91         uint32_t errorCode = ConvertProc(opts.CropRect, dstImageInfo, pixelMap, srcImageInfo);
92         if (errorCode != SUCCESS) {
93             IMAGE_LOGE("[PostProc]crop pixel map failed, errcode:%{public}u", errorCode);
94             return errorCode;
95         }
96     }
97     bool cond = false;
98     decodeOpts_.allocatorType = opts.allocatorType;
99     bool isNeedRotate = !ImageUtils::FloatCompareZero(opts.rotateDegrees);
100     if (isNeedRotate) {
101         cond = !RotatePixelMap(opts.rotateDegrees, pixelMap);
102         CHECK_ERROR_RETURN_RET_LOG(cond, ERR_IMAGE_TRANSFORM, "[PostProc]rotate:transform pixel map failed");
103     }
104     decodeOpts_.allocatorType = opts.allocatorType;
105     if (opts.desiredSize.height > 0 && opts.desiredSize.width > 0 &&
106         opts.cropAndScaleStrategy != CropAndScaleStrategy::SCALE_FIRST) {
107         cond = !ScalePixelMap(opts.desiredSize, pixelMap);
108         CHECK_ERROR_RETURN_RET_LOG(cond, ERR_IMAGE_TRANSFORM, "[PostProc]scale:transform pixel map failed");
109     } else if (opts.cropAndScaleStrategy != CropAndScaleStrategy::SCALE_FIRST) {
110         ImageInfo info;
111         pixelMap.GetImageInfo(info);
112         if ((finalOutputStep == FinalOutputStep::DENSITY_CHANGE) && (info.baseDensity != 0)) {
113             int targetWidth = (pixelMap.GetWidth() * opts.fitDensity + (info.baseDensity >> 1)) / info.baseDensity;
114             int targetHeight = (pixelMap.GetHeight() * opts.fitDensity + (info.baseDensity >> 1)) / info.baseDensity;
115             Size size;
116             size.height = targetHeight;
117             size.width = targetWidth;
118             cond = !ScalePixelMap(size, pixelMap);
119             CHECK_ERROR_RETURN_RET_LOG(cond, ERR_IMAGE_TRANSFORM,
120                                        "[PostProc]density scale:transform pixel map failed");
121             info.baseDensity = opts.fitDensity;
122             pixelMap.SetImageInfo(info, true);
123         }
124     }
125     return SUCCESS;
126 }
127 
GetDstImageInfo(const DecodeOptions & opts,PixelMap & pixelMap,ImageInfo srcImageInfo,ImageInfo & dstImageInfo)128 void PostProc::GetDstImageInfo(const DecodeOptions &opts, PixelMap &pixelMap,
129                                ImageInfo srcImageInfo, ImageInfo &dstImageInfo)
130 {
131     dstImageInfo.size = opts.desiredSize;
132     dstImageInfo.pixelFormat = opts.desiredPixelFormat;
133     dstImageInfo.baseDensity = srcImageInfo.baseDensity;
134     decodeOpts_ = opts;
135     if (opts.desiredPixelFormat == PixelFormat::UNKNOWN) {
136         if (opts.preference == MemoryUsagePreference::LOW_RAM &&
137             srcImageInfo.alphaType == AlphaType::IMAGE_ALPHA_TYPE_OPAQUE) {
138             dstImageInfo.pixelFormat = PixelFormat::RGB_565;
139         } else {
140             dstImageInfo.pixelFormat = PixelFormat::RGBA_8888;
141         }
142     }
143     // decode use, this value may be changed by real pixelFormat
144     if (pixelMap.GetAlphaType() == AlphaType::IMAGE_ALPHA_TYPE_UNPREMUL) {
145         dstImageInfo.alphaType = AlphaType::IMAGE_ALPHA_TYPE_PREMUL;
146     } else {
147         dstImageInfo.alphaType = pixelMap.GetAlphaType();
148     }
149 }
150 
CenterScale(const Size & size,PixelMap & pixelMap)151 bool PostProc::CenterScale(const Size &size, PixelMap &pixelMap)
152 {
153     int32_t srcWidth = pixelMap.GetWidth();
154     int32_t srcHeight = pixelMap.GetHeight();
155     int32_t targetWidth = size.width;
156     int32_t targetHeight = size.height;
157     if (targetWidth <= 0 || targetHeight <= 0 || srcWidth <= 0 || srcHeight <= 0) {
158         IMAGE_LOGE("[PostProc]params invalid, targetWidth:%{public}d, targetHeight:%{public}d, "
159             "srcWidth:%{public}d, srcHeight:%{public}d", targetWidth, targetHeight, srcWidth, srcHeight);
160         return false;
161     }
162     float widthScale = static_cast<float>(targetWidth) / static_cast<float>(srcWidth);
163     float heightScale = static_cast<float>(targetHeight) / static_cast<float>(srcHeight);
164     float scale = max(widthScale, heightScale);
165     if (pixelMap.IsAstc() && scale > 0) {
166         TransformData transformData;
167         pixelMap.GetTransformData(transformData);
168         transformData.scaleX *= scale;
169         transformData.scaleY *= scale;
170         transformData.cropLeft = (srcWidth - targetWidth / scale) / HALF_F;
171         transformData.cropTop = (srcHeight - targetHeight / scale) / HALF_F;
172         transformData.cropWidth = targetWidth / scale;
173         transformData.cropHeight = targetHeight / scale;
174         pixelMap.SetTransformData(transformData);
175         ImageInfo imageInfo;
176         pixelMap.GetImageInfo(imageInfo);
177         imageInfo.size.width = targetWidth;
178         imageInfo.size.height = targetHeight;
179         pixelMap.SetImageInfo(imageInfo, true);
180         return true;
181     }
182     bool cond = !ScalePixelMap(scale, scale, pixelMap);
183     CHECK_ERROR_RETURN_RET_LOG(cond, false, "[PostProc]center scale pixelmap %{public}f fail", scale);
184     srcWidth = pixelMap.GetWidth();
185     srcHeight = pixelMap.GetHeight();
186     if (srcWidth == targetWidth && srcHeight == targetHeight) {
187         return true;
188     }
189     if (srcWidth < targetWidth || srcHeight < targetHeight) {
190         IMAGE_LOGE("[PostProc]src size [%{public}d, %{public}d] must less than dst size [%{public}d,"
191             "%{public}d]", srcWidth, srcHeight, targetWidth, targetHeight);
192         return false;
193     }
194 
195     return CenterDisplay(pixelMap, srcWidth, srcHeight, targetWidth, targetHeight);
196 }
197 
CopyPixels(PixelMap & pixelMap,uint8_t * dstPixels,const Size & dstSize,const int32_t srcWidth,const int32_t srcHeight,int32_t srcRowStride,int32_t targetRowStride)198 bool PostProc::CopyPixels(PixelMap& pixelMap, uint8_t* dstPixels, const Size& dstSize,
199                           const int32_t srcWidth, const int32_t srcHeight,
200                           int32_t srcRowStride, int32_t targetRowStride)
201 {
202     int32_t targetWidth = dstSize.width;
203     int32_t targetHeight = dstSize.height;
204     int32_t left = max(0, srcWidth - targetWidth) / HALF;
205     int32_t top = max(0, srcHeight - targetHeight) / HALF;
206     int32_t pixelBytes = pixelMap.GetPixelBytes();
207     uint8_t *dstStartPixel = nullptr;
208     uint8_t *srcStartPixel = nullptr;
209     int32_t targetRowBytes = targetWidth * pixelBytes;
210     if (targetRowStride <= 0) {
211         targetRowStride = targetRowBytes;
212     }
213     int32_t srcRowBytes = srcWidth * pixelBytes;
214     if (srcRowStride <= 0) {
215         srcRowStride = srcRowBytes;
216     }
217     uint8_t *srcPixels = const_cast<uint8_t *>(pixelMap.GetPixels()) + top * srcRowStride + left * pixelBytes;
218     if (std::min(srcWidth, targetWidth) != 0 &&
219         ImageUtils::CheckMulOverflow(std::min(srcWidth, targetWidth), pixelBytes)) {
220         IMAGE_LOGE("[PostProc]invalid params, srcWidth:%{public}d, targetWidth:%{public}d, pixelBytes:%{public}d",
221                    srcWidth, targetWidth, pixelBytes);
222         return false;
223     }
224     uint32_t copyRowBytes = static_cast<uint32_t>(std::min(srcWidth, targetWidth) * pixelBytes);
225     for (int32_t scanLine = 0; scanLine < std::min(srcHeight, targetHeight); scanLine++) {
226         dstStartPixel = dstPixels + scanLine * targetRowStride;
227         srcStartPixel = srcPixels + scanLine * srcRowStride;
228         errno_t errRet = memcpy_s(dstStartPixel, static_cast<size_t>(targetRowBytes), srcStartPixel, copyRowBytes);
229         if (errRet != EOK) {
230             IMAGE_LOGE("[PostProc]memcpy scanline %{public}d fail, errorCode = %{public}d", scanLine, errRet);
231             return false;
232         }
233     }
234     return true;
235 }
236 
CenterDisplay(PixelMap & pixelMap,int32_t srcWidth,int32_t srcHeight,int32_t targetWidth,int32_t targetHeight)237 bool PostProc::CenterDisplay(PixelMap &pixelMap, int32_t srcWidth, int32_t srcHeight, int32_t targetWidth,
238                              int32_t targetHeight)
239 {
240     ImageInfo dstImageInfo;
241     pixelMap.GetImageInfo(dstImageInfo);
242     int32_t srcRowStride = pixelMap.GetAllocatorType() == AllocatorType::DMA_ALLOC ? pixelMap.GetRowStride() : 0;
243     dstImageInfo.size.width = targetWidth;
244     dstImageInfo.size.height = targetHeight;
245     bool cond = false;
246     if (pixelMap.SetImageInfo(dstImageInfo, true) != SUCCESS) {
247         IMAGE_LOGE("update ImageInfo failed");
248         return false;
249     }
250     int32_t bufferSize = pixelMap.GetByteCount();
251     uint8_t *dstPixels = nullptr;
252     void *nativeBuffer = nullptr;
253     int fd = 0;
254     int targetRowStride = 0;
255     if (pixelMap.GetAllocatorType() == AllocatorType::HEAP_ALLOC) {
256         cond = !AllocHeapBuffer(bufferSize, &dstPixels);
257         CHECK_ERROR_RETURN_RET(cond, false);
258     } else if (pixelMap.GetAllocatorType() == AllocatorType::DMA_ALLOC) {
259         dstPixels = AllocDmaMemory(dstImageInfo, bufferSize, &nativeBuffer, targetRowStride);
260     } else {
261         dstPixels = AllocSharedMemory(dstImageInfo.size, bufferSize, fd, pixelMap.GetUniqueId());
262     }
263     cond = dstPixels == nullptr;
264     CHECK_ERROR_RETURN_RET_LOG(cond, false,
265                                "[PostProc]CenterDisplay AllocMemory[%{public}d] failed",
266                                pixelMap.GetAllocatorType());
267     if (!CopyPixels(pixelMap, dstPixels, dstImageInfo.size, srcWidth, srcHeight, srcRowStride, targetRowStride)) {
268         IMAGE_LOGE("[PostProc]CopyPixels failed");
269         ReleaseBuffer(pixelMap.GetAllocatorType(), fd, bufferSize, &dstPixels, nativeBuffer);
270         return false;
271     }
272     void *fdBuffer = nullptr;
273     if (pixelMap.GetAllocatorType() == AllocatorType::HEAP_ALLOC) {
274         pixelMap.SetPixelsAddr(dstPixels, nullptr, bufferSize, AllocatorType::HEAP_ALLOC, nullptr);
275     } else if (pixelMap.GetAllocatorType() == AllocatorType::DMA_ALLOC) {
276 #if !defined(_WIN32) && !defined(_APPLE) && !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)
277         sptr<SurfaceBuffer> sourceSurfaceBuffer(reinterpret_cast<SurfaceBuffer*> (pixelMap.GetFd()));
278         sptr<SurfaceBuffer> dstSurfaceBuffer(reinterpret_cast<SurfaceBuffer*> (nativeBuffer));
279         VpeUtils::CopySurfaceBufferInfo(sourceSurfaceBuffer, dstSurfaceBuffer);
280 #endif
281         pixelMap.SetPixelsAddr(dstPixels, nativeBuffer, bufferSize, AllocatorType::DMA_ALLOC, nullptr);
282     } else {
283         fdBuffer = new int32_t();
284         *static_cast<int32_t *>(fdBuffer) = fd;
285         pixelMap.SetPixelsAddr(dstPixels, fdBuffer, bufferSize, AllocatorType::SHARE_MEM_ALLOC, nullptr);
286     }
287     return true;
288 }
289 
ProcessScanlineFilter(ScanlineFilter & scanlineFilter,const Rect & cropRect,PixelMap & pixelMap,uint8_t * resultData,uint32_t rowBytes)290 bool PostProc::ProcessScanlineFilter(ScanlineFilter &scanlineFilter, const Rect &cropRect, PixelMap &pixelMap,
291                                      uint8_t *resultData, uint32_t rowBytes)
292 {
293     auto srcData = pixelMap.GetPixels();
294     int32_t scanLine = 0;
295     while (scanLine < pixelMap.GetHeight()) {
296         FilterRowType filterRow = scanlineFilter.GetFilterRowType(scanLine);
297         if (filterRow == FilterRowType::NON_REFERENCE_ROW) {
298             scanLine++;
299             continue;
300         }
301         if (filterRow == FilterRowType::LAST_REFERENCE_ROW) {
302             break;
303         }
304         uint32_t ret = scanlineFilter.FilterLine(resultData + ((scanLine - cropRect.top) * rowBytes), rowBytes,
305                                                  srcData + (scanLine * pixelMap.GetRowBytes()));
306         bool cond = ret != SUCCESS;
307         CHECK_ERROR_RETURN_RET_LOG(cond, false, "[PostProc]scan line failed, ret:%{public}u", ret);
308         scanLine++;
309     }
310     return true;
311 }
312 
CheckScanlineFilter(const Rect & cropRect,ImageInfo & dstImageInfo,PixelMap & pixelMap,int32_t pixelBytes,ScanlineFilter & scanlineFilter)313 uint32_t PostProc::CheckScanlineFilter(const Rect &cropRect, ImageInfo &dstImageInfo, PixelMap &pixelMap,
314                                        int32_t pixelBytes, ScanlineFilter &scanlineFilter)
315 {
316     if (ImageUtils::CheckMulOverflow(dstImageInfo.size.width, dstImageInfo.size.height, pixelBytes)) {
317         IMAGE_LOGE("[PostProc]size is too large, width:%{public}d, height:%{public}d",
318                    dstImageInfo.size.width,  dstImageInfo.size.height);
319         return ERR_IMAGE_CROP;
320     }
321     uint64_t bufferSize = static_cast<uint64_t>(dstImageInfo.size.width) *
322             static_cast<uint64_t>(dstImageInfo.size.height) *
323             static_cast<uint64_t>(pixelBytes);
324     uint8_t *resultData = nullptr;
325     int fd = 0;
326     if (decodeOpts_.allocatorType == AllocatorType::SHARE_MEM_ALLOC) {
327         resultData = AllocSharedMemory(dstImageInfo.size, bufferSize, fd, pixelMap.GetUniqueId());
328         bool cond = resultData == nullptr;
329         CHECK_ERROR_RETURN_RET_LOG(cond, ERR_IMAGE_CROP, "[PostProc]AllocSharedMemory failed");
330     } else {
331         if (!AllocHeapBuffer(bufferSize, &resultData)) {
332             return ERR_IMAGE_CROP;
333         }
334     }
335     if (ImageUtils::CheckMulOverflow(dstImageInfo.size.width, pixelBytes)) {
336         IMAGE_LOGE("[PostProc]size.width:%{public}d, is too large",
337             dstImageInfo.size.width);
338         ReleaseBuffer(decodeOpts_.allocatorType, fd, bufferSize, &resultData);
339         return ERR_IMAGE_CROP;
340     }
341     uint32_t rowBytes = pixelBytes * dstImageInfo.size.width;
342     if (!ProcessScanlineFilter(scanlineFilter, cropRect, pixelMap, resultData, rowBytes)) {
343         IMAGE_LOGE("[PostProc]ProcessScanlineFilter failed");
344         ReleaseBuffer(decodeOpts_.allocatorType, fd, bufferSize, &resultData);
345         return ERR_IMAGE_CROP;
346     }
347     uint32_t result = pixelMap.SetImageInfo(dstImageInfo);
348     if (result != SUCCESS) {
349         ReleaseBuffer(decodeOpts_.allocatorType, fd, bufferSize, &resultData);
350         return result;
351     }
352 
353     if (decodeOpts_.allocatorType == AllocatorType::HEAP_ALLOC) {
354         pixelMap.SetPixelsAddr(resultData, nullptr, bufferSize, decodeOpts_.allocatorType, nullptr);
355         return result;
356     }
357     void *fdBuffer = new int32_t();
358     *static_cast<int32_t *>(fdBuffer) = fd;
359     pixelMap.SetPixelsAddr(resultData, fdBuffer, bufferSize, decodeOpts_.allocatorType, nullptr);
360     return result;
361 }
362 
ConvertProc(const Rect & cropRect,ImageInfo & dstImageInfo,PixelMap & pixelMap,ImageInfo & srcImageInfo)363 uint32_t PostProc::ConvertProc(const Rect &cropRect, ImageInfo &dstImageInfo, PixelMap &pixelMap,
364                                ImageInfo &srcImageInfo)
365 {
366     bool hasPixelConvert = HasPixelConvert(srcImageInfo, dstImageInfo);
367     uint32_t ret = NeedScanlineFilter(cropRect, srcImageInfo.size, hasPixelConvert);
368     if (ret != NEED_NEXT) {
369         return ret;
370     }
371 
372     // we suppose a quick method to scanline in mostly seen cases: NO CROP && hasPixelConvert
373     if (GetCropValue(cropRect, srcImageInfo.size) == CropValue::NOCROP &&
374         dstImageInfo.pixelFormat == PixelFormat::ARGB_8888 && hasPixelConvert) {
375         IMAGE_LOGI("[PostProc]no need crop, only pixel convert.");
376         return PixelConvertProc(dstImageInfo, pixelMap, srcImageInfo);
377     }
378 
379     ScanlineFilter scanlineFilter(srcImageInfo.pixelFormat);
380     // this method maybe update dst image size to crop size
381     SetScanlineCropAndConvert(cropRect, dstImageInfo, srcImageInfo, scanlineFilter, hasPixelConvert);
382 
383     int32_t pixelBytes = ImageUtils::GetPixelBytes(dstImageInfo.pixelFormat);
384     if (pixelBytes == 0) {
385         return ERR_IMAGE_CROP;
386     }
387     if (ImageUtils::CheckMulOverflow(dstImageInfo.size.width, dstImageInfo.size.height, pixelBytes)) {
388         IMAGE_LOGE("[PostProc]size.width:%{public}d, size.height:%{public}d is too large",
389             dstImageInfo.size.width, dstImageInfo.size.height);
390         return ERR_IMAGE_CROP;
391     }
392     return CheckScanlineFilter(cropRect, dstImageInfo, pixelMap, pixelBytes, scanlineFilter);
393 }
394 
PixelConvertProc(ImageInfo & dstImageInfo,PixelMap & pixelMap,ImageInfo & srcImageInfo)395 uint32_t PostProc::PixelConvertProc(ImageInfo &dstImageInfo, PixelMap &pixelMap,
396                                     ImageInfo &srcImageInfo)
397 {
398     uint32_t ret;
399     int fd = 0;
400     uint64_t bufferSize = 0;
401     uint8_t *resultData = nullptr;
402 
403     // as no crop, the size is same as src
404     dstImageInfo.size = srcImageInfo.size;
405     if (AllocBuffer(dstImageInfo, &resultData, bufferSize, fd, pixelMap.GetUniqueId()) != SUCCESS) {
406         ReleaseBuffer(decodeOpts_.allocatorType, fd, bufferSize, &resultData);
407         return ERR_IMAGE_CROP;
408     }
409 
410     int32_t pixelBytes = ImageUtils::GetPixelBytes(srcImageInfo.pixelFormat);
411     if (pixelBytes == 0) {
412         ReleaseBuffer(decodeOpts_.allocatorType, fd, bufferSize, &resultData);
413         return ERR_IMAGE_CROP;
414     }
415 
416     ret = pixelMap.SetImageInfo(dstImageInfo);
417     if (ret != SUCCESS) {
418         ReleaseBuffer(decodeOpts_.allocatorType, fd, bufferSize, &resultData);
419         return ret;
420     }
421 
422     if (decodeOpts_.allocatorType == AllocatorType::HEAP_ALLOC) {
423         pixelMap.SetPixelsAddr(resultData, nullptr, bufferSize, decodeOpts_.allocatorType, nullptr);
424         return ret;
425     }
426 
427     void *fdBuffer = new int32_t();
428     *static_cast<int32_t *>(fdBuffer) = fd;
429     pixelMap.SetPixelsAddr(resultData, fdBuffer, bufferSize, decodeOpts_.allocatorType, nullptr);
430     return ret;
431 }
432 
AllocBuffer(ImageInfo imageInfo,uint8_t ** resultData,uint64_t & bufferSize,int & fd,uint32_t id)433 uint32_t PostProc::AllocBuffer(ImageInfo imageInfo, uint8_t **resultData, uint64_t &bufferSize, int &fd, uint32_t id)
434 {
435     int32_t pixelBytes = ImageUtils::GetPixelBytes(imageInfo.pixelFormat);
436     bool cond = false;
437     if (pixelBytes == 0) {
438         return ERR_IMAGE_CROP;
439     }
440     if (ImageUtils::CheckMulOverflow(imageInfo.size.width, imageInfo.size.height, pixelBytes)) {
441         IMAGE_LOGE("[PostProc]size.width:%{public}d, size.height:%{public}d is too large",
442             imageInfo.size.width, imageInfo.size.height);
443         return ERR_IMAGE_CROP;
444     }
445     bufferSize = static_cast<uint64_t>(imageInfo.size.width) *
446             static_cast<uint64_t>(imageInfo.size.height) *
447             static_cast<uint64_t>(pixelBytes);
448     IMAGE_LOGD("[PostProc]size.width:%{public}d, size.height:%{public}d, bufferSize:%{public}lld",
449         imageInfo.size.width, imageInfo.size.height, static_cast<long long>(bufferSize));
450     if (decodeOpts_.allocatorType == AllocatorType::SHARE_MEM_ALLOC) {
451         *resultData = AllocSharedMemory(imageInfo.size, bufferSize, fd, id);
452         cond = *resultData == nullptr;
453         CHECK_ERROR_RETURN_RET_LOG(cond, ERR_IMAGE_CROP, "[PostProc]AllocSharedMemory failed");
454     } else {
455         cond = !AllocHeapBuffer(bufferSize, resultData);
456         CHECK_ERROR_RETURN_RET(cond, ERR_IMAGE_CROP);
457     }
458     return SUCCESS;
459 }
460 
AllocHeapBuffer(uint64_t bufferSize,uint8_t ** buffer)461 bool PostProc::AllocHeapBuffer(uint64_t bufferSize, uint8_t **buffer)
462 {
463     bool cond = bufferSize == 0 || bufferSize > MALLOC_MAX_LENTH;
464     CHECK_ERROR_RETURN_RET_LOG(cond, false, "[PostProc]Invalid value of bufferSize");
465     *buffer = static_cast<uint8_t *>(malloc(bufferSize));
466     if (*buffer == nullptr) {
467         IMAGE_LOGE("[PostProc]alloc covert color buffersize[%{public}llu] failed.",
468             static_cast<unsigned long long>(bufferSize));
469         return false;
470     }
471 #ifdef _WIN32
472     errno_t backRet = memset_s(*buffer, 0, bufferSize);
473     if (backRet != EOK) {
474         IMAGE_LOGE("[PostProc]memset convertData fail, errorCode = %{public}d", backRet);
475         ReleaseBuffer(AllocatorType::HEAP_ALLOC, 0, 0, buffer);
476         return false;
477     }
478     return true;
479 #else
480     errno_t errRet = memset_s(*buffer, bufferSize, 0, bufferSize);
481     if (errRet != EOK) {
482         IMAGE_LOGE("[PostProc]memset convertData fail, errorCode = %{public}d", errRet);
483         ReleaseBuffer(AllocatorType::HEAP_ALLOC, 0, 0, buffer);
484         return false;
485     }
486     return true;
487 #endif
488 }
489 
AllocSharedMemory(const Size & size,const uint64_t bufferSize,int & fd,uint32_t uniqueId)490 uint8_t *PostProc::AllocSharedMemory(const Size &size, const uint64_t bufferSize, int &fd, uint32_t uniqueId)
491 {
492 #if defined(_WIN32) || defined(_APPLE) || defined(IOS_PLATFORM) || defined(ANDROID_PLATFORM)
493         return nullptr;
494 #else
495     std::string name = "Parcel RawData, uniqueId: " + std::to_string(getpid()) + '_' + std::to_string(uniqueId);
496     fd = AshmemCreate(name.c_str(), bufferSize);
497     if (fd < 0) {
498         IMAGE_LOGE("[PostProc]AllocSharedMemory fd error, bufferSize %{public}lld",
499             static_cast<long long>(bufferSize));
500         return nullptr;
501     }
502     int result = AshmemSetProt(fd, PROT_READ | PROT_WRITE);
503     if (result < 0) {
504         IMAGE_LOGE("[PostProc]AshmemSetProt error");
505         ::close(fd);
506         return nullptr;
507     }
508     void* ptr = ::mmap(nullptr, bufferSize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
509     if (ptr == MAP_FAILED) {
510         IMAGE_LOGE("[PostProc]mmap error, errno: %{public}s, fd %{public}d, bufferSize %{public}lld",
511             strerror(errno), fd, (long long)bufferSize);
512         ::close(fd);
513         return nullptr;
514     }
515     return reinterpret_cast<uint8_t *>(ptr);
516 #endif
517 }
518 
AllocDmaMemory(ImageInfo info,const uint64_t bufferSize,void ** nativeBuffer,int & targetRowStride)519 uint8_t *PostProc::AllocDmaMemory(ImageInfo info, const uint64_t bufferSize,
520                                   void **nativeBuffer, int &targetRowStride)
521 {
522 #if defined(_WIN32) || defined(_APPLE) || defined(IOS_PLATFORM) || defined(ANDROID_PLATFORM)
523     return nullptr;
524 #else
525     MemoryData memoryData = {nullptr, (uint32_t)bufferSize, "PostProc", {info.size.width, info.size.height}};
526     memoryData.format = info.pixelFormat;
527     auto dstMemory = MemoryManager::CreateMemory(AllocatorType::DMA_ALLOC, memoryData);
528     bool cond = dstMemory == nullptr;
529     CHECK_ERROR_RETURN_RET(cond, nullptr);
530     *nativeBuffer = dstMemory->extend.data;
531     auto sbBuffer = reinterpret_cast<SurfaceBuffer *>(dstMemory->extend.data);
532     targetRowStride = sbBuffer->GetStride();
533     return (uint8_t *)dstMemory->data.data;
534 #endif
535 }
536 
ReleaseBuffer(AllocatorType allocatorType,int fd,uint64_t dataSize,uint8_t ** buffer,void * nativeBuffer)537 void PostProc::ReleaseBuffer(AllocatorType allocatorType, int fd,
538                              uint64_t dataSize, uint8_t **buffer, void *nativeBuffer)
539 {
540 #if !defined(_WIN32) && !defined(_APPLE) && !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)
541     if (allocatorType == AllocatorType::SHARE_MEM_ALLOC) {
542         if (*buffer != nullptr) {
543             ::munmap(*buffer, dataSize);
544             ::close(fd);
545         }
546         return;
547     }
548     if (allocatorType == AllocatorType::DMA_ALLOC) {
549         if (nativeBuffer != nullptr) {
550             int32_t err = ImageUtils::SurfaceBuffer_Unreference(static_cast<SurfaceBuffer*>(nativeBuffer));
551             if (err != OHOS::GSERROR_OK) {
552                 IMAGE_LOGE("PostProc NativeBufferReference failed");
553             }
554         }
555         return;
556     }
557 #endif
558 
559     if (allocatorType == AllocatorType::HEAP_ALLOC) {
560         if (*buffer != nullptr) {
561             free(*buffer);
562             *buffer = nullptr;
563         }
564         return;
565     }
566 }
567 
NeedScanlineFilter(const Rect & cropRect,const Size & srcSize,const bool & hasPixelConvert)568 uint32_t PostProc::NeedScanlineFilter(const Rect &cropRect, const Size &srcSize, const bool &hasPixelConvert)
569 {
570     CropValue value = GetCropValue(cropRect, srcSize);
571     if (value == CropValue::NOCROP && !hasPixelConvert) {
572         IMAGE_LOGI("[PostProc]no need crop and pixel convert.");
573         return SUCCESS;
574     } else if (value == CropValue::INVALID) {
575         IMAGE_LOGE("[PostProc]invalid corp region, top:%{public}d, left:%{public}d, "
576             "width:%{public}d, height:%{public}d", cropRect.top, cropRect.left, cropRect.width, cropRect.height);
577         return ERR_IMAGE_CROP;
578     }
579     return NEED_NEXT;
580 }
581 
ConvertPixelMapToPixmapInfo(PixelMap & pixelMap,PixmapInfo & pixmapInfo)582 void PostProc::ConvertPixelMapToPixmapInfo(PixelMap &pixelMap, PixmapInfo &pixmapInfo)
583 {
584     pixmapInfo.imageInfo.size.width = pixelMap.GetWidth();
585     pixmapInfo.imageInfo.size.height = pixelMap.GetHeight();
586     pixmapInfo.imageInfo.pixelFormat = pixelMap.GetPixelFormat();
587     pixmapInfo.imageInfo.colorSpace = pixelMap.GetColorSpace();
588     pixmapInfo.imageInfo.alphaType = pixelMap.GetAlphaType();
589     pixmapInfo.imageInfo.baseDensity = pixelMap.GetBaseDensity();
590     pixmapInfo.data = const_cast<uint8_t *>(pixelMap.GetPixels());
591     pixmapInfo.bufferSize = pixelMap.GetByteCount();
592 }
593 
RotatePixelMap(float rotateDegrees,PixelMap & pixelMap)594 bool PostProc::RotatePixelMap(float rotateDegrees, PixelMap &pixelMap)
595 {
596     BasicTransformer trans;
597     PixmapInfo input(false);
598     ConvertPixelMapToPixmapInfo(pixelMap, input);
599     // Default rotation at the center of the image, so divide 2
600     trans.SetRotateParam(rotateDegrees, static_cast<float>(input.imageInfo.size.width) * FHALF,
601                          static_cast<float>(input.imageInfo.size.height) * FHALF);
602     return Transform(trans, input, pixelMap);
603 }
604 
ScalePixelMap(const Size & size,PixelMap & pixelMap)605 bool PostProc::ScalePixelMap(const Size &size, PixelMap &pixelMap)
606 {
607     int32_t srcWidth = pixelMap.GetWidth();
608     int32_t srcHeight = pixelMap.GetHeight();
609     if (srcWidth <= 0 || srcHeight <= 0) {
610         IMAGE_LOGE("[PostProc]src width:%{public}d, height:%{public}d is invalid.", srcWidth, srcHeight);
611         return false;
612     }
613     float scaleX = static_cast<float>(size.width) / static_cast<float>(srcWidth);
614     float scaleY = static_cast<float>(size.height) / static_cast<float>(srcHeight);
615     return ScalePixelMap(scaleX, scaleY, pixelMap);
616 }
617 
ScalePixelMap(float scaleX,float scaleY,PixelMap & pixelMap)618 bool PostProc::ScalePixelMap(float scaleX, float scaleY, PixelMap &pixelMap)
619 {
620     // returns directly with a scale of 1.0
621     if ((fabs(scaleX - 1.0f) < EPSILON) && (fabs(scaleY - 1.0f) < EPSILON)) {
622         return true;
623     }
624     return pixelMap.resize(scaleX, scaleY);
625 }
TranslatePixelMap(float tX,float tY,PixelMap & pixelMap)626 bool PostProc::TranslatePixelMap(float tX, float tY, PixelMap &pixelMap)
627 {
628     BasicTransformer trans;
629     PixmapInfo input(false);
630     ConvertPixelMapToPixmapInfo(pixelMap, input);
631 
632     trans.SetTranslateParam(tX, tY);
633     return Transform(trans, input, pixelMap);
634 }
635 
Transform(BasicTransformer & trans,const PixmapInfo & input,PixelMap & pixelMap)636 bool PostProc::Transform(BasicTransformer &trans, const PixmapInfo &input, PixelMap &pixelMap)
637 {
638     if (pixelMap.IsTransformered()) {
639         IMAGE_LOGE("[PostProc]Transform pixelmap is transforming");
640         return false;
641     }
642     pixelMap.SetTransformered(true);
643     PixmapInfo output(false);
644     output.uniqueId = pixelMap.GetUniqueId();
645     uint32_t ret;
646     if (decodeOpts_.allocatorType == AllocatorType::SHARE_MEM_ALLOC) {
647         typedef uint8_t *(*AllocMemory)(const Size &size, const uint64_t bufferSize, int &fd, uint32_t uniqueId);
648         AllocMemory allcFunc = AllocSharedMemory;
649         ret = trans.TransformPixmap(input, output, allcFunc);
650     } else {
651         ret = trans.TransformPixmap(input, output);
652     }
653     if (ret != IMAGE_SUCCESS) {
654         output.Destroy();
655         return false;
656     }
657 
658     if (pixelMap.SetImageInfo(output.imageInfo) != SUCCESS) {
659         output.Destroy();
660         return false;
661     }
662     pixelMap.SetPixelsAddr(output.data, output.context, output.bufferSize, decodeOpts_.allocatorType, nullptr);
663     pixelMap.SetTransformered(false);
664     return true;
665 }
666 
GetCropValue(const Rect & rect,const Size & size)667 CropValue PostProc::GetCropValue(const Rect &rect, const Size &size)
668 {
669     bool isSameSize = (rect.top == 0 && rect.left == 0 && rect.height == size.height && rect.width == size.width);
670     if (!IsHasCrop(rect) || isSameSize) {
671         return CropValue::NOCROP;
672     }
673     bool isValid = ((rect.top >= 0 && rect.width > 0 && rect.left >= 0 && rect.height > 0) &&
674                     (rect.top + rect.height <= size.height) && (rect.left + rect.width <= size.width));
675     if (!isValid) {
676         return CropValue::INVALID;
677     }
678     return CropValue::VALID;
679 }
680 
ValidCropValue(Rect & rect,const Size & size)681 CropValue PostProc::ValidCropValue(Rect &rect, const Size &size)
682 {
683     CropValue res = GetCropValue(rect, size);
684     if (res == CropValue::INVALID) {
685         if (rect.top + rect.height > size.height) {
686             rect.height = size.height - rect.top;
687         }
688         if (rect.left + rect.width > size.width) {
689             rect.width = size.width - rect.left;
690         }
691         res = GetCropValue(rect, size);
692     }
693     return res;
694 }
695 
IsHasCrop(const Rect & rect)696 bool PostProc::IsHasCrop(const Rect &rect)
697 {
698     return (rect.top != 0 || rect.left != 0 || rect.width != 0 || rect.height != 0);
699 }
700 
HasPixelConvert(const ImageInfo & srcImageInfo,ImageInfo & dstImageInfo)701 bool PostProc::HasPixelConvert(const ImageInfo &srcImageInfo, ImageInfo &dstImageInfo)
702 {
703     dstImageInfo.alphaType = ImageUtils::GetValidAlphaTypeByFormat(dstImageInfo.alphaType, dstImageInfo.pixelFormat);
704     return (dstImageInfo.pixelFormat != srcImageInfo.pixelFormat || dstImageInfo.alphaType != srcImageInfo.alphaType);
705 }
706 
SetScanlineCropAndConvert(const Rect & cropRect,ImageInfo & dstImageInfo,ImageInfo & srcImageInfo,ScanlineFilter & scanlineFilter,bool hasPixelConvert)707 void PostProc::SetScanlineCropAndConvert(const Rect &cropRect, ImageInfo &dstImageInfo, ImageInfo &srcImageInfo,
708                                          ScanlineFilter &scanlineFilter, bool hasPixelConvert)
709 {
710     if (hasPixelConvert) {
711         scanlineFilter.SetPixelConvert(srcImageInfo, dstImageInfo);
712     }
713 
714     Rect srcRect = cropRect;
715     if (IsHasCrop(cropRect)) {
716         dstImageInfo.size.width = cropRect.width;
717         dstImageInfo.size.height = cropRect.height;
718     } else {
719         srcRect = { 0, 0, srcImageInfo.size.width, srcImageInfo.size.height };
720         dstImageInfo.size = srcImageInfo.size;
721     }
722     scanlineFilter.SetSrcRegion(srcRect);
723 }
724 
725 #if !defined(_WIN32) && !defined(_APPLE) && !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)
GetScaleFormat(const PixelFormat & format,AVPixelFormat & pixelFormat)726 bool GetScaleFormat(const PixelFormat &format, AVPixelFormat &pixelFormat)
727 {
728     if (format != PixelFormat::UNKNOWN) {
729         auto formatPair = PIXEL_FORMAT_MAP.find(format);
730         if (formatPair != PIXEL_FORMAT_MAP.end() && formatPair->second != 0) {
731             pixelFormat = formatPair->second;
732             return true;
733         }
734     }
735     return false;
736 }
737 
GetInterpolation(const AntiAliasingOption & option)738 int GetInterpolation(const AntiAliasingOption &option)
739 {
740     switch (option) {
741         case AntiAliasingOption::NONE:
742             return SWS_POINT;
743         case AntiAliasingOption::LOW:
744             return SWS_BILINEAR;
745         case AntiAliasingOption::MEDIUM:
746             return SWS_BICUBIC;
747         case AntiAliasingOption::HIGH:
748             return SWS_AREA;
749         case AntiAliasingOption::FAST_BILINEAER:
750             return SWS_FAST_BILINEAR;
751         case AntiAliasingOption::BICUBLIN:
752             return SWS_BICUBLIN;
753         case AntiAliasingOption::GAUSS:
754             return SWS_GAUSS;
755         case AntiAliasingOption::SINC:
756             return SWS_SINC;
757         case AntiAliasingOption::LANCZOS:
758             return SWS_LANCZOS;
759         case AntiAliasingOption::SPLINE:
760             return SWS_SPLINE;
761         default:
762             return SWS_POINT;
763     }
764 }
765 
GetNewSkSLRCacheMgr()766 static SkSLRCacheMgr GetNewSkSLRCacheMgr()
767 {
768     static SkMutex slrMutex;
769     static SLRLRUCache slrCache(SLR_CACHE_CAPACITY);
770     return SkSLRCacheMgr(slrCache, slrMutex);
771 }
772 
initSLRFactor(Size srcSize,Size dstSize)773 std::shared_ptr<SLRWeightTuple> initSLRFactor(Size srcSize, Size dstSize)
774 {
775     if (srcSize.width == 0 || srcSize.height == 0 || dstSize.width == 0 || dstSize.height == 0) {
776         IMAGE_LOGE("initSLRFactor invalid size, %{public}d, %{public}d, %{public}d, %{public}d",
777             srcSize.width, srcSize.height, dstSize.width, dstSize.height);
778         return nullptr;
779     }
780     SkSLRCacheMgr cacheMgr = GetNewSkSLRCacheMgr();
781     SLRWeightKey key(srcSize, dstSize);
782     std::shared_ptr<SLRWeightTuple> weightTuplePtr = cacheMgr.find(key.fKey);
783     if (weightTuplePtr == nullptr) {
784         SLRWeightMat slrWeightX = SLRProc::GetWeights(static_cast<float>(dstSize.width) / srcSize.width,
785             static_cast<int>(dstSize.width));
786         SLRWeightMat slrWeightY = SLRProc::GetWeights(static_cast<float>(dstSize.height) / srcSize.height,
787             static_cast<int>(dstSize.height));
788         SLRWeightTuple value{slrWeightX, slrWeightY, key};
789         std::shared_ptr<SLRWeightTuple> weightPtr = std::make_shared<SLRWeightTuple>(value);
790         cacheMgr.insert(key.fKey, weightPtr);
791         IMAGE_LOGI("initSLRFactor insert:%{public}d", key.fKey);
792         return weightPtr;
793     }
794     return weightTuplePtr;
795 }
796 
CheckPixelMapSLR(const Size & desiredSize,PixelMap & pixelMap)797 bool CheckPixelMapSLR(const Size &desiredSize, PixelMap &pixelMap)
798 {
799     ImageInfo imgInfo;
800     pixelMap.GetImageInfo(imgInfo);
801     if (imgInfo.pixelFormat != PixelFormat::RGBA_8888) {
802         IMAGE_LOGE("CheckPixelMapSLR only support RGBA_8888 format");
803         return false;
804     }
805     int32_t srcWidth = pixelMap.GetWidth();
806     int32_t srcHeight = pixelMap.GetHeight();
807     if (srcWidth <= 0 || srcHeight <= 0 || !pixelMap.GetWritablePixels()) {
808         IMAGE_LOGE("CheckPixelMapSLR invalid src size, %{public}d, %{public}d", srcWidth, srcHeight);
809         return false;
810     }
811     if (desiredSize.width <= 0 || desiredSize.height <= 0) {
812         IMAGE_LOGE("CheckPixelMapSLR invalid desired size, %{public}d, %{public}d",
813             desiredSize.width, desiredSize.height);
814         return false;
815     }
816     if (desiredSize.width == srcWidth && desiredSize.height == srcHeight) {
817         IMAGE_LOGE("CheckPixelMapSLR same source and desired size, %{public}d, %{public}d",
818             desiredSize.width, desiredSize.height);
819         return false;
820     }
821     if (static_cast<float>(desiredSize.width) / srcWidth < EPSILON ||
822         static_cast<float>(desiredSize.height) / srcHeight < EPSILON) {
823         IMAGE_LOGE("CheckPixelMapSLR scaling factor overflow");
824         return false;
825     }
826     int32_t pixelBytes = pixelMap.GetPixelBytes();
827     if (pixelBytes <= 0) {
828         IMAGE_LOGE("CheckPixelMapSLR invalid pixel bytes, %{public}d", pixelBytes);
829         return false;
830     }
831     uint64_t dstSizeOverflow =
832         static_cast<uint64_t>(desiredSize.width) * static_cast<uint64_t>(desiredSize.height) *
833         static_cast<uint64_t>(pixelBytes);
834     if (dstSizeOverflow > UINT_MAX) {
835         IMAGE_LOGE("ScalePixelMapWithSLR desired size overflow");
836         return false;
837     }
838     return true;
839 }
840 
841 #if !defined(_WIN32) && !defined(_APPLE) && !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)
842 static int g_minSize = 512;
843 static constexpr int g_maxTextureSize = 8192;
CheckPixelMapSLR(PixelMap & pixelMap,const Size & desiredSize,GPUTransformData & trans)844 static bool CheckPixelMapSLR(PixelMap &pixelMap, const Size &desiredSize, GPUTransformData &trans)
845 {
846     ImageInfo imgInfo;
847     pixelMap.GetImageInfo(imgInfo);
848     if (imgInfo.pixelFormat != PixelFormat::RGBA_8888) {
849         IMAGE_LOGE("slr_gpu CheckPixelMapSLR only support RGBA_8888 format  %{public}d", imgInfo.pixelFormat);
850         return false;
851     }
852     int32_t srcWidth = pixelMap.GetWidth();
853     int32_t srcHeight = pixelMap.GetHeight();
854     if (srcWidth <= 0 || srcHeight <= 0 || !pixelMap.GetWritablePixels()) {
855         IMAGE_LOGE("slr_gpu CheckPixelMapSLR invalid src size, %{public}d, %{public}d", srcWidth, srcHeight);
856         return false;
857     }
858     if (desiredSize.width <= 0 || desiredSize.height <= 0) {
859         IMAGE_LOGE("slr_gpu CheckPixelMapSLR invalid desired size, %{public}d, %{public}d",
860             desiredSize.width, desiredSize.height);
861         return false;
862     }
863     int32_t pixelBytes = pixelMap.GetPixelBytes();
864     if (pixelBytes <= 0) {
865         IMAGE_LOGE("slr_gpu CheckPixelMapSLR invalid pixel bytes, %{public}d", pixelBytes);
866         return false;
867     }
868     if (srcWidth > g_maxTextureSize || srcHeight > g_maxTextureSize) {
869         IMAGE_LOGI("slr_gpu CheckPixelMapSLR The maximum width and height cannot exceed:%{public}d.", g_maxTextureSize);
870         return false;
871     }
872     uint64_t dstSizeOverflow = static_cast<uint64_t>(desiredSize.width) * static_cast<uint64_t>(desiredSize.height) *
873         static_cast<uint64_t>(pixelBytes);
874     if (dstSizeOverflow > UINT_MAX) {
875         IMAGE_LOGE("slr_gpu ScalePixelMapWithSLR desired size overflow");
876         return false;
877     }
878     if (trans.transformationType == TransformationType::SCALE &&
879         (srcWidth <= desiredSize.width || srcHeight <= desiredSize.height)) {
880         IMAGE_LOGI("slr_gpu  CheckPixelMapSLR  failed. Only zoom-out is supported.");
881         return false;
882     }
883     if (trans.transformationType == TransformationType::SCALE &&
884         (srcWidth * srcHeight < g_minSize * g_minSize)) {
885         IMAGE_LOGI("slr_gpu  CheckPixelMapSLR  failed. srcWidth * srcHeight < minSize * minSize.");
886         return false;
887     }
888     if (trans.transformationType == TransformationType::ROTATE &&
889         !(std::fabs(std::fmod(trans.rotateDegreeZ, 90.f)) < 1e-6)) {
890         IMAGE_LOGI("slr_gpu  CheckPixelMapSLR  failed. Only 90* is supported.");
891         return false;
892     }
893     return true;
894 }
895 
GetPixelMapInfo(PixelMap & source,Size & size,GLenum & glFormat,int & perPixelSize)896 static void GetPixelMapInfo(PixelMap &source, Size &size, GLenum &glFormat, int &perPixelSize)
897 {
898     size = {
899         .width = source.GetWidth(),
900         .height = source.GetHeight(),
901     };
902     glFormat = GL_RGBA;
903     perPixelSize = ImageUtils::GetPixelBytes(PixelFormat::RGBA_8888);
904     PixelFormat originFormat = source.GetPixelFormat();
905     switch (originFormat) {
906         case PixelFormat::RGBA_8888:
907             glFormat = GL_RGBA;
908             break;
909         case PixelFormat::RGB_565:
910             glFormat = GL_RGB565;
911             perPixelSize = ImageUtils::GetPixelBytes(PixelFormat::RGB_565);
912             break;
913         case PixelFormat::RGB_888:
914             glFormat = GL_RGB;
915             perPixelSize = ImageUtils::GetPixelBytes(PixelFormat::RGB_888);
916             break;
917         case PixelFormat::BGRA_8888:
918             glFormat = GL_BGRA_EXT;
919             break;
920         case PixelFormat::ALPHA_8:
921             glFormat = GL_ALPHA8_EXT;
922             perPixelSize = ImageUtils::GetPixelBytes(PixelFormat::ALPHA_8);
923             break;
924         default:
925             IMAGE_LOGE("slr_gpu %{public}s format %{public}d is not support! ", __func__, originFormat);
926             break;
927     }
928 }
929 
PixelMapPostProcWithGL(PixelMap & sourcePixelMap,GPUTransformData & trans,bool needHighQuality)930 static bool PixelMapPostProcWithGL(PixelMap &sourcePixelMap, GPUTransformData &trans, bool needHighQuality)
931 {
932     Size &desiredSize = trans.targetInfo_.size;
933     if (!CheckPixelMapSLR(sourcePixelMap, trans.targetInfo_.size, trans)) {
934         return false;
935     }
936     Size sourceSize;
937     GLenum glFormat = GL_RGBA;
938     int perPixelSize = ImageUtils::GetPixelBytes(sourcePixelMap.GetPixelFormat());
939     GetPixelMapInfo(sourcePixelMap, sourceSize, glFormat, perPixelSize);
940     ImageTrace imageTrace("PixelMapPostProcWithGL (%d, %d)=>(%d, %d) stride %d type %d transtype:%d",
941         sourceSize.width, sourceSize.height, desiredSize.width, desiredSize.height,
942         sourcePixelMap.GetRowStride(), (int)sourcePixelMap.GetAllocatorType(), (int)trans.transformationType);
943     IMAGE_LOGI("slr_gpu PixelMapPostProcWithGL uniqueId:%{public}d AllocatorType:%{public}d "
944         "size (%{public}d, %{public}d)=>(%{public}d, %{public}d) stride %{public}d transtype:%{public}d",
945         sourcePixelMap.GetUniqueId(), (int)sourcePixelMap.GetAllocatorType(), sourceSize.width, sourceSize.height,
946         desiredSize.width, desiredSize.height, sourcePixelMap.GetRowStride(), (int)trans.transformationType);
947     AllocatorType allocType = sourcePixelMap.GetAllocatorType();
948     size_t buffersize = 4 * desiredSize.width * desiredSize.height;
949     MemoryData memoryData = {nullptr, buffersize, "PixelMapPostProcWithGL", desiredSize};
950     std::unique_ptr<AbsMemory> dstMemory = MemoryManager::CreateMemory(allocType, memoryData);
951     if (dstMemory == nullptr || dstMemory->data.data == nullptr) {
952         IMAGE_LOGE("slr_gpu PixelMapPostProcWithGL dstMemory is null");
953         return false;
954     }
955     int outputStride = 4 * desiredSize.width;
956     if (allocType == AllocatorType::DMA_ALLOC) {
957         SurfaceBuffer* sbBuffer = reinterpret_cast<SurfaceBuffer*>(dstMemory->extend.data);
958         outputStride = sbBuffer->GetStride();
959         buffersize = sbBuffer->GetStride() * desiredSize.height;
960     }
961     PixelMapProgramManager::BuildShader();
962     bool ret = true;
963     auto program = PixelMapProgramManager::GetInstance().GetProgram();
964     if (program == nullptr) {
965         IMAGE_LOGE("slr_gpu PixelMapPostProcWithGL %{public}s create gl context failed", __func__);
966         ret = false;
967     } else {
968         trans.targetInfo_.stride = outputStride;
969         trans.targetInfo_.pixelBytes = perPixelSize;
970         trans.targetInfo_.outdata = dstMemory->data.data;
971         trans.targetInfo_.context = dstMemory->extend.data;
972         trans.glFormat = glFormat;
973         trans.isDma = allocType == AllocatorType::DMA_ALLOC ? true : false;
974         program->SetGPUTransformData(trans);
975         ret = PixelMapProgramManager::GetInstance().ExecutProgram(program);
976     }
977     if (!ret) {
978         dstMemory->Release();
979         IMAGE_LOGE("slr_gpu PixelMapPostProcWithGL Resize failed");
980         return false;
981     }
982     sourcePixelMap.SetPixelsAddr(dstMemory->data.data, dstMemory->extend.data,
983         desiredSize.height * outputStride, allocType, nullptr);
984     ImageInfo info;
985     info.size = desiredSize;
986     info.pixelFormat = PixelFormat::RGBA_8888;
987     info.alphaType = AlphaType::IMAGE_ALPHA_TYPE_UNPREMUL;
988     sourcePixelMap.SetImageInfo(info, true);
989     return true;
990 }
991 #endif
992 
RotateInRectangularSteps(PixelMap & pixelMap,float degrees,bool useGpu)993 bool PostProc::RotateInRectangularSteps(PixelMap &pixelMap, float degrees, bool useGpu)
994 {
995 #if !defined(_WIN32) && !defined(_APPLE) && !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)
996     float oldDegrees = degrees;
997     if (useGpu && ImageSystemProperties::GetGenThumbWithGpu() &&
998         std::fabs(std::fmod(degrees, 90.f)) < 1e-6) { // degrees 90
999         ImageTrace imageTrace("RotateInRectangularSteps:%f", degrees);
1000         IMAGE_LOGI("slr_gpu RotateInRectangularSteps in :%{public}f", degrees);
1001         GPUTransformData gpuTransform;
1002         ImageInfo imageInfo;
1003         pixelMap.GetImageInfo(imageInfo);
1004         GlCommon::Mat4 tmpMat4;
1005         std::array<float, 3> axis = { 0.0f, 0.0f, 1.0f }; // capacity 3
1006         float angle = degrees * M_PI / 180.f; // degrees 180
1007         gpuTransform.targetInfo_.size = {
1008             std::abs(imageInfo.size.width * std::cos(angle)) + std::abs(imageInfo.size.height * std::sin(angle)),
1009             std::abs(imageInfo.size.height * std::cos(angle)) + std::abs(imageInfo.size.width * std::sin(angle))
1010         };
1011         degrees = std::fmod(360.f - degrees, 360.f); // degrees 360
1012         gpuTransform.rotateTrans = GlCommon::Mat4(tmpMat4, degrees, axis);
1013         gpuTransform.rotateDegreeZ = degrees;
1014         gpuTransform.sourceInfo_ = {
1015             .size = imageInfo.size,
1016             .stride = pixelMap.GetRowStride(),
1017             .pixelBytes = ImageUtils::GetPixelBytes(pixelMap.GetPixelFormat()),
1018             .addr = pixelMap.GetPixels(),
1019             .context = pixelMap.GetFd(),
1020         };
1021         gpuTransform.transformationType = TransformationType::ROTATE;
1022         if (PixelMapPostProcWithGL(pixelMap, gpuTransform, true)) {
1023             IMAGE_LOGI("slr_gpu RotateInRectangularSteps success");
1024             return true;
1025         }
1026         IMAGE_LOGI("slr_gpu RotateInRectangularSteps rotate with cpu");
1027     }
1028 #endif
1029     pixelMap.rotate(oldDegrees);
1030     return true;
1031 }
1032 
ScalePixelMapWithGPU(PixelMap & pixelMap,const Size & desiredSize,const AntiAliasingOption & option,bool useGpu)1033 bool PostProc::ScalePixelMapWithGPU(PixelMap &pixelMap, const Size &desiredSize,
1034     const AntiAliasingOption &option, bool useGpu)
1035 {
1036 #if !defined(_WIN32) && !defined(_APPLE) && !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)
1037     if (useGpu && ImageSystemProperties::GetGenThumbWithGpu() &&
1038         option == AntiAliasingOption::HIGH) {
1039         ImageTrace imageTrace("ScalePixelMapWithGPU:wh(%d,%d)->(%d,%d)",
1040             pixelMap.GetWidth(), pixelMap.GetHeight(), desiredSize.width, desiredSize.height);
1041         IMAGE_LOGI("slr_gpu ScalePixelMapWithGPU:wh(%{public}d,%{public}d)->(%{public}d,%{public}d)",
1042             pixelMap.GetWidth(), pixelMap.GetHeight(), desiredSize.width, desiredSize.height);
1043         GPUTransformData gpuTransform;
1044         gpuTransform.targetInfo_.size = desiredSize;
1045         ImageInfo imageInfo;
1046         pixelMap.GetImageInfo(imageInfo);
1047         gpuTransform.sourceInfo_ = {
1048             .size = imageInfo.size,
1049             .stride = pixelMap.GetRowStride(),
1050             .pixelBytes = ImageUtils::GetPixelBytes(pixelMap.GetPixelFormat()),
1051             .addr = pixelMap.GetPixels(),
1052             .context = pixelMap.GetFd(),
1053         };
1054         gpuTransform.transformationType = TransformationType::SCALE;
1055         if (PixelMapPostProcWithGL(pixelMap, gpuTransform, true)) {
1056             IMAGE_LOGI("slr_gpu ScalePixelMapWithGPU success");
1057             return true;
1058         }
1059         IMAGE_LOGI("slr_gpu ScalePixelMapWithGPU failed scale with cpu");
1060     }
1061 #endif
1062     PostProc postProc;
1063     return postProc.ScalePixelMapEx(desiredSize, pixelMap, option);
1064 }
1065 
CreateSLRMemory(PixelMap & pixelMap,uint32_t dstBufferSize,const Size & desiredSize,std::unique_ptr<AbsMemory> & dstMemory,bool useLap)1066 static std::unique_ptr<AbsMemory> CreateSLRMemory(PixelMap &pixelMap, uint32_t dstBufferSize, const Size &desiredSize,
1067     std::unique_ptr<AbsMemory> &dstMemory, bool useLap)
1068 {
1069     AllocatorType allocatorType = pixelMap.GetAllocatorType();
1070     if (useLap && allocatorType == AllocatorType::DMA_ALLOC) {
1071         allocatorType = AllocatorType::SHARE_MEM_ALLOC;
1072     }
1073     MemoryData memoryData = {nullptr, dstBufferSize, "ScalePixelMapWithSLR ImageData", desiredSize,
1074         pixelMap.GetPixelFormat()};
1075     dstMemory = MemoryManager::CreateMemory(allocatorType, memoryData);
1076     if (dstMemory == nullptr) {
1077         IMAGE_LOGE("ScalePixelMapWithSLR create dstMemory failed");
1078         return nullptr;
1079     }
1080     std::unique_ptr<AbsMemory> lapMemory = nullptr;
1081     if (useLap) {
1082         MemoryData lapMemoryData = {nullptr, dstBufferSize, "ScalePixelMapWithSLR ImageData Lap", desiredSize,
1083             pixelMap.GetPixelFormat()};
1084         lapMemory = MemoryManager::CreateMemory(pixelMap.GetAllocatorType(), lapMemoryData);
1085         if (lapMemory == nullptr) {
1086             IMAGE_LOGE("ScalePixelMapWithSLR create lapMemory failed");
1087             dstMemory->Release();
1088             return nullptr;
1089         }
1090     }
1091     return lapMemory;
1092 }
1093 
getLapFactor(const ImageInfo & imgInfo,const Size & desiredSize)1094 float getLapFactor(const ImageInfo& imgInfo, const Size &desiredSize)
1095 {
1096     float coeff = ((float)desiredSize.width) / imgInfo.size.width;
1097     if (coeff > 0.8f) {
1098         return .0f;
1099     }
1100     if (coeff > 0.6f) {
1101         return 0.06f;
1102     }
1103     if (coeff > 0.5f) {
1104         return 0.1f;
1105     }
1106     return 0.15f;
1107 }
1108 
1109 struct SLRContext {
1110     void *data;
1111     bool useLap;
1112 };
1113 
ExecuteSLR(PixelMap & pixelMap,const Size & desiredSize,SLRMat & src,SLRMat & dst,SLRContext scalingContext)1114 bool ExecuteSLR(PixelMap& pixelMap, const Size& desiredSize, SLRMat &src, SLRMat &dst,
1115     SLRContext scalingContext)
1116 {
1117     ImageInfo imgInfo;
1118     pixelMap.GetImageInfo(imgInfo);
1119     std::shared_ptr<SLRWeightTuple> weightTuplePtr = initSLRFactor(imgInfo.size, desiredSize);
1120     if (weightTuplePtr == nullptr) {
1121         IMAGE_LOGE("PostProcExecuteSLR init failed");
1122         return false;
1123     }
1124     SLRWeightMat slrWeightX = std::get<0>(*weightTuplePtr);
1125     SLRWeightMat slrWeightY = std::get<1>(*weightTuplePtr);
1126     if (ImageSystemProperties::GetSLRParallelEnabled()) {
1127         SLRProc::Parallel(src, dst, slrWeightX, slrWeightY);
1128     } else {
1129         SLRProc::Serial(src, dst, slrWeightX, slrWeightY);
1130     }
1131     if (scalingContext.useLap) {
1132         float factor = getLapFactor(imgInfo, desiredSize);
1133         SLRProc::Laplacian(dst, scalingContext.data, factor);
1134     }
1135     return true;
1136 }
1137 
ScalePixelMapWithSLR(const Size & desiredSize,PixelMap & pixelMap,bool useLap)1138 bool PostProc::ScalePixelMapWithSLR(const Size &desiredSize, PixelMap &pixelMap, bool useLap)
1139 {
1140     ImageInfo imgInfo;
1141     pixelMap.GetImageInfo(imgInfo);
1142     if (!CheckPixelMapSLR(desiredSize, pixelMap)) {
1143         return false;
1144     }
1145     useLap = useLap && ImageSystemProperties::GetSLRLaplacianEnabled();
1146     ImageTrace imageTrace("ScalePixelMapWithSLR");
1147     int32_t pixelBytes = pixelMap.GetPixelBytes();
1148     SLRMat src(imgInfo.size, imgInfo.pixelFormat, pixelMap.GetWritablePixels(), pixelMap.GetRowStride() / pixelBytes);
1149     uint32_t dstBufferSize = desiredSize.height * desiredSize.width * pixelBytes;
1150     std::unique_ptr<AbsMemory> m = nullptr;
1151     auto lapMemory = CreateSLRMemory(pixelMap, dstBufferSize, desiredSize, m, useLap);
1152     if (m == nullptr || (useLap && (lapMemory == nullptr))) {
1153         IMAGE_LOGE("pixelMap scale slr memory nullptr");
1154         return false;
1155     }
1156     size_t rowStride;
1157     if (m->GetType() == AllocatorType::DMA_ALLOC) {
1158 #if !defined(_WIN32) && !defined(_APPLE) && !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)
1159         rowStride = reinterpret_cast<SurfaceBuffer*>(m->extend.data)->GetStride();
1160 #endif
1161     } else {
1162         rowStride = desiredSize.width * pixelBytes;
1163     }
1164     void *data = useLap ? lapMemory->data.data : m->data.data;
1165     SLRMat dst({desiredSize.width, desiredSize.height}, imgInfo.pixelFormat, data, rowStride / pixelBytes);
1166     if (!ExecuteSLR(pixelMap, desiredSize, src, dst, {m->data.data, useLap})) {
1167         m->Release();
1168         if (useLap && lapMemory) {
1169             lapMemory->Release();
1170         }
1171         return false;
1172     }
1173     pixelMap.SetPixelsAddr(m->data.data, m->extend.data, dstBufferSize, m->GetType(), nullptr);
1174     imgInfo.size = desiredSize;
1175     pixelMap.SetImageInfo(imgInfo, true);
1176     if (m->GetType() == AllocatorType::DMA_ALLOC) {
1177         ImageUtils::FlushSurfaceBuffer(&pixelMap);
1178     }
1179     if (lapMemory) {
1180         lapMemory->Release();
1181     }
1182     return true;
1183 }
1184 
ScalePixelMapEx(const Size & desiredSize,PixelMap & pixelMap,const AntiAliasingOption & option)1185 bool PostProc::ScalePixelMapEx(const Size &desiredSize, PixelMap &pixelMap, const AntiAliasingOption &option)
1186 {
1187     ImageTrace imageTrace("PixelMap ScalePixelMapEx, srcSize[%d, %d], dstSize[%d, %d] ",
1188         pixelMap.GetWidth(), pixelMap.GetHeight(), desiredSize.width, desiredSize.height);
1189     IMAGE_LOGI("slr_gpu ScalePixelMapEx pixelMap: width = %{public}d, height = %{public}d, pixelFormat = %{public}d, "
1190         "allocatorType = %{public}d; desiredSize: width = %{public}d, height = %{public}d",
1191         pixelMap.GetWidth(), pixelMap.GetHeight(), pixelMap.GetPixelFormat(),
1192         pixelMap.GetAllocatorType(), desiredSize.width, desiredSize.height);
1193     ImageInfo imgInfo;
1194     pixelMap.GetImageInfo(imgInfo);
1195     int32_t srcWidth = pixelMap.GetWidth();
1196     int32_t srcHeight = pixelMap.GetHeight();
1197     if (srcWidth <= 0 || srcHeight <= 0 || !pixelMap.GetWritablePixels()) {
1198         IMAGE_LOGE("pixelMap param is invalid, src width:%{public}d, height:%{public}d", srcWidth, srcHeight);
1199         return false;
1200     }
1201     AVPixelFormat pixelFormat;
1202     if (!GetScaleFormat(imgInfo.pixelFormat, pixelFormat)) {
1203         IMAGE_LOGE("pixelMap format is invalid, format: %{public}d", imgInfo.pixelFormat);
1204         return false;
1205     }
1206     uint64_t dstBufferSizeOverflow =
1207         static_cast<uint64_t>(desiredSize.width) * static_cast<uint64_t>(desiredSize.height) *
1208         static_cast<uint64_t>(ImageUtils::GetPixelBytes(imgInfo.pixelFormat));
1209     if (dstBufferSizeOverflow > UINT_MAX) {
1210         IMAGE_LOGE("ScalePixelMapEx target size too large");
1211         return false;
1212     }
1213     uint32_t dstBufferSize = static_cast<uint32_t>(dstBufferSizeOverflow);
1214     MemoryData memoryData = {nullptr, dstBufferSize, "ScalePixelMapEx ImageData", desiredSize};
1215 
1216     auto mem = MemoryManager::CreateMemory(pixelMap.GetAllocatorType() == AllocatorType::CUSTOM_ALLOC ?
1217         AllocatorType::DEFAULT : pixelMap.GetAllocatorType(), memoryData);
1218     if (mem == nullptr) {
1219         IMAGE_LOGE("ScalePixelMapEx CreateMemory failed");
1220         return false;
1221     }
1222 
1223     const uint8_t *srcPixels[FFMPEG_NUM] = {};
1224     uint8_t *dstPixels[FFMPEG_NUM] = {};
1225     srcPixels[0] = pixelMap.GetPixels();
1226     dstPixels[0] = reinterpret_cast<uint8_t *>(mem->data.data);
1227     int srcRowStride[FFMPEG_NUM] = {};
1228     int dstRowStride[FFMPEG_NUM] = {};
1229     srcRowStride[0] = pixelMap.GetRowStride();
1230     dstRowStride[0] = (mem->GetType() == AllocatorType::DMA_ALLOC) ?
1231         reinterpret_cast<SurfaceBuffer*>(mem->extend.data)->GetStride() :
1232         desiredSize.width * ImageUtils::GetPixelBytes(imgInfo.pixelFormat);
1233 
1234     void *inBuf = nullptr;
1235     if (srcWidth % HALF != 0 && pixelMap.GetAllocatorType() == AllocatorType::SHARE_MEM_ALLOC) {
1236         // Workaround for crash on odd number width, caused by FFmpeg 5.0 upgrade
1237         uint64_t byteCount = static_cast<uint64_t>(srcRowStride[0]) * static_cast<uint64_t>(srcHeight);
1238         uint64_t allocSize = static_cast<uint64_t>(srcWidth + 1) * static_cast<uint64_t>(srcHeight) *
1239             static_cast<uint64_t>(ImageUtils::GetPixelBytes(imgInfo.pixelFormat));
1240         if (srcRowStride[0] <= 0 || byteCount > UINT_MAX || allocSize < byteCount || allocSize > UINT_MAX) {
1241             mem->Release();
1242             IMAGE_LOGE("ScalePixelMapEx invalid srcRowStride or pixelMap size too large");
1243             return false;
1244         }
1245         inBuf = malloc(allocSize);
1246         srcPixels[0] = reinterpret_cast<uint8_t*>(inBuf);
1247         errno_t errRet = memcpy_s(inBuf, allocSize, pixelMap.GetWritablePixels(), byteCount);
1248         if (errRet != EOK) {
1249             if (inBuf != nullptr) {
1250                 free(inBuf);
1251             }
1252             mem->Release();
1253             IMAGE_LOGE("ScalePixelMapEx memcpy_s failed with error code: %{public}d", errRet);
1254             return false;
1255         }
1256     }
1257 
1258     SwsContext *swsContext = sws_getContext(srcWidth, srcHeight, pixelFormat, desiredSize.width, desiredSize.height,
1259         pixelFormat, GetInterpolation(option), nullptr, nullptr, nullptr);
1260     if (swsContext == nullptr) {
1261         if (inBuf != nullptr) {
1262             free(inBuf);
1263         }
1264         mem->Release();
1265         IMAGE_LOGE("sws_getContext failed");
1266         return false;
1267     }
1268     auto res = sws_scale(swsContext, srcPixels, srcRowStride, 0, srcHeight, dstPixels, dstRowStride);
1269 
1270     sws_freeContext(swsContext);
1271     if (inBuf != nullptr) {
1272         free(inBuf);
1273     }
1274     if (!res) {
1275         mem->Release();
1276         IMAGE_LOGE("sws_scale failed");
1277         return false;
1278     }
1279     pixelMap.SetPixelsAddr(mem->data.data, mem->extend.data, dstBufferSize, mem->GetType(), nullptr);
1280     imgInfo.size = desiredSize;
1281     pixelMap.SetImageInfo(imgInfo, true);
1282     return true;
1283 }
1284 #endif
1285 } // namespace Media
1286 } // namespace OHOS
1287