• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024 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 "pixel_yuv_ext_utils.h"
17 
18 #include "image_log.h"
19 #include "ios"
20 #include "istream"
21 #include "image_trace.h"
22 #include "image_system_properties.h"
23 #include "media_errors.h"
24 #include "securec.h"
25 #if !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)
26 #include "surface_buffer.h"
27 #endif
28 
29 #undef LOG_DOMAIN
30 #define LOG_DOMAIN LOG_TAG_DOMAIN_ID_IMAGE
31 
32 #undef LOG_TAG
33 #define LOG_TAG "PixelYuvExtUtils"
34 
35 namespace OHOS {
36 namespace Media {
37 
38 static const uint8_t NUM_2 = 2;
39 static const uint8_t NUM_4 = 4;
40 static const uint32_t BYTE_PER_PIXEL = 2;
41 static const float ROUND_FLOAT_NUMBER = 0.5f;
42 
43 static const std::map<PixelFormat, AVPixelFormat> FFMPEG_PIXEL_FORMAT_MAP = {
44     {PixelFormat::UNKNOWN, AVPixelFormat::AV_PIX_FMT_NONE},
45     {PixelFormat::NV21, AVPixelFormat::AV_PIX_FMT_NV21},
46     {PixelFormat::NV12, AVPixelFormat::AV_PIX_FMT_NV12},
47     {PixelFormat::ARGB_8888, AVPixelFormat::AV_PIX_FMT_ARGB},
48     {PixelFormat::BGRA_8888, AVPixelFormat::AV_PIX_FMT_BGRA},
49 };
50 
GetYSize(int32_t width,int32_t height)51 static int32_t GetYSize(int32_t width, int32_t height)
52 {
53     return width * height;
54 }
55 
GetVOffset(int32_t width,int32_t height)56 static int32_t GetVOffset(int32_t width, int32_t height)
57 {
58     return width * height + ((width + 1) / NUM_2) * ((height + 1) / NUM_2);
59 }
60 
GetUStride(int32_t width)61 static int32_t GetUStride(int32_t width)
62 {
63     return (width + 1) / NUM_2;
64 }
65 
GetUVHeight(int32_t height)66 static int32_t GetUVHeight(int32_t height)
67 {
68     return (height + 1) / NUM_2;
69 }
70 
71 // Yuv420SP, u、 v blend planer
GetUVStride(int32_t width)72 static int32_t GetUVStride(int32_t width)
73 {
74     return (width + 1) / NUM_2 * NUM_2;
75 }
76 
GetImageSize(int32_t width,int32_t height)77 static uint32_t GetImageSize(int32_t width, int32_t height)
78 {
79     return width * height + ((width + 1) / NUM_2) * ((height + 1) / NUM_2) * NUM_2;
80 }
81 
BGRAToYuv420(const uint8_t * src,uint8_t * dst,int srcW,int srcH,PixelFormat pixelFormat,YUVDataInfo & info)82 bool PixelYuvExtUtils::BGRAToYuv420(const uint8_t *src, uint8_t *dst, int srcW, int srcH,
83     PixelFormat pixelFormat, YUVDataInfo &info)
84 {
85     auto converter = ConverterHandle::GetInstance().GetHandle();
86     int32_t r = 0;
87     if (pixelFormat == PixelFormat::NV12) {
88         r = converter.ARGBToNV12(src, srcW * NUM_4,
89                                  dst, info.yStride,
90                                  dst + info.uvOffset,
91                                  info.uvStride, srcW, srcH);
92     } else if (pixelFormat == PixelFormat::NV21) {
93         r = converter.ARGBToNV21(src, srcW * NUM_4,
94                                  dst, info.yStride,
95                                  dst + info.uvOffset,
96                                  info.uvStride, srcW, srcH);
97     }
98     return r == 0;
99 }
100 
Yuv420ToBGRA(const uint8_t * sample,uint8_t * dstArgb,Size & size,PixelFormat pixelFormat,YUVDataInfo & info)101 bool PixelYuvExtUtils::Yuv420ToBGRA(const uint8_t *sample, uint8_t *dstArgb,
102     Size &size, PixelFormat pixelFormat, YUVDataInfo &info)
103 {
104     info.uvStride = (info.uvStride +1) & ~1;
105     const uint8_t *srcY = sample + info.yOffset;
106     const uint8_t *srcUV = sample + info.uvOffset;
107     const uint32_t dstStrideARGB = static_cast<uint32_t>(size.width) * NUM_4;
108     auto converter = ConverterHandle::GetInstance().GetHandle();
109     if (pixelFormat == PixelFormat::NV12) {
110         converter.NV12ToARGB(srcY, info.yStride, srcUV, info.uvStride,
111             dstArgb, dstStrideARGB, size.width, size.height);
112     } else if (pixelFormat == PixelFormat::NV21) {
113         converter.NV21ToARGB(srcY, info.yStride, srcUV, info.uvStride,
114             dstArgb, dstStrideARGB, size.width, size.height);
115     }
116     return true;
117 }
118 
Yuv420ToARGB(const uint8_t * sample,uint8_t * dstArgb,Size & size,PixelFormat pixelFormat,YUVDataInfo & info)119 bool PixelYuvExtUtils::Yuv420ToARGB(const uint8_t *sample, uint8_t *dstArgb,
120     Size &size, PixelFormat pixelFormat, YUVDataInfo &info)
121 {
122     std::unique_ptr<uint8_t[]> temp = std::make_unique<uint8_t[]>(size.width * size.height * NUM_4);
123     if (!Yuv420ToBGRA(sample, temp.get(), size, pixelFormat, info)) {
124         IMAGE_LOGE("Yuv420ToBGRA failed");
125         return false;
126     }
127     auto converter = ConverterHandle::GetInstance().GetHandle();
128     bool cond = converter.ARGBToBGRA(temp.get(), size.width * NUM_4, dstArgb,
129                                      size.width * NUM_4, size.width, size.height) != SUCCESS;
130     CHECK_ERROR_RETURN_RET_LOG(cond, false, "ARGBToBGRA failed");
131     return true;
132 }
133 
134 
NV12Rotate(uint8_t * src,PixelSize & size,YUVDataInfo & info,OpenSourceLibyuv::RotationMode & rotateNum,uint8_t * dst,YUVStrideInfo & dstStrides)135 bool PixelYuvExtUtils::NV12Rotate(uint8_t *src, PixelSize &size, YUVDataInfo &info,
136     OpenSourceLibyuv::RotationMode &rotateNum, uint8_t* dst, YUVStrideInfo &dstStrides)
137 {
138     std::unique_ptr<uint8_t[]> tmpPixels = std::make_unique<uint8_t[]>(GetImageSize(size.dstW, size.dstH));
139     uint8_t *srcY = src + info.yOffset;
140     uint8_t *srcUV = src + info.uvOffset;
141     uint8_t *tmpY = tmpPixels.get();
142     uint8_t *tmpU = tmpPixels.get()+ GetYSize(size.dstW, size.dstH);
143     uint8_t *tmpV = tmpPixels.get()+ GetVOffset(size.dstW, size.dstH);
144 
145     auto converter = ConverterHandle::GetInstance().GetHandle();
146 
147     int srcYStride = static_cast<int>(info.yStride);
148     int srcUVStride = static_cast<int>(info.uvStride);
149     int tmpYStride = size.dstW;
150     int tmpUStride = GetUStride(size.dstW);
151     int tmpVStride =  GetUStride(size.dstW);
152     if (converter.NV12ToI420Rotate(srcY, srcYStride, srcUV, srcUVStride,
153         tmpY, tmpYStride,
154         tmpU, tmpUStride,
155         tmpV, tmpVStride,
156         size.srcW, size.srcH, rotateNum) == -1) {
157         return false;
158     }
159 
160     int dstYStride = static_cast<int>(dstStrides.yStride);
161     int dstUVStride = static_cast<int>(dstStrides.uvStride);
162     int dstWidth = size.dstW;
163     int dstHeight = size.dstH;
164     auto dstY = dst + dstStrides.yOffset;
165     auto dstUV = dst + dstStrides.uvOffset;
166     IMAGE_LOGI("Image params: srcSizeW=%{public}d, srcSizeH=%{public}d, "
167         "dstSizeW=%{public}d, dstSizeH=%{public}d, RotationMode=%{public}d",
168         size.srcW, size.srcH, size.dstW, size.dstH,
169         static_cast<int>(rotateNum));
170     IMAGE_LOGI("Strides: srcYStride=%{public}d, srcUVStride=%{public}d, tmpYStride=%{public}d, "
171         "tmpUStride=%{public}d, tmpVStride=%{public}d, dstYStride=%{public}d, dstUVStride=%{public}d",
172         srcYStride, srcUVStride, tmpYStride, tmpUStride, tmpVStride, dstYStride, dstUVStride);
173     if (converter.I420ToNV12(tmpY, tmpYStride, tmpU, tmpUStride, tmpV, tmpVStride,
174         dstY, dstYStride, dstUV, dstUVStride, dstWidth, dstHeight) == -1) {
175         return false;
176     }
177 
178     return true;
179 }
180 
NV12P010Rotate(YuvPixels yuvPixels,PixelSize & size,YUVDataInfo & info,OpenSourceLibyuv::RotationMode & rotateNum,YUVStrideInfo & dstStrides)181 static bool NV12P010Rotate(YuvPixels yuvPixels, PixelSize& size, YUVDataInfo& info,
182     OpenSourceLibyuv::RotationMode& rotateNum, YUVStrideInfo& dstStrides)
183 {
184     std::unique_ptr<uint16_t[]> dstPixels = std::make_unique<uint16_t[]>(GetImageSize(info.yStride, size.srcH));
185     uint16_t* srcbuffer = reinterpret_cast<uint16_t *>(yuvPixels.srcPixels);
186     uint16_t* srcY = srcbuffer + info.yOffset;
187     uint16_t* srcUV = srcbuffer + info.uvOffset;
188 
189     uint16_t* dstY = dstPixels.get();
190     uint16_t* dstU = dstPixels.get() + GetYSize(info.yStride, size.srcH);
191     uint16_t* dstV = dstPixels.get() + GetVOffset(info.yStride, size.srcH);
192     auto converter = ConverterHandle::GetInstance().GetHandle();
193     if (converter.P010ToI010(srcY, info.yStride, srcUV, GetUVStride(info.yStride),
194         dstY, info.yStride, dstU, GetUStride(info.yStride),
195         dstV, GetUStride(info.yStride), size.srcW, size.srcH) == -1) {
196         IMAGE_LOGE("NV12P010ToI010 failed");
197         return false;
198     }
199 
200     std::unique_ptr<uint16_t[]> rotatePixels = std::make_unique<uint16_t[]>(GetImageSize(size.srcW, size.srcH));
201     uint16_t* rotateY = rotatePixels.get();
202     uint16_t* rotateU = rotatePixels.get() + GetYSize(size.dstW, size.dstH);
203     uint16_t* rotateV = rotatePixels.get() + GetVOffset(size.dstW, size.dstH);
204 
205     if (converter.I010Rotate(dstY, info.yStride, dstU, GetUStride(info.yStride),
206         dstV, GetUStride(info.yStride), rotateY, size.dstW, rotateU, GetUStride(size.dstW),
207         rotateV, GetUStride(size.dstW), size.srcW, size.srcH, rotateNum) == -1) {
208         IMAGE_LOGE("I010Rotate failed");
209         return false;
210     }
211 
212     uint16_t* dstbuffer = reinterpret_cast<uint16_t *>(yuvPixels.dstPixels);
213     int32_t dstYStride = static_cast<int32_t>(dstStrides.yStride);
214     int32_t dstUVStride = static_cast<int32_t>(dstStrides.uvStride);
215     uint16_t* dstbufferY = dstbuffer + dstStrides.yOffset;
216     uint16_t* dstbufferUV = dstbuffer + dstStrides.uvOffset;
217     if (converter.I010ToP010(rotateY, size.dstW, rotateU, GetUStride(size.dstW), rotateV, GetUStride(size.dstW),
218         dstbufferY, dstYStride, dstbufferUV, dstUVStride, size.dstW, size.dstH) == -1) {
219         IMAGE_LOGE("I010ToP010 failed");
220         return false;
221     }
222     return true;
223 }
224 
YuvRotate(uint8_t * srcPixels,const PixelFormat & format,YUVDataInfo & info,Size & dstSize,uint8_t * dstPixels,YUVStrideInfo & dstStrides,OpenSourceLibyuv::RotationMode & rotateNum)225 bool PixelYuvExtUtils::YuvRotate(uint8_t* srcPixels, const PixelFormat& format, YUVDataInfo& info,
226     Size& dstSize, uint8_t* dstPixels, YUVStrideInfo& dstStrides, OpenSourceLibyuv::RotationMode &rotateNum)
227 {
228     int32_t dstWidth = dstSize.width;
229     int32_t dstHeight = dstSize.height;
230     PixelSize pixelSize = {info.imageSize.width, info.imageSize.height, dstWidth, dstHeight};
231     if (format == PixelFormat::YCBCR_P010 || format == PixelFormat::YCRCB_P010) {
232         IMAGE_LOGD("YuvRotate P010Rotate enter");
233         YuvPixels yuvPixels = {srcPixels, dstPixels, 0, 0};
234         if (!NV12P010Rotate(yuvPixels, pixelSize, info, rotateNum, dstStrides)) {
235             IMAGE_LOGE("YuvRotate P010Rotate fail");
236             return false;
237         }
238         return true;
239     }
240     if (!NV12Rotate(srcPixels, pixelSize, info, rotateNum, dstPixels, dstStrides)) {
241         return false;
242     }
243 
244     return true;
245 }
246 
ConvertYuvMode(OpenSourceLibyuv::FilterMode & filterMode,const AntiAliasingOption & option)247 void PixelYuvExtUtils::ConvertYuvMode(OpenSourceLibyuv::FilterMode &filterMode, const AntiAliasingOption &option)
248 {
249     switch (option) {
250         case AntiAliasingOption::NONE:
251             filterMode = OpenSourceLibyuv::FilterMode::kFilterNone;
252             break;
253         case AntiAliasingOption::LOW:
254             filterMode = OpenSourceLibyuv::FilterMode::kFilterLinear;
255             break;
256         case AntiAliasingOption::MEDIUM:
257             filterMode = OpenSourceLibyuv::FilterMode::kFilterBilinear;
258             break;
259         case AntiAliasingOption::HIGH:
260             filterMode = OpenSourceLibyuv::FilterMode::kFilterBox;
261             break;
262         default:
263             break;
264     }
265 }
266 
ScaleUVPlane(const uint8_t * src,uint8_t * dst,OpenSourceLibyuv::FilterMode filterMode,YuvImageInfo & yuvInfo,uint32_t dstYStride,uint32_t dstYHeight,uint32_t dstYWidth)267 static void ScaleUVPlane(const uint8_t *src, uint8_t*dst, OpenSourceLibyuv::FilterMode filterMode,
268     YuvImageInfo &yuvInfo, uint32_t dstYStride, uint32_t dstYHeight, uint32_t dstYWidth)
269 {
270     uint32_t srcUWidth = static_cast<uint32_t>(GetUStride(yuvInfo.width));
271     uint32_t srcUHeight = static_cast<uint32_t>(GetUVHeight(yuvInfo.height));
272     uint32_t dstUWidth = static_cast<uint32_t>(GetUStride(dstYWidth));
273     uint32_t dstUHeight = static_cast<uint32_t>(GetUVHeight(dstYHeight));
274     // Split VUplane
275     std::unique_ptr<uint8_t[]> uvData = std::make_unique<uint8_t[]>(NUM_2 * srcUWidth * srcUHeight);
276     if (uvData == nullptr) {
277         IMAGE_LOGE("ScaleUVPlane make unique ptr for uvData failed.");
278         return;
279     }
280     uint8_t *uData = nullptr;
281     uint8_t *vData = nullptr;
282     uint32_t dstSplitStride = srcUWidth;
283     const uint8_t *srcUV = src + yuvInfo.yuvDataInfo.uvOffset;
284     uint32_t uvStride = yuvInfo.yuvDataInfo.uvStride;
285     auto converter = ConverterHandle::GetInstance().GetHandle();
286     if (yuvInfo.yuvFormat == PixelFormat::NV12) {
287         uData = uvData.get();
288         vData = uvData.get() + srcUWidth * srcUHeight;
289         converter.SplitUVPlane(srcUV, uvStride, uData, dstSplitStride, vData, dstSplitStride, srcUWidth, srcUHeight);
290     } else if (yuvInfo.yuvFormat == PixelFormat::NV21) {
291         vData = uvData.get();
292         uData = uvData.get() + srcUWidth * srcUHeight;
293         converter.SplitUVPlane(srcUV, uvStride, vData, dstSplitStride, uData, dstSplitStride, srcUWidth, srcUHeight);
294     }
295     // malloc memory to store temp u v
296     std::unique_ptr<uint8_t[]> tempUVData = std::make_unique<uint8_t[]>(NUM_2 * dstUWidth * dstUHeight);
297     if (tempUVData == nullptr) {
298         IMAGE_LOGE("ScaleUVPlane make unique ptr for tempUVData failed.");
299         return;
300     }
301     uint8_t *tempUData = nullptr;
302     uint8_t *tempVData = nullptr;
303     if (yuvInfo.yuvFormat == PixelFormat::NV12) {
304         tempUData = tempUVData.get();
305         tempVData = tempUVData.get() + dstUWidth * dstUHeight;
306     } else if (yuvInfo.yuvFormat == PixelFormat::NV21) {
307         tempVData = tempUVData.get();
308         tempUData = tempUVData.get() + dstUWidth * dstUHeight;
309     }
310 
311     // resize u* and v
312     converter.ScalePlane(uData, dstSplitStride, srcUWidth, srcUHeight,
313                          tempUData, dstUWidth, dstUWidth, dstUHeight, filterMode);
314 
315     converter.ScalePlane(vData, dstSplitStride, srcUWidth, srcUHeight,
316                          tempVData, dstUWidth, dstUWidth, dstUHeight, filterMode);
317     // Merge  the UV
318     uint8_t *dstUV = dst + GetYSize(dstYStride, dstYHeight);
319 
320     int32_t dstUVStride = static_cast<int32_t>(dstUWidth * NUM_2);
321     //AllocatorType DMA_ALLOC
322     if (dstYStride != dstYWidth) {
323         dstUVStride = static_cast<int32_t>(dstYStride);
324     }
325     if (yuvInfo.yuvFormat == PixelFormat::NV12) {
326         converter.MergeUVPlane(tempUData, dstUWidth, tempVData, dstUWidth, dstUV, dstUVStride, dstUWidth, dstUHeight);
327     } else if (yuvInfo.yuvFormat == PixelFormat::NV21) {
328         converter.MergeUVPlane(tempVData, dstUWidth, tempUData, dstUWidth, dstUV, dstUVStride, dstUWidth, dstUHeight);
329     }
330 
331     uData = vData = nullptr;
332     tempUData = tempVData = nullptr;
333 }
334 
CopyP010Pixels(uint16_t * src,YUVStrideInfo & srcStrides,uint16_t * dst,YUVStrideInfo & dstStrides,YuvCopyInfo & yuvCopyInfo)335 static bool CopyP010Pixels(
336     uint16_t *src, YUVStrideInfo &srcStrides, uint16_t *dst, YUVStrideInfo &dstStrides, YuvCopyInfo &yuvCopyInfo)
337 {
338     uint16_t* srcY = src + srcStrides.yOffset;
339     uint16_t* srcUV = srcY + srcStrides.uvOffset;
340     uint16_t* dstY = dst + dstStrides.yOffset;
341     uint16_t* dstUV = dstY + dstStrides.uvOffset;
342     uint32_t stride = std::min(srcStrides.yStride, dstStrides.yStride);
343     uint32_t uvStride = std::min(srcStrides.uvStride, dstStrides.uvStride);
344     uint32_t yHeight = yuvCopyInfo.dstHeight;
345     if ((srcStrides.yOffset + srcStrides.uvOffset +
346         uvStride * static_cast<uint32_t>(GetUVHeight(yHeight))) * BYTE_PER_PIXEL > yuvCopyInfo.pixelsSize) {
347         IMAGE_LOGE("CopyP010Pixels src buffer size is invalid, pixelsSize:%{public}u", yuvCopyInfo.pixelsSize);
348         return false;
349     }
350     for (uint32_t y = 0; y < yHeight; y++) {
351         errno_t ret = memcpy_s(dstY, stride * BYTE_PER_PIXEL, srcY, stride * BYTE_PER_PIXEL);
352         if (ret != EOK) {
353             IMAGE_LOGE("CopyP010Pixels memcpy dstY failed.");
354             return false;
355         }
356         dstY += dstStrides.yStride;
357         srcY += srcStrides.yStride;
358     }
359     for (uint32_t y = 0; y < static_cast<uint32_t>(GetUVHeight(yHeight)); y++) {
360         errno_t ret = memcpy_s(dstUV, uvStride * BYTE_PER_PIXEL, srcUV, uvStride * BYTE_PER_PIXEL);
361         if (ret != EOK) {
362             IMAGE_LOGE("CopyP010Pixels memcpy dstY failed.");
363             return false;
364         }
365         dstUV += dstStrides.uvStride;
366         srcUV += srcStrides.uvStride;
367     }
368     return true;
369 }
370 
ScaleP010(YuvPixels yuvPixels,OpenSourceLibyuv::ImageYuvConverter & converter,OpenSourceLibyuv::FilterMode & filterMode,YuvImageInfo & yuvInfo,YUVStrideInfo & dstStrides)371 static void ScaleP010(YuvPixels yuvPixels, OpenSourceLibyuv::ImageYuvConverter &converter,
372     OpenSourceLibyuv::FilterMode &filterMode, YuvImageInfo &yuvInfo, YUVStrideInfo &dstStrides)
373 {
374     uint32_t height = yuvInfo.yuvDataInfo.yHeight;
375     std::unique_ptr<uint16_t[]> srcPixels = std::make_unique<uint16_t[]>(GetImageSize(yuvInfo.width, height));
376     if (srcPixels == nullptr) {
377         IMAGE_LOGE("ScaleP010 srcPixels make unique ptr failed");
378         return;
379     }
380     uint16_t *srcBuffer = reinterpret_cast<uint16_t *>(yuvPixels.srcPixels);
381     YUVStrideInfo srcStrides = {yuvInfo.yuvDataInfo.yStride, yuvInfo.yuvDataInfo.uvStride,
382         yuvInfo.yuvDataInfo.yOffset, yuvInfo.yuvDataInfo.uvOffset};
383     YUVStrideInfo dstStride = {yuvInfo.width, GetUVStride(yuvInfo.width), 0, GetYSize(yuvInfo.width, yuvInfo.height)};
384     IMAGE_LOGI("%{public}s, YuvImageInfo:width:%{public}d, height:%{public}d\n"
385         "YUVDataInfo: %{public}s, pixelsSize:%{public}u", __func__, yuvInfo.width,
386         yuvInfo.height, yuvInfo.yuvDataInfo.ToString().c_str(), yuvInfo.pixelsSize);
387     YuvCopyInfo yuvCopyInfo = {yuvInfo.yuvDataInfo.yHeight, yuvInfo.pixelsSize};
388     if (!CopyP010Pixels(srcBuffer, srcStrides, srcPixels.get(), dstStride, yuvCopyInfo)) {
389         return;
390     }
391     uint16_t* srcY = srcPixels.get();
392     uint16_t* srcUV = srcPixels.get() + GetYSize(yuvInfo.width, yuvInfo.yuvDataInfo.yHeight);
393     int32_t srcWidth = yuvInfo.width;
394     int32_t srcHeight = yuvInfo.height;
395     uint16_t *dstBuffer = reinterpret_cast<uint16_t *>(yuvPixels.dstPixels);
396     int32_t dstWidth = yuvPixels.sizeType == YuvSizeType::FLOAT ?
397         yuvInfo.width * yuvPixels.xAxis + ROUND_FLOAT_NUMBER : yuvPixels.dstWidth;
398     int32_t dstHeight = yuvPixels.sizeType == YuvSizeType::FLOAT ?
399         yuvInfo.height * yuvPixels.yAxis + ROUND_FLOAT_NUMBER : yuvPixels.dstHeight;
400     std::unique_ptr<uint16_t[]> dstPixels = std::make_unique<uint16_t[]>(GetImageSize(srcWidth, srcHeight));
401     if (dstPixels == nullptr) {
402         IMAGE_LOGE("ScaleP010 dstPixels make unique ptr failed");
403         return;
404     }
405 
406     uint16_t* dstY = dstPixels.get();
407     uint16_t* dstU = dstPixels.get() + GetYSize(srcWidth, srcHeight);
408     uint16_t* dstV = dstPixels.get() + GetVOffset(srcWidth, srcHeight);
409     if (converter.P010ToI010(srcY, srcWidth, srcUV,
410         GetUVStride(srcWidth), dstY, srcWidth, dstU, GetUStride(srcWidth), dstV,
411         GetUStride(srcWidth), srcWidth, srcHeight) == -1) {
412         IMAGE_LOGE("NV12P010ToI010 failed");
413         return;
414     }
415     std::unique_ptr<uint16_t[]> scalePixels = std::make_unique<uint16_t[]>(GetImageSize(dstWidth, dstHeight));
416     if (scalePixels == nullptr) {
417         IMAGE_LOGE("ScaleP010 scalePixels make unique ptr failed");
418         return;
419     }
420     uint16_t* scaleY = scalePixels.get();
421     uint16_t* scaleU = scalePixels.get() + GetYSize(dstWidth, dstHeight);
422     uint16_t* scaleV = scalePixels.get() + GetVOffset(dstWidth, dstHeight);
423     if (converter.I420Scale_16(dstY, srcWidth, dstU, GetUStride(srcWidth), dstV,
424         GetUStride(srcWidth), srcWidth, srcHeight, scaleY, dstWidth, scaleU,
425         GetUStride(dstWidth), scaleV, GetUStride(dstWidth), dstWidth, dstHeight, filterMode) == -1) {
426         IMAGE_LOGE("I420Scale_16 failed");
427         return;
428     }
429 
430     std::unique_ptr<uint16_t[]> dstPixel = std::make_unique<uint16_t[]>(GetImageSize(dstWidth, dstHeight));
431     if (dstPixel == nullptr) {
432         IMAGE_LOGE("ScaleP010 dstPixel make unique ptr failed");
433         return;
434     }
435     uint16_t* dstPixelY = dstPixel.get();
436     uint16_t* dstPixelUV = dstPixel.get() + GetYSize(dstWidth, dstHeight);
437     if (converter.I010ToP010(scaleY, dstWidth, scaleU, GetUStride(dstWidth),
438         scaleV, GetUStride(dstWidth), dstPixelY, dstWidth, dstPixelUV, GetUVStride(dstWidth),
439         dstWidth, dstHeight) == -1) {
440         IMAGE_LOGE("I010ToP010 failed");
441         return;
442     }
443     YUVStrideInfo dstPixelStrides = {dstWidth, GetUVStride(dstWidth), 0, GetYSize(dstWidth, dstHeight)};
444     yuvCopyInfo.dstHeight = static_cast<uint32_t>(dstHeight);
445     yuvCopyInfo.pixelsSize = GetImageSize(dstWidth, dstHeight) * BYTE_PER_PIXEL;
446     if (!CopyP010Pixels(dstPixelY, dstPixelStrides, dstBuffer, dstStrides, yuvCopyInfo)) {
447         return;
448     }
449 }
450 
ScaleYuv420(float xAxis,float yAxis,const AntiAliasingOption & option,YuvImageInfo & yuvInfo,uint8_t * src,uint8_t * dst,YUVStrideInfo & dstStrides)451 void PixelYuvExtUtils::ScaleYuv420(float xAxis, float yAxis, const AntiAliasingOption &option,
452     YuvImageInfo &yuvInfo, uint8_t *src, uint8_t *dst, YUVStrideInfo &dstStrides)
453 {
454     OpenSourceLibyuv::FilterMode filterMode = OpenSourceLibyuv ::FilterMode::kFilterLinear;
455     ConvertYuvMode(filterMode, option);
456 
457     uint8_t* srcY = src + yuvInfo.yuvDataInfo.yOffset;
458     int srcYStride = static_cast<int>(yuvInfo.yuvDataInfo.yStride)
459     uint8_t* srcUV = srcY + yuvInfo.yuvDataInfo.uvOffset;
460     int srcUVStride = static_cast<int>(yuvInfo.yuvDataInfo.uvStride);
461     int srcWidth = yuvInfo.width;
462     int srcHeight = yuvInfo.height;
463 
464     int32_t dstWidth = (yuvInfo.width * xAxis + ROUND_FLOAT_NUMBER);
465     int32_t dstHeight = (yuvInfo.height * yAxis + ROUND_FLOAT_NUMBER);
466     uint8_t* dstY = dst + dstStrides.yOffset;
467     int dstYStride = static_cast<int>(dstStrides.yStride);
468     uint8_t* dstUV = dst + dstStrides.uvOffset;
469     int dstUVStride = static_cast<int>(dstStrides.uvStride);
470     auto converter = ConverterHandle::GetInstance().GetHandle();
471     YuvPixels yuvPixels = {src, dst, xAxis, yAxis};
472     if (yuvInfo.yuvFormat == PixelFormat::YCBCR_P010 || yuvInfo.yuvFormat == PixelFormat::YCRCB_P010) {
473         ScaleP010(yuvPixels, converter, filterMode, yuvInfo, dstStrides);
474     } else {
475         converter.NV12Scale(srcY, srcYStride, srcUV, srcUVStride, srcWidth, srcHeight,
476             dstY, dstYStride, dstUV, dstUVStride, dstWidth, dstHeight, filterMode);
477     }
478 }
479 
ScaleYuv420(int32_t dstWidth,int32_t dstHeight,const AntiAliasingOption & option,YuvImageInfo & yuvInfo,uint8_t * src,uint8_t * dst,YUVStrideInfo & dstStrides)480 void PixelYuvExtUtils::ScaleYuv420(int32_t dstWidth, int32_t dstHeight, const AntiAliasingOption &option,
481     YuvImageInfo &yuvInfo, uint8_t *src, uint8_t *dst, YUVStrideInfo &dstStrides)
482 {
483     OpenSourceLibyuv::FilterMode filterMode = OpenSourceLibyuv ::FilterMode::kFilterLinear;
484     ConvertYuvMode(filterMode, option);
485 
486     uint8_t* srcY = src + yuvInfo.yuvDataInfo.yOffset;
487     int srcYStride = static_cast<int>(yuvInfo.yuvDataInfo.yStride);
488     uint8_t* srcUV = srcY + yuvInfo.yuvDataInfo.uvOffset;
489     int srcUVStride = static_cast<int>(yuvInfo.yuvDataInfo.uvStride);
490     int srcWidth = yuvInfo.width;
491     int srcHeight = yuvInfo.height;
492 
493     uint8_t* dstY = dst + dstStrides.yOffset;
494     int dstYStride = static_cast<int>(dstStrides.yStride);
495     uint8_t* dstUV = dst + dstStrides.uvOffset;
496     int dstUVStride = static_cast<int>(dstStrides.uvStride);
497     auto converter = ConverterHandle::GetInstance().GetHandle();
498 
499     YuvPixels yuvPixels = {src, dst, 0.0, 0.0, dstWidth, dstHeight, YuvSizeType::INT};
500     if (yuvInfo.yuvFormat == PixelFormat::YCBCR_P010 || yuvInfo.yuvFormat == PixelFormat::YCRCB_P010) {
501         ScaleP010(yuvPixels, converter, filterMode, yuvInfo, dstStrides);
502     } else {
503         converter.NV12Scale(srcY, srcYStride, srcUV, srcUVStride, srcWidth, srcHeight,
504             dstY, dstYStride, dstUV, dstUVStride, dstWidth, dstHeight, filterMode);
505     }
506 }
507 
FlipXaxis(uint8_t * src,uint8_t * dst,Size & size,PixelFormat format,YUVDataInfo & info,YUVStrideInfo & dstStrides)508 bool PixelYuvExtUtils::FlipXaxis(uint8_t *src, uint8_t *dst, Size &size, PixelFormat format,
509     YUVDataInfo &info, YUVStrideInfo &dstStrides)
510 {
511     IMAGE_LOGE("PixelYuvExtUtils FlipXaxis");
512     uint8_t *srcY = src + info.yOffset;
513     uint8_t *srcUV = src + info.uvOffset;
514     int srcYStride = static_cast<int>(info.yStride);
515     int srcUVStride = static_cast<int>(info.uvStride);
516     int32_t width = size.width;
517     int32_t height = size.height;
518 
519     uint8_t* dstY = dst + dstStrides.yOffset;
520     uint8_t* dstUV = dst + dstStrides.uvOffset;
521     int dstYStride = static_cast<int>(dstStrides.yStride);
522     int dstUVStride = static_cast<int>(dstStrides.uvStride);
523 
524     auto converter = ConverterHandle::GetInstance().GetHandle();
525     converter.NV12Copy(srcY, srcYStride, srcUV, srcUVStride, dstY, dstYStride, dstUV, dstUVStride, width, -height);
526     return true;
527 }
528 
Mirror(uint8_t * src,uint8_t * dst,Size & size,PixelFormat format,YUVDataInfo & info,YUVStrideInfo & dstStrides,bool isReversed)529 bool PixelYuvExtUtils::Mirror(uint8_t *src, uint8_t *dst, Size &size, PixelFormat format, YUVDataInfo &info,
530     YUVStrideInfo &dstStrides, bool isReversed)
531 {
532     auto converter = ConverterHandle::GetInstance().GetHandle();
533     uint8_t *srcY = src + info.yOffset;
534     uint8_t *srcUV = src + info.uvOffset;
535     int32_t width = size.width;
536     int32_t height = size.height;
537     int srcYStride = static_cast<int>(info.yStride);
538     int srcUVStride = static_cast<int>(info.uvStride);
539 
540     uint8_t *dstY = dst + dstStrides.yOffset;
541     uint8_t *dstUV = dst +  dstStrides.uvOffset;
542     int dstYStride = static_cast<int>(dstStrides.yStride);
543     int dstUVStride = static_cast<int>(dstStrides.uvStride);
544     height = isReversed? -height : height;
545 
546     int iret = converter.NV12Mirror(srcY, srcYStride, srcUV, srcUVStride, dstY, dstYStride,
547         dstUV, dstUVStride, width, height);
548     if (iret == -1) {
549         return false;
550     }
551     return true;
552 }
553 } // namespace Media
554 } // namespace OHOS