From c0d364c15219f3c30f2e7a3f586fbc8bef526de6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?William=20B=C3=A9rub=C3=A9?= Date: Sun, 14 Jul 2024 10:12:27 -0400 Subject: [PATCH] Preparing to add support for hisi-gen2 --- README.md | 44 +- src/hal/hisi/v2_aud.h | 108 +++++ src/hal/hisi/v2_common.h | 118 +++++ src/hal/hisi/v2_config.h | 542 +++++++++++++++++++++++ src/hal/hisi/v2_hal.c | 920 +++++++++++++++++++++++++++++++++++++++ src/hal/hisi/v2_hal.h | 62 +++ src/hal/hisi/v2_isp.h | 103 +++++ src/hal/hisi/v2_rgn.h | 162 +++++++ src/hal/hisi/v2_snr.h | 84 ++++ src/hal/hisi/v2_sys.h | 141 ++++++ src/hal/hisi/v2_vb.h | 111 +++++ src/hal/hisi/v2_venc.h | 395 +++++++++++++++++ src/hal/hisi/v2_vi.h | 132 ++++++ src/hal/hisi/v2_vpss.h | 104 +++++ src/hal/support.c | 17 +- src/hal/support.h | 4 +- src/hal/types.h | 1 + src/jpeg.c | 3 + src/main.c | 2 + src/media.c | 23 + src/region.c | 9 + 21 files changed, 3062 insertions(+), 23 deletions(-) create mode 100644 src/hal/hisi/v2_aud.h create mode 100644 src/hal/hisi/v2_common.h create mode 100644 src/hal/hisi/v2_config.h create mode 100644 src/hal/hisi/v2_hal.c create mode 100644 src/hal/hisi/v2_hal.h create mode 100644 src/hal/hisi/v2_isp.h create mode 100644 src/hal/hisi/v2_rgn.h create mode 100644 src/hal/hisi/v2_snr.h create mode 100644 src/hal/hisi/v2_sys.h create mode 100644 src/hal/hisi/v2_vb.h create mode 100644 src/hal/hisi/v2_venc.h create mode 100644 src/hal/hisi/v2_vi.h create mode 100644 src/hal/hisi/v2_vpss.h diff --git a/README.md b/README.md index 82c5d80..5869a92 100644 --- a/README.md +++ b/README.md @@ -19,34 +19,38 @@ In spite of these design choices, Divinus boasts numerous features that cater to | SoC Family | Audio Stream | JPEG Snapshot | fMP4 Stream | RTSP Stream | On-Screen Display* | |-------------------------|:------------:|:-------------:|:-----------:|:-----------:|:------------------:| | GM813x | ✗ | ✔️ | ✔️ | ✔️ | ✗ | -| Hi3516CV300[^1] | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | -| Hi3516CV500[^2] | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | -| Hi3516EV200[^3] | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | -| GK7205V200[^4] | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | -| Hi3519V100[^5] | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | +| Hi3516AV100[^1] | ↻ | ↻ | ↻ | ↻ | ↻ | +| Hi3516CV200[^2] | ↻ | ↻ | ↻ | ↻ | ↻ | +| Hi3516CV300[^3] | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | +| Hi3516CV500[^4] | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | +| Hi3516EV200[^5] | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | +| GK7205V200[^6] | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | +| Hi3519V100[^7] | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | | Hi3519AV100 | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | | Hi3559AV100 | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | | T31 series | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | -| infinity6[^6] | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | -| infinity6b0[^7] | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | -| infinity6e[^8] | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | -| infinity6c[^9] | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | -| infinity6f[^10] | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | +| infinity6[^8] | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | +| infinity6b0[^9] | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | +| infinity6e[^10] | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | +| infinity6c[^11] | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | +| infinity6f[^12] | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | _✔️ - supported, ↻ - in development, ✗ - unsupported, ⁿ/ₐ - not supported by hardware_ _* At the moment, only text, 24-bit and 32-bit RGB overlays are handled, matricial formats and covers are to follow_ -[^1]: Hi3516CV300 and Hi3516EV100 -[^2]: Hi3516AV300, Hi3516CV500 and Hi3516DV300 -[^3]: Hi3516DV200, Hi3516EV200/300 and Hi3518EV300 -[^4]: GK7202V300, GK7205V200/300 and GK7605V100 -[^5]: Hi3516AV200 and Hi3519V101 -[^6]: SSC323, SSC325(D/DE) and SSC327(D/DE/Q) -[^7]: SSC333/35/37(DE) -[^8]: SSC30K\[D/Q\], SSC336\[D/Q\], SSC338\[D/G/Q\] and SSC339G -[^9]: SSC377(D/DE/QE) or SSC378\[DE/QE\] -[^10]: SSC379G +[^1]: Hi3516AV100 and Hi3516DV100 +[^2]: Hi3516CV200 and Hi3518EV20\[0/1\] +[^3]: Hi3516CV300 and Hi3516EV100 +[^4]: Hi3516AV300, Hi3516CV500 and Hi3516DV300 +[^5]: Hi3516DV200, Hi3516EV200/300 and Hi3518EV300 +[^6]: GK7202V300, GK7205V200/300 and GK7605V100 +[^7]: Hi3516AV200 and Hi3519V101 +[^8]: SSC323, SSC325(D/DE) and SSC327(D/DE/Q) +[^9]: SSC333/35/37(DE) +[^10]: SSC30K\[D/Q\], SSC336\[D/Q\], SSC338\[D/G/Q\] and SSC339G +[^11]: SSC377(D/DE/QE) or SSC378\[DE/QE\] +[^12]: SSC379G ### Documentation diff --git a/src/hal/hisi/v2_aud.h b/src/hal/hisi/v2_aud.h new file mode 100644 index 0000000..d770049 --- /dev/null +++ b/src/hal/hisi/v2_aud.h @@ -0,0 +1,108 @@ +#pragma once + +#include "v2_common.h" + +#define V2_AUD_CHN_NUM 2 + +typedef enum { + V2_AUD_BIT_8, + V2_AUD_BIT_16, + V2_AUD_BIT_24 +} v2_aud_bit; + +typedef enum { + V2_AUD_INTF_I2S_MASTER, + V2_AUD_INTF_I2S_SLAVE, + V2_AUD_INTF_PCM_SLAVE_STD, + V2_AUD_INTF_PCM_SLAVE_NSTD, + V2_AUD_INTF_PCM_MASTER_STD, + V2_AUD_INTF_PCM_MASTER_NSTD, + V2_AUD_INTF_END +} v2_aud_intf; + +typedef struct { + // Accept industry standards from + // 8000 to 96000Hz, plus 64000Hz + int rate; + v2_aud_bit bit; + v2_aud_intf intf; + int stereoOn; + // 8-to-16 bit, expand mode + unsigned int expandOn; + unsigned int frmNum; + unsigned int packNumPerFrm; + unsigned int chnNum; + unsigned int syncRxClkOn; +} v2_aud_cnf; + +typedef struct { + v2_aud_bit bit; + int stereoOn; + void *addr[2]; + unsigned int phy[2]; + unsigned long long timestamp; + unsigned int sequence; + unsigned int length; + unsigned int poolId[2]; +} v2_aud_frm; + +typedef struct { + v2_aud_frm frame; + char isValid; + char isSysBound; +} v2_aud_efrm; + +typedef struct { + void *handle; + + int (*fnDisableDevice)(int device); + int (*fnEnableDevice)(int device); + int (*fnSetDeviceConfig)(int device, v2_aud_cnf *config); + + int (*fnDisableChannel)(int device, int channel); + int (*fnEnableChannel)(int device, int channel); + + int (*fnFreeFrame)(int device, int channel, v2_aud_frm *frame, v2_aud_efrm *encFrame); + int (*fnGetFrame)(int device, int channel, v2_aud_frm *frame, v2_aud_efrm *encFrame, int millis); +} v2_aud_impl; + +static int v2_aud_load(v2_aud_impl *aud_lib) { + if (!(aud_lib->handle = dlopen("libmpi.so", RTLD_LAZY | RTLD_GLOBAL))) + HAL_ERROR("v2_aud", "Failed to load library!\nError: %s\n", dlerror()); + + if (!(aud_lib->fnDisableDevice = (int(*)(int device)) + hal_symbol_load("v2_aud", aud_lib->handle, "HI_MPI_AI_Disable"))) + return EXIT_FAILURE; + + if (!(aud_lib->fnEnableDevice = (int(*)(int device)) + hal_symbol_load("v2_aud", aud_lib->handle, "HI_MPI_AI_Enable"))) + return EXIT_FAILURE; + + if (!(aud_lib->fnSetDeviceConfig = (int(*)(int device, v2_aud_cnf *config)) + hal_symbol_load("v2_aud", aud_lib->handle, "HI_MPI_AI_SetPubAttr"))) + return EXIT_FAILURE; + + if (!(aud_lib->fnDisableChannel = (int(*)(int device, int channel)) + hal_symbol_load("v2_aud", aud_lib->handle, "HI_MPI_AI_DisableChn"))) + return EXIT_FAILURE; + + if (!(aud_lib->fnEnableChannel = (int(*)(int device, int channel)) + hal_symbol_load("v2_aud", aud_lib->handle, "HI_MPI_AI_EnableChn"))) + return EXIT_FAILURE; + + if (!(aud_lib->fnFreeFrame = (int(*)(int device, int channel, v2_aud_frm *frame, v2_aud_efrm *encFrame)) + hal_symbol_load("v2_aud", aud_lib->handle, "HI_MPI_AI_ReleaseFrame"))) + return EXIT_FAILURE; + + if (!(aud_lib->fnGetFrame = (int(*)(int device, int channel, v2_aud_frm *frame, v2_aud_efrm *encFrame, int millis)) + hal_symbol_load("v2_aud", aud_lib->handle, "HI_MPI_AI_GetFrame"))) + return EXIT_FAILURE; + + return EXIT_SUCCESS; +} + +static void v2_aud_unload(v2_aud_impl *aud_lib) { + if (aud_lib->handle) dlclose(aud_lib->handle); + aud_lib->handle = NULL; + memset(aud_lib, 0, sizeof(*aud_lib)); +} \ No newline at end of file diff --git a/src/hal/hisi/v2_common.h b/src/hal/hisi/v2_common.h new file mode 100644 index 0000000..6569839 --- /dev/null +++ b/src/hal/hisi/v2_common.h @@ -0,0 +1,118 @@ +#pragma once + +#include +#include +#include +#include +#include + +#include "../symbols.h" +#include "../types.h" + +typedef enum { + V2_BAYER_RG, + V2_BAYER_GR, + V2_BAYER_GB, + V2_BAYER_BG, + V2_BAYER_END +} v2_common_bayer; + +typedef enum { + V2_COMPR_NONE, + V2_COMPR_SEG, + V2_COMPR_SEG128, + V2_COMPR_LINE, + V2_COMPR_FRAME, + V2_COMPR_END +} v2_common_compr; + +typedef enum { + V2_PIXFMT_1BPP, + V2_PIXFMT_2BPP, + V2_PIXFMT_4BPP, + V2_PIXFMT_8BPP, + V2_PIXFMT_RGB444, + V2_PIXFMT_ARGB4444, + V2_PIXFMT_RGB555, + V2_PIXFMT_RGB565, + V2_PIXFMT_ARGB1555, + V2_PIXFMT_RGB888, + V2_PIXFMT_ARGB8888, + V2_PIXFMT_RGB888P, + V2_PIXFMT_RGB_BAYER_8BPP, + V2_PIXFMT_RGB_BAYER_10BPP, + V2_PIXFMT_RGB_BAYER_12BPP, + V2_PIXFMT_RGB_BAYER_14BPP, + V2_PIXFMT_RGB_BAYER_16BPP, + V2_PIXFMT_YUV_A422, + V2_PIXFMT_YUV_A444, + V2_PIXFMT_YUV422P, + V2_PIXFMT_YUV420P, + V2_PIXFMT_YUV444P, + V2_PIXFMT_YUV422SP, + V2_PIXFMT_YUV420SP, + V2_PIXFMT_YUV444SP, + V2_PIXFMT_YUV422_UYVY, + V2_PIXFMT_YUV422_YUYV, + V2_PIXFMT_YUV422_VYUY, + V2_PIXFMT_YCbCrP, + V2_PIXFMT_YUV400, + V2_PIXFMT_END +} v2_common_pixfmt; + +typedef enum { + V2_PREC_8BPP, + V2_PREC_10BPP, + V2_PREC_12BPP, + V2_PREC_14BPP, + V2_PREC_16BPP, + V2_PREC_END +} v2_common_prec; + +typedef enum { + V2_VIDFMT_LINEAR, + V2_VIDFMT_TILE_256X16, + V2_VIDFMT_TILE_64X16, + V2_VIDFMT_END +} v2_common_vidfmt; + +typedef enum { + V2_WDR_NONE, + V2_WDR_BUILTIN, + V2_WDR_QUDRA, + V2_WDR_2TO1_LINE, + V2_WDR_2TO1_FRAME, + V2_WDR_2TO1_FRAME_FULLRATE, + V2_WDR_3TO1_LINE, + V2_WDR_3TO1_FRAME, + V2_WDR_3TO1_FRAME_FULLRATE, + V2_WDR_4TO1_LINE, + V2_WDR_4TO1_FRAME, + V2_WDR_4TO1_FRAME_FULLRATE, + V2_WDR_END +} v2_common_wdr; + +typedef struct { + unsigned int topWidth; + unsigned int bottomWidth; + unsigned int leftWidth; + unsigned int rightWidth; + unsigned int color; +} v2_common_bord; + +typedef struct { + unsigned int width; + unsigned int height; +} v2_common_dim; + +typedef struct { + int x; + int y; +} v2_common_pnt; + +typedef struct { + int x; + int y; + unsigned int width; + unsigned int height; +} v2_common_rect; diff --git a/src/hal/hisi/v2_config.h b/src/hal/hisi/v2_config.h new file mode 100644 index 0000000..e2e22d7 --- /dev/null +++ b/src/hal/hisi/v2_config.h @@ -0,0 +1,542 @@ +#pragma once + +#include "v2_common.h" +#include "v2_isp.h" +#include "v2_snr.h" +#include "v2_vi.h" + +#include +#include +#include + +#include "../config.h" +#include "../tools.h" + +typedef struct { + // [sensor] + char sensor_type[128]; + v2_common_wdr mode; + char dll_file[256]; + + // [mode] + v2_snr_input input_mode; + + // [mipi] + v2_snr_mipi mipi; + + // [lvds] + v2_snr_lvds lvds; + + // [isp_image] + v2_isp_dev isp; + + // [vi_dev] + v2_vi_dev videv; + + // [vi_chn] + v2_vi_chn vichn; +} v2_config_impl; + +extern v2_config_impl v2_config; + +static enum ConfigError v2_parse_config_lvds( + struct IniConfig *ini, const char *section, v2_snr_lvds *lvds) { + enum ConfigError err; + err = parse_int(ini, section, "img_size_w", 0, INT_MAX, &lvds->dest.width); + if (err != CONFIG_OK) + return err; + err = parse_int(ini, section, "img_size_h", 0, INT_MAX, &lvds->dest.height); + if (err != CONFIG_OK) + return err; + { + const char *possible_values[] = { + "HI_WDR_MODE_NONE", "HI_WDR_MODE_2F", "HI_WDR_MODE_3F", + "HI_WDR_MODE_4F", "HI_WDR_MODE_DOL_2F", "HI_WDR_MODE_DOL_3F", + "HI_WDR_MODE_DOL_4F"}; + const int count = sizeof(possible_values) / sizeof(const char *); + err = parse_enum( + ini, section, "wdr_mode", (void*)&lvds->wdr, possible_values, + count, 0); + if (err != CONFIG_OK) + return err; + } + { + const char *possible_values[] = { + "LVDS_SYNC_MODE_SOL", "LVDS_SYNC_MODE_SAV"}; + const int count = sizeof(possible_values) / sizeof(const char *); + err = parse_enum( + ini, section, "sync_mode", (void*)&lvds->syncSavOn, + possible_values, count, 0); + if (err != CONFIG_OK) + return err; + } + { + const char *possible_values[] = { + "RAW_DATA_8BIT", "RAW_DATA_10BIT", "RAW_DATA_12BIT", + "RAW_DATA_14BIT", "RAW_DATA_16BIT"}; + const int count = sizeof(possible_values) / sizeof(const char *); + err = parse_enum( + ini, section, "raw_data_type", (void*)&lvds->prec, + possible_values, count, 1); + if (err != CONFIG_OK) + return err; + } + { + const char *possible_values[] = { + "LVDS_ENDIAN_LITTLE", "LVDS_ENDIAN_BIG"}; + const int count = sizeof(possible_values) / sizeof(const char *); + err = parse_enum( + ini, section, "data_endian", (void*)&lvds->dataBeOn, + possible_values, count, 1); + if (err != CONFIG_OK) + return err; + err = parse_enum( + ini, section, "sync_code_endian", (void*)&lvds->syncBeOn, + possible_values, count, 1); + if (err != CONFIG_OK) + return err; + } + int laneId[4]; + err = parse_array(ini, section, "lane_id", laneId, 4); + if (err != CONFIG_OK) + return err; + else for (char i = 0; i < 4; i++) + lvds->laneId[i] = (short)laneId[i]; + char syncname[16]; + int synccode[128]; + for (int i = 0; i < 8; i++) { + sprintf(syncname, "sync_code_%d", i); + err = parse_array(ini, section, syncname, synccode + i * 16, 16); + if (err != CONFIG_OK) + return err; + } + for (int j = 0; j < 64; j++) + lvds->syncCode[j] = (unsigned short)synccode[j]; + return CONFIG_OK; +} + +static enum ConfigError v2_parse_config_videv( + struct IniConfig *ini, const char *section, v2_vi_dev *device) { + enum ConfigError err; + memset(device, 0, sizeof(*device)); + { + const char *possible_values[] = { + "VI_MODE_BT656", "VI_MODE_BT601", + "VI_MODE_DIGITAL_CAMERA", "VI_MODE_BT1120_STANDARD", + "VI_MODE_BT1120_INTERLEAVED", "VI_MODE_MIPI", + "VI_MODE_LVDS", "VI_MODE_HISPI"}; + const int count = sizeof(possible_values) / sizeof(const char *); + err = parse_enum( + ini, section, "input_mod", (void*)&device->intf, + possible_values, count, 0); + if (err != CONFIG_OK) + return err; + } + { + const char *possible_values[] = { + "VI_WORK_MODE_1Multiplex", "VI_WORK_MODE_2Multiplex", + "VI_WORK_MODE_4Multiplex"}; + const int count = sizeof(possible_values) / sizeof(const char *); + err = parse_enum( + ini, section, "work_mod", (void*)&device->work, possible_values, + count, 0); + if (err != CONFIG_OK) + device->work = V2_VI_WORK_1MULTIPLEX; + } + err = parse_uint32(ini, section, "mask_0", 0, UINT_MAX - 1, &device->cmpntMask[0]); + if (err != CONFIG_OK) + return err; + err = parse_uint32(ini, section, "mask_1", 0, UINT_MAX - 1, &device->cmpntMask[1]); + if (err != CONFIG_OK) + return err; + unsigned int maskNum; + err = parse_uint32(ini, section, "mask_num", 0, 2, &maskNum); + if (err != CONFIG_OK) + return err; + if (maskNum < 1) device->cmpntMask[1] = UINT_MAX; + if (maskNum < 2) device->cmpntMask[0] = UINT_MAX; + { + const char *possible_values[] = { + "VI_SCAN_INTERLACED", "VI_SCAN_PROGRESSIVE"}; + const int count = sizeof(possible_values) / sizeof(const char *); + err = parse_enum( + ini, section, "scan_mode", (void*)&device->progressiveOn, + possible_values, count, 0); + if (err != CONFIG_OK) + return err; + } + { + const char *possible_values[] = { + "VI_DATA_SEQ_VUVU", "VI_DATA_SEQ_UVUV", + "VI_DATA_SEQ_UYVY", "VI_DATA_SEQ_VYUY", + "VI_DATA_SEQ_YUYV", "VI_DATA_SEQ_YVYU"}; + const int count = sizeof(possible_values) / sizeof(const char *); + err = parse_enum( + ini, section, "data_seq", (void*)&device->seq, + possible_values, count, 0); + if (err != CONFIG_OK) + return err; + } + { + const char *possible_values[] = {"VI_VSYNC_FIELD", "VI_VSYNC_PULSE"}; + const int count = sizeof(possible_values) / sizeof(const char *); + err = parse_enum( + ini, section, "vsync", (void*)&device->sync.vsyncPulse, possible_values, + count, 0); + if (err != CONFIG_OK) + return err; + } + { + const char *possible_values[] = { + "VI_VSYNC_NEG_HIGH", "VI_VSYNC_NEG_LOW"}; + const int count = sizeof(possible_values) / sizeof(const char *); + err = parse_enum( + ini, section, "vsyncneg", (void*)&device->sync.vsyncInv, + possible_values, count, 0); + if (err != CONFIG_OK) + return err; + } + { + const char *possible_values[] = { + "VI_HSYNC_VALID_SIGNAL", "VI_HSYNC_PULSE"}; + const int count = sizeof(possible_values) / sizeof(const char *); + err = parse_enum( + ini, section, "hsync", (void*)&device->sync.hsyncPulse, possible_values, + count, 0); + if (err != CONFIG_OK) + return err; + } + { + const char *possible_values[] = { + "VI_HSYNC_NEG_HIGH", "VI_HSYNC_NEG_LOW"}; + const int count = sizeof(possible_values) / sizeof(const char *); + err = parse_enum( + ini, section, "hsyncneg", (void*)&device->sync.hsyncInv, + possible_values, count, 0); + if (err != CONFIG_OK) + return err; + } + { + const char *possible_values[] = { + "VI_VSYNC_NORM_PULSE", "VI_VSYNC_VALID_SIGNAL"}; + const int count = sizeof(possible_values) / sizeof(const char *); + err = parse_enum( + ini, section, "vsyncvalid", (void*)&device->sync.vsyncValid, + possible_values, count, 0); + if (err != CONFIG_OK) + return err; + } + { + const char *possible_values[] = { + "VI_VSYNC_VALID_NEG_HIGH", "VI_VSYNC_VALID_NEG_LOW"}; + const int count = sizeof(possible_values) / sizeof(const char *); + err = parse_enum( + ini, section, "vsyncvalidneg", (void*)&device->sync.vsyncValidInv, + possible_values, count, 0); + if (err != CONFIG_OK) + return err; + } + err = parse_int( + ini, section, "timingblank_hsynchfb", 0, INT_MAX, + &device->sync.timing.hsyncFront); + if (err != CONFIG_OK) + return err; + err = parse_int( + ini, section, "timingblank_hsyncact", 0, INT_MAX, + &device->sync.timing.hsyncWidth); + if (err != CONFIG_OK) + return err; + err = parse_int( + ini, section, "timingblank_hsynchbb", 0, INT_MAX, + &device->sync.timing.hsyncBack); + if (err != CONFIG_OK) + return err; + err = parse_int( + ini, section, "timingblank_vsyncvfb", 0, INT_MAX, + &device->sync.timing.vsyncFront); + if (err != CONFIG_OK) + return err; + err = parse_int( + ini, section, "timingblank_vsyncvact", 0, INT_MAX, + &device->sync.timing.vsyncWidth); + if (err != CONFIG_OK) + return err; + err = parse_int( + ini, section, "timingblank_vsyncvbb", 0, INT_MAX, + &device->sync.timing.vsyncBack); + if (err != CONFIG_OK) + return err; + err = parse_int( + ini, section, "timingblank_vsyncvbfb", 0, INT_MAX, + &device->sync.timing.vsyncIntrlFront); + if (err != CONFIG_OK) + return err; + err = parse_int( + ini, section, "timingblank_vsyncvbact", 0, INT_MAX, + &device->sync.timing.vsyncIntrlWidth); + if (err != CONFIG_OK) + return err; + err = parse_int( + ini, section, "timingblank_vsyncvbbb", 0, INT_MAX, + &device->sync.timing.vsyncIntrlBack); + if (err != CONFIG_OK) + return err; + err = parse_int(ini, section, "datarev", 0, INT_MAX, &device->dataRevOn); + if (err != CONFIG_OK) + return err; + err = parse_int(ini, section, "devrect_x", 0, INT_MAX, &device->rect.x); + if (err != CONFIG_OK) + return err; + err = parse_int(ini, section, "devrect_y", 0, INT_MAX, &device->rect.y); + if (err != CONFIG_OK) + return err; + err = parse_int(ini, section, "devrect_w", 0, INT_MAX, &device->rect.width); + if (err != CONFIG_OK) + return err; + int height; + err = parse_int(ini, section, "devrect_h", 0, INT_MAX, &device->rect.height); + if (err != CONFIG_OK) + return err; + + if (device->intf == V2_VI_INTF_MIPI || device->intf == V2_VI_INTF_LVDS) + device->rgbModeOn = 1; + else device->rgbModeOn = 0; + + return CONFIG_OK; +} + +static enum ConfigError v2_parse_config_vichn( + struct IniConfig *ini, const char *section, v2_vi_chn *channel) { + enum ConfigError err; + err = parse_int(ini, section, "caprect_x", 0, INT_MAX, &channel->capt.x); + if (err != CONFIG_OK) + return err; + err = parse_int(ini, section, "caprect_y", 0, INT_MAX,&channel->capt.y); + if (err != CONFIG_OK) + return err; + err = parse_int( + ini, section, "caprect_width", 0, INT_MAX, &channel->capt.width); + if (err != CONFIG_OK) + return err; + err = parse_int( + ini, section, "caprect_height", 0, INT_MAX, &channel->capt.height); + if (err != CONFIG_OK) + return err; + err = parse_int( + ini, section, "destsize_width", 0, INT_MAX, &channel->dest.width); + if (err != CONFIG_OK) + return err; + err = parse_int( + ini, section, "destsize_height", 0, INT_MAX, &channel->dest.height); + if (err != CONFIG_OK) + return err; + { + const char *possible_values[] = { + "VI_CAPSEL_TOP", "VI_CAPSEL_BOTTOM", "VI_CAPSEL_BOTH"}; + const int count = sizeof(possible_values) / sizeof(const char *); + err = parse_enum( + ini, section, "capsel", (void *)&channel->field, possible_values, + count, 0); + if (err != CONFIG_OK) + return err; + } + { + const char *possible_values[] = { + "PIXEL_FORMAT_RGB_1BPP", + "PIXEL_FORMAT_RGB_2BPP", + "PIXEL_FORMAT_RGB_4BPP", + "PIXEL_FORMAT_RGB_8BPP", + "PIXEL_FORMAT_RGB_444", + "PIXEL_FORMAT_RGB_4444", + "PIXEL_FORMAT_RGB_555", + "PIXEL_FORMAT_RGB_565", + "PIXEL_FORMAT_RGB_1555", + "PIXEL_FORMAT_RGB_888", + "PIXEL_FORMAT_RGB_8888", + "PIXEL_FORMAT_RGB_PLANAR_888", + "PIXEL_FORMAT_RGB_BAYER_8BPP", + "PIXEL_FORMAT_RGB_BAYER_10BPP", + "PIXEL_FORMAT_RGB_BAYER_12BPP", + "PIXEL_FORMAT_RGB_BAYER_14BPP", + "PIXEL_FORMAT_RGB_BAYER", + "PIXEL_FORMAT_YUV_A422", + "PIXEL_FORMAT_YUV_A444", + "PIXEL_FORMAT_YUV_PLANAR_422", + "PIXEL_FORMAT_YUV_PLANAR_420", + "PIXEL_FORMAT_YUV_PLANAR_444", + "PIXEL_FORMAT_YUV_SEMIPLANAR_422", + "PIXEL_FORMAT_YUV_SEMIPLANAR_420", + "PIXEL_FORMAT_YUV_SEMIPLANAR_444", + "PIXEL_FORMAT_UYVY_PACKAGE_422", + "PIXEL_FORMAT_YUYV_PACKAGE_422", + "PIXEL_FORMAT_VYUY_PACKAGE_422", + "PIXEL_FORMAT_YCbCr_PLANAR", + "PIXEL_FORMAT_YUV_400"}; + const int count = sizeof(possible_values) / sizeof(const char *); + err = parse_enum( + ini, section, "pixformat", (void *)&channel->pixFmt, + possible_values, count, 0); + if (err != CONFIG_OK) + return err; + } + { + const char *possible_values[] = { + "COMPRESS_MODE_NONE", "COMPRESS_MODE_SEG", "COMPRESS_MODE_SEG128", + "COMPRESS_MODE_LINE", "COMPRESS_MODE_FRAME"}; + const int count = sizeof(possible_values) / sizeof(const char *); + err = parse_enum( + ini, section, "compressmode", (void *)&channel->compress, + possible_values, count, 0); + if (err != CONFIG_OK) + return err; + } + err = parse_int( + ini, section, "srcframerate", INT_MIN, INT_MAX, &channel->srcFps); + if (err != CONFIG_OK) + return err; + err = parse_int( + ini, section, "framerate", INT_MIN, INT_MAX, &channel->dstFps); + if (err != CONFIG_OK) + return err; + return CONFIG_OK; +} + +static enum ConfigError v2_parse_config_isp( + struct IniConfig *ini, const char *section, v2_isp_dev *isp) { + enum ConfigError err; + + err = parse_int(ini, "isp_image", "isp_x", 0, INT_MAX, &isp->capt.x); + if (err != CONFIG_OK) + return err; + err = parse_int(ini, "isp_image", "isp_y", 0, INT_MAX, &isp->capt.y); + if (err != CONFIG_OK) + return err; + err = parse_int(ini, "isp_image", "isp_w", 0, INT_MAX, &isp->capt.width); + if (err != CONFIG_OK) + return err; + err = parse_int(ini, "isp_image", "isp_h", 0, INT_MAX, &isp->capt.height); + if (err != CONFIG_OK) + return err; + int value; + err = parse_int( + ini, "isp_image", "isp_framerate", 0, INT_MAX, &value); + if (err != CONFIG_OK) + return err; + else isp->framerate = value * 1.0f; + { + const char *possible_values[] = { + "BAYER_RGGB", "BAYER_GRBG", "BAYER_GBRG", "BAYER_BGGR"}; + const int count = sizeof(possible_values) / sizeof(const char *); + err = parse_enum( + ini, "isp_image", "isp_bayer", (void*)&isp->bayer, + possible_values, count, 0); + if (err != CONFIG_OK) + return err; + } + return CONFIG_OK; +} + +static enum ConfigError v2_parse_sensor_config(char *path, v2_config_impl *config) { + if (config == NULL) + return (enum ConfigError)-1; + memset(config, 0, sizeof(config)); + struct IniConfig ini; + memset(&ini, 0, sizeof(ini)); + enum ConfigError err; + + // load config file to string + if (!open_config(&ini, path)) + return (enum ConfigError)-1; + + find_sections(&ini); + + // [sensor] + err = parse_param_value(&ini, "sensor", "sensor_type", config->sensor_type); + if (err != CONFIG_OK) + goto RET_ERR; + { + const char *possible_values[] = { + "WDR_MODE_NONE", + "WDR_MODE_BUILT_IN", + "WDR_MODE_QUDRA", + "WDR_MODE_2To1_LINE", + "WDR_MODE_2To1_FRAME", + "WDR_MODE_2To1_FRAME_FULL_RATE", + "WDR_MODE_3To1_LINE", + "WDR_MODE_3To1_FRAME", + "WDR_MODE_3To1_FRAME_FULL_RATE", + "WDR_MODE_4To1_LINE", + "WDR_MODE_4To1_FRAME", + "WDR_MODE_4To1_FRAME_FULL_RATE"}; + const int count = sizeof(possible_values) / sizeof(const char *); + err = parse_enum( + &ini, "sensor", "mode", (void*)&config->mode, possible_values, + count, 0); + if (err != CONFIG_OK) + goto RET_ERR; + } + err = parse_param_value(&ini, "sensor", "dllfile", config->dll_file); + if (err != CONFIG_OK) + goto RET_ERR; + + // [mode] + { + const char *possible_values[] = { + "INPUT_MODE_MIPI", "INPUT_MODE_SUBLVDS", "INPUT_MODE_LVDS", + "INPUT_MODE_HISPI", "INPUT_MODE_CMOS_18V", "INPUT_MODE_CMOS_33V", + "INPUT_MODE_BT1120", "INPUT_MODE_BYPASS"}; + const int count = sizeof(possible_values) / sizeof(const char *); + err = parse_enum( + &ini, "mode", "input_mode", (void*)&config->input_mode, + possible_values, count, 0); + if (err != CONFIG_OK) + config->input_mode = V2_SNR_INPUT_MIPI; + } + + if (config->input_mode == V2_SNR_INPUT_MIPI) { + // [mipi] + { + const char *possible_values[] = {"RAW_DATA_8BIT", "RAW_DATA_10BIT", + "RAW_DATA_12BIT", "RAW_DATA_14BIT", + "RAW_DATA_16BIT"}; + const int count = sizeof(possible_values) / sizeof(const char *); + err = parse_enum( + &ini, "mipi", "data_type", (void *)&config->mipi.prec, + possible_values, count, 1); + if (err != CONFIG_OK) + goto RET_ERR; + } + int laneId[4]; + err = parse_array(&ini, "mipi", "lane_id", (int*)&laneId, 4); + if (err != CONFIG_OK) + goto RET_ERR; + else for (char i = 0; i < 4; i++) + config->mipi.laneId[i] = laneId[i]; + } else if (config->input_mode == V2_SNR_INPUT_LVDS) { + // [lvds] + err = v2_parse_config_lvds(&ini, "lvds", &config->lvds); + if (err != CONFIG_OK) + goto RET_ERR; + } + + // [isp_image] + err = v2_parse_config_isp(&ini, "isp_image", &config->isp); + if (err != CONFIG_OK) + goto RET_ERR; + + // [vi_dev] + err = v2_parse_config_videv(&ini, "vi_dev", &config->videv); + if (err != CONFIG_OK) + goto RET_ERR; + // [vi_chn] + err = v2_parse_config_vichn(&ini, "vi_chn", &config->vichn); + if (err != CONFIG_OK) + goto RET_ERR; + + v2_config = *config; + free(ini.str); + return CONFIG_OK; +RET_ERR: + free(ini.str); + return err; +} \ No newline at end of file diff --git a/src/hal/hisi/v2_hal.c b/src/hal/hisi/v2_hal.c new file mode 100644 index 0000000..c9020c1 --- /dev/null +++ b/src/hal/hisi/v2_hal.c @@ -0,0 +1,920 @@ +#ifdef __arm__ + +#include "v2_hal.h" + +v2_isp_alg v2_ae_lib = { .id = 0, .libName = "hisi_ae_lib" }; +v2_aud_impl v2_aud; +v2_isp_alg v2_awb_lib = { .id = 0, .libName = "hisi_awb_lib" }; +v2_config_impl v2_config; +v2_isp_impl v2_isp; +v2_snr_drv_impl v2_snr_drv; +v2_rgn_impl v2_rgn; +v2_sys_impl v2_sys; +v2_vb_impl v2_vb; +v2_venc_impl v2_venc; +v2_vi_impl v2_vi; +v2_vpss_impl v2_vpss; + +hal_chnstate v2_state[V2_VENC_CHN_NUM] = {0}; +int (*v2_aud_cb)(hal_audframe*); +int (*v2_vid_cb)(char, hal_vidstream*); + +char _v2_aud_chn = 0; +char _v2_aud_dev = 0; +char _v2_isp_chn = 0; +char _v2_isp_dev = 0; +char _v2_venc_dev = 0; +char _v2_vi_chn = 0; +char _v2_vi_dev = 0; +char _v2_vpss_chn = 0; +char _v2_vpss_grp = 0; + +void v2_hal_deinit(void) +{ + v2_vpss_unload(&v2_vpss); + v2_vi_unload(&v2_vi); + v2_venc_unload(&v2_venc); + v2_vb_unload(&v2_vb); + v2_rgn_unload(&v2_rgn); + v2_isp_unload(&v2_isp); + v2_aud_unload(&v2_aud); + v2_sys_unload(&v2_sys); +} + +int v2_hal_init(void) +{ + int ret; + + if (ret = v2_sys_load(&v2_sys)) + return ret; + if (ret = v2_aud_load(&v2_aud)) + return ret; + if (ret = v2_isp_load(&v2_isp)) + return ret; + if (ret = v2_rgn_load(&v2_rgn)) + return ret; + if (ret = v2_vb_load(&v2_vb)) + return ret; + if (ret = v2_venc_load(&v2_venc)) + return ret; + if (ret = v2_vi_load(&v2_vi)) + return ret; + if (ret = v2_vpss_load(&v2_vpss)) + return ret; + + return EXIT_SUCCESS; +} + +void v2_audio_deinit(void) +{ + v2_aud.fnDisableChannel(_v2_aud_dev, _v2_aud_chn); + + v2_aud.fnDisableDevice(_v2_aud_dev); +} + +int v2_audio_init(int samplerate) +{ + int ret; + + { + v2_aud_cnf config; + config.rate = samplerate; + config.bit = V2_AUD_BIT_16; + config.intf = V2_AUD_INTF_I2S_MASTER; + config.stereoOn = 0; + config.expandOn = 0; + config.frmNum = 30; + config.packNumPerFrm = 320; + config.chnNum = 1; + config.syncRxClkOn = 0; + if (ret = v2_aud.fnSetDeviceConfig(_v2_aud_dev, &config)) + return ret; + } + if (ret = v2_aud.fnEnableDevice(_v2_aud_dev)) + return ret; + + if (ret = v2_aud.fnEnableChannel(_v2_aud_dev, _v2_aud_chn)) + return ret; + + return EXIT_SUCCESS; +} + +void *v2_audio_thread(void) +{ + int ret; + + v2_aud_frm frame; + v2_aud_efrm echoFrame; + memset(&frame, 0, sizeof(frame)); + memset(&echoFrame, 0, sizeof(echoFrame)); + + while (keepRunning) { + if (ret = v2_aud.fnGetFrame(_v2_aud_dev, _v2_aud_chn, + &frame, &echoFrame, 128)) { + HAL_WARNING("v2_aud", "Getting the frame failed " + "with %#x!\n", ret); + continue; + } + + if (v2_aud_cb) { + hal_audframe outFrame; + outFrame.channelCnt = 1; + outFrame.data[0] = frame.addr[0]; + outFrame.length[0] = frame.length; + outFrame.seq = frame.sequence; + outFrame.timestamp = frame.timestamp; + (v2_aud_cb)(&outFrame); + } + + if (ret = v2_aud.fnFreeFrame(_v2_aud_dev, _v2_aud_chn, + &frame, &echoFrame)) { + HAL_WARNING("v2_aud", "Releasing the frame failed" + " with %#x!\n", ret); + } + } + HAL_INFO("v2_aud", "Shutting down capture thread...\n"); +} + +int v2_channel_bind(char index) +{ + int ret; + + if (ret = v2_vpss.fnEnableChannel(_v2_vpss_grp, index)) + return ret; + + { + v2_sys_bind source = { .module = V2_SYS_MOD_VPSS, + .device = _v2_vpss_grp, .channel = index }; + v2_sys_bind dest = { .module = V2_SYS_MOD_VENC, + .device = _v2_venc_dev, .channel = index }; + if (ret = v2_sys.fnBind(&source, &dest)) + return ret; + } + + return EXIT_SUCCESS; +} + +int v2_channel_create(char index, short width, short height, char mirror, char flip, char framerate) +{ + int ret; + + { + v2_vpss_chn channel; + memset(&channel, 0, sizeof(channel)); + channel.srcFps = v2_config.isp.framerate; + channel.dstFps = framerate; + channel.mirror = mirror; + channel.flip = flip; + if (ret = v2_vpss.fnSetChannelConfig(_v2_vpss_grp, index, &channel)) + return ret; + } + { + v2_vpss_mode mode; + mode.userModeOn = 1; + mode.dest.width = width; + mode.dest.height = height; + mode.doubleOn = 0; + mode.pixFmt = V2_PIXFMT_YUV420SP; + mode.compress = V2_COMPR_NONE; + if (ret = v2_vpss.fnSetChannelMode(_v2_vpss_grp, index, &mode)) + return ret; + } + + return EXIT_SUCCESS; +} + +int v2_channel_grayscale(char enable) +{ + int ret; + int active = enable; + + for (char i = 0; i < V2_VENC_CHN_NUM; i++) + if (v2_state[i].enable) + if (ret = v2_venc.fnSetColorToGray(i, &active)) + return ret; + + return EXIT_SUCCESS; +} + +int v2_channel_unbind(char index) +{ + int ret; + + if (ret = v2_vpss.fnDisableChannel(_v2_vpss_grp, index)) + return ret; + + { + v2_sys_bind source = { .module = V2_SYS_MOD_VPSS, + .device = _v2_vpss_grp, .channel = index }; + v2_sys_bind dest = { .module = V2_SYS_MOD_VENC, + .device = _v2_venc_dev, .channel = index }; + if (ret = v2_sys.fnUnbind(&source, &dest)) + return ret; + } + + return EXIT_SUCCESS; +} + +void *v2_image_thread(void) +{ + int ret; + + if (ret = v2_isp.fnRun(_v2_isp_dev)) + HAL_DANGER("v2_isp", "Operation failed with %#x!\n", ret); + HAL_INFO("v2_isp", "Shutting down ISP thread...\n"); +} + +int v2_pipeline_create(void) +{ + int ret; + + if (ret = v2_sensor_config()) + return ret; + + if (ret = v2_vi.fnSetDeviceConfig(_v2_vi_dev, &v2_config.videv)) + return ret; + if (ret = v2_vi.fnEnableDevice(_v2_vi_dev)) + return ret; + + { + v2_vi_chn channel; + channel.capt.width = v2_config.vichn.capt.width ? + v2_config.vichn.capt.width : v2_config.videv.rect.width; + channel.capt.height = v2_config.vichn.capt.height ? + v2_config.vichn.capt.height : v2_config.videv.rect.height; + channel.capt.x = 0; + channel.capt.y = 0; + channel.dest.width = v2_config.vichn.dest.width ? + v2_config.vichn.dest.width : v2_config.videv.rect.width; + channel.dest.height = v2_config.vichn.dest.height ? + v2_config.vichn.dest.height : v2_config.videv.rect.height; + channel.field = v2_config.vichn.field; + channel.pixFmt = V2_PIXFMT_YUV420SP; + channel.compress = V2_COMPR_NONE; + channel.mirror = 0; + channel.flip = 0; + channel.srcFps = v2_config.isp.framerate; + channel.dstFps = v2_config.isp.framerate; + if (ret = v2_vi.fnSetChannelConfig(_v2_vi_chn, &channel)) + return ret; + } + if (ret = v2_vi.fnEnableChannel(_v2_vi_chn)) + return ret; + + if (ret = v2_snr_drv.fnRegisterCallback()) + return ret; + + if (ret = v2_isp.fnRegisterAE(_v2_vi_dev, &v2_ae_lib)) + return ret; + if (ret = v2_isp.fnRegisterAWB(_v2_vi_dev, &v2_awb_lib)) + return ret; + if (ret = v2_isp.fnMemInit(_v2_vi_dev)) + return ret; + + if (ret = v2_isp.fnSetWDRMode(_v2_vi_dev, &v2_config.mode)) + return ret; + if (ret = v2_isp.fnSetDeviceConfig(_v2_vi_dev, &v2_config.isp)) + return ret; + if (ret = v2_isp.fnInit(_v2_vi_dev)) + return ret; + + { + v2_vpss_grp group; + memset(&group, 0, sizeof(group)); + group.dest.width = v2_config.vichn.capt.width ? + v2_config.vichn.capt.width : v2_config.videv.rect.width; + group.dest.height = v2_config.vichn.capt.height ? + v2_config.vichn.capt.height : v2_config.videv.rect.height; + group.pixFmt = V2_PIXFMT_YUV420SP; + group.nredOn = 1; + group.interlMode = v2_config.videv.progressiveOn ? 1 : 2; + if (ret = v2_vpss.fnCreateGroup(_v2_vpss_grp, &group)) + return ret; + } + if (ret = v2_vpss.fnStartGroup(_v2_vpss_grp)) + return ret; + + { + v2_sys_bind source = { .module = V2_SYS_MOD_VIU, + .device = _v2_vi_dev, .channel = _v2_vi_chn }; + v2_sys_bind dest = { .module = V2_SYS_MOD_VPSS, + .device = _v2_vpss_grp, .channel = 0 }; + if (ret = v2_sys.fnBind(&source, &dest)) + return ret; + } + + return EXIT_SUCCESS; +} + +void v2_pipeline_destroy(void) +{ + v2_isp.fnExit(_v2_vi_dev); + v2_isp.fnUnregisterAE(_v2_vi_dev, &v2_ae_lib); + v2_isp.fnUnregisterAWB(_v2_vi_dev, &v2_awb_lib); + + v2_snr_drv.fnUnRegisterCallback(); + + for (char grp = 0; grp < V2_VPSS_GRP_NUM; grp++) + { + for (char chn = 0; chn < V2_VPSS_CHN_NUM; chn++) + v2_vpss.fnDisableChannel(grp, chn); + + { + v2_sys_bind source = { .module = V2_SYS_MOD_VIU, + .device = _v2_vi_dev, .channel = _v2_vi_chn }; + v2_sys_bind dest = { .module = V2_SYS_MOD_VPSS, + .device = grp, .channel = 0 }; + v2_sys.fnUnbind(&source, &dest); + } + + v2_vpss.fnStopGroup(grp); + v2_vpss.fnDestroyGroup(grp); + } + + v2_vi.fnDisableChannel(_v2_vi_chn); + + v2_vi.fnDisableDevice(_v2_vi_dev); + + v2_sensor_deconfig(); +} + +int v2_region_create(char handle, hal_rect rect, short opacity) +{ + int ret; + + v2_sys_bind channel = { .module = V2_SYS_MOD_VENC, + .device = _v2_venc_dev, .channel = 0 }; + v2_rgn_cnf region, regionCurr; + v2_rgn_chn attrib, attribCurr; + + memset(®ion, 0, sizeof(region)); + region.type = V2_RGN_TYPE_OVERLAY; + region.overlay.pixFmt = V2_PIXFMT_ARGB1555; + region.overlay.size.width = rect.width; + region.overlay.size.height = rect.height; + region.overlay.canvas = handle + 1; + + if (v2_rgn.fnGetRegionConfig(handle, ®ionCurr)) { + HAL_INFO("v2_rgn", "Creating region %d...\n", handle); + if (ret = v2_rgn.fnCreateRegion(handle, ®ion)) + return ret; + } else if (regionCurr.overlay.size.height != region.overlay.size.height || + regionCurr.overlay.size.width != region.overlay.size.width) { + HAL_INFO("v2_rgn", "Parameters are different, recreating " + "region %d...\n", handle); + v2_rgn.fnDetachChannel(handle, &channel); + v2_rgn.fnDestroyRegion(handle); + if (ret = v2_rgn.fnCreateRegion(handle, ®ion)) + return ret; + } + + if (v2_rgn.fnGetChannelConfig(handle, &channel, &attribCurr)) + HAL_INFO("v2_rgn", "Attaching region %d...\n", handle); + else if (attribCurr.overlay.point.x != rect.x || attribCurr.overlay.point.x != rect.y) { + HAL_INFO("v2_rgn", "Position has changed, reattaching " + "region %d...\n", handle); + v2_rgn.fnDetachChannel(handle, &channel); + } + + memset(&attrib, 0, sizeof(attrib)); + attrib.show = 1; + attrib.type = V2_RGN_TYPE_OVERLAY; + attrib.overlay.bgAlpha = 0; + attrib.overlay.fgAlpha = opacity >> 1; + attrib.overlay.point.x = rect.x; + attrib.overlay.point.y = rect.y; + attrib.overlay.layer = 7; + + v2_rgn.fnAttachChannel(handle, &channel, &attrib); + + return EXIT_SUCCESS; +} + +void v2_region_destroy(char handle) +{ + v2_sys_bind channel = { .module = V2_SYS_MOD_VENC, + .device = _v2_venc_dev, .channel = 0 }; + + v2_rgn.fnDetachChannel(handle, &channel); + v2_rgn.fnDestroyRegion(handle); +} + +int v2_region_setbitmap(int handle, hal_bitmap *bitmap) +{ + v2_rgn_bmp nativeBmp = { .data = bitmap->data, .pixFmt = V2_PIXFMT_ARGB1555, + .size.height = bitmap->dim.height, .size.width = bitmap->dim.width }; + + return v2_rgn.fnSetBitmap(handle, &nativeBmp); +} + +int v2_sensor_config(void) { + int fd; + v2_snr_dev config; + memset(&config, 0, sizeof(config)); + config.device = 0; + config.input = v2_config.input_mode; + if (config.input == V2_SNR_INPUT_MIPI) + memcpy(&config.mipi, &v2_config.mipi, sizeof(v2_snr_mipi)); + else if (config.input == V2_SNR_INPUT_LVDS) + memcpy(&config.lvds, &v2_config.lvds, sizeof(v2_snr_lvds)); + + if (!access(v2_snr_endp, F_OK)) + fd = open(v2_snr_endp, O_RDWR); + else fd = open("/dev/mipi", O_RDWR); + if (fd < 0) + HAL_ERROR("v2_snr", "Opening imaging device has failed!\n"); + + ioctl(fd, _IOW(V2_SNR_IOC_MAGIC, V2_SNR_CMD_RST_MIPI, unsigned int), &config.device); + + ioctl(fd, _IOW(V2_SNR_IOC_MAGIC, V2_SNR_CMD_RST_SENS, unsigned int), &config.device); + + if (ioctl(fd, _IOW(V2_SNR_IOC_MAGIC, V2_SNR_CMD_CONF_DEV, v2_snr_dev), &config)) + HAL_ERROR("v2_snr", "Configuring imaging device has failed!\n"); + + ioctl(fd, _IOW(V2_SNR_IOC_MAGIC, V2_SNR_CMD_UNRST_MIPI, unsigned int), &config.device); + + ioctl(fd, _IOW(V2_SNR_IOC_MAGIC, V2_SNR_CMD_UNRST_SENS, unsigned int), &config.device); + + close(fd); + + return EXIT_SUCCESS; +} + +void v2_sensor_deconfig(void) { + int fd; + v2_snr_dev config; + config.device = 0; + + if (!access(v2_snr_endp, F_OK)) + fd = open(v2_snr_endp, O_RDWR); + else fd = open("/dev/mipi", O_RDWR); + if (fd < 0) + HAL_DANGER("v2_snr", "Opening imaging device has failed!\n"); + + ioctl(fd, _IOW(V2_SNR_IOC_MAGIC, V2_SNR_CMD_RST_SENS, unsigned int), &config.device); + + ioctl(fd, _IOW(V2_SNR_IOC_MAGIC, V2_SNR_CMD_RST_MIPI, unsigned int), &config.device); + + close(fd); +} + +void v2_sensor_deinit(void) +{ + dlclose(v2_snr_drv.handle); + v2_snr_drv.handle = NULL; +} + +int v2_sensor_init(char *name, char *obj) +{ + char path[128]; + char* dirs[] = {"%s", "./%s", "/usr/lib/sensors/%s"}; + char **dir = dirs; + + while (*dir) { + sprintf(path, *dir++, name); + if (v2_snr_drv.handle = dlopen(path, RTLD_NOW | RTLD_GLOBAL)) + break; + } if (!v2_snr_drv.handle) + HAL_ERROR("v2_snr", "Failed to load the sensor driver"); + + if (!(v2_snr_drv.fnRegisterCallback = (int(*)(void))dlsym(v2_snr_drv.handle, "sensor_register_callback"))) + HAL_ERROR("v2_snr", "Failed to connect the callback register function"); + if (!(v2_snr_drv.fnUnRegisterCallback = (int(*)(void))dlsym(v2_snr_drv.handle, "sensor_unregister_callback"))) + HAL_ERROR("v2_snr", "Failed to connect the callback register function"); + + return EXIT_SUCCESS; +} + +int v2_video_create(char index, hal_vidconfig *config) +{ + int ret; + v2_venc_chn channel; + v2_venc_attr_h26x *attrib; + memset(&channel, 0, sizeof(channel)); + + if (config->codec == HAL_VIDCODEC_JPG) { + channel.attrib.codec = V2_VENC_CODEC_JPEG; + channel.attrib.jpg.maxPic.width = config->width; + channel.attrib.jpg.maxPic.height = config->height; + channel.attrib.jpg.bufSize = + config->height * config->width * 2; + channel.attrib.jpg.byFrame = 1; + channel.attrib.jpg.pic.width = config->width; + channel.attrib.jpg.pic.height = config->height; + channel.attrib.jpg.dcfThumbs = 0; + goto attach; + } else if (config->codec == HAL_VIDCODEC_MJPG) { + channel.attrib.codec = V2_VENC_CODEC_MJPG; + channel.attrib.mjpg.maxPic.width = config->width; + channel.attrib.mjpg.maxPic.height = config->height; + channel.attrib.mjpg.bufSize = + config->height * config->width * 2; + channel.attrib.mjpg.byFrame = 1; + channel.attrib.mjpg.pic.width = config->width; + channel.attrib.mjpg.pic.height = config->height; + switch (config->mode) { + case HAL_VIDMODE_CBR: + channel.rate.mode = V2_VENC_RATEMODE_MJPGCBR; + channel.rate.mjpgCbr = (v2_venc_rate_mjpgcbr){ .statTime = 1, .srcFps = config->framerate, + .dstFps = config->framerate, .bitrate = config->bitrate, .avgLvl = 1 }; break; + case HAL_VIDMODE_VBR: + channel.rate.mode = V2_VENC_RATEMODE_MJPGVBR; + channel.rate.mjpgVbr = (v2_venc_rate_mjpgvbr){ .statTime = 1, .srcFps = config->framerate, + .dstFps = config->framerate , .maxBitrate = MAX(config->bitrate, config->maxBitrate), + .maxQual = config->maxQual, .minQual = config->maxQual }; break; + case HAL_VIDMODE_QP: + channel.rate.mode = V2_VENC_RATEMODE_MJPGQP; + channel.rate.mjpgQp = (v2_venc_rate_mjpgqp){ .srcFps = config->framerate, + .dstFps = config->framerate, .quality = config->maxQual }; break; + default: + HAL_ERROR("v2_venc", "MJPEG encoder can only support CBR, VBR or fixed QP modes!"); + } + goto attach; + } else if (config->codec == HAL_VIDCODEC_H265) { + channel.attrib.codec = V2_VENC_CODEC_H265; + attrib = &channel.attrib.h265; + switch (config->mode) { + case HAL_VIDMODE_CBR: + channel.rate.mode = V2_VENC_RATEMODE_H265CBR; + channel.rate.h265Cbr = (v2_venc_rate_h26xcbr){ .gop = config->gop, + .statTime = 1, .srcFps = config->framerate, .dstFps = config->framerate, + .bitrate = config->bitrate, .avgLvl = 1 }; break; + case HAL_VIDMODE_VBR: + channel.rate.mode = V2_VENC_RATEMODE_H265VBR; + channel.rate.h265Vbr = (v2_venc_rate_h26xvbr){ .gop = config->gop, + .statTime = 1, .srcFps = config->framerate, .dstFps = config->framerate, + .maxBitrate = MAX(config->bitrate, config->maxBitrate), .maxQual = config->maxQual, + .minQual = config->minQual, .minIQual = config->minQual }; break; + case HAL_VIDMODE_QP: + channel.rate.mode = V2_VENC_RATEMODE_H265QP; + channel.rate.h265Qp = (v2_venc_rate_h26xqp){ .gop = config->gop, + .srcFps = config->framerate, .dstFps = config->framerate, .interQual = config->maxQual, + .predQual = config->minQual, .bipredQual = config->minQual }; break; + case HAL_VIDMODE_AVBR: + channel.rate.mode = V2_VENC_RATEMODE_H265AVBR; + channel.rate.h265Avbr = (v2_venc_rate_h26xavbr){ .gop = config->gop, + .statTime = 1, .srcFps = config->framerate, .dstFps = config->framerate, + .bitrate = config->bitrate }; break; + default: + HAL_ERROR("v2_venc", "H.265 encoder does not support this mode!"); + } + } else if (config->codec == HAL_VIDCODEC_H264) { + channel.attrib.codec = V2_VENC_CODEC_H264; + attrib = &channel.attrib.h264; + switch (config->mode) { + case HAL_VIDMODE_CBR: + channel.rate.mode = V2_VENC_RATEMODE_H264CBR; + channel.rate.h264Cbr = (v2_venc_rate_h26xcbr){ .gop = config->gop, + .statTime = 1, .srcFps = config->framerate, .dstFps = config->framerate, + .bitrate = config->bitrate, .avgLvl = 1 }; break; + case HAL_VIDMODE_VBR: + channel.rate.mode = V2_VENC_RATEMODE_H264VBR; + channel.rate.h264Vbr = (v2_venc_rate_h26xvbr){ .gop = config->gop, + .statTime = 1, .srcFps = config->framerate, .dstFps = config->framerate, + .maxBitrate = MAX(config->bitrate, config->maxBitrate), .maxQual = config->maxQual, + .minQual = config->minQual, .minIQual = config->minQual }; break; + case HAL_VIDMODE_QP: + channel.rate.mode = V2_VENC_RATEMODE_H264QP; + channel.rate.h264Qp = (v2_venc_rate_h26xqp){ .gop = config->gop, + .srcFps = config->framerate, .dstFps = config->framerate, .interQual = config->maxQual, + .predQual = config->minQual, .bipredQual = config->minQual }; break; + case HAL_VIDMODE_AVBR: + channel.rate.mode = V2_VENC_RATEMODE_H264AVBR; + channel.rate.h264Avbr = (v2_venc_rate_h26xavbr){ .gop = config->gop, + .statTime = 1, .srcFps = config->framerate, .dstFps = config->framerate, + .bitrate = config->bitrate }; break; + default: + HAL_ERROR("v2_venc", "H.264 encoder does not support this mode!"); + } + } else HAL_ERROR("v2_venc", "This codec is not supported by the hardware!"); + attrib->maxPic.width = config->width; + attrib->maxPic.height = config->height; + attrib->bufSize = config->height * config->width * 2; + attrib->profile = config->profile; + attrib->byFrame = 1; + attrib->pic.width = config->width; + attrib->pic.height = config->height; +attach: + if (ret = v2_venc.fnCreateChannel(index, &channel)) + return ret; + + if (config->codec != HAL_VIDCODEC_JPG && + (ret = v2_venc.fnStartReceiving(index))) + return ret; + + v2_state[index].payload = config->codec; + + return EXIT_SUCCESS; +} + +int v2_video_destroy(char index) +{ + int ret; + + v2_state[index].enable = 0; + v2_state[index].payload = HAL_VIDCODEC_UNSPEC; + + v2_venc.fnStopReceiving(index); + + { + v2_sys_bind source = { .module = V2_SYS_MOD_VPSS, + .device = _v2_vpss_grp, .channel = index }; + v2_sys_bind dest = { .module = V2_SYS_MOD_VENC, + .device = _v2_venc_dev, .channel = index }; + if (ret = v2_sys.fnUnbind(&source, &dest)) + return ret; + } + + if (ret = v2_venc.fnDestroyChannel(index)) + return ret; + + if (ret = v2_vpss.fnDisableChannel(_v2_vpss_grp, index)) + return ret; + + return EXIT_SUCCESS; +} + +int v2_video_destroy_all(void) +{ + int ret; + + for (char i = 0; i < V2_VENC_CHN_NUM; i++) + if (v2_state[i].enable) + if (ret = v2_video_destroy(i)) + return ret; + + return EXIT_SUCCESS; +} + +void v2_video_request_idr(char index) +{ + v2_venc.fnRequestIdr(index, 1); +} + +int v2_video_snapshot_grab(char index, hal_jpegdata *jpeg) +{ + int ret; + + if (ret = v2_channel_bind(index)) { + HAL_DANGER("v2_venc", "Binding the encoder channel " + "%d failed with %#x!\n", index, ret); + goto abort; + } + + unsigned int count = 1; + if (v2_venc.fnStartReceivingEx(index, &count)) { + HAL_DANGER("v2_venc", "Requesting one frame " + "%d failed with %#x!\n", index, ret); + goto abort; + } + + int fd = v2_venc.fnGetDescriptor(index); + + struct timeval timeout = { .tv_sec = 2, .tv_usec = 0 }; + fd_set readFds; + FD_ZERO(&readFds); + FD_SET(fd, &readFds); + ret = select(fd + 1, &readFds, NULL, NULL, &timeout); + if (ret < 0) { + HAL_DANGER("v2_venc", "Select operation failed!\n"); + goto abort; + } else if (ret == 0) { + HAL_DANGER("v2_venc", "Capture stream timed out!\n"); + goto abort; + } + + if (FD_ISSET(fd, &readFds)) { + v2_venc_stat stat; + if (v2_venc.fnQuery(index, &stat)) { + HAL_DANGER("v2_venc", "Querying the encoder channel " + "%d failed with %#x!\n", index, ret); + goto abort; + } + + if (!stat.curPacks) { + HAL_DANGER("v2_venc", "Current frame is empty, skipping it!\n"); + goto abort; + } + + v2_venc_strm strm; + memset(&strm, 0, sizeof(strm)); + strm.packet = (v2_venc_pack*)malloc(sizeof(v2_venc_pack) * stat.curPacks); + if (!strm.packet) { + HAL_DANGER("v2_venc", "Memory allocation on channel %d failed!\n", index); + goto abort; + } + strm.count = stat.curPacks; + + if (ret = v2_venc.fnGetStream(index, &strm, stat.curPacks)) { + HAL_DANGER("v2_venc", "Getting the stream on " + "channel %d failed with %#x!\n", index, ret); + free(strm.packet); + strm.packet = NULL; + goto abort; + } + + { + jpeg->jpegSize = 0; + for (unsigned int i = 0; i < strm.count; i++) { + v2_venc_pack *pack = &strm.packet[i]; + unsigned int packLen = pack->length - pack->offset; + unsigned char *packData = pack->data + pack->offset; + + unsigned int newLen = jpeg->jpegSize + packLen; + if (newLen > jpeg->length) { + jpeg->data = realloc(jpeg->data, newLen); + jpeg->length = newLen; + } + memcpy(jpeg->data + jpeg->jpegSize, packData, packLen); + jpeg->jpegSize += packLen; + } + } + +abort: + v2_venc.fnFreeStream(index, &strm); + } + + v2_venc.fnFreeDescriptor(index); + + v2_venc.fnStopReceiving(index); + + v2_channel_unbind(index); + + return ret; +} + +void *v2_video_thread(void) +{ + int ret; + int maxFd = 0; + + for (int i = 0; i < V2_VENC_CHN_NUM; i++) { + if (!v2_state[i].enable) continue; + if (!v2_state[i].mainLoop) continue; + + ret = v2_venc.fnGetDescriptor(i); + if (ret < 0) { + HAL_DANGER("v2_venc", "Getting the encoder descriptor failed with %#x!\n", ret); + return NULL; + } + v2_state[i].fileDesc = ret; + + if (maxFd <= v2_state[i].fileDesc) + maxFd = v2_state[i].fileDesc; + } + + v2_venc_stat stat; + v2_venc_strm stream; + struct timeval timeout; + fd_set readFds; + + while (keepRunning) { + FD_ZERO(&readFds); + for(int i = 0; i < V2_VENC_CHN_NUM; i++) { + if (!v2_state[i].enable) continue; + if (!v2_state[i].mainLoop) continue; + FD_SET(v2_state[i].fileDesc, &readFds); + } + + timeout.tv_sec = 2; + timeout.tv_usec = 0; + ret = select(maxFd + 1, &readFds, NULL, NULL, &timeout); + if (ret < 0) { + HAL_DANGER("v2_venc", "Select operation failed!\n"); + break; + } else if (ret == 0) { + HAL_WARNING("v2_venc", "Main stream loop timed out!\n"); + continue; + } else { + for (int i = 0; i < V2_VENC_CHN_NUM; i++) { + if (!v2_state[i].enable) continue; + if (!v2_state[i].mainLoop) continue; + if (FD_ISSET(v2_state[i].fileDesc, &readFds)) { + memset(&stream, 0, sizeof(stream)); + + if (ret = v2_venc.fnQuery(i, &stat)) { + HAL_DANGER("v2_venc", "Querying the encoder channel " + "%d failed with %#x!\n", i, ret); + break; + } + + if (!stat.curPacks) { + HAL_WARNING("v2_venc", " Current frame is empty, skipping it!\n"); + continue; + } + + stream.packet = (v2_venc_pack*)malloc( + sizeof(v2_venc_pack) * stat.curPacks); + if (!stream.packet) { + HAL_DANGER("v2_venc", "Memory allocation on channel %d failed!\n", i); + break; + } + stream.count = stat.curPacks; + + if (ret = v2_venc.fnGetStream(i, &stream, 40)) { + HAL_DANGER("v2_venc", "Getting the stream on " + "channel %d failed with %#x!\n", i, ret); + break; + } + + if (v2_vid_cb) { + hal_vidstream outStrm; + hal_vidpack outPack[stream.count]; + outStrm.count = stream.count; + outStrm.seq = stream.sequence; + for (int j = 0; j < stream.count; j++) { + v2_venc_pack *pack = &stream.packet[j]; + outPack[j].data = pack->data; + outPack[j].length = pack->length; + outPack[j].naluCnt = 1; + outPack[j].nalu[0].length = pack->length; + outPack[j].nalu[0].offset = pack->offset; + switch (v2_state[i].payload) { + case HAL_VIDCODEC_H264: + outPack[j].nalu[0].type = pack->naluType.h264Nalu; + break; + case HAL_VIDCODEC_H265: + outPack[j].nalu[0].type = pack->naluType.h265Nalu; + break; + } + outPack[j].offset = pack->offset; + outPack[j].timestamp = pack->timestamp; + } + outStrm.pack = outPack; + (*v2_vid_cb)(i, &outStrm); + } + + if (ret = v2_venc.fnFreeStream(i, &stream)) { + HAL_WARNING("v2_venc", "Releasing the stream on " + "channel %d failed with %#x!\n", i, ret); + } + free(stream.packet); + stream.packet = NULL; + } + } + } + } + HAL_INFO("v2_venc", "Shutting down encoding thread...\n"); +} + +void v2_system_deinit(void) +{ + v2_sys.fnExit(); + v2_vb.fnExit(); + + v2_sensor_deinit(); +} + +int v2_system_init(char *snrConfig) +{ + int ret; + + { + v2_sys_ver version; + v2_sys.fnGetVersion(&version); + printf("App built with headers v%s\n", V2_SYS_API); + printf("%s\n", version.version); + } + + if (v2_parse_sensor_config(snrConfig, &v2_config) != CONFIG_OK) + HAL_ERROR("v2_sys", "Can't load sensor config\n"); + + if (ret = v2_sensor_init(v2_config.dll_file, v2_config.sensor_type)) + return ret; + + v2_sys.fnExit(); + v2_vb.fnExit(); + + { + int alignWidth = 16; + v2_vb_pool pool; + + memset(&pool, 0, sizeof(pool)); + + pool.count = 1; + pool.comm[0].blockSize = v2_buffer_calculate_venc( + v2_config.vichn.capt.width ? + v2_config.vichn.capt.width : v2_config.videv.rect.width, + v2_config.vichn.capt.height ? + v2_config.vichn.capt.height : v2_config.videv.rect.height, + V2_PIXFMT_YUV420SP, alignWidth); + pool.comm[0].blockCnt = 4; + + if (ret = v2_vb.fnConfigPool(&pool)) + return ret; + v2_vb_supl supl = V2_VB_JPEG_MASK; + if (ret = v2_vb.fnConfigSupplement(&supl)) + return ret; + if (ret = v2_vb.fnInit()) + return ret; + + if (ret = v2_sys.fnSetAlignment(&alignWidth)) + return ret; + } + if (ret = v2_sys.fnInit()) + return ret; + + return EXIT_SUCCESS; +} + +#endif \ No newline at end of file diff --git a/src/hal/hisi/v2_hal.h b/src/hal/hisi/v2_hal.h new file mode 100644 index 0000000..4bc8e89 --- /dev/null +++ b/src/hal/hisi/v2_hal.h @@ -0,0 +1,62 @@ +#pragma once + +#include "v2_common.h" +#include "v2_aud.h" +#include "v2_config.h" +#include "v2_isp.h" +#include "v2_rgn.h" +#include "v2_snr.h" +#include "v2_sys.h" +#include "v2_vb.h" +#include "v2_venc.h" +#include "v2_vi.h" +#include "v2_vpss.h" + +#include +#include +#include +#include + +extern char keepRunning; + +extern hal_chnstate v2_state[V2_VENC_CHN_NUM]; +extern int (*v2_aud_cb)(hal_audframe*); +extern int (*v2_vid_cb)(char, hal_vidstream*); + +void v2_hal_deinit(void); +int v2_hal_init(void); + +void v2_audio_deinit(void); +int v2_audio_init(int samplerate); +void *v2_audio_thread(void); + +int v2_channel_bind(char index); +int v2_channel_create(char index, short width, short height, char mirror, char flip, char framerate); +int v2_channel_grayscale(char enable); +int v2_channel_unbind(char index); + +void *v2_image_thread(void); + +int v2_pipeline_create(void); +void v2_pipeline_destroy(void); + +int v2_region_create(char handle, hal_rect rect, short opacity); +void v2_region_destroy(char handle); +int v2_region_setbitmap(int handle, hal_bitmap *bitmap); + +void v2_sensor_deconfig(void); +int v2_sensor_config(void); +void v2_sensor_deinit(void); +int v2_sensor_init(char *name, char *obj); + +int v2_video_create(char index, hal_vidconfig *config); +int v2_video_destroy(char index); +int v2_video_destroy_all(void); +void v2_video_request_idr(char index); +int v2_video_snapshot_grab(char index, hal_jpegdata *jpeg); +void *v2_video_thread(void); + +int v2_system_calculate_block(short width, short height, v2_common_pixfmt pixFmt, + unsigned int alignWidth); +void v2_system_deinit(void); +int v2_system_init(char *snrConfig); \ No newline at end of file diff --git a/src/hal/hisi/v2_isp.h b/src/hal/hisi/v2_isp.h new file mode 100644 index 0000000..a9fff79 --- /dev/null +++ b/src/hal/hisi/v2_isp.h @@ -0,0 +1,103 @@ +#pragma once + +#include "v2_common.h" + +extern int (*fnISP_AlgRegisterDehaze)(int); +extern int (*fnISP_AlgRegisterDrc)(int); + +typedef struct { + int id; + char libName[20]; +} v2_isp_alg; + +typedef struct { + v2_common_rect capt; + float framerate; + v2_common_bayer bayer; +} v2_isp_dev; + +typedef struct { + void *handle, *handleAwb, *handleAe, *handleDefog, *handleIrAuto; + + int (*fnExit)(int device); + int (*fnInit)(int device); + int (*fnMemInit)(int device); + int (*fnRun)(int device); + + int (*fnSetDeviceConfig)(int device, v2_isp_dev *config); + int (*fnSetWDRMode)(int device, v2_common_wdr *mode); + + int (*fnRegisterAE)(int device, v2_isp_alg *library); + int (*fnRegisterAWB)(int device, v2_isp_alg *library); + int (*fnUnregisterAE)(int device, v2_isp_alg *library); + int (*fnUnregisterAWB)(int device, v2_isp_alg *library); +} v2_isp_impl; + +static int v2_isp_load(v2_isp_impl *isp_lib) { + if (!(isp_lib->handle = dlopen("libisp.so", RTLD_LAZY | RTLD_GLOBAL)) || + !(isp_lib->handleAe = dlopen("lib_hiae.so", RTLD_LAZY | RTLD_GLOBAL)) || + !(isp_lib->handleAwb = dlopen("lib_hiawb.so", RTLD_LAZY | RTLD_GLOBAL)) || + !(isp_lib->handleDefog = dlopen("lib_hidefog.so", RTLD_LAZY | RTLD_GLOBAL)) || + !(isp_lib->handleIrAuto = dlopen("lib_hiirauto.so", RTLD_LAZY | RTLD_GLOBAL))) + HAL_ERROR("v2_isp", "Failed to load library!\nError: %s\n", dlerror()); + + if (!(fnISP_AlgRegisterDehaze = (int(*)(int)) + hal_symbol_load("v2_isp", isp_lib->handleDefog, "ISP_AlgRegisterDehaze"))) + return EXIT_FAILURE; + + if (!(fnISP_AlgRegisterDrc = (int(*)(int)) + hal_symbol_load("v2_isp", isp_lib->handle, "ISP_AlgRegisterDrc"))) + return EXIT_FAILURE; + + if (!(isp_lib->fnExit = (int(*)(int device)) + hal_symbol_load("v2_isp", isp_lib->handle, "HI_MPI_ISP_Exit"))) + return EXIT_FAILURE; + + if (!(isp_lib->fnInit = (int(*)(int device)) + hal_symbol_load("v2_isp", isp_lib->handle, "HI_MPI_ISP_Init"))) + return EXIT_FAILURE; + + if (!(isp_lib->fnMemInit = (int(*)(int device)) + hal_symbol_load("v2_isp", isp_lib->handle, "HI_MPI_ISP_MemInit"))) + return EXIT_FAILURE; + + if (!(isp_lib->fnRun = (int(*)(int device)) + hal_symbol_load("v2_isp", isp_lib->handle, "HI_MPI_ISP_Run"))) + return EXIT_FAILURE; + + if (!(isp_lib->fnSetDeviceConfig = (int(*)(int device, v2_isp_dev *config)) + hal_symbol_load("v2_isp", isp_lib->handle, "HI_MPI_ISP_SetPubAttr"))) + return EXIT_FAILURE; + + if (!(isp_lib->fnSetWDRMode = (int(*)(int device, v2_common_wdr *mode)) + hal_symbol_load("v2_isp", isp_lib->handle, "HI_MPI_ISP_SetWDRMode"))) + return EXIT_FAILURE; + + if (!(isp_lib->fnRegisterAE = (int(*)(int device, v2_isp_alg *library)) + hal_symbol_load("v2_isp", isp_lib->handleAe, "HI_MPI_AE_Register"))) + return EXIT_FAILURE; + + if (!(isp_lib->fnRegisterAWB = (int(*)(int device, v2_isp_alg *library)) + hal_symbol_load("v2_isp", isp_lib->handleAwb, "HI_MPI_AWB_Register"))) + return EXIT_FAILURE; + + if (!(isp_lib->fnUnregisterAE = (int(*)(int device, v2_isp_alg *library)) + hal_symbol_load("v2_isp", isp_lib->handleAe, "HI_MPI_AE_UnRegister"))) + return EXIT_FAILURE; + + if (!(isp_lib->fnUnregisterAWB = (int(*)(int device, v2_isp_alg *library)) + hal_symbol_load("v2_isp", isp_lib->handleAwb, "HI_MPI_AWB_UnRegister"))) + return EXIT_FAILURE; + + return EXIT_SUCCESS; +} + +static void v2_isp_unload(v2_isp_impl *isp_lib) { + if (isp_lib->handleAe) dlclose(isp_lib->handleAe); + isp_lib->handleAe = NULL; + if (isp_lib->handleAwb) dlclose(isp_lib->handleAwb); + isp_lib->handleAwb = NULL; + if (isp_lib->handle) dlclose(isp_lib->handle); + isp_lib->handle = NULL; + memset(isp_lib, 0, sizeof(*isp_lib)); +} diff --git a/src/hal/hisi/v2_rgn.h b/src/hal/hisi/v2_rgn.h new file mode 100644 index 0000000..a61a7c0 --- /dev/null +++ b/src/hal/hisi/v2_rgn.h @@ -0,0 +1,162 @@ +#pragma once + +#include "v2_common.h" +#include "v2_sys.h" + +typedef enum { + V2_RGN_TYPE_OVERLAY, + V2_RGN_TYPE_COVER, + V2_RGN_TYPE_COVEREX, + V2_RGN_TYPE_OVERLAYEX, + V2_RGN_TYPE_END +} v2_rgn_type; + +typedef struct { + v2_common_pixfmt pixFmt; + v2_common_dim size; + void *data; +} v2_rgn_bmp; + +typedef struct { + v2_common_dim invColArea; + unsigned int lumThresh; + unsigned int highThanOn; + int invColOn; +} v2_rgn_inv; + +typedef struct { + v2_common_pnt point; + unsigned int fgAlpha; + unsigned int bgAlpha; + // Accepts values from 0-7 + unsigned int layer; + int adsQualOn; + int quality; + int qualOff; + v2_rgn_inv invert; +} v2_rgn_ovlc; + +typedef struct { + int solidOn; + unsigned int lineThick; + v2_common_pnt point[4]; +} v2_rgn_qdr; + +typedef struct { + int quadRangleOn; + union { + v2_common_rect rect; + v2_rgn_qdr quadR; + }; + unsigned int color; + unsigned int layer; +} v2_rgn_covc; + +typedef struct { + v2_common_pnt point; + unsigned int fgAlpha; + unsigned int bgAlpha; + // Accepts values from 0-15 + unsigned int layer; +} v2_rgn_ovlxc; + +typedef struct { + int quadRangleOn; + union { + v2_common_rect rect; + v2_rgn_qdr quadR; + }; + unsigned int color; + unsigned int layer; +} v2_rgn_covxc; + +typedef struct { + int show; + v2_rgn_type type; + union { + v2_rgn_ovlc overlay; + v2_rgn_covc cover; + v2_rgn_covxc coverex; + v2_rgn_ovlxc overlayex; + }; +} v2_rgn_chn; + +typedef struct { + v2_common_pixfmt pixFmt; + unsigned int bgColor; + v2_common_dim size; + unsigned int canvas; +} v2_rgn_ovl; + +typedef struct { + v2_rgn_type type; + union { + v2_rgn_ovl overlay; + v2_rgn_ovl overlayex; + }; +} v2_rgn_cnf; + +typedef struct { + void *handle; + + int (*fnCreateRegion)(unsigned int handle, v2_rgn_cnf *config); + int (*fnDestroyRegion)(unsigned int handle); + int (*fnGetRegionConfig)(unsigned int handle, v2_rgn_cnf *config); + int (*fnSetRegionConfig)(unsigned int handle, v2_rgn_cnf *config); + + int (*fnAttachChannel)(unsigned int handle, v2_sys_bind *dest, v2_rgn_chn *config); + int (*fnDetachChannel)(unsigned int handle, v2_sys_bind *dest); + int (*fnGetChannelConfig)(unsigned int handle, v2_sys_bind *dest, v2_rgn_chn *config); + int (*fnSetChannelConfig)(unsigned int handle, v2_sys_bind *dest, v2_rgn_chn *config); + + int (*fnSetBitmap)(unsigned int handle, v2_rgn_bmp *bitmap); +} v2_rgn_impl; + +static int v2_rgn_load(v2_rgn_impl *rgn_lib) { + if (!(rgn_lib->handle = dlopen("libmpi.so", RTLD_LAZY | RTLD_GLOBAL))) + HAL_ERROR("v2_rgn", "Failed to load library!\nError: %s\n", dlerror()); + + if (!(rgn_lib->fnCreateRegion = (int(*)(unsigned int handle, v2_rgn_cnf *config)) + hal_symbol_load("v2_rgn", rgn_lib->handle, "HI_MPI_RGN_Create"))) + return EXIT_FAILURE; + + if (!(rgn_lib->fnDestroyRegion = (int(*)(unsigned int handle)) + hal_symbol_load("v2_rgn", rgn_lib->handle, "HI_MPI_RGN_Destroy"))) + return EXIT_FAILURE; + + if (!(rgn_lib->fnGetRegionConfig = (int(*)(unsigned int handle, v2_rgn_cnf *config)) + hal_symbol_load("v2_rgn", rgn_lib->handle, "HI_MPI_RGN_GetAttr"))) + return EXIT_FAILURE; + + if (!(rgn_lib->fnSetRegionConfig = (int(*)(unsigned int handle, v2_rgn_cnf *config)) + hal_symbol_load("v2_rgn", rgn_lib->handle, "HI_MPI_RGN_SetAttr"))) + return EXIT_FAILURE; + + if (!(rgn_lib->fnAttachChannel = (int(*)(unsigned int handle, v2_sys_bind *dest, v2_rgn_chn *config)) + hal_symbol_load("v2_rgn", rgn_lib->handle, "HI_MPI_RGN_AttachToChn"))) + return EXIT_FAILURE; + + if (!(rgn_lib->fnDetachChannel = (int(*)(unsigned int handle, v2_sys_bind *dest)) + hal_symbol_load("v2_rgn", rgn_lib->handle, "HI_MPI_RGN_DetachFromChn"))) + return EXIT_FAILURE; + + if (!(rgn_lib->fnGetChannelConfig = (int(*)(unsigned int handle, v2_sys_bind *dest, v2_rgn_chn *config)) + hal_symbol_load("v2_rgn", rgn_lib->handle, "HI_MPI_RGN_GetDisplayAttr"))) + return EXIT_FAILURE; + + if (!(rgn_lib->fnSetChannelConfig = (int(*)(unsigned int handle, v2_sys_bind *dest, v2_rgn_chn *config)) + hal_symbol_load("v2_rgn", rgn_lib->handle, "HI_MPI_RGN_SetDisplayAttr"))) + return EXIT_FAILURE; + + if (!(rgn_lib->fnSetBitmap = (int(*)(unsigned int handle, v2_rgn_bmp *bitmap)) + hal_symbol_load("v2_rgn", rgn_lib->handle, "HI_MPI_RGN_SetBitMap"))) + return EXIT_FAILURE; + + return EXIT_SUCCESS; +} + +static void v2_rgn_unload(v2_rgn_impl *rgn_lib) { + if (rgn_lib->handle) dlclose(rgn_lib->handle); + rgn_lib->handle = NULL; + memset(rgn_lib, 0, sizeof(*rgn_lib)); +} \ No newline at end of file diff --git a/src/hal/hisi/v2_snr.h b/src/hal/hisi/v2_snr.h new file mode 100644 index 0000000..ad96bc0 --- /dev/null +++ b/src/hal/hisi/v2_snr.h @@ -0,0 +1,84 @@ +#pragma once + +#include "v2_common.h" + +#include +#include + +#define V2_SNR_IOC_MAGIC 'm' +#define V2_SNR_LANE_NUM 8 +#define V2_SNR_WDR_VC_NUM 4 + +enum { + V2_SNR_CMD_CONF_DEV = 1, + V2_SNR_CMD_CONF_EDGE, + V2_SNR_CMD_CONF_MSB, + V2_SNR_CMD_CONF_CMV, + V2_SNR_CMD_RST_SENS, + V2_SNR_CMD_UNRST_SENS, + V2_SNR_CMD_RST_MIPI, + V2_SNR_CMD_UNRST_MIPI, + V2_SNR_CMD_CONF_CROP +}; + +typedef enum { + V2_SNR_INPUT_MIPI, + V2_SNR_INPUT_SUBLVDS, + V2_SNR_INPUT_LVDS, + V2_SNR_INPUT_HISPI, + V2_SNR_INPUT_CMOS_18V, + V2_SNR_INPUT_CMOS_33V, + V2_SNR_INPUT_BT1120, + V2_SNR_INPUT_BYPASS, + V2_SNR_INPUT_END +} v2_snr_input; + +typedef enum { + V2_SNR_LWDR_NONE, + V2_SNR_LWDR_2F, + V2_SNR_LWDR_3F, + V2_SNR_LWDR_4F, + V2_SNR_LWDR_DOL2F, + V2_SNR_LWDR_DOL3F, + V2_SNR_LWDR_DOL4F, + V2_SNR_LWDR_END +} v2_snr_lwdr; + +typedef struct { + v2_common_dim dest; + v2_snr_lwdr wdr; + int syncSavOn; + v2_common_prec prec; + int dataBeOn; + int syncBeOn; + // Value -1 signifies a lane is disabled + short laneId[V2_SNR_LANE_NUM]; + /* Each lane has two virtual channel, each has four params + If syncSavOn is false: SOF, EOF, SOL, EOL + If syncSavOn is true: invalid sav, invalid eav, valid sav, valid eav */ + unsigned short syncCode[V2_SNR_LANE_NUM * V2_SNR_WDR_VC_NUM * 4]; +} v2_snr_lvds; + +typedef struct { + v2_common_prec prec; + // Value -1 signifies a lane is disabled + short laneId[V2_SNR_LANE_NUM]; +} v2_snr_mipi; + +typedef struct { + unsigned int device; + v2_snr_input input; + union { + v2_snr_mipi mipi; + v2_snr_lvds lvds; + }; +} v2_snr_dev; + +typedef struct { + void *handle; + + int (*fnRegisterCallback)(void); + int (*fnUnRegisterCallback)(void); +} v2_snr_drv_impl; + +static const char v2_snr_endp[] = {"/dev/hi_mipi"}; \ No newline at end of file diff --git a/src/hal/hisi/v2_sys.h b/src/hal/hisi/v2_sys.h new file mode 100644 index 0000000..c5d3f51 --- /dev/null +++ b/src/hal/hisi/v2_sys.h @@ -0,0 +1,141 @@ +#pragma once + +#include "v2_common.h" + +#define V2_SYS_API "1.0" + +typedef enum { + V2_SYS_MOD_CMPI, + V2_SYS_MOD_VB, + V2_SYS_MOD_SYS, + V2_SYS_MOD_RGN, + V2_SYS_MOD_CHNL, + V2_SYS_MOD_VDEC, + V2_SYS_MOD_GROUP, + V2_SYS_MOD_VPSS, + V2_SYS_MOD_VENC, + V2_SYS_MOD_VDA, + V2_SYS_MOD_H264E, + V2_SYS_MOD_JPEGE, + V2_SYS_MOD_MPEG4E, + V2_SYS_MOD_H264D, + V2_SYS_MOD_JPEGD, + V2_SYS_MOD_VOU, + V2_SYS_MOD_VIU, + V2_SYS_MOD_DSU, + V2_SYS_MOD_VALG, + V2_SYS_MOD_RC, + V2_SYS_MOD_AIO, + V2_SYS_MOD_AI, + V2_SYS_MOD_AO, + V2_SYS_MOD_AENC, + V2_SYS_MOD_ADEC, + V2_SYS_MOD_AVENC, + V2_SYS_MOD_PCIV, + V2_SYS_MOD_PCIVFMW, + V2_SYS_MOD_ISP, + V2_SYS_MOD_IVE, + V2_SYS_MOD_DCCM = 31, + V2_SYS_MOD_DCCS, + V2_SYS_MOD_PROC, + V2_SYS_MOD_LOG, + V2_SYS_MOD_MST_LOG, + V2_SYS_MOD_VD, + V2_SYS_MOD_VCMP = 38, + V2_SYS_MOD_FB, + V2_SYS_MOD_HDMI, + V2_SYS_MOD_VOIE, + V2_SYS_MOD_TDE, + V2_SYS_MOD_USR, + V2_SYS_MOD_VEDU, + V2_SYS_MOD_VGS, + V2_SYS_MOD_H265E, + V2_SYS_MOD_FD, + V2_SYS_MOD_ODT, + V2_SYS_MOD_VQA, + V2_SYS_MOD_LPR, + V2_SYS_MOD_FISHEYE, + V2_SYS_MOD_PHOTO, + V2_SYS_MOD_EXTAO, + V2_SYS_MOD_END +} v2_sys_mod; + +typedef struct { + v2_sys_mod module; + int device; + int channel; +} v2_sys_bind; + +typedef struct { + char version[64]; +} v2_sys_ver; + +typedef struct { + void *handle, *handleVoiceEngine, *handleDnvqe, *handleUpvqe; + + int (*fnExit)(void); + int (*fnGetChipId)(unsigned int *chip); + int (*fnGetVersion)(v2_sys_ver *version); + + int (*fnInit)(void); + int (*fnSetAlignment)(unsigned int *width); + + int (*fnBind)(v2_sys_bind *source, v2_sys_bind *dest); + int (*fnUnbind)(v2_sys_bind *source, v2_sys_bind *dest); + + int (*fnGetViVpssMode)(unsigned int *onlineOn); +} v2_sys_impl; + +static int v2_sys_load(v2_sys_impl *sys_lib) { + if (!(sys_lib->handleUpvqe = dlopen("libupvqe.so", RTLD_LAZY | RTLD_GLOBAL)) || + !(sys_lib->handleDnvqe = dlopen("libdnvqe.so", RTLD_LAZY | RTLD_GLOBAL)) || + !(sys_lib->handleVoiceEngine = dlopen("libVoiceEngine.so", RTLD_LAZY | RTLD_GLOBAL)) || + !(sys_lib->handle = dlopen("libmpi.so", RTLD_LAZY | RTLD_GLOBAL))) + HAL_ERROR("v2_sys", "Failed to load library!\nError: %s\n", dlerror()); + + if (!(sys_lib->fnExit = (int(*)(void)) + hal_symbol_load("v2_sys", sys_lib->handle, "HI_MPI_SYS_Exit"))) + return EXIT_FAILURE; + + if (!(sys_lib->fnGetChipId = (int(*)(unsigned int *chip)) + hal_symbol_load("v2_sys", sys_lib->handle, "HI_MPI_SYS_GetChipId"))) + return EXIT_FAILURE; + + if (!(sys_lib->fnGetVersion = (int(*)(v2_sys_ver *version)) + hal_symbol_load("v2_sys", sys_lib->handle, "HI_MPI_SYS_GetVersion"))) + return EXIT_FAILURE; + + if (!(sys_lib->fnInit = (int(*)(void)) + hal_symbol_load("v2_sys", sys_lib->handle, "HI_MPI_SYS_Init"))) + return EXIT_FAILURE; + + if (!(sys_lib->fnSetAlignment = (int(*)(unsigned int *width)) + hal_symbol_load("v2_sys", sys_lib->handle, "HI_MPI_SYS_SetConf"))) + return EXIT_FAILURE; + + if (!(sys_lib->fnBind = (int(*)(v2_sys_bind *source, v2_sys_bind *dest)) + hal_symbol_load("v2_sys", sys_lib->handle, "HI_MPI_SYS_Bind"))) + return EXIT_FAILURE; + + if (!(sys_lib->fnUnbind = (int(*)(v2_sys_bind *source, v2_sys_bind *dest)) + hal_symbol_load("v2_sys", sys_lib->handle, "HI_MPI_SYS_UnBind"))) + return EXIT_FAILURE; + + if (!(sys_lib->fnGetViVpssMode = (int(*)(unsigned int *onlineOn)) + hal_symbol_load("v2_sys", sys_lib->handle, "HI_MPI_SYS_GetViVpssMode"))) + return EXIT_FAILURE; + + return EXIT_SUCCESS; +} + +static void v2_sys_unload(v2_sys_impl *sys_lib) { + if (sys_lib->handleUpvqe) dlclose(sys_lib->handleUpvqe); + sys_lib->handleUpvqe = NULL; + if (sys_lib->handleDnvqe) dlclose(sys_lib->handleDnvqe); + sys_lib->handleDnvqe = NULL; + if (sys_lib->handleVoiceEngine) dlclose(sys_lib->handleVoiceEngine); + sys_lib->handleVoiceEngine = NULL; + if (sys_lib->handle) dlclose(sys_lib->handle); + sys_lib->handle = NULL; + memset(sys_lib, 0, sizeof(*sys_lib)); +} \ No newline at end of file diff --git a/src/hal/hisi/v2_vb.h b/src/hal/hisi/v2_vb.h new file mode 100644 index 0000000..40d740a --- /dev/null +++ b/src/hal/hisi/v2_vb.h @@ -0,0 +1,111 @@ +#pragma once + +#include "v2_common.h" + +typedef enum { + V2_VB_JPEG_MASK = 0x1 +} v2_vb_supl; + +typedef struct { + unsigned int count; + struct { + unsigned int blockSize; + unsigned int blockCnt; + char heapName[16]; + } comm[16]; +} v2_vb_pool; + +typedef struct { + void *handle; + + int (*fnConfigPool)(v2_vb_pool *config); + int (*fnConfigSupplement)(v2_vb_supl *value); + int (*fnExit)(void); + int (*fnInit)(void); +} v2_vb_impl; + +static int v2_vb_load(v2_vb_impl *vb_lib) { + if (!(vb_lib->handle = dlopen("libmpi.so", RTLD_LAZY | RTLD_GLOBAL))) + HAL_ERROR("v2_vb", "Failed to load library!\nError: %s\n", dlerror()); + + if (!(vb_lib->fnConfigPool = (int(*)(v2_vb_pool *config)) + hal_symbol_load("v2_vb", vb_lib->handle, "HI_MPI_VB_SetConf"))) + return EXIT_FAILURE; + + if (!(vb_lib->fnConfigSupplement = (int(*)(v2_vb_supl *value)) + hal_symbol_load("v2_vb", vb_lib->handle, "HI_MPI_VB_SetSupplementConf"))) + return EXIT_FAILURE; + + if (!(vb_lib->fnExit = (int(*)(void)) + hal_symbol_load("v2_vb", vb_lib->handle, "HI_MPI_VB_Exit"))) + return EXIT_FAILURE; + + if (!(vb_lib->fnInit = (int(*)(void)) + hal_symbol_load("v2_vb", vb_lib->handle, "HI_MPI_VB_Init"))) + return EXIT_FAILURE; + + return EXIT_SUCCESS; +} + +static void v2_vb_unload(v2_vb_impl *vb_lib) { + if (vb_lib->handle) dlclose(vb_lib->handle); + vb_lib->handle = NULL; + memset(vb_lib, 0, sizeof(*vb_lib)); +} + +inline static unsigned int v2_buffer_calculate_vi( + unsigned int width, unsigned int height, v2_common_pixfmt pixFmt, + v2_common_compr compr, unsigned int alignWidth) +{ + unsigned int bitWidth; + unsigned int size = 0, stride = 0; + unsigned int cmpRatioLine = 1600, cmpRatioFrame = 2000; + + if (!alignWidth) + alignWidth = 16; + else if (alignWidth > 64) + alignWidth = 64; + else + alignWidth = ALIGN_UP(alignWidth, 16); + + switch (pixFmt) { + case V2_PIXFMT_RGB_BAYER_8BPP: bitWidth = 8; break; + case V2_PIXFMT_RGB_BAYER_10BPP: bitWidth = 10; break; + case V2_PIXFMT_RGB_BAYER_12BPP: bitWidth = 12; break; + case V2_PIXFMT_RGB_BAYER_14BPP: bitWidth = 14; break; + case V2_PIXFMT_RGB_BAYER_16BPP: bitWidth = 16; break; + default: bitWidth = 0; break; + } + + if (compr == V2_COMPR_NONE) { + stride = ALIGN_UP(ALIGN_UP(width * bitWidth, 8) / 8, + alignWidth); + size = stride * height; + } else if (compr == V2_COMPR_LINE) { + unsigned int temp = ALIGN_UP( + (16 + width * bitWidth * 1000UL / + cmpRatioLine + 8192 + 127) / 128, 2); + stride = ALIGN_UP(temp * 16, alignWidth); + size = stride * height; + } else if (compr == V2_COMPR_FRAME) { + size = ALIGN_UP(height * width * bitWidth * 1000UL / + (cmpRatioFrame * 8), alignWidth); + } + + return size; +} + +inline static unsigned int v2_buffer_calculate_venc(short width, short height, v2_common_pixfmt pixFmt, + unsigned int alignWidth) +{ + unsigned int bufSize = CEILING_2_POWER(width, alignWidth) * + CEILING_2_POWER(height, alignWidth) * + (pixFmt == V2_PIXFMT_YUV422SP ? 2 : 1.5); + unsigned int headSize = 16 * height; + if (pixFmt == V2_PIXFMT_YUV422SP || pixFmt >= V2_PIXFMT_RGB_BAYER_8BPP) + headSize *= 2; + else if (pixFmt == V2_PIXFMT_YUV420SP) + headSize *= 3; + headSize >>= 1; + return bufSize + headSize; +} \ No newline at end of file diff --git a/src/hal/hisi/v2_venc.h b/src/hal/hisi/v2_venc.h new file mode 100644 index 0000000..b38e95b --- /dev/null +++ b/src/hal/hisi/v2_venc.h @@ -0,0 +1,395 @@ +#pragma once + +#include "v2_common.h" + +#define V2_VENC_CHN_NUM 16 + +typedef enum { + V2_VENC_CODEC_JPEG = 26, + V2_VENC_CODEC_H264 = 96, + V2_VENC_CODEC_H265 = 265, + V2_VENC_CODEC_MJPG = 1002, + V2_VENC_CODEC_END +} v2_venc_codec; + +typedef enum { + V2_VENC_GOPMODE_NORMALP, + V2_VENC_GOPMODE_DUALP, + V2_VENC_GOPMODE_SMARTP, + V2_VENC_GOPMODE_BIPREDB, + V2_VENC_GOPMODE_LOWDELAYB, + V2_VENC_GOPMODE_END +} v2_venc_gopmode; + +typedef enum { + V2_VENC_NALU_H264_BSLICE, + V2_VENC_NALU_H264_PSLICE, + V2_VENC_NALU_H264_ISLICE, + V2_VENC_NALU_H264_IDRSLICE = 5, + V2_VENC_NALU_H264_SEI, + V2_VENC_NALU_H264_SPS, + V2_VENC_NALU_H264_PPS, + V2_VENC_NALU_H264_END +} v2_venc_nalu_h264; + +typedef enum { + V2_VENC_NALU_H265_BSLICE, + V2_VENC_NALU_H265_PSLICE, + V2_VENC_NALU_H265_ISLICE, + V2_VENC_NALU_H265_IDRSLICE = 19, + V2_VENC_NALU_H265_VPS = 32, + V2_VENC_NALU_H265_SPS, + V2_VENC_NALU_H265_PPS, + V2_VENC_NALU_H265_SEI = 39, + V2_VENC_NALU_H265_END +} v2_venc_nalu_h265; + +typedef enum { + V2_VENC_NALU_MJPG_ECS = 5, + V2_VENC_NALU_MJPG_APP, + V2_VENC_NALU_MJPG_VDO, + V2_VENC_NALU_MJPG_PIC, + V2_VENC_NALU_MJPG_END +} v2_venc_nalu_mjpg; + +typedef enum { + V2_VENC_RATEMODE_H264CBR = 1, + V2_VENC_RATEMODE_H264VBR, + V2_VENC_RATEMODE_H264AVBR, + V2_VENC_RATEMODE_H264ABR, + V2_VENC_RATEMODE_H264QP, + V2_VENC_RATEMODE_MJPGCBR, + V2_VENC_RATEMODE_MJPGVBR, + V2_VENC_RATEMODE_MJPGABR, + V2_VENC_RATEMODE_MJPGQP, + V2_VENC_RATEMODE_H265CBR = 14, + V2_VENC_RATEMODE_H265VBR, + V2_VENC_RATEMODE_H265AVBR, + V2_VENC_RATEMODE_H265QP, + V2_VENC_RATEMODE_END +} v2_venc_ratemode; + +typedef struct { + v2_common_dim maxPic; + unsigned int bufSize; + unsigned int profile; + int byFrame; + v2_common_dim pic; +} v2_venc_attr_h26x; + +typedef struct { + v2_common_dim maxPic; + unsigned int bufSize; + int byFrame; + v2_common_dim pic; +} v2_venc_attr_mjpg; + +typedef struct { + v2_common_dim maxPic; + unsigned int bufSize; + int byFrame; + v2_common_dim pic; + int dcfThumbs; +} v2_venc_attr_jpg; + +typedef struct { + v2_venc_codec codec; + union { + v2_venc_attr_h26x h264; + v2_venc_attr_mjpg mjpg; + v2_venc_attr_jpg jpg; + v2_venc_attr_h26x h265; + }; +} v2_venc_attrib; + +typedef struct { + unsigned int gop; + unsigned int statTime; + unsigned int srcFps; + unsigned int dstFps; + unsigned int bitrate; + unsigned int avgLvl; +} v2_venc_rate_h26xcbr; + +typedef struct { + unsigned int gop; + unsigned int statTime; + unsigned int srcFps; + unsigned int dstFps; + unsigned int maxBitrate; + unsigned int maxQual; + unsigned int minQual; + unsigned int minIQual; +} v2_venc_rate_h26xvbr; + +typedef struct { + unsigned int gop; + unsigned int statTime; + unsigned int srcFps; + unsigned int dstFps; + unsigned int bitrate; +} v2_venc_rate_h26xavbr; + +typedef struct { + unsigned int gop; + unsigned int srcFps; + unsigned int dstFps; + unsigned int interQual; + unsigned int predQual; + unsigned int bipredQual; +} v2_venc_rate_h26xqp; + +typedef struct { + unsigned int gop; + unsigned int statTime; + unsigned int srcFps; + unsigned int dstFps; + unsigned int avgBitrate; + unsigned int maxBitrate; +} v2_venc_rate_h264abr; + +typedef struct { + unsigned int statTime; + unsigned int srcFps; + unsigned int dstFps; + unsigned int bitrate; + unsigned int avgLvl; +} v2_venc_rate_mjpgcbr; + +typedef struct { + unsigned int statTime; + unsigned int srcFps; + unsigned int dstFps; + unsigned int maxBitrate; + unsigned int maxQual; + unsigned int minQual; +} v2_venc_rate_mjpgvbr; + +typedef struct { + unsigned int srcFps; + unsigned int dstFps; + unsigned int quality; +} v2_venc_rate_mjpgqp; +typedef struct { + v2_venc_ratemode mode; + union { + v2_venc_rate_h26xcbr h264Cbr; + v2_venc_rate_h26xvbr h264Vbr; + v2_venc_rate_h26xavbr h264Avbr; + v2_venc_rate_h26xqp h264Qp; + v2_venc_rate_h264abr h264Abr; + v2_venc_rate_mjpgcbr mjpgCbr; + v2_venc_rate_mjpgqp mjpgQp; + v2_venc_rate_mjpgvbr mjpgVbr; + v2_venc_rate_h26xcbr h265Cbr; + v2_venc_rate_h26xvbr h265Vbr; + v2_venc_rate_h26xavbr h265Avbr; + v2_venc_rate_h26xqp h265Qp; + }; + void *extend; +} v2_venc_rate; + +typedef struct { + v2_venc_attrib attrib; + v2_venc_rate rate; +} v2_venc_chn; + +typedef struct { + unsigned int quality; + unsigned char qtLuma[64]; + unsigned char qtChromaBlue[64]; + unsigned char qtChromaRed[64]; + unsigned int mcuPerEcs; +} v2_venc_jpg; + +typedef union { + v2_venc_nalu_h264 h264Nalu; + v2_venc_nalu_mjpg mjpgNalu; + v2_venc_nalu_h265 h265Nalu; +} v2_venc_nalu; + +typedef struct { + v2_venc_nalu packType; + unsigned int offset; + unsigned int length; +} v2_venc_packinfo; + +typedef struct { + unsigned int addr; + unsigned char *data; + unsigned int length; + unsigned long long timestamp; + int endFrame; + v2_venc_nalu naluType; + unsigned int offset; + unsigned int packNum; + v2_venc_packinfo packetInfo[8]; +} v2_venc_pack; + +typedef struct { + unsigned int leftPics; + unsigned int leftBytes; + unsigned int leftFrames; + unsigned int curPacks; + unsigned int leftRecvPics; + unsigned int leftEncPics; +} v2_venc_stat; + +typedef struct { + unsigned int size; + unsigned int pSkip; + unsigned int ipcmMb; + unsigned int iMb16x8; + unsigned int iMb16x16; + unsigned int iMb8x16; + unsigned int iMb8x8; + unsigned int pMb16; + unsigned int pMb8; + unsigned int pMb4; + unsigned int refSliceType; + unsigned int refType; + unsigned int updAttrCnt; + unsigned int startQual; + int pSkipOn; +} v2_venc_strminfo_h264; + +typedef struct { + unsigned int size; + unsigned int iCu64x64; + unsigned int iCu32x32; + unsigned int iCu16x16; + unsigned int iCu8x8; + unsigned int pCu32x32; + unsigned int pCu16x16; + unsigned int pCu8x8; + unsigned int pCu4x4; + unsigned int refType; + unsigned int updAttrCnt; + unsigned int startQual; + int pSkipOn; +} v2_venc_strminfo_h265; + +typedef struct { + unsigned int size; + unsigned int updAttrCnt; + unsigned int quality; +} v2_venc_strminfo_mjpg; + +typedef struct { + v2_venc_pack *packet; + unsigned int count; + unsigned int sequence; + union { + v2_venc_strminfo_h264 h264Info; + v2_venc_strminfo_mjpg mjpgInfo; + v2_venc_strminfo_h265 h265Info; + }; +} v2_venc_strm; + +typedef struct { + void *handle; + + int (*fnCreateChannel)(int channel, v2_venc_chn *config); + int (*fnGetChannelConfig)(int channel, v2_venc_chn *config); + int (*fnDestroyChannel)(int channel); + int (*fnResetChannel)(int channel); + int (*fnSetChannelConfig)(int channel, v2_venc_chn *config); + int (*fnSetColorToGray)(int channel, int *active); + + int (*fnFreeDescriptor)(int channel); + int (*fnGetDescriptor)(int channel); + + int (*fnGetJpegParam)(int channel, v2_venc_jpg *param); + int (*fnSetJpegParam)(int channel, v2_venc_jpg *param); + + int (*fnFreeStream)(int channel, v2_venc_strm *stream); + int (*fnGetStream)(int channel, v2_venc_strm *stream, unsigned int timeout); + + int (*fnQuery)(int channel, v2_venc_stat* stats); + + int (*fnRequestIdr)(int channel, int instant); + int (*fnStartReceiving)(int channel); + int (*fnStartReceivingEx)(int channel, int *count); + int (*fnStopReceiving)(int channel); +} v2_venc_impl; + +static int v2_venc_load(v2_venc_impl *venc_lib) { + if (!(venc_lib->handle = dlopen("libmpi.so", RTLD_LAZY | RTLD_GLOBAL))) + HAL_ERROR("v2_venc", "Failed to load library!\nError: %s\n", dlerror()); + + if (!(venc_lib->fnCreateChannel = (int(*)(int channel, v2_venc_chn *config)) + hal_symbol_load("v2_venc", venc_lib->handle, "HI_MPI_VENC_CreateChn"))) + return EXIT_FAILURE; + + if (!(venc_lib->fnDestroyChannel = (int(*)(int channel)) + hal_symbol_load("v2_venc", venc_lib->handle, "HI_MPI_VENC_DestroyChn"))) + return EXIT_FAILURE; + + if (!(venc_lib->fnGetChannelConfig = (int(*)(int channel, v2_venc_chn *config)) + hal_symbol_load("v2_venc", venc_lib->handle, "HI_MPI_VENC_GetChnAttr"))) + return EXIT_FAILURE; + + if (!(venc_lib->fnResetChannel = (int(*)(int channel)) + hal_symbol_load("v2_venc", venc_lib->handle, "HI_MPI_VENC_ResetChn"))) + return EXIT_FAILURE; + + if (!(venc_lib->fnSetChannelConfig = (int(*)(int channel, v2_venc_chn *config)) + hal_symbol_load("v2_venc", venc_lib->handle, "HI_MPI_VENC_SetChnAttr"))) + return EXIT_FAILURE; + + if (!(venc_lib->fnSetColorToGray = (int(*)(int channel, int *active)) + hal_symbol_load("v2_venc", venc_lib->handle, "HI_MPI_VENC_SetColor2Grey"))) + return EXIT_FAILURE; + + if (!(venc_lib->fnFreeDescriptor = (int(*)(int channel)) + hal_symbol_load("v2_venc", venc_lib->handle, "HI_MPI_VENC_CloseFd"))) + return EXIT_FAILURE; + + if (!(venc_lib->fnGetDescriptor = (int(*)(int channel)) + hal_symbol_load("v2_venc", venc_lib->handle, "HI_MPI_VENC_GetFd"))) + return EXIT_FAILURE; + + if (!(venc_lib->fnGetJpegParam = (int(*)(int channel, v2_venc_jpg *param)) + hal_symbol_load("v2_venc", venc_lib->handle, "HI_MPI_VENC_GetJpegParam"))) + return EXIT_FAILURE; + + if (!(venc_lib->fnSetJpegParam = (int(*)(int channel, v2_venc_jpg *param)) + hal_symbol_load("v2_venc", venc_lib->handle, "HI_MPI_VENC_SetJpegParam"))) + return EXIT_FAILURE; + + if (!(venc_lib->fnFreeStream = (int(*)(int channel, v2_venc_strm *stream)) + hal_symbol_load("v2_venc", venc_lib->handle, "HI_MPI_VENC_ReleaseStream"))) + return EXIT_FAILURE; + + if (!(venc_lib->fnGetStream = (int(*)(int channel, v2_venc_strm *stream, unsigned int timeout)) + hal_symbol_load("v2_venc", venc_lib->handle, "HI_MPI_VENC_GetStream"))) + return EXIT_FAILURE; + + if (!(venc_lib->fnQuery = (int(*)(int channel, v2_venc_stat *stats)) + hal_symbol_load("v2_venc", venc_lib->handle, "HI_MPI_VENC_Query"))) + return EXIT_FAILURE; + + if (!(venc_lib->fnRequestIdr = (int(*)(int channel, int instant)) + hal_symbol_load("v2_venc", venc_lib->handle, "HI_MPI_VENC_RequestIDR"))) + return EXIT_FAILURE; + + if (!(venc_lib->fnStartReceiving = (int(*)(int channel)) + hal_symbol_load("v2_venc", venc_lib->handle, "HI_MPI_VENC_StartRecvPic"))) + return EXIT_FAILURE; + + if (!(venc_lib->fnStartReceivingEx = (int(*)(int channel, int *count)) + hal_symbol_load("v2_venc", venc_lib->handle, "HI_MPI_VENC_StartRecvPicEx"))) + return EXIT_FAILURE; + + if (!(venc_lib->fnStopReceiving = (int(*)(int channel)) + hal_symbol_load("v2_venc", venc_lib->handle, "HI_MPI_VENC_StopRecvPic"))) + return EXIT_FAILURE; + + return EXIT_SUCCESS; +} + +static void v2_venc_unload(v2_venc_impl *venc_lib) { + if (venc_lib->handle) dlclose(venc_lib->handle); + venc_lib->handle = NULL; + memset(venc_lib, 0, sizeof(*venc_lib)); +} \ No newline at end of file diff --git a/src/hal/hisi/v2_vi.h b/src/hal/hisi/v2_vi.h new file mode 100644 index 0000000..951e347 --- /dev/null +++ b/src/hal/hisi/v2_vi.h @@ -0,0 +1,132 @@ +#pragma once + +#include "v2_common.h" + +typedef enum { + V2_VI_INTF_BT656, + V2_VI_INTF_BT601, + V2_VI_INTF_DIGITAL_CAMERA, + V2_VI_INTF_BT1120_STANDARD, + V2_VI_INTF_BT1120_INTERLEAVED, + V2_VI_INTF_MIPI, + V2_VI_INTF_LVDS, + V2_VI_INTF_HISPI, + V2_VI_INTF_END +} v2_vi_intf; + +typedef enum { + V2_VI_SEQ_VUVU, + V2_VI_SEQ_UVUV, + V2_VI_SEQ_UYVY, + V2_VI_SEQ_VYUY, + V2_VI_SEQ_YUYV, + V2_VI_SEQ_YVYU, + V2_VI_SEQ_END +} v2_vi_seq; + +typedef enum { + V2_VI_WORK_1MULTIPLEX, + V2_VI_WORK_2MULTIPLEX, + V2_VI_WORK_4MULTIPLEX +} v2_vi_work; + +typedef struct { + v2_common_rect capt; + v2_common_dim dest; + // Accepts values from 0-2 (top, bottom, both) + int field; + v2_common_pixfmt pixFmt; + v2_common_compr compress; + int mirror; + int flip; + int srcFps; + int dstFps; +} v2_vi_chn; + +typedef struct { + unsigned int hsyncFront; + unsigned int hsyncWidth; + unsigned int hsyncBack; + unsigned int vsyncFront; + unsigned int vsyncWidth; + unsigned int vsyncBack; + // Next three are valid on interlace mode + // and define even-frame timings + unsigned int vsyncIntrlFront; + unsigned int vsyncIntrlWidth; + unsigned int vsyncIntrlBack; +} v2_vi_timing; + +typedef struct { + int vsyncPulse; + int vsyncInv; + int hsyncPulse; + int hsyncInv; + int vsyncValid; + int vsyncValidInv; + v2_vi_timing timing; +} v2_vi_sync; + +typedef struct { + v2_vi_intf intf; + v2_vi_work work; + unsigned int cmpntMask[2]; + int progressiveOn; + int adChn[4]; + v2_vi_seq seq; + v2_vi_sync sync; + // Accepts values from 0-2 (bypass, isp, raw) + int dataPath; + int rgbModeOn; + int dataRevOn; + v2_common_rect rect; +} v2_vi_dev; + +typedef struct { + void *handle; + + int (*fnDisableDevice)(int device); + int (*fnEnableDevice)(int device); + int (*fnSetDeviceConfig)(int device, v2_vi_dev *config); + + int (*fnDisableChannel)(int channel); + int (*fnEnableChannel)(int channel); + int (*fnSetChannelConfig)(int channel, v2_vi_chn *config); +} v2_vi_impl; + +static int v2_vi_load(v2_vi_impl *vi_lib) { + if (!(vi_lib->handle = dlopen("libmpi.so", RTLD_LAZY | RTLD_GLOBAL))) + HAL_ERROR("v2_vi", "Failed to load library!\nError: %s\n", dlerror()); + + if (!(vi_lib->fnDisableDevice = (int(*)(int device)) + hal_symbol_load("v2_vi", vi_lib->handle, "HI_MPI_VI_DisableDev"))) + return EXIT_FAILURE; + + if (!(vi_lib->fnEnableDevice = (int(*)(int device)) + hal_symbol_load("v2_vi", vi_lib->handle, "HI_MPI_VI_EnableDev"))) + return EXIT_FAILURE; + + if (!(vi_lib->fnSetDeviceConfig = (int(*)(int device, v2_vi_dev *config)) + hal_symbol_load("v2_vi", vi_lib->handle, "HI_MPI_VI_SetDevAttr"))) + return EXIT_FAILURE; + + if (!(vi_lib->fnDisableChannel = (int(*)(int channel)) + hal_symbol_load("v2_vi", vi_lib->handle, "HI_MPI_VI_DisableChn"))) + return EXIT_FAILURE; + + if (!(vi_lib->fnEnableChannel = (int(*)(int channel)) + hal_symbol_load("v2_vi", vi_lib->handle, "HI_MPI_VI_EnableChn"))) + return EXIT_FAILURE; + + if (!(vi_lib->fnSetChannelConfig = (int(*)(int channel, v2_vi_chn *config)) + hal_symbol_load("v2_vi", vi_lib->handle, "HI_MPI_VI_SetChnAttr"))) + return EXIT_FAILURE; + + return EXIT_SUCCESS; +} + +static void v2_vi_unload(v2_vi_impl *vi_lib) { + if (vi_lib->handle) dlclose(vi_lib->handle); + vi_lib->handle = NULL; + memset(vi_lib, 0, sizeof(*vi_lib)); +} \ No newline at end of file diff --git a/src/hal/hisi/v2_vpss.h b/src/hal/hisi/v2_vpss.h new file mode 100644 index 0000000..b1e285c --- /dev/null +++ b/src/hal/hisi/v2_vpss.h @@ -0,0 +1,104 @@ +#pragma once + +#include "v2_common.h" + +#define V2_VPSS_CHN_NUM 11 +#define V2_VPSS_GRP_NUM 32 + +typedef struct { + int sharpOn; + int borderEn; + int mirror; + int flip; + int srcFps; + int dstFps; + v2_common_bord border; +} v2_vpss_chn; + +typedef struct { + v2_common_dim dest; + v2_common_pixfmt pixFmt; + int enhOn; + int dciOn; + int nredOn; + int histEn; + // Accepts values from 0-2 (auto, off, on) + int interlMode; +} v2_vpss_grp; + +typedef struct { + int userModeOn; + v2_common_dim dest; + int doubleOn; + v2_common_pixfmt pixFmt; + v2_common_compr compress; +} v2_vpss_mode; + +typedef struct { + void *handle; + + int (*fnCreateGroup)(int group, v2_vpss_grp *config); + int (*fnDestroyGroup)(int group); + int (*fnResetGroup)(int group); + int (*fnSetGroupConfig)(int channel, v2_vpss_grp *config); + int (*fnStartGroup)(int group); + int (*fnStopGroup)(int group); + + int (*fnDisableChannel)(int group, int channel); + int (*fnEnableChannel)(int group, int channel); + int (*fnSetChannelConfig)(int group, int channel, v2_vpss_chn *config); + int (*fnSetChannelMode)(int group, int channel, v2_vpss_mode *config); +} v2_vpss_impl; + +static int v2_vpss_load(v2_vpss_impl *vpss_lib) { + if (!(vpss_lib->handle = dlopen("libmpi.so", RTLD_LAZY | RTLD_GLOBAL))) + HAL_ERROR("v2_vpss", "Failed to load library!\nError: %s\n", dlerror()); + + if (!(vpss_lib->fnCreateGroup = (int(*)(int group, v2_vpss_grp *config)) + hal_symbol_load("v2_vpss", vpss_lib->handle, "HI_MPI_VPSS_CreateGrp"))) + return EXIT_SUCCESS; + + if (!(vpss_lib->fnDestroyGroup = (int(*)(int group)) + hal_symbol_load("v2_vpss", vpss_lib->handle, "HI_MPI_VPSS_DestroyGrp"))) + return EXIT_FAILURE; + + if (!(vpss_lib->fnResetGroup = (int(*)(int group)) + hal_symbol_load("v2_vpss", vpss_lib->handle, "HI_MPI_VPSS_ResetGrp"))) + return EXIT_FAILURE; + + if (!(vpss_lib->fnSetGroupConfig = (int(*)(int group, v2_vpss_grp *config)) + hal_symbol_load("v2_vpss", vpss_lib->handle, "HI_MPI_VPSS_SetGrpAttr"))) + return EXIT_FAILURE; + + if (!(vpss_lib->fnStartGroup = (int(*)(int group)) + hal_symbol_load("v2_vpss", vpss_lib->handle, "HI_MPI_VPSS_StartGrp"))) + return EXIT_FAILURE; + + if (!(vpss_lib->fnStopGroup = (int(*)(int group)) + hal_symbol_load("v2_vpss", vpss_lib->handle, "HI_MPI_VPSS_StopGrp"))) + return EXIT_FAILURE; + + if (!(vpss_lib->fnDisableChannel = (int(*)(int group, int channel)) + hal_symbol_load("v2_vpss", vpss_lib->handle, "HI_MPI_VPSS_DisableChn"))) + return EXIT_FAILURE; + + if (!(vpss_lib->fnEnableChannel = (int(*)(int group, int channel)) + hal_symbol_load("v2_vpss", vpss_lib->handle, "HI_MPI_VPSS_EnableChn"))) + return EXIT_FAILURE; + + if (!(vpss_lib->fnSetChannelConfig = (int(*)(int group, int channel, v2_vpss_chn *config)) + hal_symbol_load("v2_vpss", vpss_lib->handle, "HI_MPI_VPSS_SetChnAttr"))) + return EXIT_FAILURE; + + if (!(vpss_lib->fnSetChannelMode = (int(*)(int group, int channel, v2_vpss_mode *config)) + hal_symbol_load("v2_vpss", vpss_lib->handle, "HI_MPI_VPSS_SetChnMode"))) + return EXIT_FAILURE; + + return EXIT_SUCCESS; +} + +static void v2_vpss_unload(v2_vpss_impl *vpss_lib) { + if (vpss_lib->handle) dlclose(vpss_lib->handle); + vpss_lib->handle = NULL; + memset(vpss_lib, 0, sizeof(*vpss_lib)); +} diff --git a/src/hal/support.c b/src/hal/support.c index 4f2cd56..a6527a4 100644 --- a/src/hal/support.c +++ b/src/hal/support.c @@ -148,7 +148,7 @@ void hal_identify(void) { fclose(file); } - char v3series = 0; + char v2series = 0, v3series = 0; switch (val) { case 0x12040000: @@ -157,7 +157,10 @@ void hal_identify(void) { val = 0x12020000; v3series = 1; break; - case 0x20080000: val = 0x20050000; break; + case 0x20080000: + val = 0x20050000; + v2series = 1; + break; default: return; } @@ -181,6 +184,16 @@ void hal_identify(void) { chipId[11] = '\0'; } + if (v2series) { + plat = HAL_PLATFORM_V2; + chnCount = V2_VENC_CHN_NUM; + chnState = (hal_chnstate*)v2_state; + aud_thread = v2_audio_thread; + isp_thread = v2_image_thread; + vid_thread = v2_video_thread; + return; + } + if (v3series) { plat = HAL_PLATFORM_V3; chnCount = V3_VENC_CHN_NUM; diff --git a/src/hal/support.h b/src/hal/support.h index 2cff960..da67a75 100644 --- a/src/hal/support.h +++ b/src/hal/support.h @@ -1,6 +1,7 @@ #include "types.h" #if defined(__arm__) #include "plus/gm_hal.h" +#include "hisi/v2_hal.h" #include "hisi/v3_hal.h" #include "hisi/v4_hal.h" #include "star/i6_hal.h" @@ -45,7 +46,8 @@ extern int series; #if defined(__arm__) extern hal_chnstate gm_state[GM_VENC_CHN_NUM]; -extern hal_chnstate v3_state[V4_VENC_CHN_NUM]; +extern hal_chnstate v2_state[V2_VENC_CHN_NUM]; +extern hal_chnstate v3_state[V3_VENC_CHN_NUM]; extern hal_chnstate v4_state[V4_VENC_CHN_NUM]; extern hal_chnstate i6_state[I6_VENC_CHN_NUM]; extern hal_chnstate i6c_state[I6C_VENC_CHN_NUM]; diff --git a/src/hal/types.h b/src/hal/types.h index 159c2c5..c03827d 100644 --- a/src/hal/types.h +++ b/src/hal/types.h @@ -25,6 +25,7 @@ typedef enum { HAL_PLATFORM_I6C, HAL_PLATFORM_I6F, HAL_PLATFORM_T31, + HAL_PLATFORM_V2, HAL_PLATFORM_V3, HAL_PLATFORM_V4 } hal_platform; diff --git a/src/jpeg.c b/src/jpeg.c index 2bad8e4..895c22e 100644 --- a/src/jpeg.c +++ b/src/jpeg.c @@ -38,6 +38,7 @@ int jpeg_init() { case HAL_PLATFORM_I6: ret = i6_video_create(jpeg_index, &config); break; case HAL_PLATFORM_I6C: ret = i6c_video_create(jpeg_index, &config); break; case HAL_PLATFORM_I6F: ret = i6f_video_create(jpeg_index, &config); break; + case HAL_PLATFORM_V2: ret = v2_video_create(jpeg_index, &config); break; case HAL_PLATFORM_V3: ret = v3_video_create(jpeg_index, &config); break; case HAL_PLATFORM_V4: ret = v4_video_create(jpeg_index, &config); break; #elif defined(__mips__) @@ -72,6 +73,7 @@ void jpeg_deinit() { case HAL_PLATFORM_I6: i6_video_destroy(jpeg_index); break; case HAL_PLATFORM_I6C: i6c_video_destroy(jpeg_index); break; case HAL_PLATFORM_I6F: i6f_video_destroy(jpeg_index); break; + case HAL_PLATFORM_V2: v2_video_destroy(jpeg_index); break; case HAL_PLATFORM_V3: v3_video_destroy(jpeg_index); break; case HAL_PLATFORM_V4: v4_video_destroy(jpeg_index); break; #elif defined(__mips__) @@ -107,6 +109,7 @@ int jpeg_get(short width, short height, char quality, char grayscale, case HAL_PLATFORM_I6: ret = i6_video_snapshot_grab(jpeg_index, quality, jpeg); break; case HAL_PLATFORM_I6C: ret = i6c_video_snapshot_grab(jpeg_index, quality, jpeg); break; case HAL_PLATFORM_I6F: ret = i6f_video_snapshot_grab(jpeg_index, quality, jpeg); break; + case HAL_PLATFORM_V2: ret = v2_video_snapshot_grab(jpeg_index, jpeg); break; case HAL_PLATFORM_V3: ret = v3_video_snapshot_grab(jpeg_index, jpeg); break; case HAL_PLATFORM_V4: ret = v4_video_snapshot_grab(jpeg_index, jpeg); break; #elif defined(__mips__) diff --git a/src/main.c b/src/main.c index c0b87fd..5f9c9d0 100644 --- a/src/main.c +++ b/src/main.c @@ -29,6 +29,8 @@ int main(int argc, char *argv[]) { fprintf(stderr, "Divinus for infinity6c\n"); break; case HAL_PLATFORM_I6F: fprintf(stderr, "Divinus for infinity6f\n"); break; + case HAL_PLATFORM_V2: + fprintf(stderr, "Divinus for hisi-gen2\n"); break; case HAL_PLATFORM_V3: fprintf(stderr, "Divinus for hisi-gen3\n"); break; case HAL_PLATFORM_V4: diff --git a/src/media.c b/src/media.c index be96e23..c09cc59 100644 --- a/src/media.c +++ b/src/media.c @@ -155,6 +155,7 @@ void request_idr(void) { case HAL_PLATFORM_I6: i6_video_request_idr(index); break; case HAL_PLATFORM_I6C: i6c_video_request_idr(index); break; case HAL_PLATFORM_I6F: i6f_video_request_idr(index); break; + case HAL_PLATFORM_V2: v2_video_request_idr(index); break; case HAL_PLATFORM_V3: v3_video_request_idr(index); break; case HAL_PLATFORM_V4: v4_video_request_idr(index); break; #elif defined(__mips__) @@ -171,6 +172,7 @@ void set_grayscale(bool active) { case HAL_PLATFORM_I6: i6_channel_grayscale(active); break; case HAL_PLATFORM_I6C: i6c_channel_grayscale(active); break; case HAL_PLATFORM_I6F: i6f_channel_grayscale(active); break; + case HAL_PLATFORM_V2: v2_channel_grayscale(active); break; case HAL_PLATFORM_V3: v3_channel_grayscale(active); break; case HAL_PLATFORM_V4: v4_channel_grayscale(active); break; #elif defined(__mips__) @@ -204,6 +206,8 @@ int create_channel(char index, short width, short height, char framerate, char j app_config.mirror, app_config.flip, jpeg); case HAL_PLATFORM_I6F: return i6f_channel_create(index, width, height, app_config.mirror, app_config.flip, jpeg); + case HAL_PLATFORM_V2: return v2_channel_create(index, width, height, + app_config.mirror, app_config.flip, framerate); case HAL_PLATFORM_V3: return v3_channel_create(index, width, height, app_config.mirror, app_config.flip, framerate); case HAL_PLATFORM_V4: return v4_channel_create(index, app_config.mirror, @@ -222,6 +226,7 @@ int bind_channel(char index, char framerate, char jpeg) { case HAL_PLATFORM_I6: return i6_channel_bind(index, framerate); case HAL_PLATFORM_I6C: return i6c_channel_bind(index, framerate); case HAL_PLATFORM_I6F: return i6f_channel_bind(index, framerate); + case HAL_PLATFORM_V2: return v2_channel_bind(index); case HAL_PLATFORM_V3: return v3_channel_bind(index); case HAL_PLATFORM_V4: return v4_channel_bind(index); #elif defined(__mips__) @@ -237,6 +242,7 @@ int unbind_channel(char index, char jpeg) { case HAL_PLATFORM_I6: return i6_channel_unbind(index); case HAL_PLATFORM_I6C: return i6c_channel_unbind(index); case HAL_PLATFORM_I6F: return i6f_channel_unbind(index); + case HAL_PLATFORM_V2: return v2_channel_unbind(index); case HAL_PLATFORM_V3: return v3_channel_unbind(index); case HAL_PLATFORM_V4: return v4_channel_unbind(index); #elif defined(__mips__) @@ -252,6 +258,7 @@ int disable_video(char index, char jpeg) { case HAL_PLATFORM_I6: return i6_video_destroy(index); case HAL_PLATFORM_I6C: return i6c_video_destroy(index); case HAL_PLATFORM_I6F: return i6f_video_destroy(index); + case HAL_PLATFORM_V2: return v2_video_destroy(index); case HAL_PLATFORM_V3: return v3_video_destroy(index); case HAL_PLATFORM_V4: return v4_video_destroy(index); #elif defined(__mips__) @@ -271,6 +278,7 @@ void disable_audio(void) { case HAL_PLATFORM_I6: i6_audio_deinit(); break; case HAL_PLATFORM_I6C: i6c_audio_deinit(); break; case HAL_PLATFORM_I6F: i6f_audio_deinit(); break; + case HAL_PLATFORM_V2: v2_audio_deinit(); break; case HAL_PLATFORM_V3: v3_audio_deinit(); break; case HAL_PLATFORM_V4: v4_audio_deinit(); break; #elif defined(__mips__) @@ -287,6 +295,7 @@ int enable_audio(void) { case HAL_PLATFORM_I6: ret = i6_audio_init(app_config.audio_srate); break; case HAL_PLATFORM_I6C: ret = i6c_audio_init(app_config.audio_srate); break; case HAL_PLATFORM_I6F: ret = i6f_audio_init(app_config.audio_srate); break; + case HAL_PLATFORM_V2: ret = v2_audio_init(app_config.audio_srate); break; case HAL_PLATFORM_V3: ret = v3_audio_init(app_config.audio_srate); break; case HAL_PLATFORM_V4: ret = v4_audio_init(app_config.audio_srate); break; #elif defined(__mips__) @@ -387,6 +396,7 @@ int enable_mjpeg(void) { case HAL_PLATFORM_I6: ret = i6_video_create(index, &config); break; case HAL_PLATFORM_I6C: ret = i6c_video_create(index, &config); break; case HAL_PLATFORM_I6F: ret = i6f_video_create(index, &config); break; + case HAL_PLATFORM_V2: ret = v2_video_create(index, &config); break; case HAL_PLATFORM_V3: ret = v3_video_create(index, &config); break; case HAL_PLATFORM_V4: ret = v4_video_create(index, &config); break; #elif defined(__mips__) @@ -455,6 +465,7 @@ int enable_mp4(void) { case HAL_PLATFORM_I6: ret = i6_video_create(index, &config); break; case HAL_PLATFORM_I6C: ret = i6c_video_create(index, &config); break; case HAL_PLATFORM_I6F: ret = i6f_video_create(index, &config); break; + case HAL_PLATFORM_V2: ret = v2_video_create(index, &config); break; case HAL_PLATFORM_V3: ret = v3_video_create(index, &config); break; case HAL_PLATFORM_V4: ret = v4_video_create(index, &config); break; #elif defined(__mips__) @@ -487,6 +498,7 @@ int start_sdk(void) { case HAL_PLATFORM_I6: ret = i6_hal_init(); break; case HAL_PLATFORM_I6C: ret = i6c_hal_init(); break; case HAL_PLATFORM_I6F: ret = i6f_hal_init(); break; + case HAL_PLATFORM_V2: ret = v2_hal_init(); break; case HAL_PLATFORM_V3: ret = v3_hal_init(); break; case HAL_PLATFORM_V4: ret = v4_hal_init(); break; #elif defined(__mips__) @@ -512,6 +524,10 @@ int start_sdk(void) { i6f_aud_cb = save_audio_stream; i6f_vid_cb = save_video_stream; break; + case HAL_PLATFORM_V2: + v2_aud_cb = save_audio_stream; + v2_vid_cb = save_video_stream; + break; case HAL_PLATFORM_V3: v3_aud_cb = save_audio_stream; v3_vid_cb = save_video_stream; @@ -534,6 +550,7 @@ int start_sdk(void) { case HAL_PLATFORM_I6: ret = i6_system_init(); break; case HAL_PLATFORM_I6C: ret = i6c_system_init(); break; case HAL_PLATFORM_I6F: ret = i6f_system_init(); break; + case HAL_PLATFORM_V2: ret = v2_system_init(app_config.sensor_config); break; case HAL_PLATFORM_V3: ret = v3_system_init(app_config.sensor_config); break; case HAL_PLATFORM_V4: ret = v4_system_init(app_config.sensor_config); break; #elif defined(__mips__) @@ -565,6 +582,7 @@ int start_sdk(void) { height, framerate); break; case HAL_PLATFORM_I6F: ret = i6f_pipeline_create(0, width, height, framerate); break; + case HAL_PLATFORM_V2: ret = v2_pipeline_create(); break; case HAL_PLATFORM_V3: ret = v3_pipeline_create(); break; case HAL_PLATFORM_V4: ret = v4_pipeline_create(); break; #elif defined(__mips__) @@ -655,6 +673,7 @@ int stop_sdk(void) { case HAL_PLATFORM_I6: i6_video_destroy_all(); break; case HAL_PLATFORM_I6C: i6c_video_destroy_all(); break; case HAL_PLATFORM_I6F: i6f_video_destroy_all(); break; + case HAL_PLATFORM_V2: v2_video_destroy_all(); break; case HAL_PLATFORM_V3: v3_video_destroy_all(); break; case HAL_PLATFORM_V4: v4_video_destroy_all(); break; #elif defined(__mips__) @@ -668,6 +687,7 @@ int stop_sdk(void) { case HAL_PLATFORM_I6: i6_pipeline_destroy(); break; case HAL_PLATFORM_I6C: i6c_pipeline_destroy(); break; case HAL_PLATFORM_I6F: i6f_pipeline_destroy(); break; + case HAL_PLATFORM_V2: v2_pipeline_destroy(); break; case HAL_PLATFORM_V3: v3_pipeline_destroy(); break; case HAL_PLATFORM_V4: v4_pipeline_destroy(); break; #elif defined(__mips__) @@ -687,6 +707,7 @@ int stop_sdk(void) { case HAL_PLATFORM_I6: i6_system_deinit(); break; case HAL_PLATFORM_I6C: i6c_system_deinit(); break; case HAL_PLATFORM_I6F: i6f_system_deinit(); break; + case HAL_PLATFORM_V2: v2_system_deinit(); break; case HAL_PLATFORM_V3: v3_system_deinit(); break; case HAL_PLATFORM_V4: v4_system_deinit(); break; #elif defined(__mips__) @@ -696,6 +717,7 @@ int stop_sdk(void) { switch (plat) { #if defined(__arm__) + case HAL_PLATFORM_V2: v2_sensor_deinit(); break; case HAL_PLATFORM_V3: v3_sensor_deinit(); break; case HAL_PLATFORM_V4: v4_sensor_deinit(); break; #endif @@ -707,6 +729,7 @@ int stop_sdk(void) { case HAL_PLATFORM_I6: i6_hal_deinit(); break; case HAL_PLATFORM_I6C: i6c_hal_deinit(); break; case HAL_PLATFORM_I6F: i6f_hal_deinit(); break; + case HAL_PLATFORM_V2: v2_hal_deinit(); break; case HAL_PLATFORM_V3: v3_hal_deinit(); break; case HAL_PLATFORM_V4: v4_hal_deinit(); break; #elif defined(__mips__) diff --git a/src/region.c b/src/region.c index d55e46d..5d0e4f0 100644 --- a/src/region.c +++ b/src/region.c @@ -249,6 +249,10 @@ void *region_thread(void) i6f_region_create(id, rect, osds[id].opal); i6f_region_setbitmap(id, &bitmap); break; + case HAL_PLATFORM_V2: + v2_region_create(id, rect, osds[id].opal); + v2_region_setbitmap(id, &bitmap); + break; case HAL_PLATFORM_V3: v3_region_create(id, rect, osds[id].opal); v3_region_setbitmap(id, &bitmap); @@ -293,6 +297,10 @@ void *region_thread(void) i6f_region_create(id, rect, osds[id].opal); i6f_region_setbitmap(id, &bitmap); break; + case HAL_PLATFORM_V2: + v2_region_create(id, rect, osds[id].opal); + v2_region_setbitmap(id, &bitmap); + break; case HAL_PLATFORM_V3: v3_region_create(id, rect, osds[id].opal); v3_region_setbitmap(id, &bitmap); @@ -317,6 +325,7 @@ void *region_thread(void) case HAL_PLATFORM_I6: i6_region_destroy(id); break; case HAL_PLATFORM_I6C: i6c_region_destroy(id); break; case HAL_PLATFORM_I6F: i6f_region_destroy(id); break; + case HAL_PLATFORM_V2: v2_region_destroy(id); break; case HAL_PLATFORM_V3: v3_region_destroy(id); break; case HAL_PLATFORM_V4: v4_region_destroy(id); break; #elif defined(__mips__)