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