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 <unistd.h>
19
20 #include "basic_transformer.h"
21 #include "image_log.h"
22 #include "image_trace.h"
23 #include "image_utils.h"
24 #include "media_errors.h"
25 #include "memory_manager.h"
26 #include "pixel_convert_adapter.h"
27 #ifndef _WIN32
28 #include "securec.h"
29 #else
30 #include "memory.h"
31 #endif
32
33 #if !defined(_WIN32) && !defined(_APPLE) && !defined(IOS_PLATFORM) && !defined(A_PLATFORM)
34 #include <sys/mman.h>
35 #include "ashmem.h"
36 #include "surface_buffer.h"
37
38 #ifdef __cplusplus
39 extern "C" {
40 #endif
41 #include "libswscale/swscale.h"
42 #ifdef __cplusplus
43 };
44 #endif
45 #endif
46
47 #undef LOG_DOMAIN
48 #define LOG_DOMAIN LOG_TAG_DOMAIN_ID_IMAGE
49
50 #undef LOG_TAG
51 #define LOG_TAG "PostProc"
52
53 namespace OHOS {
54 namespace Media {
55 using namespace std;
56 constexpr uint32_t NEED_NEXT = 1;
57 constexpr float EPSILON = 1e-6;
58 constexpr uint8_t HALF = 2;
59 constexpr float HALF_F = 2;
60 constexpr int FFMPEG_NUM = 8;
61
62 #if !defined(_WIN32) && !defined(_APPLE) && !defined(IOS_PLATFORM) && !defined(A_PLATFORM)
63 static const map<PixelFormat, AVPixelFormat> PIXEL_FORMAT_MAP = {
64 { PixelFormat::ALPHA_8, AVPixelFormat::AV_PIX_FMT_GRAY8 },
65 { PixelFormat::RGB_565, AVPixelFormat::AV_PIX_FMT_RGB565BE },
66 { PixelFormat::RGB_888, AVPixelFormat::AV_PIX_FMT_RGB24 },
67 { PixelFormat::RGBA_8888, AVPixelFormat::AV_PIX_FMT_RGBA },
68 { PixelFormat::ARGB_8888, AVPixelFormat::AV_PIX_FMT_ARGB },
69 { PixelFormat::BGRA_8888, AVPixelFormat::AV_PIX_FMT_BGRA },
70 { PixelFormat::RGBA_F16, AVPixelFormat::AV_PIX_FMT_RGBA64BE },
71 };
72 #endif
73
DecodePostProc(const DecodeOptions & opts,PixelMap & pixelMap,FinalOutputStep finalOutputStep)74 uint32_t PostProc::DecodePostProc(const DecodeOptions &opts, PixelMap &pixelMap, FinalOutputStep finalOutputStep)
75 {
76 ImageInfo srcImageInfo;
77 pixelMap.GetImageInfo(srcImageInfo);
78 ImageInfo dstImageInfo;
79 GetDstImageInfo(opts, pixelMap, srcImageInfo, dstImageInfo);
80 uint32_t errorCode = ConvertProc(opts.CropRect, dstImageInfo, pixelMap, srcImageInfo);
81 if (errorCode != SUCCESS) {
82 IMAGE_LOGE("[PostProc]crop pixel map failed, errcode:%{public}u", errorCode);
83 return errorCode;
84 }
85 decodeOpts_.allocatorType = opts.allocatorType;
86 bool isNeedRotate = !ImageUtils::FloatCompareZero(opts.rotateDegrees);
87 if (isNeedRotate) {
88 if (!RotatePixelMap(opts.rotateDegrees, pixelMap)) {
89 IMAGE_LOGE("[PostProc]rotate:transform pixel map failed");
90 return ERR_IMAGE_TRANSFORM;
91 }
92 }
93 decodeOpts_.allocatorType = opts.allocatorType;
94 if (opts.desiredSize.height > 0 && opts.desiredSize.width > 0) {
95 if (!ScalePixelMap(opts.desiredSize, pixelMap)) {
96 IMAGE_LOGE("[PostProc]scale:transform pixel map failed");
97 return ERR_IMAGE_TRANSFORM;
98 }
99 } else {
100 ImageInfo info;
101 pixelMap.GetImageInfo(info);
102 if ((finalOutputStep == FinalOutputStep::DENSITY_CHANGE) && (info.baseDensity != 0)) {
103 int targetWidth = (pixelMap.GetWidth() * opts.fitDensity + (info.baseDensity >> 1)) / info.baseDensity;
104 int targetHeight = (pixelMap.GetHeight() * opts.fitDensity + (info.baseDensity >> 1)) / info.baseDensity;
105 Size size;
106 size.height = targetHeight;
107 size.width = targetWidth;
108 if (!ScalePixelMap(size, pixelMap)) {
109 IMAGE_LOGE("[PostProc]density scale:transform pixel map failed");
110 return ERR_IMAGE_TRANSFORM;
111 }
112 info.baseDensity = opts.fitDensity;
113 pixelMap.SetImageInfo(info, true);
114 }
115 }
116 return SUCCESS;
117 }
118
GetDstImageInfo(const DecodeOptions & opts,PixelMap & pixelMap,ImageInfo srcImageInfo,ImageInfo & dstImageInfo)119 void PostProc::GetDstImageInfo(const DecodeOptions &opts, PixelMap &pixelMap,
120 ImageInfo srcImageInfo, ImageInfo &dstImageInfo)
121 {
122 dstImageInfo.size = opts.desiredSize;
123 dstImageInfo.pixelFormat = opts.desiredPixelFormat;
124 dstImageInfo.baseDensity = srcImageInfo.baseDensity;
125 decodeOpts_ = opts;
126 if (opts.desiredPixelFormat == PixelFormat::UNKNOWN) {
127 if (opts.preference == MemoryUsagePreference::LOW_RAM &&
128 srcImageInfo.alphaType == AlphaType::IMAGE_ALPHA_TYPE_OPAQUE) {
129 dstImageInfo.pixelFormat = PixelFormat::RGB_565;
130 } else {
131 dstImageInfo.pixelFormat = PixelFormat::RGBA_8888;
132 }
133 }
134 // decode use, this value may be changed by real pixelFormat
135 if (pixelMap.GetAlphaType() == AlphaType::IMAGE_ALPHA_TYPE_UNPREMUL) {
136 dstImageInfo.alphaType = AlphaType::IMAGE_ALPHA_TYPE_PREMUL;
137 } else {
138 dstImageInfo.alphaType = pixelMap.GetAlphaType();
139 }
140 }
141
CenterScale(const Size & size,PixelMap & pixelMap)142 bool PostProc::CenterScale(const Size &size, PixelMap &pixelMap)
143 {
144 int32_t srcWidth = pixelMap.GetWidth();
145 int32_t srcHeight = pixelMap.GetHeight();
146 int32_t targetWidth = size.width;
147 int32_t targetHeight = size.height;
148 if (targetWidth <= 0 || targetHeight <= 0 || srcWidth <= 0 || srcHeight <= 0) {
149 IMAGE_LOGE("[PostProc]params invalid, targetWidth:%{public}d, targetHeight:%{public}d, "
150 "srcWidth:%{public}d, srcHeight:%{public}d", targetWidth, targetHeight, srcWidth, srcHeight);
151 return false;
152 }
153 float widthScale = static_cast<float>(targetWidth) / static_cast<float>(srcWidth);
154 float heightScale = static_cast<float>(targetHeight) / static_cast<float>(srcHeight);
155 float scale = max(widthScale, heightScale);
156 if (pixelMap.IsAstc() && scale > 0) {
157 TransformData transformData;
158 pixelMap.GetTransformData(transformData);
159 transformData.scaleX *= scale;
160 transformData.scaleY *= scale;
161 transformData.cropLeft = (srcWidth - targetWidth / scale) / HALF_F;
162 transformData.cropTop = (srcHeight - targetHeight / scale) / HALF_F;
163 transformData.cropWidth = targetWidth / scale;
164 transformData.cropHeight = targetHeight / scale;
165 pixelMap.SetTransformData(transformData);
166 ImageInfo imageInfo;
167 pixelMap.GetImageInfo(imageInfo);
168 imageInfo.size.width = targetWidth;
169 imageInfo.size.height = targetHeight;
170 pixelMap.SetImageInfo(imageInfo, true);
171 return true;
172 }
173 if (!ScalePixelMap(scale, scale, pixelMap)) {
174 IMAGE_LOGE("[PostProc]center scale pixelmap %{public}f fail", scale);
175 return false;
176 }
177 srcWidth = pixelMap.GetWidth();
178 srcHeight = pixelMap.GetHeight();
179 if (srcWidth == targetWidth && srcHeight == targetHeight) {
180 return true;
181 }
182 if (srcWidth < targetWidth || srcHeight < targetHeight) {
183 IMAGE_LOGE("[PostProc]src size [%{public}d, %{public}d] must less than dst size [%{public}d,"
184 "%{public}d]", srcWidth, srcHeight, targetWidth, targetHeight);
185 return false;
186 }
187
188 return CenterDisplay(pixelMap, srcWidth, srcHeight, targetWidth, targetHeight);
189 }
190
CopyPixels(PixelMap & pixelMap,uint8_t * dstPixels,const Size & dstSize,const int32_t srcWidth,const int32_t srcHeight,int32_t srcRowStride,int32_t targetRowStride)191 bool PostProc::CopyPixels(PixelMap& pixelMap, uint8_t* dstPixels, const Size& dstSize,
192 const int32_t srcWidth, const int32_t srcHeight,
193 int32_t srcRowStride, int32_t targetRowStride)
194 {
195 int32_t targetWidth = dstSize.width;
196 int32_t targetHeight = dstSize.height;
197 int32_t left = max(0, srcWidth - targetWidth) / HALF;
198 int32_t top = max(0, srcHeight - targetHeight) / HALF;
199 int32_t pixelBytes = pixelMap.GetPixelBytes();
200 uint8_t *srcPixels = const_cast<uint8_t *>(pixelMap.GetPixels()) + (top * srcWidth + left) * pixelBytes;
201 uint8_t *dstStartPixel = nullptr;
202 uint8_t *srcStartPixel = nullptr;
203 uint32_t targetRowBytes = targetWidth * pixelBytes;
204 if (targetRowStride <= 0) {
205 targetRowStride = targetRowBytes;
206 }
207 uint32_t srcRowBytes = srcWidth * pixelBytes;
208 if (srcRowStride <= 0) {
209 srcRowStride = srcRowBytes;
210 }
211 uint32_t copyRowBytes = std::min(srcWidth, targetWidth) * pixelBytes;
212 for (int32_t scanLine = 0; scanLine < std::min(srcHeight, targetHeight); scanLine++) {
213 dstStartPixel = dstPixels + scanLine * targetRowStride;
214 srcStartPixel = srcPixels + scanLine * srcRowStride;
215 errno_t errRet = memcpy_s(dstStartPixel, targetRowBytes, srcStartPixel, copyRowBytes);
216 if (errRet != EOK) {
217 IMAGE_LOGE("[PostProc]memcpy scanline %{public}d fail, errorCode = %{public}d", scanLine, errRet);
218 return false;
219 }
220 }
221 return true;
222 }
223
CenterDisplay(PixelMap & pixelMap,int32_t srcWidth,int32_t srcHeight,int32_t targetWidth,int32_t targetHeight)224 bool PostProc::CenterDisplay(PixelMap &pixelMap, int32_t srcWidth, int32_t srcHeight, int32_t targetWidth,
225 int32_t targetHeight)
226 {
227 ImageInfo dstImageInfo;
228 pixelMap.GetImageInfo(dstImageInfo);
229 int32_t srcRowStride = pixelMap.GetAllocatorType() == AllocatorType::DMA_ALLOC ? pixelMap.GetRowStride() : 0;
230 dstImageInfo.size.width = targetWidth;
231 dstImageInfo.size.height = targetHeight;
232 if (pixelMap.SetImageInfo(dstImageInfo, true) != SUCCESS) {
233 IMAGE_LOGE("update ImageInfo failed");
234 return false;
235 }
236 int32_t bufferSize = pixelMap.GetByteCount();
237 uint8_t *dstPixels = nullptr;
238 void *nativeBuffer = nullptr;
239 int fd = 0;
240 int targetRowStride = 0;
241 if (pixelMap.GetAllocatorType() == AllocatorType::HEAP_ALLOC) {
242 if (!AllocHeapBuffer(bufferSize, &dstPixels)) {
243 return false;
244 }
245 } else if (pixelMap.GetAllocatorType() == AllocatorType::DMA_ALLOC) {
246 dstPixels = AllocDmaMemory(dstImageInfo.size, bufferSize, &nativeBuffer, targetRowStride);
247 if (dstPixels == nullptr) {
248 IMAGE_LOGE("[PostProc]CenterDisplay AllocDmaMemory failed");
249 return false;
250 }
251 } else {
252 dstPixels = AllocSharedMemory(dstImageInfo.size, bufferSize, fd, pixelMap.GetUniqueId());
253 if (dstPixels == nullptr) {
254 IMAGE_LOGE("[PostProc]CenterDisplay AllocSharedMemory failed");
255 return false;
256 }
257 }
258 if (!CopyPixels(pixelMap, dstPixels, dstImageInfo.size, srcWidth, srcHeight, srcRowStride, targetRowStride)) {
259 IMAGE_LOGE("[PostProc]CopyPixels failed");
260 ReleaseBuffer(pixelMap.GetAllocatorType(), fd, bufferSize, &dstPixels, nativeBuffer);
261 return false;
262 }
263 void *fdBuffer = nullptr;
264 if (pixelMap.GetAllocatorType() == AllocatorType::HEAP_ALLOC) {
265 pixelMap.SetPixelsAddr(dstPixels, nullptr, bufferSize, AllocatorType::HEAP_ALLOC, nullptr);
266 } else if (pixelMap.GetAllocatorType() == AllocatorType::DMA_ALLOC) {
267 pixelMap.SetPixelsAddr(dstPixels, nativeBuffer, bufferSize, AllocatorType::DMA_ALLOC, nullptr);
268 } else {
269 fdBuffer = new int32_t();
270 *static_cast<int32_t *>(fdBuffer) = fd;
271 pixelMap.SetPixelsAddr(dstPixels, fdBuffer, bufferSize, AllocatorType::SHARE_MEM_ALLOC, nullptr);
272 }
273 return true;
274 }
275
ProcessScanlineFilter(ScanlineFilter & scanlineFilter,const Rect & cropRect,PixelMap & pixelMap,uint8_t * resultData,uint32_t rowBytes)276 bool PostProc::ProcessScanlineFilter(ScanlineFilter &scanlineFilter, const Rect &cropRect, PixelMap &pixelMap,
277 uint8_t *resultData, uint32_t rowBytes)
278 {
279 auto srcData = pixelMap.GetPixels();
280 int32_t scanLine = 0;
281 while (scanLine < pixelMap.GetHeight()) {
282 FilterRowType filterRow = scanlineFilter.GetFilterRowType(scanLine);
283 if (filterRow == FilterRowType::NON_REFERENCE_ROW) {
284 scanLine++;
285 continue;
286 }
287 if (filterRow == FilterRowType::LAST_REFERENCE_ROW) {
288 break;
289 }
290 uint32_t ret = scanlineFilter.FilterLine(resultData + ((scanLine - cropRect.top) * rowBytes), rowBytes,
291 srcData + (scanLine * pixelMap.GetRowBytes()));
292 if (ret != SUCCESS) {
293 IMAGE_LOGE("[PostProc]scan line failed, ret:%{public}u", ret);
294 return false;
295 }
296 scanLine++;
297 }
298 return true;
299 }
300
CheckScanlineFilter(const Rect & cropRect,ImageInfo & dstImageInfo,PixelMap & pixelMap,int32_t pixelBytes,ScanlineFilter & scanlineFilter)301 uint32_t PostProc::CheckScanlineFilter(const Rect &cropRect, ImageInfo &dstImageInfo, PixelMap &pixelMap,
302 int32_t pixelBytes, ScanlineFilter &scanlineFilter)
303 {
304 uint64_t bufferSize = static_cast<uint64_t>(dstImageInfo.size.width) * dstImageInfo.size.height * pixelBytes;
305 uint8_t *resultData = nullptr;
306 int fd = 0;
307 if (decodeOpts_.allocatorType == AllocatorType::SHARE_MEM_ALLOC) {
308 resultData = AllocSharedMemory(dstImageInfo.size, bufferSize, fd, pixelMap.GetUniqueId());
309 if (resultData == nullptr) {
310 IMAGE_LOGE("[PostProc]AllocSharedMemory failed");
311 return ERR_IMAGE_CROP;
312 }
313 } else {
314 if (!AllocHeapBuffer(bufferSize, &resultData)) {
315 return ERR_IMAGE_CROP;
316 }
317 }
318 if (ImageUtils::CheckMulOverflow(dstImageInfo.size.width, pixelBytes)) {
319 IMAGE_LOGE("[PostProc]size.width:%{public}d, is too large",
320 dstImageInfo.size.width);
321 ReleaseBuffer(decodeOpts_.allocatorType, fd, bufferSize, &resultData);
322 return ERR_IMAGE_CROP;
323 }
324 uint32_t rowBytes = pixelBytes * dstImageInfo.size.width;
325 if (!ProcessScanlineFilter(scanlineFilter, cropRect, pixelMap, resultData, rowBytes)) {
326 IMAGE_LOGE("[PostProc]ProcessScanlineFilter failed");
327 ReleaseBuffer(decodeOpts_.allocatorType, fd, bufferSize, &resultData);
328 return ERR_IMAGE_CROP;
329 }
330 uint32_t result = pixelMap.SetImageInfo(dstImageInfo);
331 if (result != SUCCESS) {
332 ReleaseBuffer(decodeOpts_.allocatorType, fd, bufferSize, &resultData);
333 return result;
334 }
335
336 if (decodeOpts_.allocatorType == AllocatorType::HEAP_ALLOC) {
337 pixelMap.SetPixelsAddr(resultData, nullptr, bufferSize, decodeOpts_.allocatorType, nullptr);
338 return result;
339 }
340 void *fdBuffer = new int32_t();
341 *static_cast<int32_t *>(fdBuffer) = fd;
342 pixelMap.SetPixelsAddr(resultData, fdBuffer, bufferSize, decodeOpts_.allocatorType, nullptr);
343 return result;
344 }
345
ConvertProc(const Rect & cropRect,ImageInfo & dstImageInfo,PixelMap & pixelMap,ImageInfo & srcImageInfo)346 uint32_t PostProc::ConvertProc(const Rect &cropRect, ImageInfo &dstImageInfo, PixelMap &pixelMap,
347 ImageInfo &srcImageInfo)
348 {
349 bool hasPixelConvert = HasPixelConvert(srcImageInfo, dstImageInfo);
350 uint32_t ret = NeedScanlineFilter(cropRect, srcImageInfo.size, hasPixelConvert);
351 if (ret != NEED_NEXT) {
352 return ret;
353 }
354
355 // we suppose a quick method to scanline in mostly seen cases: NO CROP && hasPixelConvert
356 if (GetCropValue(cropRect, srcImageInfo.size) == CropValue::NOCROP &&
357 dstImageInfo.pixelFormat == PixelFormat::ARGB_8888 && hasPixelConvert) {
358 IMAGE_LOGI("[PostProc]no need crop, only pixel convert.");
359 return PixelConvertProc(dstImageInfo, pixelMap, srcImageInfo);
360 }
361
362 ScanlineFilter scanlineFilter(srcImageInfo.pixelFormat);
363 // this method maybe update dst image size to crop size
364 SetScanlineCropAndConvert(cropRect, dstImageInfo, srcImageInfo, scanlineFilter, hasPixelConvert);
365
366 int32_t pixelBytes = ImageUtils::GetPixelBytes(dstImageInfo.pixelFormat);
367 if (pixelBytes == 0) {
368 return ERR_IMAGE_CROP;
369 }
370 if (ImageUtils::CheckMulOverflow(dstImageInfo.size.width, dstImageInfo.size.height, pixelBytes)) {
371 IMAGE_LOGE("[PostProc]size.width:%{public}d, size.height:%{public}d is too large",
372 dstImageInfo.size.width, dstImageInfo.size.height);
373 return ERR_IMAGE_CROP;
374 }
375 return CheckScanlineFilter(cropRect, dstImageInfo, pixelMap, pixelBytes, scanlineFilter);
376 }
377
PixelConvertProc(ImageInfo & dstImageInfo,PixelMap & pixelMap,ImageInfo & srcImageInfo)378 uint32_t PostProc::PixelConvertProc(ImageInfo &dstImageInfo, PixelMap &pixelMap,
379 ImageInfo &srcImageInfo)
380 {
381 uint32_t ret;
382 int fd = 0;
383 uint64_t bufferSize = 0;
384 uint8_t *resultData = nullptr;
385
386 // as no crop, the size is same as src
387 dstImageInfo.size = srcImageInfo.size;
388 if (AllocBuffer(dstImageInfo, &resultData, bufferSize, fd, pixelMap.GetUniqueId()) != SUCCESS) {
389 ReleaseBuffer(decodeOpts_.allocatorType, fd, bufferSize, &resultData);
390 return ERR_IMAGE_CROP;
391 }
392
393 int32_t pixelBytes = ImageUtils::GetPixelBytes(srcImageInfo.pixelFormat);
394 if (pixelBytes == 0) {
395 return ERR_IMAGE_CROP;
396 }
397
398 ret = pixelMap.SetImageInfo(dstImageInfo);
399 if (ret != SUCCESS) {
400 ReleaseBuffer(decodeOpts_.allocatorType, fd, bufferSize, &resultData);
401 return ret;
402 }
403
404 if (decodeOpts_.allocatorType == AllocatorType::HEAP_ALLOC) {
405 pixelMap.SetPixelsAddr(resultData, nullptr, bufferSize, decodeOpts_.allocatorType, nullptr);
406 return ret;
407 }
408
409 void *fdBuffer = new int32_t();
410 *static_cast<int32_t *>(fdBuffer) = fd;
411 pixelMap.SetPixelsAddr(resultData, fdBuffer, bufferSize, decodeOpts_.allocatorType, nullptr);
412 return ret;
413 }
414
AllocBuffer(ImageInfo imageInfo,uint8_t ** resultData,uint64_t & bufferSize,int & fd,uint32_t id)415 uint32_t PostProc::AllocBuffer(ImageInfo imageInfo, uint8_t **resultData, uint64_t &bufferSize, int &fd, uint32_t id)
416 {
417 int32_t pixelBytes = ImageUtils::GetPixelBytes(imageInfo.pixelFormat);
418 if (pixelBytes == 0) {
419 return ERR_IMAGE_CROP;
420 }
421 if (ImageUtils::CheckMulOverflow(imageInfo.size.width, imageInfo.size.height, pixelBytes)) {
422 IMAGE_LOGE("[PostProc]size.width:%{public}d, size.height:%{public}d is too large",
423 imageInfo.size.width, imageInfo.size.height);
424 return ERR_IMAGE_CROP;
425 }
426 bufferSize = static_cast<uint64_t>(imageInfo.size.width) * imageInfo.size.height * pixelBytes;
427 IMAGE_LOGD("[PostProc]size.width:%{public}d, size.height:%{public}d, bufferSize:%{public}lld",
428 imageInfo.size.width, imageInfo.size.height, static_cast<long long>(bufferSize));
429 if (decodeOpts_.allocatorType == AllocatorType::SHARE_MEM_ALLOC) {
430 *resultData = AllocSharedMemory(imageInfo.size, bufferSize, fd, id);
431 if (*resultData == nullptr) {
432 IMAGE_LOGE("[PostProc]AllocSharedMemory failed");
433 return ERR_IMAGE_CROP;
434 }
435 } else {
436 if (!AllocHeapBuffer(bufferSize, resultData)) {
437 return ERR_IMAGE_CROP;
438 }
439 }
440 return SUCCESS;
441 }
442
AllocHeapBuffer(uint64_t bufferSize,uint8_t ** buffer)443 bool PostProc::AllocHeapBuffer(uint64_t bufferSize, uint8_t **buffer)
444 {
445 if (bufferSize == 0 || bufferSize > MALLOC_MAX_LENTH) {
446 IMAGE_LOGE("[PostProc]Invalid value of bufferSize");
447 return false;
448 }
449 *buffer = static_cast<uint8_t *>(malloc(bufferSize));
450 if (*buffer == nullptr) {
451 IMAGE_LOGE("[PostProc]alloc covert color buffersize[%{public}llu] failed.",
452 static_cast<unsigned long long>(bufferSize));
453 return false;
454 }
455 #ifdef _WIN32
456 errno_t backRet = memset_s(*buffer, 0, bufferSize);
457 if (backRet != EOK) {
458 IMAGE_LOGE("[PostProc]memset convertData fail, errorCode = %{public}d", backRet);
459 ReleaseBuffer(AllocatorType::HEAP_ALLOC, 0, 0, buffer);
460 return false;
461 }
462 return true;
463 #else
464 errno_t errRet = memset_s(*buffer, bufferSize, 0, bufferSize);
465 if (errRet != EOK) {
466 IMAGE_LOGE("[PostProc]memset convertData fail, errorCode = %{public}d", errRet);
467 ReleaseBuffer(AllocatorType::HEAP_ALLOC, 0, 0, buffer);
468 return false;
469 }
470 return true;
471 #endif
472 }
473
AllocSharedMemory(const Size & size,const uint64_t bufferSize,int & fd,uint32_t uniqueId)474 uint8_t *PostProc::AllocSharedMemory(const Size &size, const uint64_t bufferSize, int &fd, uint32_t uniqueId)
475 {
476 #if defined(_WIN32) || defined(_APPLE) || defined(IOS_PLATFORM) || defined(A_PLATFORM)
477 return nullptr;
478 #else
479 std::string name = "Parcel RawData, uniqueId: " + std::to_string(getpid()) + '_' + std::to_string(uniqueId);
480 fd = AshmemCreate(name.c_str(), bufferSize);
481 if (fd < 0) {
482 IMAGE_LOGE("[PostProc]AllocSharedMemory fd error, bufferSize %{public}lld",
483 static_cast<long long>(bufferSize));
484 return nullptr;
485 }
486 int result = AshmemSetProt(fd, PROT_READ | PROT_WRITE);
487 if (result < 0) {
488 IMAGE_LOGE("[PostProc]AshmemSetProt error");
489 ::close(fd);
490 return nullptr;
491 }
492 void* ptr = ::mmap(nullptr, bufferSize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
493 if (ptr == MAP_FAILED) {
494 IMAGE_LOGE("[PostProc]mmap error, errno: %{public}s, fd %{public}d, bufferSize %{public}lld",
495 strerror(errno), fd, (long long)bufferSize);
496 ::close(fd);
497 return nullptr;
498 }
499 return reinterpret_cast<uint8_t *>(ptr);
500 #endif
501 }
502
AllocDmaMemory(const Size & size,const uint64_t bufferSize,void ** nativeBuffer,int & targetRowStride)503 uint8_t *PostProc::AllocDmaMemory(const Size &size, const uint64_t bufferSize,
504 void **nativeBuffer, int &targetRowStride)
505 {
506 #if defined(_WIN32) || defined(_APPLE) || defined(IOS_PLATFORM) || defined(A_PLATFORM)
507 return nullptr;
508 #else
509 MemoryData memoryData = {nullptr, (uint32_t)bufferSize, "PostProc", {size.width, size.height}};
510 auto dstMemory = MemoryManager::CreateMemory(AllocatorType::DMA_ALLOC, memoryData);
511 if (dstMemory == nullptr) {
512 return nullptr;
513 }
514 *nativeBuffer = dstMemory->extend.data;
515 auto sbBuffer = reinterpret_cast<SurfaceBuffer *>(dstMemory->extend.data);
516 targetRowStride = sbBuffer->GetStride();
517 return (uint8_t *)dstMemory->data.data;
518 #endif
519 }
520
ReleaseBuffer(AllocatorType allocatorType,int fd,uint64_t dataSize,uint8_t ** buffer,void * nativeBuffer)521 void PostProc::ReleaseBuffer(AllocatorType allocatorType, int fd,
522 uint64_t dataSize, uint8_t **buffer, void *nativeBuffer)
523 {
524 #if !defined(_WIN32) && !defined(_APPLE) && !defined(IOS_PLATFORM) && !defined(A_PLATFORM)
525 if (allocatorType == AllocatorType::SHARE_MEM_ALLOC) {
526 if (*buffer != nullptr) {
527 ::munmap(*buffer, dataSize);
528 ::close(fd);
529 }
530 return;
531 }
532 if (allocatorType == AllocatorType::DMA_ALLOC) {
533 if (nativeBuffer != nullptr) {
534 int32_t err = ImageUtils::SurfaceBuffer_Unreference(static_cast<SurfaceBuffer*>(nativeBuffer));
535 if (err != OHOS::GSERROR_OK) {
536 IMAGE_LOGE("PostProc NativeBufferReference failed");
537 }
538 }
539 return;
540 }
541 #endif
542
543 if (allocatorType == AllocatorType::HEAP_ALLOC) {
544 if (*buffer != nullptr) {
545 free(*buffer);
546 *buffer = nullptr;
547 }
548 return;
549 }
550 }
551
NeedScanlineFilter(const Rect & cropRect,const Size & srcSize,const bool & hasPixelConvert)552 uint32_t PostProc::NeedScanlineFilter(const Rect &cropRect, const Size &srcSize, const bool &hasPixelConvert)
553 {
554 CropValue value = GetCropValue(cropRect, srcSize);
555 if (value == CropValue::NOCROP && !hasPixelConvert) {
556 IMAGE_LOGI("[PostProc]no need crop and pixel convert.");
557 return SUCCESS;
558 } else if (value == CropValue::INVALID) {
559 IMAGE_LOGE("[PostProc]invalid corp region, top:%{public}d, left:%{public}d, "
560 "width:%{public}d, height:%{public}d", cropRect.top, cropRect.left, cropRect.width, cropRect.height);
561 return ERR_IMAGE_CROP;
562 }
563 return NEED_NEXT;
564 }
565
ConvertPixelMapToPixmapInfo(PixelMap & pixelMap,PixmapInfo & pixmapInfo)566 void PostProc::ConvertPixelMapToPixmapInfo(PixelMap &pixelMap, PixmapInfo &pixmapInfo)
567 {
568 pixmapInfo.imageInfo.size.width = pixelMap.GetWidth();
569 pixmapInfo.imageInfo.size.height = pixelMap.GetHeight();
570 pixmapInfo.imageInfo.pixelFormat = pixelMap.GetPixelFormat();
571 pixmapInfo.imageInfo.colorSpace = pixelMap.GetColorSpace();
572 pixmapInfo.imageInfo.alphaType = pixelMap.GetAlphaType();
573 pixmapInfo.imageInfo.baseDensity = pixelMap.GetBaseDensity();
574 pixmapInfo.data = const_cast<uint8_t *>(pixelMap.GetPixels());
575 pixmapInfo.bufferSize = pixelMap.GetByteCount();
576 }
577
RotatePixelMap(float rotateDegrees,PixelMap & pixelMap)578 bool PostProc::RotatePixelMap(float rotateDegrees, PixelMap &pixelMap)
579 {
580 BasicTransformer trans;
581 PixmapInfo input(false);
582 ConvertPixelMapToPixmapInfo(pixelMap, input);
583 // Default rotation at the center of the image, so divide 2
584 trans.SetRotateParam(rotateDegrees, static_cast<float>(input.imageInfo.size.width) * FHALF,
585 static_cast<float>(input.imageInfo.size.height) * FHALF);
586 return Transform(trans, input, pixelMap);
587 }
588
ScalePixelMap(const Size & size,PixelMap & pixelMap)589 bool PostProc::ScalePixelMap(const Size &size, PixelMap &pixelMap)
590 {
591 int32_t srcWidth = pixelMap.GetWidth();
592 int32_t srcHeight = pixelMap.GetHeight();
593 if (srcWidth <= 0 || srcHeight <= 0) {
594 IMAGE_LOGE("[PostProc]src width:%{public}d, height:%{public}d is invalid.", srcWidth, srcHeight);
595 return false;
596 }
597 float scaleX = static_cast<float>(size.width) / static_cast<float>(srcWidth);
598 float scaleY = static_cast<float>(size.height) / static_cast<float>(srcHeight);
599 return ScalePixelMap(scaleX, scaleY, pixelMap);
600 }
601
ScalePixelMap(float scaleX,float scaleY,PixelMap & pixelMap)602 bool PostProc::ScalePixelMap(float scaleX, float scaleY, PixelMap &pixelMap)
603 {
604 // returns directly with a scale of 1.0
605 if ((fabs(scaleX - 1.0f) < EPSILON) && (fabs(scaleY - 1.0f) < EPSILON)) {
606 return true;
607 }
608 return pixelMap.resize(scaleX, scaleY);
609 }
TranslatePixelMap(float tX,float tY,PixelMap & pixelMap)610 bool PostProc::TranslatePixelMap(float tX, float tY, PixelMap &pixelMap)
611 {
612 BasicTransformer trans;
613 PixmapInfo input(false);
614 ConvertPixelMapToPixmapInfo(pixelMap, input);
615
616 trans.SetTranslateParam(tX, tY);
617 return Transform(trans, input, pixelMap);
618 }
619
Transform(BasicTransformer & trans,const PixmapInfo & input,PixelMap & pixelMap)620 bool PostProc::Transform(BasicTransformer &trans, const PixmapInfo &input, PixelMap &pixelMap)
621 {
622 if (pixelMap.IsTransformered()) {
623 IMAGE_LOGE("[PostProc]Transform pixelmap is transforming");
624 return false;
625 }
626 pixelMap.SetTransformered(true);
627 PixmapInfo output(false);
628 output.uniqueId = pixelMap.GetUniqueId();
629 uint32_t ret;
630 if (decodeOpts_.allocatorType == AllocatorType::SHARE_MEM_ALLOC) {
631 typedef uint8_t *(*AllocMemory)(const Size &size, const uint64_t bufferSize, int &fd, uint32_t uniqueId);
632 AllocMemory allcFunc = AllocSharedMemory;
633 ret = trans.TransformPixmap(input, output, allcFunc);
634 } else {
635 ret = trans.TransformPixmap(input, output);
636 }
637 if (ret != IMAGE_SUCCESS) {
638 output.Destroy();
639 return false;
640 }
641
642 if (pixelMap.SetImageInfo(output.imageInfo) != SUCCESS) {
643 output.Destroy();
644 return false;
645 }
646 pixelMap.SetPixelsAddr(output.data, output.context, output.bufferSize, decodeOpts_.allocatorType, nullptr);
647 pixelMap.SetTransformered(false);
648 return true;
649 }
650
GetCropValue(const Rect & rect,const Size & size)651 CropValue PostProc::GetCropValue(const Rect &rect, const Size &size)
652 {
653 bool isSameSize = (rect.top == 0 && rect.left == 0 && rect.height == size.height && rect.width == size.width);
654 if (!IsHasCrop(rect) || isSameSize) {
655 return CropValue::NOCROP;
656 }
657 bool isValid = ((rect.top >= 0 && rect.width > 0 && rect.left >= 0 && rect.height > 0) &&
658 (rect.top + rect.height <= size.height) && (rect.left + rect.width <= size.width));
659 if (!isValid) {
660 return CropValue::INVALID;
661 }
662 return CropValue::VALID;
663 }
664
ValidCropValue(Rect & rect,const Size & size)665 CropValue PostProc::ValidCropValue(Rect &rect, const Size &size)
666 {
667 CropValue res = GetCropValue(rect, size);
668 if (res == CropValue::INVALID) {
669 if (rect.top + rect.height > size.height) {
670 rect.height = size.height - rect.top;
671 }
672 if (rect.left + rect.width > size.width) {
673 rect.width = size.width - rect.left;
674 }
675 res = GetCropValue(rect, size);
676 }
677 return res;
678 }
679
IsHasCrop(const Rect & rect)680 bool PostProc::IsHasCrop(const Rect &rect)
681 {
682 return (rect.top != 0 || rect.left != 0 || rect.width != 0 || rect.height != 0);
683 }
684
HasPixelConvert(const ImageInfo & srcImageInfo,ImageInfo & dstImageInfo)685 bool PostProc::HasPixelConvert(const ImageInfo &srcImageInfo, ImageInfo &dstImageInfo)
686 {
687 dstImageInfo.alphaType = ImageUtils::GetValidAlphaTypeByFormat(dstImageInfo.alphaType, dstImageInfo.pixelFormat);
688 return (dstImageInfo.pixelFormat != srcImageInfo.pixelFormat || dstImageInfo.alphaType != srcImageInfo.alphaType);
689 }
690
SetScanlineCropAndConvert(const Rect & cropRect,ImageInfo & dstImageInfo,ImageInfo & srcImageInfo,ScanlineFilter & scanlineFilter,bool hasPixelConvert)691 void PostProc::SetScanlineCropAndConvert(const Rect &cropRect, ImageInfo &dstImageInfo, ImageInfo &srcImageInfo,
692 ScanlineFilter &scanlineFilter, bool hasPixelConvert)
693 {
694 if (hasPixelConvert) {
695 scanlineFilter.SetPixelConvert(srcImageInfo, dstImageInfo);
696 }
697
698 Rect srcRect = cropRect;
699 if (IsHasCrop(cropRect)) {
700 dstImageInfo.size.width = cropRect.width;
701 dstImageInfo.size.height = cropRect.height;
702 } else {
703 srcRect = { 0, 0, srcImageInfo.size.width, srcImageInfo.size.height };
704 dstImageInfo.size = srcImageInfo.size;
705 }
706 scanlineFilter.SetSrcRegion(srcRect);
707 }
708
709 #if !defined(_WIN32) && !defined(_APPLE) && !defined(IOS_PLATFORM) && !defined(A_PLATFORM)
GetScaleFormat(const PixelFormat & format,AVPixelFormat & pixelFormat)710 bool GetScaleFormat(const PixelFormat &format, AVPixelFormat &pixelFormat)
711 {
712 if (format != PixelFormat::UNKNOWN) {
713 auto formatPair = PIXEL_FORMAT_MAP.find(format);
714 if (formatPair != PIXEL_FORMAT_MAP.end() && formatPair->second != 0) {
715 pixelFormat = formatPair->second;
716 return true;
717 }
718 }
719 return false;
720 }
721
GetInterpolation(const AntiAliasingOption & option)722 int GetInterpolation(const AntiAliasingOption &option)
723 {
724 switch (option) {
725 case AntiAliasingOption::NONE:
726 return SWS_POINT;
727 case AntiAliasingOption::LOW:
728 return SWS_BILINEAR;
729 case AntiAliasingOption::MEDIUM:
730 return SWS_BICUBIC;
731 case AntiAliasingOption::HIGH:
732 return SWS_AREA;
733 case AntiAliasingOption::FAST_BILINEAER:
734 return SWS_FAST_BILINEAR;
735 case AntiAliasingOption::BICUBLIN:
736 return SWS_BICUBLIN;
737 case AntiAliasingOption::GAUSS:
738 return SWS_GAUSS;
739 case AntiAliasingOption::SINC:
740 return SWS_SINC;
741 case AntiAliasingOption::LANCZOS:
742 return SWS_LANCZOS;
743 case AntiAliasingOption::SPLINE:
744 return SWS_SPLINE;
745 default:
746 return SWS_POINT;
747 }
748 }
749
ScalePixelMapEx(const Size & desiredSize,PixelMap & pixelMap,const AntiAliasingOption & option)750 bool PostProc::ScalePixelMapEx(const Size &desiredSize, PixelMap &pixelMap, const AntiAliasingOption &option)
751 {
752 ImageTrace imageTrace("PixelMap ScalePixelMapEx");
753 ImageInfo imgInfo;
754 pixelMap.GetImageInfo(imgInfo);
755 int32_t srcWidth = pixelMap.GetWidth();
756 int32_t srcHeight = pixelMap.GetHeight();
757 if (srcWidth <= 0 || srcHeight <= 0 || !pixelMap.GetWritablePixels()) {
758 IMAGE_LOGE("pixelMap param is invalid, src width:%{public}d, height:%{public}d", srcWidth, srcHeight);
759 return false;
760 }
761 AVPixelFormat pixelFormat;
762 if (!GetScaleFormat(imgInfo.pixelFormat, pixelFormat)) {
763 IMAGE_LOGE("pixelMap format is invalid, format: %{public}d", imgInfo.pixelFormat);
764 return false;
765 }
766 uint32_t dstBufferSize = desiredSize.height * desiredSize.width * ImageUtils::GetPixelBytes(imgInfo.pixelFormat);
767 MemoryData memoryData = {nullptr, dstBufferSize, "ScalePixelMapEx ImageData", desiredSize};
768 auto mem = MemoryManager::CreateMemory(pixelMap.GetAllocatorType(), memoryData);
769 if (mem == nullptr) {
770 IMAGE_LOGE("ScalePixelMapEx CreateMemory failed");
771 return false;
772 }
773
774 const uint8_t *srcPixels[FFMPEG_NUM] = {};
775 uint8_t *dstPixels[FFMPEG_NUM] = {};
776 srcPixels[0] = pixelMap.GetPixels();
777 dstPixels[0] = reinterpret_cast<uint8_t *>(mem->data.data);
778 int srcRowStride[FFMPEG_NUM] = {};
779 int dstRowStride[FFMPEG_NUM] = {};
780 srcRowStride[0] = pixelMap.GetRowStride();
781 if (mem->GetType() == AllocatorType::DMA_ALLOC) {
782 dstRowStride[0] = reinterpret_cast<SurfaceBuffer*>(mem->extend.data)->GetStride();
783 } else {
784 dstRowStride[0] = desiredSize.width * ImageUtils::GetPixelBytes(imgInfo.pixelFormat);
785 }
786 SwsContext *swsContext = sws_getContext(srcWidth, srcHeight, pixelFormat, desiredSize.width, desiredSize.height,
787 pixelFormat, GetInterpolation(option), nullptr, nullptr, nullptr);
788 auto res = sws_scale(swsContext, srcPixels, srcRowStride, 0, srcHeight, dstPixels, dstRowStride);
789 if (!res) {
790 sws_freeContext(swsContext);
791 mem->Release();
792 IMAGE_LOGE("sws_scale failed");
793 return false;
794 }
795 pixelMap.SetPixelsAddr(mem->data.data, mem->extend.data, dstBufferSize, mem->GetType(), nullptr);
796 imgInfo.size = desiredSize;
797 pixelMap.SetImageInfo(imgInfo, true);
798 sws_freeContext(swsContext);
799 return true;
800 }
801 #endif
802 } // namespace Media
803 } // namespace OHOS
804