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