• 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     if (converter.I420ToNV12(tmpY, tmpYStride, tmpU, tmpUStride, tmpV, tmpVStride,
167         dstY, dstYStride, dstUV, dstUVStride, dstWidth, dstHeight) == -1) {
168         return false;
169     }
170 
171     return true;
172 }
173 
NV12P010Rotate(YuvPixels yuvPixels,PixelSize & size,YUVDataInfo & info,OpenSourceLibyuv::RotationMode & rotateNum,YUVStrideInfo & dstStrides)174 static bool NV12P010Rotate(YuvPixels yuvPixels, PixelSize& size, YUVDataInfo& info,
175     OpenSourceLibyuv::RotationMode& rotateNum, YUVStrideInfo& dstStrides)
176 {
177     std::unique_ptr<uint16_t[]> dstPixels = std::make_unique<uint16_t[]>(GetImageSize(info.yStride, size.srcH));
178     uint16_t* srcbuffer = reinterpret_cast<uint16_t *>(yuvPixels.srcPixels);
179     uint16_t* srcY = srcbuffer + info.yOffset;
180     uint16_t* srcUV = srcbuffer + info.uvOffset;
181 
182     uint16_t* dstY = dstPixels.get();
183     uint16_t* dstU = dstPixels.get() + GetYSize(info.yStride, size.srcH);
184     uint16_t* dstV = dstPixels.get() + GetVOffset(info.yStride, size.srcH);
185     auto converter = ConverterHandle::GetInstance().GetHandle();
186     if (converter.P010ToI010(srcY, info.yStride, srcUV, GetUVStride(info.yStride),
187         dstY, info.yStride, dstU, GetUStride(info.yStride),
188         dstV, GetUStride(info.yStride), size.srcW, size.srcH) == -1) {
189         IMAGE_LOGE("NV12P010ToI010 failed");
190         return false;
191     }
192 
193     std::unique_ptr<uint16_t[]> rotatePixels = std::make_unique<uint16_t[]>(GetImageSize(size.srcW, size.srcH));
194     uint16_t* rotateY = rotatePixels.get();
195     uint16_t* rotateU = rotatePixels.get() + GetYSize(size.dstW, size.dstH);
196     uint16_t* rotateV = rotatePixels.get() + GetVOffset(size.dstW, size.dstH);
197 
198     if (converter.I010Rotate(dstY, info.yStride, dstU, GetUStride(info.yStride),
199         dstV, GetUStride(info.yStride), rotateY, size.dstW, rotateU, GetUStride(size.dstW),
200         rotateV, GetUStride(size.dstW), size.srcW, size.srcH, rotateNum) == -1) {
201         IMAGE_LOGE("I010Rotate failed");
202         return false;
203     }
204 
205     uint16_t* dstbuffer = reinterpret_cast<uint16_t *>(yuvPixels.dstPixels);
206     int32_t dstYStride = static_cast<int32_t>(dstStrides.yStride);
207     int32_t dstUVStride = static_cast<int32_t>(dstStrides.uvStride);
208     uint16_t* dstbufferY = dstbuffer + dstStrides.yOffset;
209     uint16_t* dstbufferUV = dstbuffer + dstStrides.uvOffset;
210     if (converter.I010ToP010(rotateY, size.dstW, rotateU, GetUStride(size.dstW), rotateV, GetUStride(size.dstW),
211         dstbufferY, dstYStride, dstbufferUV, dstUVStride, size.dstW, size.dstH) == -1) {
212         IMAGE_LOGE("I010ToP010 failed");
213         return false;
214     }
215     return true;
216 }
217 
YuvRotate(uint8_t * srcPixels,const PixelFormat & format,YUVDataInfo & info,Size & dstSize,uint8_t * dstPixels,YUVStrideInfo & dstStrides,OpenSourceLibyuv::RotationMode & rotateNum)218 bool PixelYuvExtUtils::YuvRotate(uint8_t* srcPixels, const PixelFormat& format, YUVDataInfo& info,
219     Size& dstSize, uint8_t* dstPixels, YUVStrideInfo& dstStrides, OpenSourceLibyuv::RotationMode &rotateNum)
220 {
221     int32_t dstWidth = dstSize.width;
222     int32_t dstHeight = dstSize.height;
223     PixelSize pixelSize = {info.imageSize.width, info.imageSize.height, dstWidth, dstHeight};
224     if (format == PixelFormat::YCBCR_P010 || format == PixelFormat::YCRCB_P010) {
225         IMAGE_LOGD("YuvRotate P010Rotate enter");
226         YuvPixels yuvPixels = {srcPixels, dstPixels, 0, 0};
227         if (!NV12P010Rotate(yuvPixels, pixelSize, info, rotateNum, dstStrides)) {
228             IMAGE_LOGE("YuvRotate P010Rotate fail");
229             return false;
230         }
231         return true;
232     }
233     if (!NV12Rotate(srcPixels, pixelSize, info, rotateNum, dstPixels, dstStrides)) {
234         return false;
235     }
236 
237     return true;
238 }
239 
ConvertYuvMode(OpenSourceLibyuv::FilterMode & filterMode,const AntiAliasingOption & option)240 void PixelYuvExtUtils::ConvertYuvMode(OpenSourceLibyuv::FilterMode &filterMode, const AntiAliasingOption &option)
241 {
242     switch (option) {
243         case AntiAliasingOption::NONE:
244             filterMode = OpenSourceLibyuv::FilterMode::kFilterNone;
245             break;
246         case AntiAliasingOption::LOW:
247             filterMode = OpenSourceLibyuv::FilterMode::kFilterLinear;
248             break;
249         case AntiAliasingOption::MEDIUM:
250             filterMode = OpenSourceLibyuv::FilterMode::kFilterBilinear;
251             break;
252         case AntiAliasingOption::HIGH:
253             filterMode = OpenSourceLibyuv::FilterMode::kFilterBox;
254             break;
255         default:
256             break;
257     }
258 }
259 
ScaleUVPlane(const uint8_t * src,uint8_t * dst,OpenSourceLibyuv::FilterMode filterMode,YuvImageInfo & yuvInfo,uint32_t dstYStride,uint32_t dstYHeight,uint32_t dstYWidth)260 static void ScaleUVPlane(const uint8_t *src, uint8_t*dst, OpenSourceLibyuv::FilterMode filterMode,
261     YuvImageInfo &yuvInfo, uint32_t dstYStride, uint32_t dstYHeight, uint32_t dstYWidth)
262 {
263     uint32_t srcUWidth = static_cast<uint32_t>(GetUStride(yuvInfo.width));
264     uint32_t srcUHeight = static_cast<uint32_t>(GetUVHeight(yuvInfo.height));
265     uint32_t dstUWidth = static_cast<uint32_t>(GetUStride(dstYWidth));
266     uint32_t dstUHeight = static_cast<uint32_t>(GetUVHeight(dstYHeight));
267     // Split VUplane
268     std::unique_ptr<uint8_t[]> uvData = std::make_unique<uint8_t[]>(NUM_2 * srcUWidth * srcUHeight);
269     if (uvData == nullptr) {
270         IMAGE_LOGE("ScaleUVPlane make unique ptr for uvData failed.");
271         return;
272     }
273     uint8_t *uData = nullptr;
274     uint8_t *vData = nullptr;
275     uint32_t dstSplitStride = srcUWidth;
276     const uint8_t *srcUV = src + yuvInfo.yuvDataInfo.uvOffset;
277     uint32_t uvStride = yuvInfo.yuvDataInfo.uvStride;
278     auto converter = ConverterHandle::GetInstance().GetHandle();
279     if (yuvInfo.yuvFormat == PixelFormat::NV12) {
280         uData = uvData.get();
281         vData = uvData.get() + srcUWidth * srcUHeight;
282         converter.SplitUVPlane(srcUV, uvStride, uData, dstSplitStride, vData, dstSplitStride, srcUWidth, srcUHeight);
283     } else if (yuvInfo.yuvFormat == PixelFormat::NV21) {
284         vData = uvData.get();
285         uData = uvData.get() + srcUWidth * srcUHeight;
286         converter.SplitUVPlane(srcUV, uvStride, vData, dstSplitStride, uData, dstSplitStride, srcUWidth, srcUHeight);
287     }
288     // malloc memory to store temp u v
289     std::unique_ptr<uint8_t[]> tempUVData = std::make_unique<uint8_t[]>(NUM_2 * dstUWidth * dstUHeight);
290     if (tempUVData == nullptr) {
291         IMAGE_LOGE("ScaleUVPlane make unique ptr for tempUVData failed.");
292         return;
293     }
294     uint8_t *tempUData = nullptr;
295     uint8_t *tempVData = nullptr;
296     if (yuvInfo.yuvFormat == PixelFormat::NV12) {
297         tempUData = tempUVData.get();
298         tempVData = tempUVData.get() + dstUWidth * dstUHeight;
299     } else if (yuvInfo.yuvFormat == PixelFormat::NV21) {
300         tempVData = tempUVData.get();
301         tempUData = tempUVData.get() + dstUWidth * dstUHeight;
302     }
303 
304     // resize u* and v
305     converter.ScalePlane(uData, dstSplitStride, srcUWidth, srcUHeight,
306                          tempUData, dstUWidth, dstUWidth, dstUHeight, filterMode);
307 
308     converter.ScalePlane(vData, dstSplitStride, srcUWidth, srcUHeight,
309                          tempVData, dstUWidth, dstUWidth, dstUHeight, filterMode);
310     // Merge  the UV
311     uint8_t *dstUV = dst + GetYSize(dstYStride, dstYHeight);
312 
313     int32_t dstUVStride = static_cast<int32_t>(dstUWidth * NUM_2);
314     //AllocatorType DMA_ALLOC
315     if (dstYStride != dstYWidth) {
316         dstUVStride = static_cast<int32_t>(dstYStride);
317     }
318     if (yuvInfo.yuvFormat == PixelFormat::NV12) {
319         converter.MergeUVPlane(tempUData, dstUWidth, tempVData, dstUWidth, dstUV, dstUVStride, dstUWidth, dstUHeight);
320     } else if (yuvInfo.yuvFormat == PixelFormat::NV21) {
321         converter.MergeUVPlane(tempVData, dstUWidth, tempUData, dstUWidth, dstUV, dstUVStride, dstUWidth, dstUHeight);
322     }
323 
324     uData = vData = nullptr;
325     tempUData = tempVData = nullptr;
326 }
327 
CopyP010Pixels(uint16_t * src,YUVStrideInfo & srcStrides,uint16_t * dst,YUVStrideInfo & dstStrides,uint32_t yHeight)328 static bool CopyP010Pixels(
329     uint16_t *src, YUVStrideInfo &srcStrides, uint16_t *dst, YUVStrideInfo &dstStrides, uint32_t yHeight)
330 {
331     uint16_t* srcY = src + srcStrides.yOffset;
332     uint16_t* srcUV = srcY + srcStrides.uvOffset;
333     uint16_t* dstY = dst + dstStrides.yOffset;
334     uint16_t* dstUV = dstY + dstStrides.uvOffset;
335     uint32_t stride = std::min(srcStrides.yStride, dstStrides.yStride);
336     for (uint32_t y = 0; y < yHeight; y++) {
337         errno_t ret = memcpy_s(dstY, stride * BYTE_PER_PIXEL, srcY, stride * BYTE_PER_PIXEL);
338         if (ret != EOK) {
339             IMAGE_LOGE("CopyP010Pixels memcpy dstY failed.");
340             return false;
341         }
342         dstY += dstStrides.yStride;
343         srcY += srcStrides.yStride;
344     }
345     uint32_t uvStride = std::min(srcStrides.uvStride, dstStrides.uvStride);
346     for (uint32_t y = 0; y < static_cast<uint32_t>(GetUVHeight(yHeight)); y++) {
347         errno_t ret = memcpy_s(dstUV, uvStride * BYTE_PER_PIXEL, srcUV, uvStride * BYTE_PER_PIXEL);
348         if (ret != EOK) {
349             IMAGE_LOGE("CopyP010Pixels memcpy dstY failed.");
350             return false;
351         }
352         dstUV += dstStrides.uvStride;
353         srcUV += srcStrides.uvStride;
354     }
355     return true;
356 }
357 
ScaleP010(YuvPixels yuvPixels,OpenSourceLibyuv::ImageYuvConverter & converter,OpenSourceLibyuv::FilterMode & filterMode,YuvImageInfo & yuvInfo,YUVStrideInfo & dstStrides)358 static void ScaleP010(YuvPixels yuvPixels, OpenSourceLibyuv::ImageYuvConverter &converter,
359     OpenSourceLibyuv::FilterMode &filterMode, YuvImageInfo &yuvInfo, YUVStrideInfo &dstStrides)
360 {
361     uint32_t height = yuvInfo.yuvDataInfo.yHeight;
362     std::unique_ptr<uint16_t[]> srcPixels = std::make_unique<uint16_t[]>(GetImageSize(yuvInfo.width, height));
363     if (srcPixels == nullptr) {
364         IMAGE_LOGE("ScaleP010 srcPixels make unique ptr failed");
365         return;
366     }
367     uint16_t *srcBuffer = reinterpret_cast<uint16_t *>(yuvPixels.srcPixels);
368     YUVStrideInfo srcStrides = {yuvInfo.yuvDataInfo.yStride, yuvInfo.yuvDataInfo.uvStride,
369         yuvInfo.yuvDataInfo.yOffset, yuvInfo.yuvDataInfo.uvOffset};
370     YUVStrideInfo dstStride = {yuvInfo.width, GetUVStride(yuvInfo.width), 0, GetYSize(yuvInfo.width, yuvInfo.height)};
371     if (!CopyP010Pixels(srcBuffer, srcStrides, srcPixels.get(), dstStride, yuvInfo.yuvDataInfo.yHeight)) {
372         return;
373     }
374     uint16_t* srcY = srcPixels.get();
375     uint16_t* srcUV = srcPixels.get() + GetYSize(yuvInfo.width, yuvInfo.yuvDataInfo.yHeight);
376     int32_t srcWidth = yuvInfo.width;
377     int32_t srcHeight = yuvInfo.height;
378     uint16_t *dstBuffer = reinterpret_cast<uint16_t *>(yuvPixels.dstPixels);
379     int32_t dstWidth = yuvPixels.sizeType == YuvSizeType::FLOAT ?
380         yuvInfo.width * yuvPixels.xAxis + ROUND_FLOAT_NUMBER : yuvPixels.dstWidth;
381     int32_t dstHeight = yuvPixels.sizeType == YuvSizeType::FLOAT ?
382         yuvInfo.height * yuvPixels.yAxis + ROUND_FLOAT_NUMBER : yuvPixels.dstHeight;
383     std::unique_ptr<uint16_t[]> dstPixels = std::make_unique<uint16_t[]>(GetImageSize(srcWidth, srcHeight));
384     if (dstPixels == nullptr) {
385         IMAGE_LOGE("ScaleP010 dstPixels make unique ptr failed");
386         return;
387     }
388 
389     uint16_t* dstY = dstPixels.get();
390     uint16_t* dstU = dstPixels.get() + GetYSize(srcWidth, srcHeight);
391     uint16_t* dstV = dstPixels.get() + GetVOffset(srcWidth, srcHeight);
392     if (converter.P010ToI010(srcY, srcWidth, srcUV,
393         GetUVStride(srcWidth), dstY, srcWidth, dstU, GetUStride(srcWidth), dstV,
394         GetUStride(srcWidth), srcWidth, srcHeight) == -1) {
395         IMAGE_LOGE("NV12P010ToI010 failed");
396         return;
397     }
398     std::unique_ptr<uint16_t[]> scalePixels = std::make_unique<uint16_t[]>(GetImageSize(dstWidth, dstHeight));
399     if (scalePixels == nullptr) {
400         IMAGE_LOGE("ScaleP010 scalePixels make unique ptr failed");
401         return;
402     }
403     uint16_t* scaleY = scalePixels.get();
404     uint16_t* scaleU = scalePixels.get() + GetYSize(dstWidth, dstHeight);
405     uint16_t* scaleV = scalePixels.get() + GetVOffset(dstWidth, dstHeight);
406     if (converter.I420Scale_16(dstY, srcWidth, dstU, GetUStride(srcWidth), dstV,
407         GetUStride(srcWidth), srcWidth, srcHeight, scaleY, dstWidth, scaleU,
408         GetUStride(dstWidth), scaleV, GetUStride(dstWidth), dstWidth, dstHeight, filterMode) == -1) {
409         IMAGE_LOGE("I420Scale_16 failed");
410         return;
411     }
412 
413     std::unique_ptr<uint16_t[]> dstPixel = std::make_unique<uint16_t[]>(GetImageSize(dstWidth, dstHeight));
414     if (dstPixel == nullptr) {
415         IMAGE_LOGE("ScaleP010 dstPixel make unique ptr failed");
416         return;
417     }
418     uint16_t* dstPixelY = dstPixel.get();
419     uint16_t* dstPixelUV = dstPixel.get() + GetYSize(dstWidth, dstHeight);
420     if (converter.I010ToP010(scaleY, dstWidth, scaleU, GetUStride(dstWidth),
421         scaleV, GetUStride(dstWidth), dstPixelY, dstWidth, dstPixelUV, GetUVStride(dstWidth),
422         dstWidth, dstHeight) == -1) {
423         IMAGE_LOGE("I010ToP010 failed");
424         return;
425     }
426     YUVStrideInfo dstPixelStrides = {dstWidth, GetUVStride(dstWidth), 0, GetYSize(dstWidth, dstHeight)};
427     if (!CopyP010Pixels(dstPixelY, dstPixelStrides, dstBuffer, dstStrides, dstHeight)) {
428         return;
429     }
430 }
431 
ScaleYuv420(float xAxis,float yAxis,const AntiAliasingOption & option,YuvImageInfo & yuvInfo,uint8_t * src,uint8_t * dst,YUVStrideInfo & dstStrides)432 void PixelYuvExtUtils::ScaleYuv420(float xAxis, float yAxis, const AntiAliasingOption &option,
433     YuvImageInfo &yuvInfo, uint8_t *src, uint8_t *dst, YUVStrideInfo &dstStrides)
434 {
435     OpenSourceLibyuv::FilterMode filterMode = OpenSourceLibyuv ::FilterMode::kFilterLinear;
436     ConvertYuvMode(filterMode, option);
437 
438     uint8_t* srcY = src + yuvInfo.yuvDataInfo.yOffset;
439     int srcYStride = static_cast<int>(yuvInfo.yuvDataInfo.yStride)
440     uint8_t* srcUV = srcY + yuvInfo.yuvDataInfo.uvOffset;
441     int srcUVStride = static_cast<int>(yuvInfo.yuvDataInfo.uvStride);
442     int srcWidth = yuvInfo.width;
443     int srcHeight = yuvInfo.height;
444 
445     int32_t dstWidth = (yuvInfo.width * xAxis + ROUND_FLOAT_NUMBER);
446     int32_t dstHeight = (yuvInfo.height * yAxis + ROUND_FLOAT_NUMBER);
447     uint8_t* dstY = dst + dstStrides.yOffset;
448     int dstYStride = static_cast<int>(dstStrides.yStride);
449     uint8_t* dstUV = dst + dstStrides.uvOffset;
450     int dstUVStride = static_cast<int>(dstStrides.uvStride);
451     auto converter = ConverterHandle::GetInstance().GetHandle();
452     YuvPixels yuvPixels = {src, dst, xAxis, yAxis};
453     if (yuvInfo.yuvFormat == PixelFormat::YCBCR_P010 || yuvInfo.yuvFormat == PixelFormat::YCRCB_P010) {
454         ScaleP010(yuvPixels, converter, filterMode, yuvInfo, dstStrides);
455     } else {
456         converter.NV12Scale(srcY, srcYStride, srcUV, srcUVStride, srcWidth, srcHeight,
457             dstY, dstYStride, dstUV, dstUVStride, dstWidth, dstHeight, filterMode);
458     }
459 }
460 
ScaleYuv420(int32_t dstWidth,int32_t dstHeight,const AntiAliasingOption & option,YuvImageInfo & yuvInfo,uint8_t * src,uint8_t * dst,YUVStrideInfo & dstStrides)461 void PixelYuvExtUtils::ScaleYuv420(int32_t dstWidth, int32_t dstHeight, const AntiAliasingOption &option,
462     YuvImageInfo &yuvInfo, uint8_t *src, uint8_t *dst, YUVStrideInfo &dstStrides)
463 {
464     OpenSourceLibyuv::FilterMode filterMode = OpenSourceLibyuv ::FilterMode::kFilterLinear;
465     ConvertYuvMode(filterMode, option);
466 
467     uint8_t* srcY = src + yuvInfo.yuvDataInfo.yOffset;
468     int srcYStride = static_cast<int>(yuvInfo.yuvDataInfo.yStride);
469     uint8_t* srcUV = srcY + yuvInfo.yuvDataInfo.uvOffset;
470     int srcUVStride = static_cast<int>(yuvInfo.yuvDataInfo.uvStride);
471     int srcWidth = yuvInfo.width;
472     int srcHeight = yuvInfo.height;
473 
474     uint8_t* dstY = dst + dstStrides.yOffset;
475     int dstYStride = static_cast<int>(dstStrides.yStride);
476     uint8_t* dstUV = dst + dstStrides.uvOffset;
477     int dstUVStride = static_cast<int>(dstStrides.uvStride);
478     auto converter = ConverterHandle::GetInstance().GetHandle();
479 
480     YuvPixels yuvPixels = {src, dst, 0.0, 0.0, dstWidth, dstHeight, YuvSizeType::INT};
481     if (yuvInfo.yuvFormat == PixelFormat::YCBCR_P010 || yuvInfo.yuvFormat == PixelFormat::YCRCB_P010) {
482         ScaleP010(yuvPixels, converter, filterMode, yuvInfo, dstStrides);
483     } else {
484         converter.NV12Scale(srcY, srcYStride, srcUV, srcUVStride, srcWidth, srcHeight,
485             dstY, dstYStride, dstUV, dstUVStride, dstWidth, dstHeight, filterMode);
486     }
487 }
488 
FlipXaxis(uint8_t * src,uint8_t * dst,Size & size,PixelFormat format,YUVDataInfo & info,YUVStrideInfo & dstStrides)489 bool PixelYuvExtUtils::FlipXaxis(uint8_t *src, uint8_t *dst, Size &size, PixelFormat format,
490     YUVDataInfo &info, YUVStrideInfo &dstStrides)
491 {
492     IMAGE_LOGE("PixelYuvExtUtils FlipXaxis");
493     uint8_t *srcY = src + info.yOffset;
494     uint8_t *srcUV = src + info.uvOffset;
495     int srcYStride = static_cast<int>(info.yStride);
496     int srcUVStride = static_cast<int>(info.uvStride);
497     int32_t width = size.width;
498     int32_t height = size.height;
499 
500     uint8_t* dstY = dst + dstStrides.yOffset;
501     uint8_t* dstUV = dst + dstStrides.uvOffset;
502     int dstYStride = static_cast<int>(dstStrides.yStride);
503     int dstUVStride = static_cast<int>(dstStrides.uvStride);
504 
505     auto converter = ConverterHandle::GetInstance().GetHandle();
506     converter.NV12Copy(srcY, srcYStride, srcUV, srcUVStride, dstY, dstYStride, dstUV, dstUVStride, width, -height);
507     return true;
508 }
509 
Mirror(uint8_t * src,uint8_t * dst,Size & size,PixelFormat format,YUVDataInfo & info,YUVStrideInfo & dstStrides,bool isReversed)510 bool PixelYuvExtUtils::Mirror(uint8_t *src, uint8_t *dst, Size &size, PixelFormat format, YUVDataInfo &info,
511     YUVStrideInfo &dstStrides, bool isReversed)
512 {
513     auto converter = ConverterHandle::GetInstance().GetHandle();
514     uint8_t *srcY = src + info.yOffset;
515     uint8_t *srcUV = src + info.uvOffset;
516     int32_t width = size.width;
517     int32_t height = size.height;
518     int srcYStride = static_cast<int>(info.yStride);
519     int srcUVStride = static_cast<int>(info.uvStride);
520 
521     uint8_t *dstY = dst + dstStrides.yOffset;
522     uint8_t *dstUV = dst +  dstStrides.uvOffset;
523     int dstYStride = static_cast<int>(dstStrides.yStride);
524     int dstUVStride = static_cast<int>(dstStrides.uvStride);
525     height = isReversed? -height : height;
526 
527     int iret = converter.NV12Mirror(srcY, srcYStride, srcUV, srcUVStride, dstY, dstYStride,
528         dstUV, dstUVStride, width, height);
529     if (iret == -1) {
530         return false;
531     }
532     return true;
533 }
534 } // namespace Media
535 } // namespace OHOS