• 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 <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