From 738d9b49d9a2f383d1be4906aa84b985df4fca47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?William=20B=C3=A9rub=C3=A9?= Date: Sun, 25 Aug 2024 04:14:18 -0400 Subject: [PATCH] First tests on real hardware for CVITEK/Sophon --- .vscode/c_cpp_properties.json | 6 + build.sh | 13 +- src/compat.c | 9 +- src/hal/hisi/v1_hal.c | 6 +- src/hal/hisi/v4_hal.c | 4 +- src/hal/plus/cvi_config.h | 3 +- src/hal/plus/cvi_hal.c | 904 ++++++++++++++++++++++++++++++++++ src/hal/plus/cvi_hal.h | 62 +++ src/hal/plus/cvi_isp.h | 129 +++++ src/hal/plus/cvi_snr.h | 219 ++++++++ src/hal/plus/cvi_sys.h | 13 +- src/hal/plus/cvi_venc.h | 488 ++++++++++++++++++ src/hal/plus/cvi_vi.h | 4 +- src/hal/star/i6_hal.h | 2 +- src/hal/support.c | 16 +- src/hal/support.h | 2 + src/hal/types.h | 1 + src/media.c | 40 ++ 18 files changed, 1895 insertions(+), 26 deletions(-) create mode 100644 src/hal/plus/cvi_hal.c create mode 100644 src/hal/plus/cvi_hal.h create mode 100644 src/hal/plus/cvi_isp.h create mode 100644 src/hal/plus/cvi_snr.h create mode 100644 src/hal/plus/cvi_venc.h diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json index 027be6b..5b34844 100644 --- a/.vscode/c_cpp_properties.json +++ b/.vscode/c_cpp_properties.json @@ -42,6 +42,12 @@ "defines": ["__mips__"], "compilerPath": "toolchain/mips_xburst-gcc13-musl-3_10/bin/mipsel-openipc-linux-musl-gcc", "cStandard": "c11" + },{ + "name": "riscv64-musl", + "includePath": ["${workspaceFolder}/**"], + "defines": ["__riscv", "__riscv__"], + "compilerPath": "toolchain/riscv64-lp64d--musl--stable-2024.05-1/bin/riscv64-linux-gcc", + "cStandard": "c11" } ], "version": 4 diff --git a/build.sh b/build.sh index a7fbbfd..ad84e70 100755 --- a/build.sh +++ b/build.sh @@ -1,12 +1,13 @@ #!/bin/sh DL="https://github.com/openipc/firmware/releases/download/latest" +EXT="tgz" toolchain() { if [ ! -e toolchain/$1 ]; then - wget -c -q $DL/$1.tgz -P $PWD + wget -c -q $DL/$1.$EXT -P $PWD mkdir -p toolchain/$1 - tar -xf $1.tgz -C toolchain/$1 --strip-components=1 || exit 1 - rm -f $1.tgz + tar -xf $1.$EXT -C toolchain/$1 --strip-components=1 || exit 1 + rm -f $1.$EXT fi make -j $(nproc) -C src -B CC=$PWD/toolchain/$1/bin/$2-linux-gcc OPT="$OPT $3" } @@ -31,6 +32,10 @@ elif [ "$1" = "armhf-musl" ]; then toolchain cortex_a7_thumb2_hf-gcc13-musl-4_9 arm elif [ "$1" = "mips-musl" ]; then toolchain mips_xburst-gcc13-musl-3_10 mipsel +elif [ "$1" = "riscv64-musl" ]; then + DL="https://toolchains.bootlin.com/downloads/releases/toolchains/riscv64-lp64d/tarballs" + EXT="tar.xz" + toolchain riscv64-lp64d--musl--stable-2024.05-1 riscv64 else - echo "Usage: $0 [arm-musl|arm9-musl3|arm9-musl4|arm9-uclibc|armhf-glibc|armhf-musl|mips-musl]" + echo "Usage: $0 [arm-musl|arm9-musl3|arm9-musl4|arm9-uclibc|armhf-glibc|armhf-musl|mips-musl|riscv64-musl]" fi diff --git a/src/compat.c b/src/compat.c index 1d7ee57..9f3a486 100644 --- a/src/compat.c +++ b/src/compat.c @@ -29,6 +29,7 @@ void __assert(void) {} void backtrace(void) {} void backtrace_symbols(void) {} void __ctype_b(void) {} +void __ctype_b_loc(void) {} void __ctype_tolower(void) {} void _MI_PRINT_GetDebugLevel(void) {} void __pthread_register_cancel(void) {} @@ -39,10 +40,16 @@ float __expf_finite(float x) { return expf(x); } int __fgetc_unlocked(FILE *stream) { return fgetc(stream); } double __log_finite(double x) { return log(x); } +#if !defined(__riscv) && !defined(__riscv__) void *mmap(void *start, size_t len, int prot, int flags, int fd, uint32_t off) { return (void*)syscall(SYS_mmap2, start, len, prot, flags, fd, off >> 12); } void *mmap64(void *start, size_t len, int prot, int flags, int fd, off_t off) { return (void*)syscall(SYS_mmap2, start, len, prot, flags, fd, off >> 12); -} \ No newline at end of file +} +#else +void *mmap64(void *start, size_t len, int prot, int flags, int fd, off_t off) { + return (void*)syscall(SYS_mmap, start, len, prot, flags, fd, off); +} +#endif \ No newline at end of file diff --git a/src/hal/hisi/v1_hal.c b/src/hal/hisi/v1_hal.c index 420f8f8..352d564 100644 --- a/src/hal/hisi/v1_hal.c +++ b/src/hal/hisi/v1_hal.c @@ -84,7 +84,7 @@ int v1_audio_init(int samplerate) config.expandOn = 0; config.frmNum = 30; config.packNumPerFrm = 320; - config.chnNum = 1; + config.chnNum = 2; config.syncRxClkOn = 0; if (ret = v1_aud.fnSetDeviceConfig(_v1_aud_dev, &config)) return ret; @@ -449,7 +449,7 @@ int v1_video_create(char index, hal_vidconfig *config) channel.attrib.jpg.maxPic.height = config->height; channel.attrib.jpg.bufSize = config->height * config->width * 2; - channel.attrib.jpg.byFrame = 0; + channel.attrib.jpg.byFrame = 1; channel.attrib.jpg.fieldOrFrame = 0; channel.attrib.jpg.priority = 0; channel.attrib.jpg.pic.width = config->width; @@ -461,7 +461,7 @@ int v1_video_create(char index, hal_vidconfig *config) channel.attrib.mjpg.maxPic.height = config->height; channel.attrib.mjpg.bufSize = config->height * config->width * 2; - channel.attrib.mjpg.byFrame = 0; + channel.attrib.mjpg.byFrame = 1; channel.attrib.mjpg.mainStrmOn = 1; channel.attrib.mjpg.fieldOrFrame = 0; channel.attrib.mjpg.priority = 0; diff --git a/src/hal/hisi/v4_hal.c b/src/hal/hisi/v4_hal.c index f835d4e..d408fad 100644 --- a/src/hal/hisi/v4_hal.c +++ b/src/hal/hisi/v4_hal.c @@ -541,10 +541,10 @@ int v4_sensor_init(char *name, char *obj) if (v4_snr_drv.handle = dlopen(path, RTLD_LAZY | RTLD_GLOBAL)) break; } if (!v4_snr_drv.handle) - HAL_ERROR("v4_snr", "Failed to load the sensor driver"); + HAL_ERROR("v4_snr", "Failed to load the sensor driver\n"); if (!(v4_snr_drv.obj = (v4_snr_obj*)dlsym(v4_snr_drv.handle, obj))) - HAL_ERROR("v4_snr", "Failed to connect the sensor object"); + HAL_ERROR("v4_snr", "Failed to connect the sensor object\n"); return EXIT_SUCCESS; } diff --git a/src/hal/plus/cvi_config.h b/src/hal/plus/cvi_config.h index 8bee41e..0c05d9f 100644 --- a/src/hal/plus/cvi_config.h +++ b/src/hal/plus/cvi_config.h @@ -315,7 +315,8 @@ static enum ConfigError cvi_parse_sensor_config(char *path, cvi_config_impl *con enum ConfigError err; // load config file to string - if (!open_config(&ini, path)) + FILE *file = fopen(path, "r"); + if (!open_config(&ini, &file)) return (enum ConfigError)-1; find_sections(&ini); diff --git a/src/hal/plus/cvi_hal.c b/src/hal/plus/cvi_hal.c new file mode 100644 index 0000000..6687271 --- /dev/null +++ b/src/hal/plus/cvi_hal.c @@ -0,0 +1,904 @@ +#if defined(__riscv) || defined(__riscv__) + +#include "cvi_hal.h" + +cvi_isp_alg cvi_ae_lib = { .id = 0, .libName = "ae_lib" }; +cvi_aud_impl cvi_aud; +cvi_isp_alg cvi_awb_lib = { .id = 0, .libName = "awb_lib" }; +cvi_config_impl cvi_config; +cvi_isp_impl cvi_isp; +cvi_snr_drv_impl cvi_snr_drv; +cvi_rgn_impl cvi_rgn; +cvi_sys_impl cvi_sys; +cvi_vb_impl cvi_vb; +cvi_venc_impl cvi_venc; +cvi_vi_impl cvi_vi; +cvi_vpss_impl cvi_vpss; + +hal_chnstate cvi_state[CVI_VENC_CHN_NUM] = {0}; +int (*cvi_aud_cb)(hal_audframe*); +int (*cvi_vid_cb)(char, hal_vidstream*); + +char _cvi_aud_chn = 0; +char _cvi_aud_dev = 0; +char _cvi_isp_chn = 0; +char _cvi_isp_dev = 0; +char _cvi_venc_dev = 0; +char _cvi_vi_chn = 0; +char _cvi_vi_dev = 0; +char _cvi_vi_pipe = 0; +char _cvi_vpss_chn = 0; +char _cvi_vpss_grp = 0; + +void cvi_hal_deinit(void) +{ + cvi_vpss_unload(&cvi_vpss); + cvi_vi_unload(&cvi_vi); + cvi_venc_unload(&cvi_venc); + cvi_vb_unload(&cvi_vb); + cvi_rgn_unload(&cvi_rgn); + cvi_isp_unload(&cvi_isp); + cvi_aud_unload(&cvi_aud); + cvi_sys_unload(&cvi_sys); +} + +int cvi_hal_init(void) +{ + int ret; + + if (ret = cvi_sys_load(&cvi_sys)) + return ret; + if (ret = cvi_aud_load(&cvi_aud)) + return ret; + if (ret = cvi_isp_load(&cvi_isp)) + return ret; + if (ret = cvi_rgn_load(&cvi_rgn)) + return ret; + if (ret = cvi_vb_load(&cvi_vb)) + return ret; + if (ret = cvi_venc_load(&cvi_venc)) + return ret; + if (ret = cvi_vi_load(&cvi_vi)) + return ret; + if (ret = cvi_vpss_load(&cvi_vpss)) + return ret; + + return EXIT_SUCCESS; +} + +void cvi_audio_deinit(void) +{ + cvi_aud.fnDisableChannel(_cvi_aud_dev, _cvi_aud_chn); + + cvi_aud.fnDisableDevice(_cvi_aud_dev); +} + +int cvi_audio_init(int samplerate) +{ + int ret; + + { + cvi_aud_cnf config; + config.rate = samplerate; + config.bit = CVI_AUD_BIT_16; + config.intf = CVI_AUD_INTF_I2S_MASTER; + config.stereoOn = 0; + config.expandOn = 0; + config.frmNum = 30; + config.packNumPerFrm = 320; + config.chnNum = 1; + config.syncRxClkOn = 0; + config.i2sType = CVI_AUD_I2ST_INNERCODEC; + if (ret = cvi_aud.fnSetDeviceConfig(_cvi_aud_dev, &config)) + return ret; + } + if (ret = cvi_aud.fnEnableDevice(_cvi_aud_dev)) + return ret; + + if (ret = cvi_aud.fnEnableChannel(_cvi_aud_dev, _cvi_aud_chn)) + return ret; + + return EXIT_SUCCESS; +} + +void *cvi_audio_thread(void) +{ + int ret; + + cvi_aud_frm frame; + cvi_aud_efrm echoFrame; + memset(&frame, 0, sizeof(frame)); + memset(&echoFrame, 0, sizeof(echoFrame)); + + while (keepRunning) { + if (ret = cvi_aud.fnGetFrame(_cvi_aud_dev, _cvi_aud_chn, + &frame, &echoFrame, 128)) { + HAL_WARNING("cvi_aud", "Getting the frame failed " + "with %#x!\n", ret); + continue; + } + + if (cvi_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; + (cvi_aud_cb)(&outFrame); + } + + if (ret = cvi_aud.fnFreeFrame(_cvi_aud_dev, _cvi_aud_chn, + &frame, &echoFrame)) { + HAL_WARNING("cvi_aud", "Releasing the frame failed" + " with %#x!\n", ret); + } + } + fprintf(stderr, "[cvi_aud] Shutting down capture thread...\n"); +} + +int cvi_channel_bind(char index) +{ + int ret; + + if (ret = cvi_vpss.fnEnableChannel(_cvi_vpss_grp, index)) + return ret; + + { + cvi_sys_bind source = { .module = CVI_SYS_MOD_VPSS, + .device = _cvi_vpss_grp, .channel = index }; + cvi_sys_bind dest = { .module = CVI_SYS_MOD_VENC, + .device = _cvi_venc_dev, .channel = index }; + if (ret = cvi_sys.fnBind(&source, &dest)) + return ret; + } + + return EXIT_SUCCESS; +} + +int cvi_channel_create(char index, char mirror, char flip, char framerate) +{ + int ret; + + { + cvi_vpss_chn channel; + memset(&channel, 0, sizeof(channel)); + channel.dest.width = cvi_config.isp.capt.width; + channel.dest.height = cvi_config.isp.capt.height; + channel.pixFmt = CVI_PIXFMT_YUV420P; + channel.srcFps = cvi_config.isp.framerate; + channel.dstFps = framerate; + channel.mirror = mirror; + channel.flip = flip; + if (ret = cvi_vpss.fnSetChannelConfig(_cvi_vpss_grp, index, &channel)) + return ret; + } + + return EXIT_SUCCESS; +} + +int cvi_channel_grayscale(char enable) +{ + int ret; + + for (char i = 0; i < CVI_VENC_CHN_NUM; i++) { + cvi_venc_para param; + if (!cvi_state[i].enable) continue; + if (ret = cvi_venc.fnGetChannelParam(i, ¶m)) + return ret; + param.grayscaleOn = enable; + if (ret = cvi_venc.fnSetChannelParam(i, ¶m)) + return ret; + } + + return EXIT_SUCCESS; +} + +int cvi_channel_unbind(char index) +{ + int ret; + + if (ret = cvi_vpss.fnDisableChannel(_cvi_vpss_grp, index)) + return ret; + + { + cvi_sys_bind source = { .module = CVI_SYS_MOD_VPSS, + .device = _cvi_vpss_grp, .channel = index }; + cvi_sys_bind dest = { .module = CVI_SYS_MOD_VENC, + .device = _cvi_venc_dev, .channel = index }; + if (ret = cvi_sys.fnUnbind(&source, &dest)) + return ret; + } + + return EXIT_SUCCESS; +} + +void *cvi_image_thread(void) +{ + int ret; + + if (ret = cvi_isp.fnRun(_cvi_isp_dev)) + HAL_DANGER("cvi_isp", "Operation failed with %#x!\n", ret); + HAL_INFO("cvi_isp", "Shutting down ISP thread...\n"); +} + +int cvi_pipeline_create(void) +{ + int ret; + + { + cvi_sys_oper mode[4]; + cvi_sys.fnGetViVpssMode((cvi_sys_oper**)&mode); + mode[_cvi_vi_dev] = CVI_SYS_OPER_VIOFF_VPSSON; + if (ret = cvi_sys.fnSetViVpssMode((cvi_sys_oper**)&mode)) + return ret; + } + + if (ret = cvi_sensor_config()) + return ret; + + if (ret = cvi_vi.fnSetDeviceConfig(_cvi_vi_dev, &cvi_config.videv)) + return ret; + if (ret = cvi_vi.fnEnableDevice(_cvi_vi_dev)) + return ret; + + { + cvi_vi_bind bind; + bind.num = 1; + bind.pipeId[0] = _cvi_vi_pipe; + if (ret = cvi_vi.fnBindPipe(_cvi_vi_dev, &bind)) + return ret; + } + + { + cvi_vi_pipe pipe; + pipe.bypass = 0; + pipe.yuvSkipOn = 0; + pipe.ispBypassOn = 0; + pipe.maxSize.width = cvi_config.isp.capt.width; + pipe.maxSize.height = cvi_config.isp.capt.height; + pipe.pixFmt = CVI_PIXFMT_RGB_BAYER_8BPP + cvi_config.mipi.prec; + pipe.compress = CVI_COMPR_NONE; + pipe.prec = cvi_config.mipi.prec; + pipe.nRedOn = 0; + pipe.sharpenOn = 1; + pipe.srcFps = -1; + pipe.dstFps = -1; + if (ret = cvi_vi.fnCreatePipe(_cvi_vi_pipe, &pipe)) + return ret; + } + if (ret = cvi_vi.fnStartPipe(_cvi_vi_pipe)) + return ret; + + { + cvi_vi_chn channel; + channel.size.width = cvi_config.isp.capt.width; + channel.size.height = cvi_config.isp.capt.height; + channel.pixFmt = CVI_PIXFMT_YUV420P; + channel.dynRange = CVI_HDR_SDR8; + channel.compress = CVI_COMPR_NONE; + channel.mirror = 0; + channel.flip = 0; + channel.depth = 0; + channel.srcFps = cvi_config.isp.framerate; + channel.dstFps = cvi_config.isp.framerate; + if (ret = cvi_vi.fnSetChannelConfig(_cvi_vi_pipe, _cvi_vi_chn, &channel)) + return ret; + } + if (ret = cvi_vi.fnEnableChannel(_cvi_vi_pipe, _cvi_vi_chn)) + return ret; + + { + cvi_snr_bus bus; + bus.i2c = 0; + if (ret = cvi_snr_drv.obj->pfnSetBusInfo(_cvi_vi_pipe, bus)) + return ret; + } + + if (ret = cvi_snr_drv.obj->pfnRegisterCallback(_cvi_vi_pipe, &cvi_ae_lib, &cvi_awb_lib)) + return ret; + + if (ret = cvi_isp.fnRegisterAE(_cvi_vi_pipe, &cvi_ae_lib)) + return ret; + if (ret = cvi_isp.fnRegisterAWB(_cvi_vi_pipe, &cvi_awb_lib)) + return ret; + if (ret = cvi_isp.fnMemInit(_cvi_vi_pipe)) + return ret; + + cvi_config.isp.capt.x = 0; + cvi_config.isp.capt.y = 0; + if (ret = cvi_isp.fnSetDeviceConfig(_cvi_vi_pipe, &cvi_config.isp)) + return ret; + if (ret = cvi_isp.fnInit(_cvi_vi_pipe)) + return ret; + + { + cvi_vpss_grp group; + memset(&group, 0, sizeof(group)); + group.dest.width = cvi_config.isp.capt.width; + group.dest.height = cvi_config.isp.capt.height; + group.pixFmt = CVI_PIXFMT_YUV420P; + group.srcFps = cvi_config.isp.framerate; + group.dstFps = cvi_config.isp.framerate; + if (ret = cvi_vpss.fnCreateGroup(_cvi_vpss_grp, &group)) + return ret; + } + if (ret = cvi_vpss.fnStartGroup(_cvi_vpss_grp)) + return ret; + + { + cvi_sys_bind source = { .module = CVI_SYS_MOD_VI, + .device = _cvi_vi_dev, .channel = _cvi_vi_chn }; + cvi_sys_bind dest = { .module = CVI_SYS_MOD_VPSS, + .device = _cvi_vpss_grp, .channel = 0 }; + if (ret = cvi_sys.fnBind(&source, &dest)) + return ret; + } + + return EXIT_SUCCESS; +} + +void cvi_pipeline_destroy(void) +{ + cvi_isp.fnExit(_cvi_vi_pipe); + cvi_isp.fnUnregisterAE(_cvi_vi_pipe, &cvi_ae_lib); + cvi_isp.fnUnregisterAWB(_cvi_vi_pipe, &cvi_awb_lib); + + cvi_snr_drv.obj->pfnUnRegisterCallback(_cvi_vi_pipe, &cvi_ae_lib, &cvi_awb_lib); + + for (char grp = 0; grp < CVI_VPSS_GRP_NUM; grp++) + { + for (char chn = 0; chn < CVI_VPSS_CHN_NUM; chn++) + cvi_vpss.fnDisableChannel(grp, chn); + + { + cvi_sys_bind source = { .module = CVI_SYS_MOD_VI, + .device = _cvi_vi_dev, .channel = _cvi_vi_chn }; + cvi_sys_bind dest = { .module = CVI_SYS_MOD_VPSS, + .device = grp, .channel = 0 }; + cvi_sys.fnUnbind(&source, &dest); + } + + cvi_vpss.fnStopGroup(grp); + cvi_vpss.fnDestroyGroup(grp); + } + + cvi_vi.fnDisableChannel(_cvi_vi_pipe, _cvi_vi_chn); + + cvi_vi.fnStopPipe(_cvi_vi_pipe); + cvi_vi.fnDestroyPipe(_cvi_vi_pipe); + + cvi_vi.fnDisableDevice(_cvi_vi_dev); + + cvi_sensor_deconfig(); +} + +int cvi_region_create(char handle, hal_rect rect, short opacity) +{ + int ret; + + cvi_sys_bind channel = { .module = CVI_SYS_MOD_VENC, + .device = _cvi_venc_dev, .channel = 0 }; + cvi_rgn_cnf region, regionCurr; + cvi_rgn_chn attrib, attribCurr; + + memset(®ion, 0, sizeof(region)); + region.type = CVI_RGN_TYPE_OVERLAY; + region.overlay.pixFmt = CVI_PIXFMT_ARGB1555; + region.overlay.size.width = rect.width; + region.overlay.size.height = rect.height; + region.overlay.canvas = handle + 1; + + if (cvi_rgn.fnGetRegionConfig(handle, ®ionCurr)) { + HAL_INFO("cvi_rgn", "Creating region %d...\n", handle); + if (ret = cvi_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("cvi_rgn", "Parameters are different, recreating " + "region %d...\n", handle); + cvi_rgn.fnDetachChannel(handle, &channel); + cvi_rgn.fnDestroyRegion(handle); + if (ret = cvi_rgn.fnCreateRegion(handle, ®ion)) + return ret; + } + + if (cvi_rgn.fnGetChannelConfig(handle, &channel, &attribCurr)) + HAL_INFO("cvi_rgn", "Attaching region %d...\n", handle); + else if (attribCurr.overlay.point.x != rect.x || attribCurr.overlay.point.x != rect.y) { + HAL_INFO("cvi_rgn", "Position has changed, reattaching " + "region %d...\n", handle); + cvi_rgn.fnDetachChannel(handle, &channel); + } + + memset(&attrib, 0, sizeof(attrib)); + attrib.show = 1; + attrib.type = CVI_RGN_TYPE_OVERLAY; + attrib.overlay.point.x = rect.x; + attrib.overlay.point.y = rect.y; + attrib.overlay.layer = 7; + + cvi_rgn.fnAttachChannel(handle, &channel, &attrib); + + return EXIT_SUCCESS; +} + +void cvi_region_destroy(char handle) +{ + cvi_sys_bind channel = { .module = CVI_SYS_MOD_VENC, + .device = _cvi_venc_dev, .channel = 0 }; + + cvi_rgn.fnDetachChannel(handle, &channel); + cvi_rgn.fnDestroyRegion(handle); +} + +int cvi_region_setbitmap(int handle, hal_bitmap *bitmap) +{ + cvi_rgn_bmp nativeBmp = { .data = bitmap->data, .pixFmt = CVI_PIXFMT_ARGB1555, + .size.height = bitmap->dim.height, .size.width = bitmap->dim.width }; + + return cvi_rgn.fnSetBitmap(handle, &nativeBmp); +} + +int cvi_sensor_config(void) { + int device = 0, fd; + cvi_snr_dev config; + memset(&config, 0, sizeof(config)); + config.device = device; + config.input = cvi_config.input_mode; + config.dest.width = cvi_config.isp.capt.width; + config.dest.height = cvi_config.isp.capt.height; + if (config.input == CVI_SNR_INPUT_MIPI) + memcpy(&config.mipi, &cvi_config.mipi, sizeof(cvi_snr_mipi)); + else if (config.input == CVI_SNR_INPUT_LVDS) + memcpy(&config.lvds, &cvi_config.lvds, sizeof(cvi_snr_lvds)); + + cvi_isp.fnResetSensor(device, 1); + + cvi_isp.fnResetIntf(device, 1); + + cvi_isp.fnSetIntfConfig(_cvi_vi_pipe, &config); + + cvi_isp.fnSetSensorClock(device, 1); + + cvi_isp.fnResetSensor(device, 0); + + return EXIT_SUCCESS; +} + +void cvi_sensor_deconfig(void) { + int device = 0, fd; + + cvi_isp.fnResetSensor(device, 1); + + cvi_isp.fnSetSensorClock(device, 0); + + cvi_isp.fnResetIntf(device, 0); + + cvi_isp.fnResetSensor(device, 0); +} + +void cvi_sensor_deinit(void) +{ + dlclose(cvi_snr_drv.handle); + cvi_snr_drv.handle = NULL; +} + +int cvi_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 (cvi_snr_drv.handle = dlopen(path, RTLD_LAZY | RTLD_GLOBAL)) + break; + } if (!cvi_snr_drv.handle) + HAL_ERROR("cvi_snr", "Failed to load the sensor driver\n"); + + if (!(cvi_snr_drv.obj = (cvi_snr_obj*)dlsym(cvi_snr_drv.handle, obj))) + HAL_ERROR("cvi_snr", "Failed to connect the sensor object\nError: %s\n", dlerror()); + + return EXIT_SUCCESS; +} + +int cvi_video_create(char index, hal_vidconfig *config) +{ + int ret; + cvi_venc_chn channel; + memset(&channel, 0, sizeof(channel)); + channel.gop.mode = CVI_VENC_GOPMODE_NORMALP; + if (config->codec == HAL_VIDCODEC_JPG || config->codec == HAL_VIDCODEC_MJPG) { + channel.attrib.codec = CVI_VENC_CODEC_MJPG; + switch (config->mode) { + case HAL_VIDMODE_CBR: + channel.rate.mode = CVI_VENC_RATEMODE_MJPGCBR; + channel.rate.mjpgCbr = (cvi_venc_rate_mjpgbr){ .statTime = 1, .srcFps = config->framerate, + .dstFps = config->framerate, .maxBitrate = config->bitrate }; break; + case HAL_VIDMODE_VBR: + channel.rate.mode = CVI_VENC_RATEMODE_MJPGVBR; + channel.rate.mjpgVbr = (cvi_venc_rate_mjpgbr){ .statTime = 1, + .srcFps = config->framerate, .dstFps = config->framerate, + .maxBitrate = MAX(config->bitrate, config->maxBitrate) }; break; + case HAL_VIDMODE_QP: + channel.rate.mode = CVI_VENC_RATEMODE_MJPGQP; + channel.rate.mjpgQp = (cvi_venc_rate_mjpgqp){ .srcFps = config->framerate, + .dstFps = config->framerate, .quality = config->maxQual }; break; + default: + HAL_ERROR("cvi_venc", "MJPEG encoder can only support CBR, VBR or fixed QP modes!"); + } + } else if (config->codec == HAL_VIDCODEC_H265) { + channel.attrib.codec = CVI_VENC_CODEC_H265; + channel.gop.normalP.ipQualDelta = config->gop / config->framerate; + switch (config->mode) { + case HAL_VIDMODE_CBR: + channel.rate.mode = CVI_VENC_RATEMODE_H265CBR; + channel.rate.h265Cbr = (cvi_venc_rate_h26xbr){ .gop = config->gop, + .statTime = 1, .srcFps = config->framerate, .dstFps = config->framerate, + .maxBitrate = config->bitrate }; break; + case HAL_VIDMODE_VBR: + channel.rate.mode = CVI_VENC_RATEMODE_H265VBR; + channel.rate.h265Vbr = (cvi_venc_rate_h26xbr){ .gop = config->gop, + .statTime = 1, .srcFps = config->framerate, .dstFps = config->framerate, + .maxBitrate = MAX(config->bitrate, config->maxBitrate) }; break; + case HAL_VIDMODE_QP: + channel.rate.mode = CVI_VENC_RATEMODE_H265QP; + channel.rate.h265Qp = (cvi_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 = CVI_VENC_RATEMODE_H265AVBR; + channel.rate.h265Avbr = (cvi_venc_rate_h26xbr){ .gop = config->gop, + .statTime = 1, .srcFps = config->framerate, .dstFps = config->framerate, + .maxBitrate = config->bitrate }; break; + default: + HAL_ERROR("cvi_venc", "H.265 encoder does not support this mode!"); + } + } else if (config->codec == HAL_VIDCODEC_H264) { + channel.attrib.codec = CVI_VENC_CODEC_H264; + channel.gop.normalP.ipQualDelta = config->gop / config->framerate; + switch (config->mode) { + case HAL_VIDMODE_CBR: + channel.rate.mode = CVI_VENC_RATEMODE_H264CBR; + channel.rate.h264Cbr = (cvi_venc_rate_h26xbr){ .gop = config->gop, + .statTime = 1, .srcFps = config->framerate, .dstFps = config->framerate, + .maxBitrate = config->bitrate }; break; + case HAL_VIDMODE_VBR: + channel.rate.mode = CVI_VENC_RATEMODE_H264VBR; + channel.rate.h264Vbr = (cvi_venc_rate_h26xbr){ .gop = config->gop, + .statTime = 1, .srcFps = config->framerate, .dstFps = config->framerate, + .maxBitrate = MAX(config->bitrate, config->maxBitrate) }; break; + case HAL_VIDMODE_QP: + channel.rate.mode = CVI_VENC_RATEMODE_H264QP; + channel.rate.h264Qp = (cvi_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 = CVI_VENC_RATEMODE_H264AVBR; + channel.rate.h264Avbr = (cvi_venc_rate_h26xbr){ .gop = config->gop, + .statTime = 1, .srcFps = config->framerate, .dstFps = config->framerate, + .maxBitrate = config->bitrate }; break; + default: + HAL_ERROR("cvi_venc", "H.264 encoder does not support this mode!"); + } + } else HAL_ERROR("cvi_venc", "This codec is not supported by the hardware!"); + channel.attrib.maxPic.width = config->width; + channel.attrib.maxPic.height = config->height; + channel.attrib.bufSize = ALIGN_UP(config->height * config->width * 3 / 4, 64); + if (channel.attrib.codec == CVI_VENC_CODEC_H264) + channel.attrib.profile = MAX(config->profile, 2); + channel.attrib.byFrame = 1; + channel.attrib.pic.width = config->width; + channel.attrib.pic.height = config->height; + + if (ret = cvi_venc.fnCreateChannel(index, &channel)) + return ret; + + { + int count = -1; + if (config->codec != HAL_VIDCODEC_JPG && + (ret = cvi_venc.fnStartReceivingEx(index, &count))) + return ret; + } + + cvi_state[index].payload = config->codec; + + return EXIT_SUCCESS; +} + +int cvi_video_destroy(char index) +{ + int ret; + + cvi_state[index].enable = 0; + cvi_state[index].payload = HAL_VIDCODEC_UNSPEC; + + cvi_venc.fnStopReceiving(index); + + { + cvi_sys_bind source = { .module = CVI_SYS_MOD_VPSS, + .device = _cvi_vpss_grp, .channel = index }; + cvi_sys_bind dest = { .module = CVI_SYS_MOD_VENC, + .device = _cvi_venc_dev, .channel = index }; + if (ret = cvi_sys.fnUnbind(&source, &dest)) + return ret; + } + + if (ret = cvi_venc.fnDestroyChannel(index)) + return ret; + + if (ret = cvi_vpss.fnDisableChannel(_cvi_vpss_grp, index)) + return ret; + + return EXIT_SUCCESS; +} + +int cvi_video_destroy_all(void) +{ + int ret; + + for (char i = 0; i < CVI_VENC_CHN_NUM; i++) + if (cvi_state[i].enable) + if (ret = cvi_video_destroy(i)) + return ret; + + return EXIT_SUCCESS; +} + +void cvi_video_request_idr(char index) +{ + cvi_venc.fnRequestIdr(index, 1); +} + +int cvi_video_snapshot_grab(char index, hal_jpegdata *jpeg) +{ + int ret; + + if (ret = cvi_channel_bind(index)) { + HAL_DANGER("cvi_venc", "Binding the encoder channel " + "%d failed with %#x!\n", index, ret); + goto abort; + } + + unsigned int count = 1; + if (cvi_venc.fnStartReceivingEx(index, &count)) { + HAL_DANGER("cvi_venc", "Requesting one frame " + "%d failed with %#x!\n", index, ret); + goto abort; + } + + int fd = cvi_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("cvi_venc", "Select operation failed!\n"); + goto abort; + } else if (ret == 0) { + HAL_DANGER("cvi_venc", "Capture stream timed out!\n"); + goto abort; + } + + if (FD_ISSET(fd, &readFds)) { + cvi_venc_stat stat; + if (cvi_venc.fnQuery(index, &stat)) { + HAL_DANGER("cvi_venc", "Querying the encoder channel " + "%d failed with %#x!\n", index, ret); + goto abort; + } + + if (!stat.curPacks) { + HAL_DANGER("cvi_venc", "Current frame is empty, skipping it!\n"); + goto abort; + } + + cvi_venc_strm strm; + memset(&strm, 0, sizeof(strm)); + strm.packet = (cvi_venc_pack*)malloc(sizeof(cvi_venc_pack) * stat.curPacks); + if (!strm.packet) { + HAL_DANGER("cvi_venc", "Memory allocation on channel %d failed!\n", index); + goto abort; + } + strm.count = stat.curPacks; + + if (ret = cvi_venc.fnGetStream(index, &strm, stat.curPacks)) { + HAL_DANGER("cvi_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++) { + cvi_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: + cvi_venc.fnFreeStream(index, &strm); + } + + cvi_venc.fnFreeDescriptor(index); + + cvi_venc.fnStopReceiving(index); + + cvi_channel_unbind(index); + + return ret; +} + +void *cvi_video_thread(void) +{ + int ret; + int maxFd = 0; + + for (int i = 0; i < CVI_VENC_CHN_NUM; i++) { + if (!cvi_state[i].enable) continue; + if (!cvi_state[i].mainLoop) continue; + + ret = cvi_venc.fnGetDescriptor(i); + if (ret < 0) { + HAL_DANGER("cvi_venc", "Getting the encoder descriptor failed with %#x!\n", ret); + return NULL; + } + cvi_state[i].fileDesc = ret; + + if (maxFd <= cvi_state[i].fileDesc) + maxFd = cvi_state[i].fileDesc; + } + + cvi_venc_stat stat; + cvi_venc_strm stream; + struct timeval timeout; + fd_set readFds; + + while (keepRunning) { + FD_ZERO(&readFds); + for(int i = 0; i < CVI_VENC_CHN_NUM; i++) { + if (!cvi_state[i].enable) continue; + if (!cvi_state[i].mainLoop) continue; + FD_SET(cvi_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("cvi_venc", "Select operation failed!\n"); + break; + } else if (ret == 0) { + HAL_WARNING("cvi_venc", "Main stream loop timed out!\n"); + continue; + } else { + for (int i = 0; i < CVI_VENC_CHN_NUM; i++) { + if (!cvi_state[i].enable) continue; + if (!cvi_state[i].mainLoop) continue; + if (FD_ISSET(cvi_state[i].fileDesc, &readFds)) { + memset(&stream, 0, sizeof(stream)); + + if (ret = cvi_venc.fnQuery(i, &stat)) { + HAL_DANGER("cvi_venc", "Querying the encoder channel " + "%d failed with %#x!\n", i, ret); + break; + } + + if (!stat.curPacks) { + HAL_WARNING("cvi_venc", "Current frame is empty, skipping it!\n"); + continue; + } + + stream.packet = (cvi_venc_pack*)malloc( + sizeof(cvi_venc_pack) * stat.curPacks); + if (!stream.packet) { + HAL_DANGER("cvi_venc", "Memory allocation on channel %d failed!\n", i); + break; + } + stream.count = stat.curPacks; + + if (ret = cvi_venc.fnGetStream(i, &stream, 40)) { + HAL_DANGER("cvi_venc", "Getting the stream on " + "channel %d failed with %#x!\n", i, ret); + break; + } + + if (cvi_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++) { + cvi_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 (cvi_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; + (*cvi_vid_cb)(i, &outStrm); + } + + if (ret = cvi_venc.fnFreeStream(i, &stream)) { + HAL_WARNING("cvi_venc", "Releasing the stream on " + "channel %d failed with %#x!\n", i, ret); + } + free(stream.packet); + stream.packet = NULL; + } + } + } + } + HAL_INFO("cvi_venc", "Shutting down encoding thread...\n"); +} + +void cvi_system_deinit(void) +{ + cvi_sys.fnExit(); + cvi_vb.fnExit(); + + cvi_sensor_deinit(); +} + +int cvi_system_init(char *snrConfig) +{ + int ret; + + { + cvi_sys_ver version; + cvi_sys.fnGetVersion(&version); + printf("App built with headers v%s\n", CVI_SYS_API); + printf("%s\n", version.version); + } + + if (cvi_parse_sensor_config(snrConfig, &cvi_config) != CONFIG_OK) + HAL_ERROR("cvi_sys", "Can't load sensor config\n"); + + if (ret = cvi_sensor_init(cvi_config.dll_file, cvi_config.sensor_type)) + return ret; + + cvi_sys.fnExit(); + //cvi_vb.fnExit(); + + /*{ + cvi_vb_pool pool; + memset(&pool, 0, sizeof(pool)); + + if (ret = cvi_vb.fnConfigPool(&pool)) + return ret; + }*/ + //if (ret = cvi_vb.fnInit()) + // return ret; + + if (ret = cvi_sys.fnInit()) + return ret; + + return EXIT_SUCCESS; +} + +#endif \ No newline at end of file diff --git a/src/hal/plus/cvi_hal.h b/src/hal/plus/cvi_hal.h new file mode 100644 index 0000000..391b04a --- /dev/null +++ b/src/hal/plus/cvi_hal.h @@ -0,0 +1,62 @@ +#pragma once + +#include "cvi_common.h" +#include "cvi_aud.h" +#include "cvi_config.h" +#include "cvi_isp.h" +#include "cvi_rgn.h" +#include "cvi_snr.h" +#include "cvi_sys.h" +#include "cvi_vb.h" +#include "cvi_venc.h" +#include "cvi_vi.h" +#include "cvi_vpss.h" + +#include +#include +#include +#include + +extern char keepRunning; + +extern hal_chnstate cvi_state[CVI_VENC_CHN_NUM]; +extern int (*cvi_aud_cb)(hal_audframe*); +extern int (*cvi_vid_cb)(char, hal_vidstream*); + +void cvi_hal_deinit(void); +int cvi_hal_init(void); +void *cvi_audio_thread(void); + +void cvi_audio_deinit(void); +int cvi_audio_init(int samplerate); + +int cvi_channel_bind(char index); +int cvi_channel_create(char index, char mirror, char flip, char framerate); +int cvi_channel_grayscale(char enable); +int cvi_channel_unbind(char index); + +void *cvi_image_thread(void); + +int cvi_pipeline_create(void); +void cvi_pipeline_destroy(void); + +int cvi_region_create(char handle, hal_rect rect, short opacity); +void cvi_region_destroy(char handle); +int cvi_region_setbitmap(int handle, hal_bitmap *bitmap); + +void cvi_sensor_deconfig(void); +int cvi_sensor_config(void); +void cvi_sensor_deinit(void); +int cvi_sensor_init(char *name, char *obj); + +int cvi_video_create(char index, hal_vidconfig *config); +int cvi_video_destroy(char index); +int cvi_video_destroy_all(void); +void cvi_video_request_idr(char index); +int cvi_video_snapshot_grab(char index, hal_jpegdata *jpeg); +void *cvi_video_thread(void); + +int cvi_system_calculate_block(short width, short height, cvi_common_pixfmt pixFmt, + unsigned int alignWidth); +void cvi_system_deinit(void); +int cvi_system_init(char *snrConfig); \ No newline at end of file diff --git a/src/hal/plus/cvi_isp.h b/src/hal/plus/cvi_isp.h new file mode 100644 index 0000000..4c34ebc --- /dev/null +++ b/src/hal/plus/cvi_isp.h @@ -0,0 +1,129 @@ +#pragma once + +#include "cvi_common.h" + +typedef enum { + CVI_ISP_DIR_NORMAL, + CVI_ISP_DIR_MIRROR, + CVI_ISP_DIR_FLIP, + CVI_ISP_DIR_MIRROR_FLIP, + CVI_ISP_DIR_END +} cvi_isp_dir; + +typedef struct { + int id; + char libName[20]; +} cvi_isp_alg; + +typedef struct { + cvi_common_rect capt; + cvi_common_dim size; + float framerate; + cvi_common_bayer bayer; + cvi_common_wdr wdr; + unsigned char mode; +} cvi_isp_dev; + +typedef struct { + void *handle, *handleAlgo, *handleAwb, *handleAe; + + int (*fnExit)(int pipe); + int (*fnInit)(int pipe); + int (*fnMemInit)(int pipe); + int (*fnRun)(int pipe); + + int (*fnSetDeviceConfig)(int pipe, cvi_isp_dev *config); + + int (*fnResetIntf)(int device, int state); + int (*fnResetSensor)(int device, int state); + int (*fnSetIntfConfig)(int pipe, void *config); + int (*fnSetSensorClock)(int device, int enable); + int (*fnSetSensorEdge)(int device, int up); + int (*fnSetSensorMaster)(void *freq); + + int (*fnRegisterAE)(int pipe, cvi_isp_alg *library); + int (*fnRegisterAWB)(int pipe, cvi_isp_alg *library); + int (*fnUnregisterAE)(int pipe, cvi_isp_alg *library); + int (*fnUnregisterAWB)(int pipe, cvi_isp_alg *library); +} cvi_isp_impl; + +static int cvi_isp_load(cvi_isp_impl *isp_lib) { + if (!(isp_lib->handle = dlopen("libisp.so", RTLD_LAZY | RTLD_GLOBAL)) || + !(isp_lib->handleAlgo = dlopen("libisp_algo.so", RTLD_LAZY | RTLD_GLOBAL)) || + !(isp_lib->handleAe = dlopen("libae.so", RTLD_LAZY | RTLD_GLOBAL)) || + !(isp_lib->handleAwb = dlopen("libawb.so", RTLD_LAZY | RTLD_GLOBAL))); + + if (!(isp_lib->fnExit = (int(*)(int pipe)) + hal_symbol_load("cvi_isp", isp_lib->handle, "CVI_ISP_Exit"))) + return EXIT_FAILURE; + + if (!(isp_lib->fnInit = (int(*)(int pipe)) + hal_symbol_load("cvi_isp", isp_lib->handle, "CVI_ISP_Init"))) + return EXIT_FAILURE; + + if (!(isp_lib->fnMemInit = (int(*)(int pipe)) + hal_symbol_load("cvi_isp", isp_lib->handle, "CVI_ISP_MemInit"))) + return EXIT_FAILURE; + + if (!(isp_lib->fnRun = (int(*)(int pipe)) + hal_symbol_load("cvi_isp", isp_lib->handle, "CVI_ISP_Run"))) + return EXIT_FAILURE; + + if (!(isp_lib->fnSetDeviceConfig = (int(*)(int pipe, cvi_isp_dev *config)) + hal_symbol_load("cvi_isp", isp_lib->handle, "CVI_ISP_SetPubAttr"))) + return EXIT_FAILURE; + + if (!(isp_lib->fnResetIntf = (int(*)(int device, int state)) + hal_symbol_load("cvi_isp", isp_lib->handle, "CVI_MIPI_SetMipiReset"))) + return EXIT_FAILURE; + + if (!(isp_lib->fnResetSensor = (int(*)(int device, int state)) + hal_symbol_load("cvi_isp", isp_lib->handle, "CVI_MIPI_SetSensorReset"))) + return EXIT_FAILURE; + + if (!(isp_lib->fnSetIntfConfig = (int(*)(int pipe, void *config)) + hal_symbol_load("cvi_isp", isp_lib->handle, "CVI_MIPI_SetMipiAttr"))) + return EXIT_FAILURE; + + if (!(isp_lib->fnSetSensorClock = (int(*)(int device, int enable)) + hal_symbol_load("cvi_isp", isp_lib->handle, "CVI_MIPI_SetSensorClock"))) + return EXIT_FAILURE; + + if (!(isp_lib->fnSetSensorEdge = (int(*)(int device, int up)) + hal_symbol_load("cvi_isp", isp_lib->handle, "CVI_MIPI_SetClkEdge"))) + return EXIT_FAILURE; + + if (!(isp_lib->fnSetSensorMaster = (int(*)(void *freq)) + hal_symbol_load("cvi_isp", isp_lib->handle, "CVI_MIPI_SetSnsMclk"))) + return EXIT_FAILURE; + + if (!(isp_lib->fnRegisterAE = (int(*)(int pipe, cvi_isp_alg *library)) + hal_symbol_load("cvi_isp", isp_lib->handleAe, "CVI_AE_Register"))) + return EXIT_FAILURE; + + if (!(isp_lib->fnRegisterAWB = (int(*)(int pipe, cvi_isp_alg *library)) + hal_symbol_load("cvi_isp", isp_lib->handleAwb, "CVI_AWB_Register"))) + return EXIT_FAILURE; + + if (!(isp_lib->fnUnregisterAE = (int(*)(int pipe, cvi_isp_alg *library)) + hal_symbol_load("cvi_isp", isp_lib->handleAe, "CVI_AE_UnRegister"))) + return EXIT_FAILURE; + + if (!(isp_lib->fnUnregisterAWB = (int(*)(int pipe, cvi_isp_alg *library)) + hal_symbol_load("cvi_isp", isp_lib->handleAwb, "CVI_AWB_UnRegister"))) + return EXIT_FAILURE; + + return EXIT_SUCCESS; +} + +static void cvi_isp_unload(cvi_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->handleAlgo) dlclose(isp_lib->handleAlgo); + isp_lib->handleAlgo = 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/plus/cvi_snr.h b/src/hal/plus/cvi_snr.h new file mode 100644 index 0000000..4406521 --- /dev/null +++ b/src/hal/plus/cvi_snr.h @@ -0,0 +1,219 @@ +#pragma once + +#include "cvi_common.h" +#include "cvi_isp.h" + +#include +#include + +#define CVI_SNR_IOC_MAGIC 'm' +#define CVI_SNR_LVDS_LANE_NUM 4 +#define CVI_SNR_MIPI_LANE_NUM 4 +#define CVI_SNR_WDR_VC_NUM 2 + +enum { + CVI_SNR_CMD_CONF_DEV = 1, + CVI_SNR_CMD_CONF_CMV = 4, + CVI_SNR_CMD_RST_SENS, + CVI_SNR_CMD_UNRST_SENS, + CVI_SNR_CMD_RST_MIPI, + CVI_SNR_CMD_UNRST_MIPI, + CVI_SNR_CMD_RST_SLVS, + CVI_SNR_CMD_UNRST_SLVS, + CVI_SNR_CMD_CONF_HSMODE, + CVI_SNR_CMD_CLKON_MIPI, + CVI_SNR_CMD_CLKOFF_MIPI, + CVI_SNR_CMD_CLKON_SLVS, + CVI_SNR_CMD_CLKOFF_SLVS, + CVI_SNR_CMD_CLKON_SENS, + CVI_SNR_CMD_CLKOFF_SENS +}; + +typedef enum { + CVI_SNR_BRMUX_NONE, + CVI_SNR_BRMUX_2, + CVI_SNR_BRMUX_3, + CVI_SNR_BRMUX_4 +} cvi_snr_brmux; + +typedef enum { + CVI_SNR_GAIN_SHARE, + CVI_SNR_GAIN_WDR_2F, + CVI_SNR_GAIN_WDR_3F, + CVI_SNR_GAIN_ONLY_LEF +} cvi_snr_gain; + +typedef enum { + CVI_SNR_INPUT_BT656, + CVI_SNR_INPUT_BT601, + CVI_SNR_INPUT_DIGITAL_CAMERA, + CVI_SNR_INPUT_INTERLEAVED, + CVI_SNR_INPUT_MIPI, + CVI_SNR_INPUT_LVDS, + CVI_SNR_INPUT_HISPI, + CVI_SNR_INPUT_SUBLVDS, + CVI_SNR_INPUT_END +} cvi_snr_input; + +typedef enum { + CVI_SNR_LFID_NONE, + CVI_SNR_LFID_INSAV, + CVI_SNR_LFID_INDATA, + CVI_SNR_LFID_END +} cvi_snr_lfid; + +typedef enum { + CVI_SNR_LVSYNCT_NORMAL, + CVI_SNR_LVSYNCT_SHARE, + CVI_SNR_LVSYNCT_HCONNECT, + CVI_SNR_LVSYNCT_END +} cvi_snr_lvsynct; + +typedef enum { + CVI_SNR_LWDR_NONE, + CVI_SNR_LWDR_2F, + CVI_SNR_LWDR_3F, + CVI_SNR_LWDR_4F, + CVI_SNR_LWDR_DOL2F, + CVI_SNR_LWDR_DOL3F, + CVI_SNR_LWDR_DOL4F, + CVI_SNR_LWDR_END +} cvi_snr_lwdr; + +typedef enum { + CVI_SNR_MACCK_200M, + CVI_SNR_MACCK_300M, + CVI_SNR_MACCK_400M, + CVI_SNR_MACCK_500M, + CVI_SNR_MACCK_600M, + CVI_SNR_MACCK_END +} cvi_snr_macck; + +typedef enum { + CVI_SNR_MWDR_NONE, + CVI_SNR_MWDR_VC, + CVI_SNR_MWDR_DT, + CVI_SNR_MWDR_DOL, + CVI_SNR_MWDR_MANUAL, /* Applicable in SOI */ + CVI_SNR_MWDR_END +} cvi_snr_mwdr; + +typedef enum { + CVI_SNR_PLLFR_NONE, + CVI_SNR_PLLFR_37P125M, + CVI_SNR_PLLFR_25M, + CVI_SNR_PLLFR_27M, + CVI_SNR_PLLFR_24M, + CVI_SNR_PLLFR_26M, + CVI_SNR_PLLFR_END +} cvi_snr_pllfr; + +typedef struct { + cvi_snr_lfid type; + unsigned char outputFil; +} cvi_snr_fid; + +typedef struct { + cvi_snr_lvsynct type; + unsigned short hBlank1; + unsigned short hBlank2; +} cvi_snr_lvsync; + +typedef struct { + cvi_snr_lwdr wdr; + int syncSavOn; + cvi_common_prec prec; + int dataBeOn; + int syncBeOn; + // Value -1 signifies a lane is disabled + short laneId[CVI_SNR_LVDS_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[CVI_SNR_LVDS_LANE_NUM * CVI_SNR_WDR_VC_NUM * 4]; + cvi_snr_lvsync vsync; + cvi_snr_fid fid; + char pnSwap[CVI_SNR_LVDS_LANE_NUM + 1]; +} cvi_snr_lvds; + +typedef struct { + cvi_common_prec prec; + // Value -1 signifies a lane is disabled + short laneId[CVI_SNR_MIPI_LANE_NUM + 1]; + cvi_snr_mwdr mode; + short dataType[CVI_SNR_WDR_VC_NUM]; + char pnSwap[CVI_SNR_MIPI_LANE_NUM + 1]; + unsigned char dphyEnable; + unsigned char dphyHsSettle; + unsigned int demuxOn; + unsigned char vcMap[4]; +} cvi_snr_mipi; + +typedef struct { + unsigned int cam; + cvi_snr_pllfr freq; +} cvi_snr_pllck; + +typedef struct { + cvi_snr_input input; + cvi_snr_macck macck; + cvi_snr_pllck pllck; + union { + cvi_snr_mipi mipi; + cvi_snr_lvds lvds; + }; + unsigned int device; + cvi_common_dim dest; +} cvi_snr_dev; + +typedef union { + signed char i2c; + struct { + signed char dev : 4; + signed char cs : 4; + } ssp; +} cvi_snr_bus; + +typedef struct { + unsigned int expTime; + unsigned int aGain; + unsigned int dGain; + unsigned int ispDGain; + unsigned int exposure; + unsigned int linesPer500ms; + unsigned int pirisFNO; + unsigned short wbRGain; + unsigned short wbGGain; + unsigned short wbBGain; + unsigned short sampleRGain; + unsigned short sampleBGain; + unsigned short useHwSync; + cvi_snr_gain gain; + int l2sDstFixOn; + cvi_snr_brmux brmux; +} cvi_snr_init; + +typedef struct { + int (*pfnRegisterCallback)(int pipe, cvi_isp_alg *aeLibrary, cvi_isp_alg *awbLibrary); + int (*pfnUnRegisterCallback)(int pipe, cvi_isp_alg *aeLibrary, cvi_isp_alg *awbLibrary); + int (*pfnSetBusInfo)(int pipe, cvi_snr_bus bus); + void (*pfnStandby)(int pipe); + void (*pfnRestart)(int pipe); + void (*pfnMirrorFlip)(int pipe, cvi_isp_dir mode); + int (*pfnWriteReg)(int pipe, int addr, int data); + int (*pfnReadReg)(int pipe, int addr); + int (*pfnSetInit)(int pipe, cvi_snr_init *config); + int (*pfnPatchRxAttr)(cvi_snr_init *config); + void (*pfnPatchI2cAddr)(int addr); + int (*pfnGetRxAttr)(int pipe, cvi_snr_dev *device); + int (*pfnExpSensorCb)(void *config); + int (*pfnExpAeCb)(void *config); + int (*pfnSnsProbe)(int pipe); +} cvi_snr_obj; + +typedef struct { + void *handle; + cvi_snr_obj *obj; +} cvi_snr_drv_impl; + +static const char cvi_snr_endp[] = {"/dev/cvi-mipi-tx"}; \ No newline at end of file diff --git a/src/hal/plus/cvi_sys.h b/src/hal/plus/cvi_sys.h index 49cc577..0bd7579 100644 --- a/src/hal/plus/cvi_sys.h +++ b/src/hal/plus/cvi_sys.h @@ -64,7 +64,7 @@ typedef struct { } cvi_sys_ver; typedef struct { - void *handle, *handleVoiceEngine, *handleVqe, *handleMisc; + void *handle; int (*fnExit)(void); int (*fnGetChipId)(unsigned int *chip); @@ -79,10 +79,7 @@ typedef struct { } cvi_sys_impl; static int cvi_sys_load(cvi_sys_impl *sys_lib) { - if (!(sys_lib->handleMisc = dlopen("libmisc.so", RTLD_LAZY | RTLD_GLOBAL)) || - !(sys_lib->handleVqe = dlopen("libcvi_vqe.so", RTLD_LAZY | RTLD_GLOBAL)) || - !(sys_lib->handleVoiceEngine = dlopen("libcvi_VoiceEngine.so", RTLD_LAZY | RTLD_GLOBAL)) || - !(sys_lib->handle = dlopen("libsys.so", RTLD_LAZY | RTLD_GLOBAL))) + if (!(sys_lib->handle = dlopen("libsys.so", RTLD_LAZY | RTLD_GLOBAL))) HAL_ERROR("cvi_sys", "Failed to load library!\nError: %s\n", dlerror()); if (!(sys_lib->fnExit = (int(*)(void)) @@ -121,12 +118,6 @@ static int cvi_sys_load(cvi_sys_impl *sys_lib) { } static void cvi_sys_unload(cvi_sys_impl *sys_lib) { - if (sys_lib->handleMisc) dlclose(sys_lib->handleMisc); - sys_lib->handleMisc = NULL; - if (sys_lib->handleVqe) dlclose(sys_lib->handleVqe); - sys_lib->handleVqe = 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)); diff --git a/src/hal/plus/cvi_venc.h b/src/hal/plus/cvi_venc.h new file mode 100644 index 0000000..21eba79 --- /dev/null +++ b/src/hal/plus/cvi_venc.h @@ -0,0 +1,488 @@ +#pragma once + +#include "cvi_common.h" + +#define CVI_VENC_CHN_NUM 16 + +typedef enum { + CVI_VENC_CODEC_JPEG = 26, + CVI_VENC_CODEC_H264 = 96, + CVI_VENC_CODEC_H265 = 265, + CVI_VENC_CODEC_MJPG = 1002, + CVI_VENC_CODEC_END +} cvi_venc_codec; + +typedef enum { + CVI_VENC_GOPMODE_NORMALP, + CVI_VENC_GOPMODE_DUALP, + CVI_VENC_GOPMODE_SMARTP, + CVI_VENC_GOPMODE_ADVSMARTP, + CVI_VENC_GOPMODE_BIPREDB, + CVI_VENC_GOPMODE_LOWDELAYB, + CVI_VENC_GOPMODE_END +} cvi_venc_gopmode; + +typedef enum { + CVI_VENC_NALU_H264_BSLICE, + CVI_VENC_NALU_H264_PSLICE, + CVI_VENC_NALU_H264_ISLICE, + CVI_VENC_NALU_H264_IDRSLICE = 5, + CVI_VENC_NALU_H264_SEI, + CVI_VENC_NALU_H264_SPS, + CVI_VENC_NALU_H264_PPS, + CVI_VENC_NALU_H264_END +} cvi_venc_nalu_h264; + +typedef enum { + CVI_VENC_NALU_H265_BSLICE, + CVI_VENC_NALU_H265_PSLICE, + CVI_VENC_NALU_H265_ISLICE, + CVI_VENC_NALU_H265_IDRSLICE = 19, + CVI_VENC_NALU_H265_VPS = 32, + CVI_VENC_NALU_H265_SPS, + CVI_VENC_NALU_H265_PPS, + CVI_VENC_NALU_H265_SEI = 39, + CVI_VENC_NALU_H265_END +} cvi_venc_nalu_h265; + +typedef enum { + CVI_VENC_NALU_MJPG_ECS = 5, + CVI_VENC_NALU_MJPG_APP, + CVI_VENC_NALU_MJPG_VDO, + CVI_VENC_NALU_MJPG_PIC, + CVI_VENC_NALU_MJPG_DCF, + CVI_VENC_NALU_MJPG_DCFPIC, + CVI_VENC_NALU_MJPG_END +} cvi_venc_nalu_mjpg; + +typedef enum { + CVI_VENC_RATEMODE_H264CBR = 1, + CVI_VENC_RATEMODE_H264VBR, + CVI_VENC_RATEMODE_H264AVBR, + CVI_VENC_RATEMODE_H264QVBR, + CVI_VENC_RATEMODE_H264QP, + CVI_VENC_RATEMODE_H264QPMAP, + CVI_VENC_RATEMODE_H264UBR, + CVI_VENC_RATEMODE_MJPGCBR, + CVI_VENC_RATEMODE_MJPGVBR, + CVI_VENC_RATEMODE_MJPGQP, + CVI_VENC_RATEMODE_H265CBR, + CVI_VENC_RATEMODE_H265VBR, + CVI_VENC_RATEMODE_H265AVBR, + CVI_VENC_RATEMODE_H265QVBR, + CVI_VENC_RATEMODE_H265QP, + CVI_VENC_RATEMODE_H265QPMAP, + CVI_VENC_RATEMODE_H265UBR, + CVI_VENC_RATEMODE_END +} cvi_venc_ratemode; + +typedef struct { + char rcnRefShareBufOn; +} cvi_venc_attr_h264; + +typedef struct { + char rcnRefShareBufOn; + char singleBufLumaOn; +} cvi_venc_attr_h265; + +typedef struct { + char dcfThumbs; + unsigned char numThumbs; + cvi_common_dim sizeThumbs[2]; + int multiReceiveOn; +} cvi_venc_attr_jpg; + +typedef struct { + cvi_venc_codec codec; + cvi_common_dim maxPic; + unsigned int bufSize; + unsigned int profile; + char byFrame; + cvi_common_dim pic; + char singleCoreOn; + char esBufQueueOn; + char isolateFrmOn; + union { + cvi_venc_attr_h264 h264; + cvi_venc_attr_h265 h265; + cvi_venc_attr_jpg jpg; + int prores[3]; + }; +} cvi_venc_attrib; + +typedef struct { + unsigned int gop; + unsigned int statTime; + unsigned int srcFps; + unsigned int dstFps; + unsigned int maxBitrate; + char variFpsOn; +} cvi_venc_rate_h26xbr; + +typedef struct { + unsigned int gop; + unsigned int statTime; + unsigned int srcFps; + unsigned int dstFps; + unsigned int maxBitrate; + unsigned int shortTermStatTime; + unsigned int longTermStatTime; + unsigned int longTermMaxBitrate; + unsigned int longTermMinBitrate; + char variFpsOn; +} cvi_venc_rate_h26xcvbr; + +typedef struct { + unsigned int gop; + unsigned int srcFps; + unsigned int dstFps; + unsigned int interQual; + unsigned int predQual; + unsigned int bipredQual; + char variFpsOn; +} cvi_venc_rate_h26xqp; + +typedef struct { + unsigned int gop; + unsigned int statTime; + unsigned int srcFps; + unsigned int dstFps; + char variFpsOn; +} cvi_venc_rate_h264qpmap; + +typedef struct { + unsigned int gop; + unsigned int statTime; + unsigned int srcFps; + unsigned int dstFps; + // Accepts values from 0-2 (mean QP, min QP, max QP) + int qpMapMode; + char variFpsOn; +} cvi_venc_rate_h265qpmap; + +typedef struct { + unsigned int statTime; + unsigned int srcFps; + unsigned int dstFps; + unsigned int maxBitrate; + char variFpsOn; +} cvi_venc_rate_mjpgbr; + +typedef struct { + unsigned int srcFps; + unsigned int dstFps; + unsigned int quality; + char variFpsOn; +} cvi_venc_rate_mjpgqp; + +typedef struct { + cvi_venc_ratemode mode; + union { + cvi_venc_rate_h26xbr h264Cbr; + cvi_venc_rate_h26xbr h264Vbr; + cvi_venc_rate_h26xbr h264Avbr; + cvi_venc_rate_h26xbr h264Qvbr; + cvi_venc_rate_h26xcvbr h264Cvbr; + cvi_venc_rate_h26xqp h264Qp; + cvi_venc_rate_h264qpmap h264QpMap; + cvi_venc_rate_mjpgbr mjpgCbr; + cvi_venc_rate_mjpgbr mjpgVbr; + cvi_venc_rate_mjpgqp mjpgQp; + cvi_venc_rate_h26xbr h265Cbr; + cvi_venc_rate_h26xbr h265Vbr; + cvi_venc_rate_h26xbr h265Avbr; + cvi_venc_rate_h26xbr h265Qvbr; + cvi_venc_rate_h26xcvbr h265Cvbr; + cvi_venc_rate_h26xqp h265Qp; + cvi_venc_rate_h265qpmap h265QpMap; + }; +} cvi_venc_rate; + +typedef struct { + int ipQualDelta; +} cvi_venc_gop_normalp; + +typedef struct { + unsigned int spInterv; + int spQualDelta; + int ipQualDelta; +} cvi_venc_gop_dualp; + +typedef struct { + unsigned int bgInterv; + int bgQualDelta; + int viQualDelta; +} cvi_venc_gop_smartp; + +typedef struct { + unsigned int bFrameNum; + int bgQualDelta; + int ipQualDelta; +} cvi_venc_gop_bipredb; + +typedef struct { + cvi_venc_gopmode mode; + union { + cvi_venc_gop_normalp normalP; + cvi_venc_gop_dualp dualP; + cvi_venc_gop_smartp smartP; + cvi_venc_gop_smartp advSmartP; + cvi_venc_gop_bipredb bipredB; + }; +} cvi_venc_gop; + +typedef struct { + cvi_venc_attrib attrib; + cvi_venc_rate rate; + cvi_venc_gop gop; +} cvi_venc_chn; + +typedef struct { + unsigned int quality; + unsigned char qtLuma[64]; + unsigned char qtChromaBlue[64]; + unsigned char qtChromaRed[64]; + unsigned int mcuPerEcs; +} cvi_venc_jpg; + +typedef union { + cvi_venc_nalu_h264 h264Nalu; + cvi_venc_nalu_mjpg mjpgNalu; + cvi_venc_nalu_h265 h265Nalu; + int proresNalu; +} cvi_venc_nalu; + +typedef struct { + cvi_venc_nalu packType; + unsigned int offset; + unsigned int length; +} cvi_venc_packinfo; + +typedef struct { + unsigned long long addr; + unsigned char __attribute__((aligned (4)))*data; + unsigned int __attribute__((aligned (4)))length; + unsigned long long timestamp; + char endFrame; + cvi_venc_nalu naluType; + unsigned int offset; + unsigned int packNum; + cvi_venc_packinfo packetInfo[8]; +} cvi_venc_pack; + +typedef struct { + char grayscaleOn; + unsigned int prio; + unsigned int maxStrmCnt; + unsigned int wakeFrmCnt; + char cropOn; + cvi_common_rect crop; + int srcFps; + int dstFps; +} cvi_venc_para; + +typedef struct { + unsigned int leftPics; + unsigned int leftBytes; + unsigned int leftFrames; + unsigned int curPacks; + unsigned int leftRecvPics; + unsigned int leftEncPics; + char jpegSnapEnd; + char strmInfo[53]; +} cvi_venc_stat; + +typedef struct { + unsigned int size; + unsigned int iMb16x16; + unsigned int iMb8x8; + unsigned int pMb16; + unsigned int pMb8; + unsigned int pMb4; + unsigned int refType; + unsigned int updAttrCnt; + unsigned int startQual; + unsigned int meanQual; + char pSkip; +} cvi_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; + unsigned int meanQual; + char pSkip; +} cvi_venc_strminfo_h265; + +typedef struct { + unsigned int size; + unsigned int updAttrCnt; + unsigned int quality; +} cvi_venc_strminfo_mjpg; + +typedef struct { + unsigned int size; + unsigned int updAttrCnt; +} cvi_venc_strminfo_pres; + +typedef struct { + char sseOn; + unsigned int sseVal; +} cvi_venc_sseinfo; + +typedef struct { + unsigned int residualBitNum; + unsigned int headBitNum; + unsigned int madiVal; + unsigned int madpVal; + double psnrVal; + unsigned int mseLcuCnt; + unsigned int mseSum; + cvi_venc_sseinfo sseInfo[8]; + unsigned int qualHstgrm[52]; + unsigned int moveSceneNum; + unsigned int moveSceneBits; +} cvi_venc_strmadvinfo_h26x; + +typedef struct { + unsigned int reserved; +} cvi_venc_strmadvinfo_mjpg; + +typedef struct { + unsigned int reserved; +} cvi_venc_strmadvinfo_pres; + +typedef struct { + cvi_venc_pack __attribute__((aligned(4)))*packet; + unsigned int __attribute__((aligned(4)))count; + unsigned int sequence; + union { + cvi_venc_strminfo_h264 h264Info; + cvi_venc_strminfo_mjpg mjpgInfo; + cvi_venc_strminfo_h265 h265Info; + cvi_venc_strminfo_pres proresInfo; + }; + union { + cvi_venc_strmadvinfo_h26x h264aInfo; + cvi_venc_strmadvinfo_mjpg mjpgaInfo; + cvi_venc_strmadvinfo_h26x h265aInfo; + cvi_venc_strmadvinfo_pres proresaInfo; + }; +} cvi_venc_strm; + +typedef struct { + void *handle; + + int (*fnCreateChannel)(int channel, cvi_venc_chn *config); + int (*fnGetChannelConfig)(int channel, cvi_venc_chn *config); + int (*fnGetChannelParam)(int channel, cvi_venc_para *config); + int (*fnDestroyChannel)(int channel); + int (*fnResetChannel)(int channel); + int (*fnSetChannelConfig)(int channel, cvi_venc_chn *config); + int (*fnSetChannelParam)(int channel, cvi_venc_para *config); + int (*fnSetColorToGray)(int channel, int *active); + + int (*fnFreeDescriptor)(int channel); + int (*fnGetDescriptor)(int channel); + + int (*fnGetJpegParam)(int channel, cvi_venc_jpg *param); + int (*fnSetJpegParam)(int channel, cvi_venc_jpg *param); + + int (*fnFreeStream)(int channel, cvi_venc_strm *stream); + int (*fnGetStream)(int channel, cvi_venc_strm *stream, int millis); + + int (*fnQuery)(int channel, cvi_venc_stat* stats); + + int (*fnRequestIdr)(int channel, char instant); + int (*fnStartReceivingEx)(int channel, int *count); + int (*fnStopReceiving)(int channel); +} cvi_venc_impl; + +static int cvi_venc_load(cvi_venc_impl *venc_lib) { + if (!(venc_lib->handle = dlopen("libvenc.so", RTLD_LAZY | RTLD_GLOBAL))) + HAL_ERROR("cvi_venc", "Failed to load library!\nError: %s\n", dlerror()); + + if (!(venc_lib->fnCreateChannel = (int(*)(int channel, cvi_venc_chn *config)) + hal_symbol_load("cvi_venc", venc_lib->handle, "CVI_VENC_CreateChn"))) + return EXIT_FAILURE; + + if (!(venc_lib->fnDestroyChannel = (int(*)(int channel)) + hal_symbol_load("cvi_venc", venc_lib->handle, "CVI_VENC_DestroyChn"))) + + if (!(venc_lib->fnGetChannelConfig = (int(*)(int channel, cvi_venc_chn *config)) + hal_symbol_load("cvi_venc", venc_lib->handle, "CVI_VENC_GetChnAttr"))) + return EXIT_FAILURE; + + if (!(venc_lib->fnGetChannelParam = (int(*)(int channel, cvi_venc_para *config)) + hal_symbol_load("cvi_venc", venc_lib->handle, "CVI_VENC_GetChnParam"))) + return EXIT_FAILURE; + + if (!(venc_lib->fnResetChannel = (int(*)(int channel)) + hal_symbol_load("cvi_venc", venc_lib->handle, "CVI_VENC_ResetChn"))) + return EXIT_FAILURE; + + if (!(venc_lib->fnSetChannelConfig = (int(*)(int channel, cvi_venc_chn *config)) + hal_symbol_load("cvi_venc", venc_lib->handle, "CVI_VENC_SetChnAttr"))) + return EXIT_FAILURE; + + if (!(venc_lib->fnSetChannelParam = (int(*)(int channel, cvi_venc_para *config)) + hal_symbol_load("cvi_venc", venc_lib->handle, "CVI_VENC_SetChnParam"))) + return EXIT_FAILURE; + + if (!(venc_lib->fnFreeDescriptor = (int(*)(int channel)) + hal_symbol_load("cvi_venc", venc_lib->handle, "CVI_VENC_CloseFd"))) + return EXIT_FAILURE; + + if (!(venc_lib->fnGetDescriptor = (int(*)(int channel)) + hal_symbol_load("cvi_venc", venc_lib->handle, "CVI_VENC_GetFd"))) + return EXIT_FAILURE; + + if (!(venc_lib->fnGetJpegParam = (int(*)(int channel, cvi_venc_jpg *param)) + hal_symbol_load("cvi_venc", venc_lib->handle, "CVI_VENC_GetJpegParam"))) + return EXIT_FAILURE; + + if (!(venc_lib->fnSetJpegParam = (int(*)(int channel, cvi_venc_jpg *param)) + hal_symbol_load("cvi_venc", venc_lib->handle, "CVI_VENC_SetJpegParam"))) + return EXIT_FAILURE; + + if (!(venc_lib->fnFreeStream = (int(*)(int channel, cvi_venc_strm *stream)) + hal_symbol_load("cvi_venc", venc_lib->handle, "CVI_VENC_ReleaseStream"))) + return EXIT_FAILURE; + + if (!(venc_lib->fnGetStream = (int(*)(int channel, cvi_venc_strm *stream, int millis)) + hal_symbol_load("cvi_venc", venc_lib->handle, "CVI_VENC_GetStream"))) + return EXIT_FAILURE; + + if (!(venc_lib->fnQuery = (int(*)(int channel, cvi_venc_stat *stats)) + hal_symbol_load("cvi_venc", venc_lib->handle, "CVI_VENC_QueryStatus"))) + return EXIT_FAILURE; + + if (!(venc_lib->fnRequestIdr = (int(*)(int channel, char instant)) + hal_symbol_load("cvi_venc", venc_lib->handle, "CVI_VENC_RequestIDR"))) + return EXIT_FAILURE; + + if (!(venc_lib->fnStartReceivingEx = (int(*)(int channel, int *count)) + hal_symbol_load("cvi_venc", venc_lib->handle, "CVI_VENC_StartRecvFrame"))) + return EXIT_FAILURE; + + if (!(venc_lib->fnStopReceiving = (int(*)(int channel)) + hal_symbol_load("cvi_venc", venc_lib->handle, "CVI_VENC_StopRecvFrame"))) + return EXIT_FAILURE; + + return EXIT_SUCCESS; +} + +static void cvi_venc_unload(cvi_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/plus/cvi_vi.h b/src/hal/plus/cvi_vi.h index 65b444d..6bdf08a 100644 --- a/src/hal/plus/cvi_vi.h +++ b/src/hal/plus/cvi_vi.h @@ -105,7 +105,9 @@ typedef struct { // Accepts values from 0-2 (yuv, rgb, early yuv) int rgbMode; cvi_common_dim size; - cvi_vi_wdr wdr; + cvi_common_wdr wdrMode; + unsigned int wdrCacheLine; + char wdrSynthOn; cvi_common_bayer bayerMode; unsigned int chnNum; unsigned int snrFps; diff --git a/src/hal/star/i6_hal.h b/src/hal/star/i6_hal.h index 2a46cbe..8266ac1 100644 --- a/src/hal/star/i6_hal.h +++ b/src/hal/star/i6_hal.h @@ -19,10 +19,10 @@ extern int (*i6_vid_cb)(char, hal_vidstream*); void i6_hal_deinit(void); int i6_hal_init(void); -void *i6_audio_thread(void); void i6_audio_deinit(void); int i6_audio_init(int samplerate); +void *i6_audio_thread(void); int i6_channel_bind(char index, char framerate); int i6_channel_create(char index, short width, short height, char mirror, char flip, char jpeg); diff --git a/src/hal/support.c b/src/hal/support.c index cee6196..68f999c 100644 --- a/src/hal/support.c +++ b/src/hal/support.c @@ -65,7 +65,7 @@ void hal_identify(void) { #ifdef __arm__ if (!access("/proc/mi_modules", 0) && - hal_registry(0x1F003C00, &series, OP_READ)) + hal_registry(0x1F003C00, &series, OP_READ)) { switch (series) { case 0xEF: // Macaron (6) case 0xF1: // Pudding (6E) @@ -98,16 +98,17 @@ void hal_identify(void) { vid_thread = i6f_video_thread; return; } + } if (!access("/dev/vpd", 0)) { plat = HAL_PLATFORM_GM; strcpy(chip, "GM813x"); - strcpy(family, "grainmedia"); if (file = fopen("/proc/pmu/chipver", "r")) { fgets(line, 200, file); sscanf(line, "%4s", chip + 2); fclose(file); } + strcpy(family, "grainmedia"); chnCount = GM_VENC_CHN_NUM; chnState = (hal_chnstate*)gm_state; aud_thread = gm_audio_thread; @@ -230,4 +231,15 @@ void hal_identify(void) { isp_thread = v4_image_thread; vid_thread = v4_video_thread; #endif + +#if defined(__riscv) || defined(__riscv__) + if (!access("/proc/cvi", 0)) { + plat = HAL_PLATFORM_CVI; + strcpy(family, "CV181x"); + chnCount = CVI_VENC_CHN_NUM; + chnState = (hal_chnstate*)cvi_state; + aud_thread = cvi_audio_thread; + vid_thread = cvi_video_thread; + } +#endif } diff --git a/src/hal/support.h b/src/hal/support.h index 070594b..50aecdd 100644 --- a/src/hal/support.h +++ b/src/hal/support.h @@ -10,6 +10,8 @@ #include "star/i6f_hal.h" #elif defined(__mips__) #include "inge/t31_hal.h" +#elif defined(__riscv) || defined(__riscv__) +#include "plus/cvi_hal.h" #endif #include diff --git a/src/hal/types.h b/src/hal/types.h index 7223cfa..105e5a9 100644 --- a/src/hal/types.h +++ b/src/hal/types.h @@ -20,6 +20,7 @@ typedef enum { HAL_PLATFORM_UNK, + HAL_PLATFORM_CVI, HAL_PLATFORM_GM, HAL_PLATFORM_I3, HAL_PLATFORM_I6, diff --git a/src/media.c b/src/media.c index 9a4e179..541f40e 100644 --- a/src/media.c +++ b/src/media.c @@ -161,6 +161,8 @@ void request_idr(void) { case HAL_PLATFORM_V4: v4_video_request_idr(index); break; #elif defined(__mips__) case HAL_PLATFORM_T31: t31_video_request_idr(index); break; +#elif defined(__riscv) || defined(__riscv__) + case HAL_PLATFORM_CVI: cvi_video_request_idr(index); break; #endif } pthread_mutex_unlock(&chnMtx); @@ -179,6 +181,8 @@ void set_grayscale(bool active) { case HAL_PLATFORM_V4: v4_channel_grayscale(active); break; #elif defined(__mips__) case HAL_PLATFORM_T31: t31_channel_grayscale(active); break; +#elif defined(__riscv) || defined(__riscv__) + case HAL_PLATFORM_CVI: cvi_channel_grayscale(active); break; #endif } pthread_mutex_unlock(&chnMtx); @@ -219,6 +223,9 @@ int create_channel(char index, short width, short height, char framerate, char j #elif defined(__mips__) case HAL_PLATFORM_T31: return t31_channel_create(index, width, height, framerate); +#elif defined(__riscv) || defined(__riscv__) + case HAL_PLATFORM_CVI: return cvi_channel_create(index, app_config.mirror, + app_config.flip, framerate); #endif } } @@ -236,6 +243,8 @@ int bind_channel(char index, char framerate, char jpeg) { case HAL_PLATFORM_V4: return v4_channel_bind(index); #elif defined(__mips__) case HAL_PLATFORM_T31: return t31_channel_bind(index); +#elif defined(__riscv) || defined(__riscv__) + case HAL_PLATFORM_CVI: return cvi_channel_bind(index); #endif } } @@ -253,6 +262,8 @@ int unbind_channel(char index, char jpeg) { case HAL_PLATFORM_V4: return v4_channel_unbind(index); #elif defined(__mips__) case HAL_PLATFORM_T31: return t31_channel_unbind(index); +#elif defined(__riscv) || defined(__riscv__) + case HAL_PLATFORM_CVI: return cvi_channel_unbind(index); #endif } } @@ -270,6 +281,8 @@ int disable_video(char index, char jpeg) { case HAL_PLATFORM_V4: return v4_video_destroy(index); #elif defined(__mips__) case HAL_PLATFORM_T31: return t31_video_destroy(index); +#elif defined(__riscv) || defined(__riscv__) + case HAL_PLATFORM_CVI: return cvi_video_destroy(index); #endif } return 0; @@ -292,6 +305,8 @@ void disable_audio(void) { case HAL_PLATFORM_V4: v4_audio_deinit(); break; #elif defined(__mips__) case HAL_PLATFORM_T31: t31_audio_deinit(); break; +#elif defined(__riscv) || defined(__riscv__) + case HAL_PLATFORM_CVI: cvi_audio_deinit(); break; #endif } } @@ -311,6 +326,8 @@ int enable_audio(void) { case HAL_PLATFORM_V4: ret = v4_audio_init(app_config.audio_srate); break; #elif defined(__mips__) case HAL_PLATFORM_T31: ret = t31_audio_init(app_config.audio_srate); break; +#elif defined(__riscv) || defined(__riscv__) + case HAL_PLATFORM_CVI: ret = cvi_audio_init(app_config.audio_srate); break; #endif } if (ret) @@ -413,6 +430,8 @@ int enable_mjpeg(void) { case HAL_PLATFORM_V4: ret = v4_video_create(index, &config); break; #elif defined(__mips__) case HAL_PLATFORM_T31: ret = t31_video_create(index, &config); break; +#elif defined(__riscv) || defined(__riscv__) + case HAL_PLATFORM_CVI: ret = cvi_video_create(index, &config); break; #endif } @@ -483,6 +502,8 @@ int enable_mp4(void) { case HAL_PLATFORM_V4: ret = v4_video_create(index, &config); break; #elif defined(__mips__) case HAL_PLATFORM_T31: ret = t31_video_create(index, &config); break; +#elif defined(__riscv) || defined(__riscv__) + case HAL_PLATFORM_CVI: ret = cvi_video_create(index, &config); break; #endif } @@ -517,6 +538,8 @@ int start_sdk(void) { case HAL_PLATFORM_V4: ret = v4_hal_init(); break; #elif defined(__mips__) case HAL_PLATFORM_T31: ret = t31_hal_init(); break; +#elif defined(__riscv) || defined(__riscv__) + case HAL_PLATFORM_CVI: ret = cvi_hal_init(); break; #endif } if (ret) @@ -562,6 +585,11 @@ int start_sdk(void) { t31_aud_cb = save_audio_stream; t31_vid_cb = save_video_stream; break; +#elif defined(__riscv) || defined(__riscv__) + case HAL_PLATFORM_CVI: + cvi_aud_cb = save_audio_stream; + cvi_vid_cb = save_video_stream; + break; #endif } @@ -577,6 +605,8 @@ int start_sdk(void) { case HAL_PLATFORM_V4: ret = v4_system_init(app_config.sensor_config); break; #elif defined(__mips__) case HAL_PLATFORM_T31: ret = t31_system_init(); break; +#elif defined(__riscv) || defined(__riscv__) + case HAL_PLATFORM_CVI: ret = cvi_system_init(app_config.sensor_config); break; #endif } if (ret) @@ -611,6 +641,8 @@ int start_sdk(void) { #elif defined(__mips__) case HAL_PLATFORM_T31: ret = t31_pipeline_create(app_config.mirror, app_config.flip, app_config.antiflicker, framerate); break; +#elif defined(__riscv) || defined(__riscv__) + case HAL_PLATFORM_CVI: ret = cvi_pipeline_create(); break; #endif } if (ret) @@ -702,6 +734,8 @@ int stop_sdk(void) { case HAL_PLATFORM_V4: v4_video_destroy_all(); break; #elif defined(__mips__) case HAL_PLATFORM_T31: t31_video_destroy_all(); break; +#elif defined(__riscv) || defined(__riscv__) + case HAL_PLATFORM_CVI: cvi_video_destroy_all(); break; #endif } @@ -717,6 +751,8 @@ int stop_sdk(void) { case HAL_PLATFORM_V4: v4_pipeline_destroy(); break; #elif defined(__mips__) case HAL_PLATFORM_T31: t31_pipeline_destroy(); break; +#elif defined(__riscv) || defined(__riscv__) + case HAL_PLATFORM_CVI: cvi_pipeline_destroy(); break; #endif } @@ -738,6 +774,8 @@ int stop_sdk(void) { case HAL_PLATFORM_V4: v4_system_deinit(); break; #elif defined(__mips__) case HAL_PLATFORM_T31: t31_system_deinit(); break; +#elif defined(__riscv) || defined(__riscv__) + case HAL_PLATFORM_CVI: cvi_system_deinit(); break; #endif } @@ -762,6 +800,8 @@ int stop_sdk(void) { case HAL_PLATFORM_V4: v4_hal_deinit(); break; #elif defined(__mips__) case HAL_PLATFORM_T31: t31_hal_deinit(); break; +#elif defined(__riscv) || defined(__riscv__) + case HAL_PLATFORM_CVI: cvi_hal_deinit(); break; #endif }