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#ifndef __HI_BUFFER_H__
17#define __HI_BUFFER_H__
18
19#include "hi_math.h"
20#include "hi_type.h"
21#include "hi_common.h"
22#include "hi_comm_video.h"
23
24#ifdef __cplusplus
25#if __cplusplus
26extern "C" {
27#endif
28#endif /* __cplusplus */
29
30#define HI_MAXINUM_LIMIT 100000
31
32__inline static HI_VOID COMMON_GetPicBufferConfig(HI_U32 u32Width, HI_U32 u32Height,
33    PIXEL_FORMAT_E enPixelFormat, DATA_BITWIDTH_E enBitWidth,
34    COMPRESS_MODE_E enCmpMode, HI_U32 u32Align, VB_CAL_CONFIG_S *pstCalConfig)
35{
36    HI_U32 u32BitWidth = 0;
37    HI_U32 u32HeadStride = 0;
38    HI_U32 u32VBSize = 0;
39    HI_U32 u32HeadSize = 0;
40    HI_U32 u32AlignHeight;
41    HI_U32 u32MainStride = 0;
42    HI_U32 u32MainSize = 0;
43    HI_U32 u32ExtStride = 0;
44    HI_U32 u32ExtSize = 0;
45    HI_U32 u32ExtYSize = 0;
46    HI_U32 u32HeadYSize = 0;
47    HI_U32 u32YSize = 0;
48
49    if ((u32Width > HI_MAXINUM_LIMIT) || (u32Height > HI_MAXINUM_LIMIT)) {
50        pstCalConfig->u32VBSize = 0;
51    }
52
53    /* u32Align: 0 is automatic mode, alignment size following system. Non-0 for specified alignment size */
54    if (u32Align == 0) {
55        u32Align = DEFAULT_ALIGN;
56    } else if (u32Align > MAX_ALIGN) {
57        u32Align = MAX_ALIGN;
58    } else {
59        u32Align = (HI_ALIGN_UP(u32Align, DEFAULT_ALIGN));
60    }
61
62    switch (enBitWidth) {
63        case DATA_BITWIDTH_8: {
64            u32BitWidth = 8;
65            break;
66        }
67        case DATA_BITWIDTH_16: {
68            u32BitWidth = 16;
69            break;
70        }
71        default: {
72            u32BitWidth = 0;
73            break;
74        }
75    }
76
77    u32AlignHeight = HI_ALIGN_UP(u32Height, 2);
78
79    if (enCmpMode == COMPRESS_MODE_NONE) {
80        u32MainStride = HI_ALIGN_UP((u32Width * u32BitWidth + 7) >> 3, u32Align);
81        u32YSize = u32MainStride * u32AlignHeight;
82
83        if ((PIXEL_FORMAT_YVU_SEMIPLANAR_420 == enPixelFormat) || (PIXEL_FORMAT_YUV_SEMIPLANAR_420 == enPixelFormat)) {
84            u32MainSize = (u32MainStride * u32AlignHeight * 3) >> 1;
85        } else if (PIXEL_FORMAT_YVU_SEMIPLANAR_422 == enPixelFormat ||
86                   PIXEL_FORMAT_YUV_SEMIPLANAR_422 == enPixelFormat) {
87            u32MainSize = u32MainStride * u32AlignHeight * 2;
88        } else if ((enPixelFormat == PIXEL_FORMAT_YUV_400) || (PIXEL_FORMAT_S16C1 == enPixelFormat)) {
89            u32MainSize = u32MainStride * u32AlignHeight;
90        } else {
91            u32MainSize = u32MainStride * u32AlignHeight * 3;
92        }
93
94        u32VBSize = u32MainSize;
95    } else {
96        if (u32Width <= 4096) {
97            u32HeadStride = 16;
98        } else if (u32Width <= 8192) {
99            u32HeadStride = 32;
100        } else {
101            u32HeadStride = 64;
102        }
103
104        if (u32BitWidth == 8) {
105            u32MainStride = HI_ALIGN_UP(u32Width, u32Align);
106            u32HeadYSize = u32HeadStride * u32AlignHeight;
107            u32YSize = u32MainStride * u32AlignHeight;
108
109            if ((PIXEL_FORMAT_YVU_SEMIPLANAR_420 == enPixelFormat) ||
110                (PIXEL_FORMAT_YUV_SEMIPLANAR_420 == enPixelFormat)) {
111                u32HeadSize = (u32HeadStride * u32AlignHeight * 3) >> 1;
112                u32MainSize = (u32MainStride * u32AlignHeight * 3) >> 1;
113            } else if (PIXEL_FORMAT_YVU_SEMIPLANAR_422 == enPixelFormat ||
114                       PIXEL_FORMAT_YUV_SEMIPLANAR_422 == enPixelFormat) {
115                u32HeadSize = u32HeadStride * u32AlignHeight * 2;
116                u32MainSize = u32MainStride * u32AlignHeight * 2;
117            } else if (enPixelFormat == PIXEL_FORMAT_YUV_400) {
118                u32HeadSize = u32HeadStride * u32AlignHeight;
119                u32MainSize = u32MainStride * u32AlignHeight;
120            } else {
121                u32HeadSize = u32HeadStride * u32AlignHeight * 3;
122                u32MainSize = u32MainStride * u32AlignHeight * 3;
123            }
124        } else {
125            u32VBSize = 0;
126            u32HeadYSize = 0;
127            u32HeadSize = 0;
128            u32HeadStride = 0;
129            u32MainStride = 0;
130            u32YSize = 0;
131            u32MainSize = 0;
132            u32ExtStride = 0;
133            u32ExtYSize = 0;
134        }
135
136        u32HeadSize = HI_ALIGN_UP(u32HeadSize, u32Align);
137
138        u32VBSize = u32HeadSize + u32MainSize + u32ExtSize;
139    }
140
141    pstCalConfig->u32VBSize = u32VBSize;
142    pstCalConfig->u32HeadYSize = u32HeadYSize;
143    pstCalConfig->u32HeadSize = u32HeadSize;
144    pstCalConfig->u32HeadStride = u32HeadStride;
145    pstCalConfig->u32MainStride = u32MainStride;
146    pstCalConfig->u32MainYSize = u32YSize;
147    pstCalConfig->u32MainSize = u32MainSize;
148    pstCalConfig->u32ExtStride = u32ExtStride;
149    pstCalConfig->u32ExtYSize = u32ExtYSize;
150
151    return;
152}
153
154__inline static HI_U32 COMMON_GetPicBufferSize(HI_U32 u32Width, HI_U32 u32Height,
155                                               PIXEL_FORMAT_E enPixelFormat,
156                                               DATA_BITWIDTH_E enBitWidth, COMPRESS_MODE_E enCmpMode, HI_U32 u32Align)
157{
158    VB_CAL_CONFIG_S stCalConfig;
159
160    COMMON_GetPicBufferConfig(u32Width, u32Height, enPixelFormat, enBitWidth, enCmpMode, u32Align, &stCalConfig);
161
162    return stCalConfig.u32VBSize;
163}
164
165__inline static HI_U32 VI_GetRawBufferSizeEx(HI_U32 u32Width, HI_U32 u32Height,
166                                             PIXEL_FORMAT_E enPixelFormat,
167                                             COMPRESS_MODE_E enCmpMode, HI_U32 u32CmpRatio, HI_U32 u32Align)
168{
169    HI_U32 u32BitWidth;
170    HI_U32 u32Size = 0;
171    HI_U32 u32Stride = 0;
172    HI_U32 u32RawCmpRatio = 1600;
173
174    if ((u32Width > HI_MAXINUM_LIMIT) || (u32Height > HI_MAXINUM_LIMIT)) {
175        return 0;
176    }
177
178    if (enCmpMode == COMPRESS_MODE_LINE) {
179        u32RawCmpRatio = 1600;
180    } else if (enCmpMode == COMPRESS_MODE_FRAME) {
181        if (u32CmpRatio == 0) {
182            u32RawCmpRatio = 2000;
183        } else {
184            u32RawCmpRatio = u32CmpRatio;
185        }
186    }
187
188    /* u32Align: 0 is automatic mode, alignment size following system. Non-0 for specified alignment size */
189    if (u32Align == 0) {
190        u32Align = DEFAULT_ALIGN;
191    } else if (u32Align > MAX_ALIGN) {
192        u32Align = MAX_ALIGN;
193    } else {
194        u32Align = (HI_ALIGN_UP(u32Align, DEFAULT_ALIGN));
195    }
196
197    switch (enPixelFormat) {
198        case PIXEL_FORMAT_RGB_BAYER_8BPP: {
199            u32BitWidth = 8;
200            break;
201        }
202
203        case PIXEL_FORMAT_RGB_BAYER_10BPP: {
204            u32BitWidth = 10;
205            break;
206        }
207
208        case PIXEL_FORMAT_RGB_BAYER_12BPP: {
209            u32BitWidth = 12;
210            break;
211        }
212
213        case PIXEL_FORMAT_RGB_BAYER_14BPP: {
214            u32BitWidth = 14;
215            break;
216        }
217
218        case PIXEL_FORMAT_RGB_BAYER_16BPP: {
219            u32BitWidth = 16;
220            break;
221        }
222
223        default: {
224            u32BitWidth = 0;
225            break;
226        }
227    }
228
229    if (enCmpMode == COMPRESS_MODE_NONE) {
230        u32Stride = HI_ALIGN_UP(HI_ALIGN_UP(u32Width * u32BitWidth, 8) / 8, u32Align);
231        u32Size = u32Stride * u32Height;
232    } else if (enCmpMode == COMPRESS_MODE_LINE) {
233        HI_U32 u32Tmp;
234        u32Tmp = HI_ALIGN_UP((16 + u32Width * u32BitWidth * 1000UL / u32RawCmpRatio + 8192 + 127) / 128, 2);
235        u32Stride = HI_ALIGN_UP(u32Tmp * 16, u32Align);
236        u32Size = u32Stride * u32Height;
237    } else if (enCmpMode == COMPRESS_MODE_FRAME) {
238        u32Size = HI_ALIGN_UP(u32Height * u32Width * u32BitWidth * 1000UL / (u32RawCmpRatio * 8), u32Align);
239    }
240
241    return u32Size;
242}
243
244__inline static HI_U32 VI_GetRawBufferSize(HI_U32 u32Width, HI_U32 u32Height,
245                                           PIXEL_FORMAT_E enPixelFormat, COMPRESS_MODE_E enCmpMode, HI_U32 u32Align)
246{
247    return VI_GetRawBufferSizeEx(u32Width, u32Height, enPixelFormat, enCmpMode, 0, u32Align);
248}
249
250__inline static HI_U32 VDEC_GetPicBufferSize(PAYLOAD_TYPE_E enType, HI_U32 u32Width,
251    HI_U32 u32Height, __attribute__((unused))PIXEL_FORMAT_E enPixelFormat,
252    __attribute__((unused))DATA_BITWIDTH_E enBitWidth,
253    __attribute__((unused))HI_U32 u32Align)
254{
255    HI_U32 u32AlignWidth, u32AlignHeight;
256    HI_U32 u32Size = 0;
257
258    if ((u32Width > HI_MAXINUM_LIMIT) || (u32Height > HI_MAXINUM_LIMIT)) {
259        return 0;
260    }
261
262    if (enType == PT_H264) {
263        u32AlignWidth = HI_ALIGN_UP(u32Width, H264D_ALIGN_W);
264        u32AlignHeight = HI_ALIGN_UP(u32Height, H264D_ALIGN_H);
265        u32Size = ((u32AlignWidth * u32AlignHeight) * 3) >> 1;
266    } else if (enType == PT_H265) {
267        u32AlignWidth = HI_ALIGN_UP(u32Width, H265D_ALIGN_W);
268        u32AlignHeight = HI_ALIGN_UP(u32Height, H265D_ALIGN_H);
269        u32Size = ((u32AlignWidth * u32AlignHeight) * 3) >> 1;
270    } else if ((enType == PT_JPEG) || (enType == PT_MJPEG)) {
271        /* for PIXEL_FORMAT_YVU_SEMIPLANAR_420 */
272        u32AlignWidth = HI_ALIGN_UP(u32Width, JPEGD_ALIGN_W);
273        u32AlignHeight = HI_ALIGN_UP(u32Height, JPEGD_ALIGN_H);
274        u32Size = (u32AlignWidth * u32AlignHeight * 3) >> 1;
275    } else {
276        u32Size = 0;
277    }
278
279    return u32Size;
280}
281
282__inline static HI_U32 VDEC_GetTmvBufferSize(PAYLOAD_TYPE_E enType, HI_U32 u32Width, HI_U32 u32Height)
283{
284    HI_U32 WidthInMb, HeightInMb;
285    HI_U32 ColMbSize;
286    HI_U32 u32Size = 0;
287
288    if ((u32Width > HI_MAXINUM_LIMIT) || (u32Height > HI_MAXINUM_LIMIT)) {
289        return 0;
290    }
291
292    if (enType == PT_H264) {
293        WidthInMb = HI_ALIGN_UP(u32Width, 16) >> 4;
294        HeightInMb = HI_ALIGN_UP(u32Height, 16) >> 4;
295        ColMbSize = 16 * 4;
296        u32Size = HI_ALIGN_UP((ColMbSize * WidthInMb * HeightInMb), 128);
297    } else if (enType == PT_H265) {
298        WidthInMb = HI_ALIGN_UP(u32Width, 64) >> 4;
299        HeightInMb = HI_ALIGN_UP(u32Height, 64) >> 4;
300        ColMbSize = 4 * 4;
301        u32Size = HI_ALIGN_UP((ColMbSize * WidthInMb * HeightInMb), 128);
302    } else {
303        u32Size = 0;
304    }
305
306    return u32Size;
307}
308
309__inline static HI_U32 VENC_GetRefPicInfoBufferSize(PAYLOAD_TYPE_E enType, HI_U32 u32Width, HI_U32 u32Height,
310    __attribute__((unused))HI_U32 u32Align)
311{
312    HI_U32 u32Size;
313    HI_U32 u32AlignWidth, u32AlignHeight;
314    HI_U32 u32TmvSize, u32PmeSize, u32PmeInfoSize;
315
316    if ((u32Width > HI_MAXINUM_LIMIT) || (u32Height > HI_MAXINUM_LIMIT)) {
317        return 0;
318    }
319
320    if (enType == PT_H265) {
321        u32AlignWidth = HI_ALIGN_UP(u32Width, 64) >> 6;
322        u32AlignHeight = HI_ALIGN_UP(u32Height, 64) >> 6;
323
324        u32TmvSize = (u32AlignWidth * u32AlignHeight) << 8;
325        u32PmeSize = (u32AlignWidth << 4) * (u32AlignHeight << 4);
326
327        u32AlignWidth = HI_ALIGN_UP(u32Width, 1024) >> 10;
328        u32AlignHeight = HI_ALIGN_UP(u32Height, 64) >> 6;
329        u32PmeInfoSize = (u32AlignWidth * u32AlignHeight) << 5;
330
331        u32Size = u32TmvSize + u32PmeSize + u32PmeInfoSize;
332    } else if (enType == PT_H264) {
333        u32AlignWidth = HI_ALIGN_UP(u32Width, 16) >> 4;
334        u32AlignHeight = HI_ALIGN_UP(u32Height, 16) >> 4;
335        u32TmvSize = (u32AlignWidth * u32AlignHeight) << 5;
336
337        u32AlignWidth = HI_ALIGN_UP(u32Width, 64) >> 6;
338        u32AlignHeight = HI_ALIGN_UP(u32Height, 64) >> 6;
339        u32PmeSize = (u32AlignWidth << 4) * (u32AlignHeight << 4);
340
341        u32AlignWidth = HI_ALIGN_UP(u32Width, 4096) >> 12;
342        u32AlignHeight = HI_ALIGN_UP(u32Height, 16) >> 4;
343        u32PmeInfoSize = (u32AlignWidth * u32AlignHeight) << 5;
344
345        u32Size = u32TmvSize + u32PmeSize + u32PmeInfoSize;
346    } else {
347        u32Size = 0;
348    }
349    return u32Size;
350}
351
352__inline static HI_U32 VENC_GetRefBufferSize(PAYLOAD_TYPE_E enType, HI_U32 u32Width, HI_U32 u32Height,
353    DATA_BITWIDTH_E enBitWidth, __attribute__((unused))HI_U32 u32Align)
354{
355    HI_U32 u32Size = 0;
356    HI_U32 u32AlignWidth, u32AlignHeight, u32BitWidth;
357    HI_U32 u32YHeaderSize, u32CHeaderSize, u32YSize, u32CSize;
358
359    if ((u32Width > HI_MAXINUM_LIMIT) || (u32Height > HI_MAXINUM_LIMIT)) {
360        return 0;
361    }
362
363    if (enBitWidth == DATA_BITWIDTH_8) {
364        u32BitWidth = 8;
365    } else {
366        return 0;
367    }
368
369    if (enType == PT_H265) {
370        u32AlignWidth = HI_ALIGN_UP(u32Width, 128);
371        u32AlignHeight = HI_ALIGN_UP(u32Height, 64) >> 6;
372
373        u32YHeaderSize = u32AlignWidth / 64 * 32 * u32AlignHeight;
374        u32CHeaderSize = u32YHeaderSize;
375
376        u32AlignWidth = HI_ALIGN_UP(u32Width, 64);
377        u32AlignHeight = HI_ALIGN_UP(u32Height, 16);
378        u32YSize = (u32AlignWidth * u32AlignHeight * u32BitWidth) >> 3;
379        u32CSize = u32YSize >> 1;
380
381        u32Size = u32YHeaderSize + u32CHeaderSize + u32YSize + u32CSize;
382    } else if (enType == PT_H264) {
383        u32AlignWidth = HI_ALIGN_UP(u32Width, 512);
384        u32AlignHeight = HI_ALIGN_UP(u32Height, 16) >> 4;
385        u32YHeaderSize = ((u32AlignWidth >> 8) << 4) * u32AlignHeight;
386        u32CHeaderSize = u32YHeaderSize;
387
388        u32AlignWidth = HI_ALIGN_UP(u32Width, 64);
389        u32AlignHeight = HI_ALIGN_UP(u32Height, 16);
390        u32YSize = u32AlignWidth * u32AlignHeight;
391        u32CSize = u32YSize >> 1;
392
393        u32Size = u32YHeaderSize + u32CHeaderSize + u32YSize + u32CSize;
394    } else {
395        u32Size = 0;
396    }
397
398    return u32Size;
399}
400
401__inline static HI_U32 VENC_GetQpmapSizeStride(HI_U32 u32Width)
402{
403    if (u32Width > HI_MAXINUM_LIMIT) {
404        return 0;
405    }
406
407    return DIV_UP(u32Width, 512) * 32;
408}
409
410__inline static HI_U32 VENC_GetQpmapSize(HI_U32 u32Width, HI_U32 u32Height)
411{
412    HI_U32 u32Stride, u32AlignHeight;
413
414    if ((u32Width > HI_MAXINUM_LIMIT) || (u32Height > HI_MAXINUM_LIMIT)) {
415        return 0;
416    }
417
418    u32Stride = VENC_GetQpmapSizeStride(u32Width);
419    u32AlignHeight = DIV_UP(u32Height, 16);
420
421    return u32Stride * u32AlignHeight;
422}
423
424__inline static HI_U32 VENC_GetSkipWeightSizeStride(PAYLOAD_TYPE_E enType, HI_U32 u32Width)
425{
426    HI_U32 u32Stride;
427
428    if (u32Width > HI_MAXINUM_LIMIT) {
429        return 0;
430    }
431
432    if (enType == PT_H265) {
433        u32Stride = DIV_UP(u32Width, 2048) * 16;
434    } else if (enType == PT_H264) {
435        u32Stride = DIV_UP(u32Width, 512) * 16;
436    } else {
437        u32Stride = 0;
438    }
439
440    return u32Stride;
441}
442__inline static HI_U32 VENC_GetSkipWeightSize(PAYLOAD_TYPE_E enType, HI_U32 u32Width, HI_U32 u32Height)
443{
444    HI_U32 u32Stride, u32AlignHeight;
445
446    if ((u32Width > HI_MAXINUM_LIMIT) || (u32Height > HI_MAXINUM_LIMIT)) {
447        return 0;
448    }
449
450    u32Stride = VENC_GetSkipWeightSizeStride(enType, u32Width);
451
452    if (enType == PT_H265) {
453        u32AlignHeight = DIV_UP(u32Height, 64);
454    } else if (enType == PT_H264) {
455        u32AlignHeight = DIV_UP(u32Height, 16);
456    } else {
457        u32AlignHeight = 0;
458    }
459
460    return u32Stride * u32AlignHeight;
461}
462
463#ifdef __cplusplus
464#if __cplusplus
465}
466#endif
467#endif /* __cplusplus */
468
469#endif /* __HI_BUFFER_H__ */
470
471