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