• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 HiSilicon (Shanghai) Technologies CO., LIMITED.
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 <stdlib.h>
17 #include <string.h>
18 #include <stdio.h>
19 #include <stdbool.h>
20 #include <errno.h>
21 #include <unistd.h>
22 
23 #include "hi_comm_vb.h"
24 #include "mpi_sys.h"
25 #include "ive_img.h"
26 
27 #ifdef __cplusplus
28 #if __cplusplus
29 extern "C" {
30 #endif
31 #endif /* End of #ifdef __cplusplus */
32 
33 #define HALF_THE_HEIGHT 2 // Half the height
34 
HiAlign16(HI_U32 num)35 HI_U32 HiAlign16(HI_U32 num)
36 {
37     return (((num) + 16 - 1) / 16 * 16); // 16: align 16
38 }
39 
HiAlign32(HI_U32 num)40 HI_U32 HiAlign32(HI_U32 num)
41 {
42     return (((num) + 32 - 1) / 32 * 32); // 32: align 32
43 }
44 
45 /*
46  * VIDEO_FRAME_INFO_S格式转换成IVE_IMAGE_S格式
47  * 复制数据指针,不复制数据
48  *
49  * video frame to ive image.
50  * Copy the data pointer, do not copy the data.
51  */
FrmToOrigImg(const VIDEO_FRAME_INFO_S * frm,IVE_IMAGE_S * img)52 int FrmToOrigImg(const VIDEO_FRAME_INFO_S* frm, IVE_IMAGE_S *img)
53 {
54     static const int chnNum = 2; // Currently only supports YUV420/422, so only the addresses of 2 channels are copied
55     PIXEL_FORMAT_E pixelFormat = frm->stVFrame.enPixelFormat;
56 
57     if (memset_s(img, sizeof(*img), 0, sizeof(*img)) != EOK) {
58         HI_ASSERT(0);
59     }
60 
61     img->u32Width = frm->stVFrame.u32Width;
62     img->u32Height = frm->stVFrame.u32Height;
63 
64     if (pixelFormat == PIXEL_FORMAT_YVU_SEMIPLANAR_420) {
65         img->enType = IVE_IMAGE_TYPE_YUV420SP;
66     } else if (pixelFormat == PIXEL_FORMAT_YVU_SEMIPLANAR_422) {
67         img->enType = IVE_IMAGE_TYPE_YUV422SP;
68     } else {
69         HI_ASSERT(0);
70         return -1;
71     }
72 
73     for (int i = 0; i < chnNum; i++) {
74         img->au64PhyAddr[i] = frm->stVFrame.u64PhyAddr[i];
75         img->au64VirAddr[i] = frm->stVFrame.u64VirAddr[i];
76         img->au32Stride[i] = frm->stVFrame.u32Stride[i];
77     }
78     return 0;
79 }
80 
81 /*
82  * 计算通道的步长
83  * Calculate the stride of a channel
84  */
IveCalStride(IVE_IMAGE_TYPE_E enType,uint32_t width,AlignType align)85 static uint32_t IveCalStride(IVE_IMAGE_TYPE_E enType, uint32_t width, AlignType align)
86 {
87     uint32_t size = 1;
88 
89     switch (enType) {
90         case IVE_IMAGE_TYPE_U8C1:
91         case IVE_IMAGE_TYPE_S8C1:
92         case IVE_IMAGE_TYPE_S8C2_PACKAGE:
93         case IVE_IMAGE_TYPE_S8C2_PLANAR:
94         case IVE_IMAGE_TYPE_U8C3_PACKAGE:
95         case IVE_IMAGE_TYPE_U8C3_PLANAR:
96             size = sizeof(HI_U8);
97             break;
98         case IVE_IMAGE_TYPE_S16C1:
99         case IVE_IMAGE_TYPE_U16C1:
100             size = sizeof(HI_U16);
101             break;
102         case IVE_IMAGE_TYPE_S32C1:
103         case IVE_IMAGE_TYPE_U32C1:
104             size = sizeof(uint32_t);
105             break;
106         case IVE_IMAGE_TYPE_S64C1:
107         case IVE_IMAGE_TYPE_U64C1:
108             size = sizeof(uint64_t);
109             break;
110         default:
111             break;
112     }
113 
114     if (align == ALIGN_TYPE_16) {
115         return HiAlign16(width * size);
116     } else if (align == ALIGN_TYPE_32) {
117         return HiAlign32(width * size);
118     } else {
119         HI_ASSERT(0);
120         return 0;
121     }
122 }
123 
124 /*
125  * 根据类型和大小创建缓存
126  * Create ive image buffer based on type and size
127  */
IveImgCreate(IVE_IMAGE_S * img,IVE_IMAGE_TYPE_E enType,uint32_t width,uint32_t height)128 int IveImgCreate(IVE_IMAGE_S* img,
129     IVE_IMAGE_TYPE_E enType, uint32_t width, uint32_t height)
130 {
131     HI_ASSERT(img);
132     uint32_t oneChnSize;
133     uint32_t size;
134     int ret;
135 
136     if (memset_s(img, sizeof(*img), 0, sizeof(*img)) != EOK) {
137         HI_ASSERT(0);
138     }
139     img->enType = enType;
140     img->u32Width = width;
141     img->u32Height = height;
142     img->au32Stride[0] = IveCalStride(img->enType, img->u32Width, ALIGN_TYPE_16);
143 
144     switch (enType) {
145         case IVE_IMAGE_TYPE_U8C1:
146         case IVE_IMAGE_TYPE_S8C1: // Only 1 channel
147             size = img->au32Stride[0] * img->u32Height;
148             ret = HI_MPI_SYS_MmzAlloc(&img->au64PhyAddr[0], (void**)&img->au64VirAddr[0], NULL, NULL, size);
149             SAMPLE_CHECK_EXPR_RET(HI_SUCCESS != ret, ret, "Error(%#x), HI_MPI_SYS_MmzAlloc!\n", ret);
150             break;
151         /*
152          * 大小相当于像素的1.5倍(3/2), 相当于2个通道
153          * The size is equivalent to 1.5 times (3/2) of the pixel, which is equivalent to 2 channels
154          */
155         case IVE_IMAGE_TYPE_YUV420SP:
156         /*
157          * 大小相当于像素的2倍,相当于2个通道
158          * The size is equivalent to 2 times the pixel, which is equivalent to 2 channels
159          */
160         case IVE_IMAGE_TYPE_YUV422SP:
161             if (enType == IVE_IMAGE_TYPE_YUV420SP) {
162                 size = img->au32Stride[0] * img->u32Height * THREE_TIMES / TWO_TIMES;
163             } else {
164                 size = img->au32Stride[0] * img->u32Height * TWO_TIMES;
165             }
166             ret = HI_MPI_SYS_MmzAlloc(&img->au64PhyAddr[0], (void**)&img->au64VirAddr[0], NULL, NULL, size);
167             SAMPLE_CHECK_EXPR_RET(HI_SUCCESS != ret, ret, "Error(%#x), HI_MPI_SYS_MmzAlloc!\n", ret);
168 
169             /*
170              * 设置通道1地址的步长,两者都需要通道1
171              * Set the stride of the address of channel 1, both of which require channel 1
172              */
173             img->au32Stride[1] = img->au32Stride[0];
174             img->au64PhyAddr[1] = img->au64PhyAddr[0] + img->au32Stride[0] * (uint64_t)img->u32Height;
175             img->au64VirAddr[1] = img->au64VirAddr[0] + img->au32Stride[0] * (uint64_t)img->u32Height;
176             break;
177 
178         case IVE_IMAGE_TYPE_U8C3_PLANAR: // 3 channels, often used for RGB
179             oneChnSize = img->au32Stride[0] * img->u32Height;
180             size = oneChnSize * 3; // 3 channels have the same size
181             ret = HI_MPI_SYS_MmzAlloc(&img->au64PhyAddr[0], (void**)&img->au64VirAddr[0], NULL, NULL, size);
182             SAMPLE_CHECK_EXPR_RET(HI_SUCCESS != ret, ret, "Error(%#x), HI_MPI_SYS_MmzAlloc!\n", ret);
183 
184             /*
185              * 设置通道1和通道2的地址和步长
186              * Set the address and stride of channel 1 and channel 2
187              */
188             img->au64VirAddr[1] = img->au64VirAddr[0] + oneChnSize;
189             img->au64PhyAddr[1] = img->au64PhyAddr[0] + oneChnSize;
190             img->au32Stride[1] = img->au32Stride[0];
191             img->au64VirAddr[2] = img->au64VirAddr[1] + oneChnSize; // 2: au64VirAddr array subscript, not out of bounds
192             img->au64PhyAddr[2] = img->au64PhyAddr[1] + oneChnSize; // 2: au64VirAddr array subscript, not out of bounds
193             img->au32Stride[2] = img->au32Stride[0]; // 2: au64VirAddr array subscript, not out of bounds
194             break;
195 
196         /*
197          * 目前如下格式不支持,主要为YVC420P, YUV422P, S8C2_PACKAGE, S8C2_PLANAR,
198          * S32C1, U32C1, S64C1, U64C1, S16C1, U16C1, U8C3_PACKAGE等
199          *
200          * Types not currently supported: YVC420P, YUV422P, S8C2_PACKAGE, S8C2_PLANAR,
201          * S32C1, U32C1, S64C1, U64C1, S16C1, U16C1, U8C3_PACKAGE,etc.
202          */
203         default:
204             HI_ASSERT(0);
205             break;
206     }
207     return HI_SUCCESS;
208 }
209 
ImgYuvCrop(const IVE_IMAGE_S * src,IVE_IMAGE_S * dst,const RectBox * origBox)210 int ImgYuvCrop(const IVE_IMAGE_S *src, IVE_IMAGE_S *dst, const RectBox* origBox)
211 {
212     RectBox box = *origBox;
213     int boxWidth = box.xmax - box.xmin;
214     int boxHeight = box.ymax - box.ymin;
215     int ret;
216 
217     HI_ASSERT(boxWidth > 0 && boxWidth <= src->u32Width);
218     HI_ASSERT(boxHeight > 0 && boxHeight <= src->u32Height);
219     HI_ASSERT(src->au64VirAddr[0]);
220     HI_ASSERT(src->au32Stride[0] >= src->u32Width);
221 
222     /*
223      * 将框的宽度/高度调整为 2 的倍数
224      * Adjust the width/height of the box to a multiple of 2
225      */
226     if (boxWidth == 1 || boxHeight == 1) {
227         SAMPLE_PRT("box dstWidth=1 && dstHeight=1\n");
228         return -1;
229     }
230     if (boxWidth % HI_OVEN_BASE) {
231         box.xmax--;
232         boxWidth--;
233     }
234     if (boxHeight % HI_OVEN_BASE) {
235         box.ymax--;
236         boxHeight--;
237     }
238 
239     ret = IveImgCreate(dst, src->enType, boxWidth, boxHeight);
240     HI_ASSERT(!ret);
241 
242     /*
243      * 将框从源地址复制到目的地址
244      * copy box from src to dst
245      */
246     /*
247      * Y分量
248      * Y component
249      */
250     int srcStrideY = src->au32Stride[0];
251     int dstStrideY = dst->au32Stride[0];
252     uint8_t *srcBufY = (uint8_t*)((uintptr_t)src->au64VirAddr[0]);
253     uint8_t *dstBufY = (uint8_t*)((uintptr_t)dst->au64VirAddr[0]);
254     uint8_t *srcPtrY = &srcBufY[box.ymin * srcStrideY];
255     uint8_t *dstPtrY = dstBufY;
256     for (int h = 0; h < boxHeight; h++, srcPtrY += srcStrideY, dstPtrY += dstStrideY) {
257         if (memcpy_s(dstPtrY, boxWidth, srcPtrY + box.xmin, boxWidth) != EOK) {
258             HI_ASSERT(0);
259         }
260     }
261     HI_ASSERT(dstPtrY - dstBufY == boxHeight * dstStrideY);
262 
263     /*
264      * UV分量
265      * UV component
266      */
267     int srcStrideUV = src->au32Stride[1];
268     int dstStrideUV = dst->au32Stride[1];
269     uint8_t *srcBufUV = (uint8_t*)((uintptr_t)src->au64VirAddr[1]);
270     uint8_t *dstBufUV = (uint8_t*)((uintptr_t)dst->au64VirAddr[1]);
271     uint8_t *srcPtrUV = &srcBufUV[(box.ymin / HALF_THE_HEIGHT) * srcStrideUV];
272     uint8_t *dstPtrUV = dstBufUV;
273     for (int h = 0; h < (boxHeight / HALF_THE_HEIGHT);
274         h++, srcPtrUV += srcStrideUV, dstPtrUV += dstStrideUV) {
275         if (memcpy_s(dstPtrUV, boxWidth, srcPtrUV + box.xmin, boxWidth) != EOK) {
276             HI_ASSERT(0);
277         }
278     }
279     HI_ASSERT(dstPtrUV - dstBufUV == (boxHeight / HALF_THE_HEIGHT) * dstStrideUV);
280 
281     return ret;
282 }
283 
284 /*
285  * 销毁ive image
286  * Destory ive image
287  */
IveImgDestroy(IVE_IMAGE_S * img)288 void IveImgDestroy(IVE_IMAGE_S* img)
289 {
290     for (int i = 0; i < IMG_FULL_CHN; i++) {
291         if (img->au64PhyAddr[0] && img->au64VirAddr[0]) {
292             HI_MPI_SYS_MmzFree(img->au64PhyAddr[i], (void*)((uintptr_t)img->au64VirAddr[i]));
293             img->au64PhyAddr[i] = 0;
294             img->au64VirAddr[i] = 0;
295         }
296     }
297     if (memset_s(img, sizeof(*img), 0, sizeof(*img)) != EOK) {
298         HI_ASSERT(0);
299     }
300 }
301 
OrigImgToFrm(const IVE_IMAGE_S * img,VIDEO_FRAME_INFO_S * frm)302 int OrigImgToFrm(const IVE_IMAGE_S *img, VIDEO_FRAME_INFO_S* frm)
303 {
304     static const int chnNum = 2;
305     IVE_IMAGE_TYPE_E enType = img->enType;
306     if (memset_s(frm, sizeof(*frm), 0, sizeof(*frm)) != EOK) {
307         HI_ASSERT(0);
308     }
309 
310     frm->stVFrame.u32Width = img->u32Width;
311     frm->stVFrame.u32Height = img->u32Height;
312 
313     if (enType == IVE_IMAGE_TYPE_YUV420SP) {
314         frm->stVFrame.enPixelFormat = PIXEL_FORMAT_YVU_SEMIPLANAR_420;
315     } else if (enType == IVE_IMAGE_TYPE_YUV422SP) {
316         frm->stVFrame.enPixelFormat = PIXEL_FORMAT_YVU_SEMIPLANAR_422;
317     } else {
318         HI_ASSERT(0);
319         return -1;
320     }
321 
322     for (int i = 0; i < chnNum; i++) {
323         frm->stVFrame.u64PhyAddr[i] = img->au64PhyAddr[i];
324         frm->stVFrame.u64VirAddr[i] = img->au64VirAddr[i];
325         frm->stVFrame.u32Stride[i] = img->au32Stride[i];
326     }
327     return 0;
328 }
329 
330 #ifdef __cplusplus
331 #if __cplusplus
332 }
333 #endif
334 #endif /* End of #ifdef __cplusplus */
335