diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 829d5de..8762351 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -70,7 +70,7 @@ jobs: - name: Build Images uses: addnab/docker-run-action@v3 with: - image: ghcr.io/fishwaldo/sophgo-sg200x-debian:master + image: ghcr.io/fishwaldo/sophgo-sg200x-debian:${{ github.ref_name }} options: --privileged -v ${{ github.workspace }}/images/:/output -v ${{ github.workspace }}/configs/:/configs/ run: | make BOARD=${{ matrix.boards }} STORAGE_TYPE=${{ matrix.storage }} image diff --git a/configs/common/patches/middleware/0001-sample-vdec-venc-add-latomic.patch b/configs/common/patches/middleware/0001-sample-vdec-venc-add-latomic.patch new file mode 100644 index 0000000..7a28535 --- /dev/null +++ b/configs/common/patches/middleware/0001-sample-vdec-venc-add-latomic.patch @@ -0,0 +1,39 @@ +From ec315c37ceb367f261c928d2b1b3aa1e8305480f Mon Sep 17 00:00:00 2001 +From: builder +Date: Sat, 1 Mar 2025 16:40:13 +0000 +Subject: [PATCH] sample: vdec/venc: add -latomic + +--- + sample/vdec/Makefile | 2 +- + sample/venc/Makefile | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/sample/vdec/Makefile b/sample/vdec/Makefile +index c889325..4193aa1 100644 +--- a/sample/vdec/Makefile ++++ b/sample/vdec/Makefile +@@ -39,7 +39,7 @@ LIBS += -lnanomsg + endif + + EXTRA_CFLAGS = $(DEFS) $(INCS) +-EXTRA_LDFLAGS = $(LIBS) -lini -lm -lpthread ++EXTRA_LDFLAGS = $(LIBS) -lini -lm -lpthread -latomic + + + EXTRA_LDFLAGS_WITH_ASAN = -Wl,-Bdynamic $(LIBS) -lini -lm -lpthread +diff --git a/sample/venc/Makefile b/sample/venc/Makefile +index b112818..5907c21 100644 +--- a/sample/venc/Makefile ++++ b/sample/venc/Makefile +@@ -46,7 +46,7 @@ LIBS += -lnanomsg + endif + + EXTRA_CFLAGS = $(INCS) $(DEFS) +-EXTRA_LDFLAGS = $(LIBS) -lini -lpthread ++EXTRA_LDFLAGS = $(LIBS) -lini -lpthread -latomic + + EXTRA_LDFLAGS_WITH_ASAN = -Wl,-Bdynamic $(LIBS) -lini -lpthread + +-- +2.47.2 + diff --git a/configs/common/patches/middleware/0002-modules-vdec-enable-CVI_VDEC_GetFd.patch b/configs/common/patches/middleware/0002-modules-vdec-enable-CVI_VDEC_GetFd.patch new file mode 100644 index 0000000..9058d8f --- /dev/null +++ b/configs/common/patches/middleware/0002-modules-vdec-enable-CVI_VDEC_GetFd.patch @@ -0,0 +1,37 @@ +From af59692492292e4157be5d1cdf2a603bc1f8ce11 Mon Sep 17 00:00:00 2001 +From: scpcom +Date: Sun, 22 Sep 2024 23:55:42 +0200 +Subject: [PATCH] modules: vdec: enable CVI_VDEC_GetFd + +--- + modules/vdec/src/cvi_vdec.c | 7 ------- + 1 file changed, 7 deletions(-) + +diff --git a/modules/vdec/src/cvi_vdec.c b/modules/vdec/src/cvi_vdec.c +index 4912ea7..a0099d4 100644 +--- a/modules/vdec/src/cvi_vdec.c ++++ b/modules/vdec/src/cvi_vdec.c +@@ -121,11 +121,6 @@ CVI_S32 CVI_VDEC_QueryStatus(VDEC_CHN VdChn, VDEC_CHN_STATUS_S *pstStatus) + return CVI_FAILURE; + } + +-/* +-* CVI_VDEC_GetFd and CVI_VDEC_CloseFd is NOT used now, +-* so we comment these two APIs temporarily. +-* If you need them, you can uncomment. +- + CVI_S32 CVI_VDEC_GetFd(VDEC_CHN VdChn) + { + if (s32VdecFd[VdChn] <= 0) { +@@ -145,8 +140,6 @@ CVI_S32 CVI_VDEC_CloseFd(VDEC_CHN VdChn) + return CVI_SUCCESS; + } + +-*/ +- + CVI_S32 CVI_VDEC_ResetChn(VDEC_CHN VdChn) + { + if (s32VdecFd[VdChn] > 0) { +-- +2.34.1 + diff --git a/configs/common/patches/middleware/0003-re-add-CVI_VDEC_GetFd-CVI_VDEC_CloseFd-to-cvi_vdec.h.patch b/configs/common/patches/middleware/0003-re-add-CVI_VDEC_GetFd-CVI_VDEC_CloseFd-to-cvi_vdec.h.patch new file mode 100644 index 0000000..c03aa4e --- /dev/null +++ b/configs/common/patches/middleware/0003-re-add-CVI_VDEC_GetFd-CVI_VDEC_CloseFd-to-cvi_vdec.h.patch @@ -0,0 +1,37 @@ +From 72e2cbd18ca629e7d04070edf33c54e735964e5b Mon Sep 17 00:00:00 2001 +From: scpcom +Date: Fri, 25 Oct 2024 18:34:03 +0200 +Subject: [PATCH] re-add CVI_VDEC_GetFd/CVI_VDEC_CloseFd to cvi_vdec.h + +--- + include/cvi_vdec.h | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +diff --git a/include/cvi_vdec.h b/include/cvi_vdec.h +index 6ccdba0..bc3989a 100644 +--- a/include/cvi_vdec.h ++++ b/include/cvi_vdec.h +@@ -73,6 +73,20 @@ CVI_S32 CVI_VDEC_StopRecvStream(VDEC_CHN VdChn); + */ + CVI_S32 CVI_VDEC_QueryStatus(VDEC_CHN VdChn, VDEC_CHN_STATUS_S *pstStatus); + ++/* Get File Descriptor ++ * ++ * @param VdChn(In): channel number ++ * @return Error code (0 if successful) ++ */ ++CVI_S32 CVI_VDEC_GetFd(VDEC_CHN VdChn); ++ ++/* Close File Descriptor ++ * ++ * @param VdChn(In): channel number ++ * @return Error code (0 if successful) ++ */ ++CVI_S32 CVI_VDEC_CloseFd(VDEC_CHN VdChn); ++ + /* Reset Channel + * + * @param VdChn(In): channel number +-- +2.34.1 + diff --git a/configs/common/patches/middleware/0004-sample-add-test_mmf.patch b/configs/common/patches/middleware/0004-sample-add-test_mmf.patch new file mode 100644 index 0000000..c974322 --- /dev/null +++ b/configs/common/patches/middleware/0004-sample-add-test_mmf.patch @@ -0,0 +1,13289 @@ +From 34f678d1b92c26d6ab6db7bf6e82595622e963b9 Mon Sep 17 00:00:00 2001 +From: scpcom +Date: Sat, 8 Mar 2025 02:59:56 +0100 +Subject: [PATCH] sample: add test_mmf + +--- + Makefile | 1 + + sample/test_mmf/.gitignore | 10 + + sample/test_mmf/Makefile | 114 + + sample/test_mmf/fomat.h | 217 + + sample/test_mmf/maix_mmf.h | 282 + + sample/test_mmf/maix_mmf/Makefile | 58 + + sample/test_mmf/maix_mmf/gcc.mk | 103 + + sample/test_mmf/maix_mmf/sophgo_middleware.c | 5585 +++++++++++++++++ + .../rtsp_server/inc/h264-file-reader.h | 51 + + .../rtsp_server/inc/h264-file-source.h | 52 + + .../rtsp_server/inc/h264-memory-reader.h | 59 + + .../rtsp_server/inc/h264-memory-source.h | 53 + + .../rtsp_server/inc/h265-file-reader.h | 51 + + .../rtsp_server/inc/h265-file-source.h | 52 + + .../test_mmf/rtsp_server/inc/media-source.h | 30 + + .../rtsp_server/inc/rtp-tcp-transport.h | 35 + + .../rtsp_server/inc/rtp-udp-transport.h | 26 + + .../rtsp_server/inc/rtsp-camera-reader.h | 59 + + .../rtsp_server/inc/rtsp-camera-source.h | 53 + + sample/test_mmf/rtsp_server/inc/rtsp_server.h | 28 + + .../rtsp_server/src/h264-file-reader.cpp | 166 + + .../rtsp_server/src/h264-file-source.cpp | 207 + + .../rtsp_server/src/h264-memory-reader.cpp | 307 + + .../rtsp_server/src/h264-memory-source.cpp | 221 + + .../rtsp_server/src/h265-file-reader.cpp | 146 + + .../rtsp_server/src/h265-file-source.cpp | 216 + + .../rtsp_server/src/rtp-udp-transport.cpp | 50 + + .../rtsp_server/src/rtsp-camera-reader.cpp | 286 + + .../rtsp_server/src/rtsp-camera-source.cpp | 221 + + .../test_mmf/rtsp_server/src/rtsp_server.cpp | 1005 +++ + sample/test_mmf/sample_vio.c | 3079 +++++++++ + sample/test_mmf/sample_vio.h | 46 + + sample/test_mmf/sample_vio_main.c | 139 + + 33 files changed, 13008 insertions(+) + create mode 100644 sample/test_mmf/.gitignore + create mode 100644 sample/test_mmf/Makefile + create mode 100644 sample/test_mmf/fomat.h + create mode 100644 sample/test_mmf/maix_mmf.h + create mode 100644 sample/test_mmf/maix_mmf/Makefile + create mode 100644 sample/test_mmf/maix_mmf/gcc.mk + create mode 100644 sample/test_mmf/maix_mmf/sophgo_middleware.c + create mode 100644 sample/test_mmf/rtsp_server/inc/h264-file-reader.h + create mode 100644 sample/test_mmf/rtsp_server/inc/h264-file-source.h + create mode 100644 sample/test_mmf/rtsp_server/inc/h264-memory-reader.h + create mode 100644 sample/test_mmf/rtsp_server/inc/h264-memory-source.h + create mode 100644 sample/test_mmf/rtsp_server/inc/h265-file-reader.h + create mode 100644 sample/test_mmf/rtsp_server/inc/h265-file-source.h + create mode 100644 sample/test_mmf/rtsp_server/inc/media-source.h + create mode 100644 sample/test_mmf/rtsp_server/inc/rtp-tcp-transport.h + create mode 100644 sample/test_mmf/rtsp_server/inc/rtp-udp-transport.h + create mode 100644 sample/test_mmf/rtsp_server/inc/rtsp-camera-reader.h + create mode 100644 sample/test_mmf/rtsp_server/inc/rtsp-camera-source.h + create mode 100644 sample/test_mmf/rtsp_server/inc/rtsp_server.h + create mode 100644 sample/test_mmf/rtsp_server/src/h264-file-reader.cpp + create mode 100644 sample/test_mmf/rtsp_server/src/h264-file-source.cpp + create mode 100644 sample/test_mmf/rtsp_server/src/h264-memory-reader.cpp + create mode 100644 sample/test_mmf/rtsp_server/src/h264-memory-source.cpp + create mode 100644 sample/test_mmf/rtsp_server/src/h265-file-reader.cpp + create mode 100644 sample/test_mmf/rtsp_server/src/h265-file-source.cpp + create mode 100644 sample/test_mmf/rtsp_server/src/rtp-udp-transport.cpp + create mode 100644 sample/test_mmf/rtsp_server/src/rtsp-camera-reader.cpp + create mode 100644 sample/test_mmf/rtsp_server/src/rtsp-camera-source.cpp + create mode 100644 sample/test_mmf/rtsp_server/src/rtsp_server.cpp + create mode 100644 sample/test_mmf/sample_vio.c + create mode 100644 sample/test_mmf/sample_vio.h + create mode 100644 sample/test_mmf/sample_vio_main.c + +diff --git a/Makefile b/Makefile +index 0d493da..f5a398c 100644 +--- a/Makefile ++++ b/Makefile +@@ -60,6 +60,7 @@ install: + ifneq ($(FLASH_SIZE_SHRINK),y) + # copy sample_xxx + @cp -f sample/mipi_tx/sample_dsi $(DESTDIR)/usr/bin ++ @cp -f sample/test_mmf/test_mmf $(DESTDIR)/usr/bin + @cp -f sample/cipher/sample_cipher $(DESTDIR)/usr/bin + @cp -f sample/cvg/sample_cvg $(DESTDIR)/usr/bin + @cp -f sample/venc/sample_venc $(DESTDIR)/usr/bin +diff --git a/sample/test_mmf/.gitignore b/sample/test_mmf/.gitignore +new file mode 100644 +index 0000000..244c5ac +--- /dev/null ++++ b/sample/test_mmf/.gitignore +@@ -0,0 +1,10 @@ ++*.bin ++*.patch ++test_mmf ++!librtsp/include ++!librtsp/src ++!*/include ++!*/*/include ++!*/*/*/include ++!*/*/*/*/include ++!*/*/*/*/*/include +\ No newline at end of file +diff --git a/sample/test_mmf/Makefile b/sample/test_mmf/Makefile +new file mode 100644 +index 0000000..c0b7b4b +--- /dev/null ++++ b/sample/test_mmf/Makefile +@@ -0,0 +1,114 @@ ++SHELL = /bin/bash ++ifeq ($(PARAM_FILE), ) ++ PARAM_FILE:=../../Makefile.param ++ include $(PARAM_FILE) ++endif ++include ../sample.mk ++ ++SDIR = $(PWD) ++SRCS = $(wildcard $(SDIR)/*.c) ++INCS = -I$(MW_INC) -I$(ISP_INC) -I../common/ -I$(KERNEL_INC) -I$(MW_INC)/linux -I$(SDIR) -I$(SENSOR_LIST_INC) ++ ++SRCS_CPP += $(wildcard $(SDIR)/rtsp_server/src/*.cpp) ++ ++CFLAGS += -I$(SDIR)/rtsp_server/inc ++CPPFLAGS += -I$(SDIR)/media_server-1.0.x/include \ ++-I$(SDIR)/media_server-1.0.x/media-server/librtsp/include \ ++-I$(SDIR)/media_server-1.0.x/media-server/librtsp/source/server \ ++-I$(SDIR)/media_server-1.0.x/sdk/include \ ++-I$(SDIR)/media_server-1.0.x/sdk/libhttp/include \ ++-I$(SDIR)/media_server-1.0.x/media-server/librtp/include \ ++-I$(SDIR)/media_server-1.0.x/media-server/libmpeg/include \ ++-I$(SDIR)/media_server-1.0.x/media-server/libflv/include \ ++-I$(SDIR)/media_server-1.0.x/media-server/libmkv/include \ ++-I$(SDIR)/media_server-1.0.x \ ++-I$(SDIR)/rtsp_server/inc \ ++-I$(SDIR)/media_server-1.0.x/avcodec/avcodec/include \ ++-I$(SDIR)/media_server-1.0.x/avcodec/avbsf/include \ ++-I$(SDIR)/media_server-1.0.x/media-server/libmov/include \ ++-D__ERROR__=00*10000000+__LINE__*1000 ++ ++ ++OBJS = $(SRCS:.c=.o) ++OBJS += $(SRCS_CPP:.cpp=.o) ++DEPS = $(SRCS:.c=.d) ++ ++TARGET = test_mmf ++ifeq ($(CONFIG_ENABLE_SDK_ASAN), y) ++TARGET = test_mmf_asan ++endif ++ ++PKG_CONFIG_PATH = $(MW_PATH)/pkgconfig ++REQUIRES = cvi_common cvi_sample cvi_ive ++ ++MW_LIBS = $(shell PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) pkg-config --libs --define-variable=mw_dir=$(MW_PATH) $(REQUIRES)) ++ ++LIBS = $(MW_LIBS) ++ifeq ($(MULTI_PROCESS_SUPPORT), 1) ++DEFS += -DRPC_MULTI_PROCESS ++LIBS += -lnanomsg ++endif ++ ++EXTRA_CFLAGS = $(INCS) $(DEFS) ++EXTRA_LDFLAGS = $(LIBS) -lpthread -lm -lini ++ ++MSK_LIBD = media_server-1.0.x/release.linux ++MMF_LIBD = maix_mmf/release.linux ++ ++LIBS += -L$(SDIR)/$(MSK_LIBD) -L$(MMF_LIBD) -lrtsp -lhttp -lflv -lmov -lrtp -lmpeg -lsdk -lavcodec -lavbsf ++ ++# IVE_SUPPORT = 1 ++ifeq ($(IVE_SUPPORT), 1) ++CFLAGS += -DIVE_SUPPORT ++ ++IVE_PATH = $(MW_PATH)/../install/soc_cv1835_wevb_0002a_spinand/tpu_64/cvitek_ive_sdk ++EXTRA_CFLAGS += -I$(IVE_PATH)/include/ive ++EXTRA_LDFLAGS += -L$(IVE_PATH)/lib -lcvi_ive_tpu-static ++ ++TPU_PATH = $(MW_PATH)/../install/soc_cv1835_wevb_0002a_spinand/tpu_64/cvitek_tpu_sdk ++EXTRA_CFLAGS += -I$(TPU_PATH)/include ++EXTRA_LDFLAGS += -L$(TPU_PATH)/lib -lcviruntime-static -lcvimath-static -lcvikernel-static -lcnpy -lglog -lz ++endif ++ ++.PHONY : clean all ++all: $(TARGET) ++ ++mmflibs: ++ @$(MAKE) AR=$(AR) CC=$(CC) CXX=$(CXX) PLATFORM=linux RELEASE=1 -C media_server-1.0.x/sdk/ ++ @$(MAKE) AR=$(AR) CC=$(CC) CXX=$(CXX) PLATFORM=linux RELEASE=1 -C media_server-1.0.x/avcodec/ ++ @$(MAKE) AR=$(AR) CC=$(CC) CXX=$(CXX) PLATFORM=linux RELEASE=1 -C media_server-1.0.x/media-server/ ++ @mkdir -p $(MSK_LIBD) ++ @cp -p media_server-1.0.x/sdk/libhttp/release.linux/libhttp.a $(MSK_LIBD)/ ++ @cp -p media_server-1.0.x/sdk/libsdk/release.linux/libsdk.a $(MSK_LIBD)/ ++ @cp -p media_server-1.0.x/avcodec/avbsf/release.linux/libavbsf.a $(MSK_LIBD)/ ++ @cp -p media_server-1.0.x/avcodec/avcodec/release.linux/libavcodec.a $(MSK_LIBD)/ ++ @cp -p media_server-1.0.x/media-server/libflv/release.linux/libflv.a $(MSK_LIBD)/ ++ #@cp -p media_server-1.0.x/media-server/libmkv/release.linux/libmkv.a $(MSK_LIBD)/ ++ @cp -p media_server-1.0.x/media-server/libmov/release.linux/libmov.a $(MSK_LIBD)/ ++ @cp -p media_server-1.0.x/media-server/libmpeg/release.linux/libmpeg.a $(MSK_LIBD)/ ++ @cp -p media_server-1.0.x/media-server/librtp/release.linux/librtp.a $(MSK_LIBD)/ ++ @cp -p media_server-1.0.x/media-server/librtsp/release.linux/librtsp.a $(MSK_LIBD)/ ++ @$(MAKE) AR=$(AR) CC=$(CC) CXX=$(CXX) PLATFORM=linux RELEASE=1 -C maix_mmf/ ++ ++clean_mmflibs: ++ @$(MAKE) AR=$(AR) CC=$(CC) CXX=$(CXX) PLATFORM=linux RELEASE=1 -C media_server-1.0.x/sdk/ clean ++ @$(MAKE) AR=$(AR) CC=$(CC) CXX=$(CXX) PLATFORM=linux RELEASE=1 -C media_server-1.0.x/avcodec/ clean ++ @$(MAKE) AR=$(AR) CC=$(CC) CXX=$(CXX) PLATFORM=linux RELEASE=1 -C media_server-1.0.x/media-server/ clean ++ @$(MAKE) AR=$(AR) CC=$(CC) CXX=$(CXX) PLATFORM=linux RELEASE=1 -C maix_mmf/ clean ++ ++$(COMMON_DIR)/%.o: $(COMMON_DIR)/%.c ++ @$(CC) $(DEPFLAGS) $(CFLAGS) $(EXTRA_CFLAGS) -o $@ -c $< ++ @echo [$(notdir $(CC))] $(notdir $@) ++ ++$(SDIR)/%.o: $(SDIR)/%.c ++ @$(CC) $(DEPFLAGS) $(CFLAGS) $(EXTRA_CFLAGS) -o $@ -c $< ++ @echo [$(notdir $(CC))] $(notdir $@) ++ ++$(TARGET): mmflibs $(COMM_OBJ) $(OBJS) $(ISP_OBJ) $(MW_LIB)/libvenc.a $(MW_LIB)/libsys.a ++ @$(CXX) -o $@ -Wl,--start-group $(OBJS) $(COMM_OBJS) -lsys $(MW_LIB)/libsys.a -Wl,--end-group -lmaix_mmf $(ELFFLAGS) $(EXTRA_LDFLAGS) ++ @echo -e $(BLUE)[LINK]$(END)[$(notdir $(CXX))] $(notdir $@) ++ ++clean: clean_mmflibs ++ @rm -f $(OBJS) $(DEPS) $(COMM_OBJ) $(COMM_DEPS) $(TARGET) ++ ++-include $(DEPS) +diff --git a/sample/test_mmf/fomat.h b/sample/test_mmf/fomat.h +new file mode 100644 +index 0000000..d4d272b +--- /dev/null ++++ b/sample/test_mmf/fomat.h +@@ -0,0 +1,217 @@ ++#ifndef __OLED_FOMAT_H__ ++#define __OLED_FOMAT_H__ ++ ++#ifdef __cplusplus ++#if __cplusplus ++extern "C" { ++#endif ++#endif /* End of #ifdef __cplusplus */ ++ ++#include ++ ++/************************************6*8的点阵************************************/ ++const uint8_t oled_asc2_0806[][6] ={ ++{0x00, 0x00, 0x00, 0x00, 0x00, 0x00},// sp ++{0x00, 0x00, 0x00, 0x2f, 0x00, 0x00},// ! ++{0x00, 0x00, 0x07, 0x00, 0x07, 0x00},// " ++{0x00, 0x14, 0x7f, 0x14, 0x7f, 0x14},// # ++{0x00, 0x24, 0x2a, 0x7f, 0x2a, 0x12},// $ ++{0x00, 0x62, 0x64, 0x08, 0x13, 0x23},// % ++{0x00, 0x36, 0x49, 0x55, 0x22, 0x50},// & ++{0x00, 0x00, 0x05, 0x03, 0x00, 0x00},// ' ++{0x00, 0x00, 0x1c, 0x22, 0x41, 0x00},// ( ++{0x00, 0x00, 0x41, 0x22, 0x1c, 0x00},// ) ++{0x00, 0x14, 0x08, 0x3E, 0x08, 0x14},// * ++{0x00, 0x08, 0x08, 0x3E, 0x08, 0x08},// + ++{0x00, 0x00, 0x00, 0xA0, 0x60, 0x00},// , ++{0x00, 0x08, 0x08, 0x08, 0x08, 0x08},// - ++{0x00, 0x00, 0x60, 0x60, 0x00, 0x00},// . ++{0x00, 0x20, 0x10, 0x08, 0x04, 0x02},// / ++{0x00, 0x3E, 0x51, 0x49, 0x45, 0x3E},// 0 ++{0x00, 0x00, 0x42, 0x7F, 0x40, 0x00},// 1 ++{0x00, 0x42, 0x61, 0x51, 0x49, 0x46},// 2 ++{0x00, 0x21, 0x41, 0x45, 0x4B, 0x31},// 3 ++{0x00, 0x18, 0x14, 0x12, 0x7F, 0x10},// 4 ++{0x00, 0x27, 0x45, 0x45, 0x45, 0x39},// 5 ++{0x00, 0x3C, 0x4A, 0x49, 0x49, 0x30},// 6 ++{0x00, 0x01, 0x71, 0x09, 0x05, 0x03},// 7 ++{0x00, 0x36, 0x49, 0x49, 0x49, 0x36},// 8 ++{0x00, 0x06, 0x49, 0x49, 0x29, 0x1E},// 9 ++{0x00, 0x00, 0x36, 0x36, 0x00, 0x00},// : ++{0x00, 0x00, 0x56, 0x36, 0x00, 0x00},// ; ++{0x00, 0x08, 0x14, 0x22, 0x41, 0x00},// < ++{0x00, 0x14, 0x14, 0x14, 0x14, 0x14},// = ++{0x00, 0x00, 0x41, 0x22, 0x14, 0x08},// > ++{0x00, 0x02, 0x01, 0x51, 0x09, 0x06},// ? ++{0x00, 0x32, 0x49, 0x59, 0x51, 0x3E},// @ ++{0x00, 0x7C, 0x12, 0x11, 0x12, 0x7C},// A ++{0x00, 0x7F, 0x49, 0x49, 0x49, 0x36},// B ++{0x00, 0x3E, 0x41, 0x41, 0x41, 0x22},// C ++{0x00, 0x7F, 0x41, 0x41, 0x22, 0x1C},// D ++{0x00, 0x7F, 0x49, 0x49, 0x49, 0x41},// E ++{0x00, 0x7F, 0x09, 0x09, 0x09, 0x01},// F ++{0x00, 0x3E, 0x41, 0x49, 0x49, 0x7A},// G ++{0x00, 0x7F, 0x08, 0x08, 0x08, 0x7F},// H ++{0x00, 0x00, 0x41, 0x7F, 0x41, 0x00},// I ++{0x00, 0x20, 0x40, 0x41, 0x3F, 0x01},// J ++{0x00, 0x7F, 0x08, 0x14, 0x22, 0x41},// K ++{0x00, 0x7F, 0x40, 0x40, 0x40, 0x40},// L ++{0x00, 0x7F, 0x02, 0x0C, 0x02, 0x7F},// M ++{0x00, 0x7F, 0x04, 0x08, 0x10, 0x7F},// N ++{0x00, 0x3E, 0x41, 0x41, 0x41, 0x3E},// O ++{0x00, 0x7F, 0x09, 0x09, 0x09, 0x06},// P ++{0x00, 0x3E, 0x41, 0x51, 0x21, 0x5E},// Q ++{0x00, 0x7F, 0x09, 0x19, 0x29, 0x46},// R ++{0x00, 0x46, 0x49, 0x49, 0x49, 0x31},// S ++{0x00, 0x01, 0x01, 0x7F, 0x01, 0x01},// T ++{0x00, 0x3F, 0x40, 0x40, 0x40, 0x3F},// U ++{0x00, 0x1F, 0x20, 0x40, 0x20, 0x1F},// V ++{0x00, 0x3F, 0x40, 0x38, 0x40, 0x3F},// W ++{0x00, 0x63, 0x14, 0x08, 0x14, 0x63},// X ++{0x00, 0x07, 0x08, 0x70, 0x08, 0x07},// Y ++{0x00, 0x61, 0x51, 0x49, 0x45, 0x43},// Z ++{0x00, 0x00, 0x7F, 0x41, 0x41, 0x00},// [ ++{0x00, 0x55, 0x2A, 0x55, 0x2A, 0x55},// 55 ++{0x00, 0x00, 0x41, 0x41, 0x7F, 0x00},// ] ++{0x00, 0x04, 0x02, 0x01, 0x02, 0x04},// ^ ++{0x00, 0x40, 0x40, 0x40, 0x40, 0x40},// _ ++{0x00, 0x00, 0x01, 0x02, 0x04, 0x00},// ' ++{0x00, 0x20, 0x54, 0x54, 0x54, 0x78},// a ++{0x00, 0x7F, 0x48, 0x44, 0x44, 0x38},// b ++{0x00, 0x38, 0x44, 0x44, 0x44, 0x20},// c ++{0x00, 0x38, 0x44, 0x44, 0x48, 0x7F},// d ++{0x00, 0x38, 0x54, 0x54, 0x54, 0x18},// e ++{0x00, 0x08, 0x7E, 0x09, 0x01, 0x02},// f ++{0x00, 0x18, 0xA4, 0xA4, 0xA4, 0x7C},// g ++{0x00, 0x7F, 0x08, 0x04, 0x04, 0x78},// h ++{0x00, 0x00, 0x44, 0x7D, 0x40, 0x00},// i ++{0x00, 0x40, 0x80, 0x84, 0x7D, 0x00},// j ++{0x00, 0x7F, 0x10, 0x28, 0x44, 0x00},// k ++{0x00, 0x00, 0x41, 0x7F, 0x40, 0x00},// l ++{0x00, 0x7C, 0x04, 0x18, 0x04, 0x78},// m ++{0x00, 0x7C, 0x08, 0x04, 0x04, 0x78},// n ++{0x00, 0x38, 0x44, 0x44, 0x44, 0x38},// o ++{0x00, 0xFC, 0x24, 0x24, 0x24, 0x18},// p ++{0x00, 0x18, 0x24, 0x24, 0x18, 0xFC},// q ++{0x00, 0x7C, 0x08, 0x04, 0x04, 0x08},// r ++{0x00, 0x48, 0x54, 0x54, 0x54, 0x20},// s ++{0x00, 0x04, 0x3F, 0x44, 0x40, 0x20},// t ++{0x00, 0x3C, 0x40, 0x40, 0x20, 0x7C},// u ++{0x00, 0x1C, 0x20, 0x40, 0x20, 0x1C},// v ++{0x00, 0x3C, 0x40, 0x30, 0x40, 0x3C},// w ++{0x00, 0x44, 0x28, 0x10, 0x28, 0x44},// x ++{0x00, 0x1C, 0xA0, 0xA0, 0xA0, 0x7C},// y ++{0x00, 0x44, 0x64, 0x54, 0x4C, 0x44},// z ++{0x14, 0x14, 0x14, 0x14, 0x14, 0x14},// horiz lines ++{0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00},// vert lines ++ ++}; ++ ++ ++//16*16 ASCII字符集点阵 ++const uint8_t oled_asc2_1608[][16]={ ++{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*" ",0*/ ++{0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x33,0x30,0x00,0x00,0x00},/*"!",1*/ ++{0x00,0x10,0x0C,0x06,0x10,0x0C,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*""",2*/ ++{0x40,0xC0,0x78,0x40,0xC0,0x78,0x40,0x00,0x04,0x3F,0x04,0x04,0x3F,0x04,0x04,0x00},/*"#",3*/ ++{0x00,0x70,0x88,0xFC,0x08,0x30,0x00,0x00,0x00,0x18,0x20,0xFF,0x21,0x1E,0x00,0x00},/*"$",4*/ ++{0xF0,0x08,0xF0,0x00,0xE0,0x18,0x00,0x00,0x00,0x21,0x1C,0x03,0x1E,0x21,0x1E,0x00},/*"%",5*/ ++{0x00,0xF0,0x08,0x88,0x70,0x00,0x00,0x00,0x1E,0x21,0x23,0x24,0x19,0x27,0x21,0x10},/*"&",6*/ ++{0x10,0x16,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"'",7*/ ++{0x00,0x00,0x00,0xE0,0x18,0x04,0x02,0x00,0x00,0x00,0x00,0x07,0x18,0x20,0x40,0x00},/*"(",8*/ ++{0x00,0x02,0x04,0x18,0xE0,0x00,0x00,0x00,0x00,0x40,0x20,0x18,0x07,0x00,0x00,0x00},/*")",9*/ ++{0x40,0x40,0x80,0xF0,0x80,0x40,0x40,0x00,0x02,0x02,0x01,0x0F,0x01,0x02,0x02,0x00},/*"*",10*/ ++{0x00,0x00,0x00,0xF0,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x1F,0x01,0x01,0x01,0x00},/*"+",11*/ ++{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xB0,0x70,0x00,0x00,0x00,0x00,0x00},/*",",12*/ ++{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01},/*"-",13*/ ++{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00,0x00,0x00},/*".",14*/ ++{0x00,0x00,0x00,0x00,0x80,0x60,0x18,0x04,0x00,0x60,0x18,0x06,0x01,0x00,0x00,0x00},/*"/",15*/ ++{0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x0F,0x10,0x20,0x20,0x10,0x0F,0x00},/*"0",16*/ ++{0x00,0x10,0x10,0xF8,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00},/*"1",17*/ ++{0x00,0x70,0x08,0x08,0x08,0x88,0x70,0x00,0x00,0x30,0x28,0x24,0x22,0x21,0x30,0x00},/*"2",18*/ ++{0x00,0x30,0x08,0x88,0x88,0x48,0x30,0x00,0x00,0x18,0x20,0x20,0x20,0x11,0x0E,0x00},/*"3",19*/ ++{0x00,0x00,0xC0,0x20,0x10,0xF8,0x00,0x00,0x00,0x07,0x04,0x24,0x24,0x3F,0x24,0x00},/*"4",20*/ ++{0x00,0xF8,0x08,0x88,0x88,0x08,0x08,0x00,0x00,0x19,0x21,0x20,0x20,0x11,0x0E,0x00},/*"5",21*/ ++{0x00,0xE0,0x10,0x88,0x88,0x18,0x00,0x00,0x00,0x0F,0x11,0x20,0x20,0x11,0x0E,0x00},/*"6",22*/ ++{0x00,0x38,0x08,0x08,0xC8,0x38,0x08,0x00,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x00},/*"7",23*/ ++{0x00,0x70,0x88,0x08,0x08,0x88,0x70,0x00,0x00,0x1C,0x22,0x21,0x21,0x22,0x1C,0x00},/*"8",24*/ ++{0x00,0xE0,0x10,0x08,0x08,0x10,0xE0,0x00,0x00,0x00,0x31,0x22,0x22,0x11,0x0F,0x00},/*"9",25*/ ++{0x00,0x00,0x00,0xC0,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x00},/*":",26*/ ++{0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x60,0x00,0x00,0x00,0x00},/*";",27*/ ++{0x00,0x00,0x80,0x40,0x20,0x10,0x08,0x00,0x00,0x01,0x02,0x04,0x08,0x10,0x20,0x00},/*"<",28*/ ++{0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x00},/*"=",29*/ ++{0x00,0x08,0x10,0x20,0x40,0x80,0x00,0x00,0x00,0x20,0x10,0x08,0x04,0x02,0x01,0x00},/*">",30*/ ++{0x00,0x70,0x48,0x08,0x08,0x08,0xF0,0x00,0x00,0x00,0x00,0x30,0x36,0x01,0x00,0x00},/*"?",31*/ ++{0xC0,0x30,0xC8,0x28,0xE8,0x10,0xE0,0x00,0x07,0x18,0x27,0x24,0x23,0x14,0x0B,0x00},/*"@",32*/ ++{0x00,0x00,0xC0,0x38,0xE0,0x00,0x00,0x00,0x20,0x3C,0x23,0x02,0x02,0x27,0x38,0x20},/*"A",33*/ ++{0x08,0xF8,0x88,0x88,0x88,0x70,0x00,0x00,0x20,0x3F,0x20,0x20,0x20,0x11,0x0E,0x00},/*"B",34*/ ++{0xC0,0x30,0x08,0x08,0x08,0x08,0x38,0x00,0x07,0x18,0x20,0x20,0x20,0x10,0x08,0x00},/*"C",35*/ ++{0x08,0xF8,0x08,0x08,0x08,0x10,0xE0,0x00,0x20,0x3F,0x20,0x20,0x20,0x10,0x0F,0x00},/*"D",36*/ ++{0x08,0xF8,0x88,0x88,0xE8,0x08,0x10,0x00,0x20,0x3F,0x20,0x20,0x23,0x20,0x18,0x00},/*"E",37*/ ++{0x08,0xF8,0x88,0x88,0xE8,0x08,0x10,0x00,0x20,0x3F,0x20,0x00,0x03,0x00,0x00,0x00},/*"F",38*/ ++{0xC0,0x30,0x08,0x08,0x08,0x38,0x00,0x00,0x07,0x18,0x20,0x20,0x22,0x1E,0x02,0x00},/*"G",39*/ ++{0x08,0xF8,0x08,0x00,0x00,0x08,0xF8,0x08,0x20,0x3F,0x21,0x01,0x01,0x21,0x3F,0x20},/*"H",40*/ ++{0x00,0x08,0x08,0xF8,0x08,0x08,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00},/*"I",41*/ ++{0x00,0x00,0x08,0x08,0xF8,0x08,0x08,0x00,0xC0,0x80,0x80,0x80,0x7F,0x00,0x00,0x00},/*"J",42*/ ++{0x08,0xF8,0x88,0xC0,0x28,0x18,0x08,0x00,0x20,0x3F,0x20,0x01,0x26,0x38,0x20,0x00},/*"K",43*/ ++{0x08,0xF8,0x08,0x00,0x00,0x00,0x00,0x00,0x20,0x3F,0x20,0x20,0x20,0x20,0x30,0x00},/*"L",44*/ ++{0x08,0xF8,0xF8,0x00,0xF8,0xF8,0x08,0x00,0x20,0x3F,0x00,0x3F,0x00,0x3F,0x20,0x00},/*"M",45*/ ++{0x08,0xF8,0x30,0xC0,0x00,0x08,0xF8,0x08,0x20,0x3F,0x20,0x00,0x07,0x18,0x3F,0x00},/*"N",46*/ ++{0xE0,0x10,0x08,0x08,0x08,0x10,0xE0,0x00,0x0F,0x10,0x20,0x20,0x20,0x10,0x0F,0x00},/*"O",47*/ ++{0x08,0xF8,0x08,0x08,0x08,0x08,0xF0,0x00,0x20,0x3F,0x21,0x01,0x01,0x01,0x00,0x00},/*"P",48*/ ++{0xE0,0x10,0x08,0x08,0x08,0x10,0xE0,0x00,0x0F,0x18,0x24,0x24,0x38,0x50,0x4F,0x00},/*"Q",49*/ ++{0x08,0xF8,0x88,0x88,0x88,0x88,0x70,0x00,0x20,0x3F,0x20,0x00,0x03,0x0C,0x30,0x20},/*"R",50*/ ++{0x00,0x70,0x88,0x08,0x08,0x08,0x38,0x00,0x00,0x38,0x20,0x21,0x21,0x22,0x1C,0x00},/*"S",51*/ ++{0x18,0x08,0x08,0xF8,0x08,0x08,0x18,0x00,0x00,0x00,0x20,0x3F,0x20,0x00,0x00,0x00},/*"T",52*/ ++{0x08,0xF8,0x08,0x00,0x00,0x08,0xF8,0x08,0x00,0x1F,0x20,0x20,0x20,0x20,0x1F,0x00},/*"U",53*/ ++{0x08,0x78,0x88,0x00,0x00,0xC8,0x38,0x08,0x00,0x00,0x07,0x38,0x0E,0x01,0x00,0x00},/*"V",54*/ ++{0xF8,0x08,0x00,0xF8,0x00,0x08,0xF8,0x00,0x03,0x3C,0x07,0x00,0x07,0x3C,0x03,0x00},/*"W",55*/ ++{0x08,0x18,0x68,0x80,0x80,0x68,0x18,0x08,0x20,0x30,0x2C,0x03,0x03,0x2C,0x30,0x20},/*"X",56*/ ++{0x08,0x38,0xC8,0x00,0xC8,0x38,0x08,0x00,0x00,0x00,0x20,0x3F,0x20,0x00,0x00,0x00},/*"Y",57*/ ++{0x10,0x08,0x08,0x08,0xC8,0x38,0x08,0x00,0x20,0x38,0x26,0x21,0x20,0x20,0x18,0x00},/*"Z",58*/ ++{0x00,0x00,0x00,0xFE,0x02,0x02,0x02,0x00,0x00,0x00,0x00,0x7F,0x40,0x40,0x40,0x00},/*"[",59*/ ++{0x00,0x0C,0x30,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x06,0x38,0xC0,0x00},/*"\",60*/ ++{0x00,0x02,0x02,0x02,0xFE,0x00,0x00,0x00,0x00,0x40,0x40,0x40,0x7F,0x00,0x00,0x00},/*"]",61*/ ++{0x00,0x00,0x04,0x02,0x02,0x02,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"^",62*/ ++{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80},/*"_",63*/ ++{0x00,0x02,0x02,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"`",64*/ ++{0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x19,0x24,0x22,0x22,0x22,0x3F,0x20},/*"a",65*/ ++{0x08,0xF8,0x00,0x80,0x80,0x00,0x00,0x00,0x00,0x3F,0x11,0x20,0x20,0x11,0x0E,0x00},/*"b",66*/ ++{0x00,0x00,0x00,0x80,0x80,0x80,0x00,0x00,0x00,0x0E,0x11,0x20,0x20,0x20,0x11,0x00},/*"c",67*/ ++{0x00,0x00,0x00,0x80,0x80,0x88,0xF8,0x00,0x00,0x0E,0x11,0x20,0x20,0x10,0x3F,0x20},/*"d",68*/ ++{0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x1F,0x22,0x22,0x22,0x22,0x13,0x00},/*"e",69*/ ++{0x00,0x80,0x80,0xF0,0x88,0x88,0x88,0x18,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00},/*"f",70*/ ++{0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x6B,0x94,0x94,0x94,0x93,0x60,0x00},/*"g",71*/ ++{0x08,0xF8,0x00,0x80,0x80,0x80,0x00,0x00,0x20,0x3F,0x21,0x00,0x00,0x20,0x3F,0x20},/*"h",72*/ ++{0x00,0x80,0x98,0x98,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00},/*"i",73*/ ++{0x00,0x00,0x00,0x80,0x98,0x98,0x00,0x00,0x00,0xC0,0x80,0x80,0x80,0x7F,0x00,0x00},/*"j",74*/ ++{0x08,0xF8,0x00,0x00,0x80,0x80,0x80,0x00,0x20,0x3F,0x24,0x02,0x2D,0x30,0x20,0x00},/*"k",75*/ ++{0x00,0x08,0x08,0xF8,0x00,0x00,0x00,0x00,0x00,0x20,0x20,0x3F,0x20,0x20,0x00,0x00},/*"l",76*/ ++{0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x00,0x20,0x3F,0x20,0x00,0x3F,0x20,0x00,0x3F},/*"m",77*/ ++{0x80,0x80,0x00,0x80,0x80,0x80,0x00,0x00,0x20,0x3F,0x21,0x00,0x00,0x20,0x3F,0x20},/*"n",78*/ ++{0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x1F,0x20,0x20,0x20,0x20,0x1F,0x00},/*"o",79*/ ++{0x80,0x80,0x00,0x80,0x80,0x00,0x00,0x00,0x80,0xFF,0xA1,0x20,0x20,0x11,0x0E,0x00},/*"p",80*/ ++{0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x0E,0x11,0x20,0x20,0xA0,0xFF,0x80},/*"q",81*/ ++{0x80,0x80,0x80,0x00,0x80,0x80,0x80,0x00,0x20,0x20,0x3F,0x21,0x20,0x00,0x01,0x00},/*"r",82*/ ++{0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x33,0x24,0x24,0x24,0x24,0x19,0x00},/*"s",83*/ ++{0x00,0x80,0x80,0xE0,0x80,0x80,0x00,0x00,0x00,0x00,0x00,0x1F,0x20,0x20,0x00,0x00},/*"t",84*/ ++{0x80,0x80,0x00,0x00,0x00,0x80,0x80,0x00,0x00,0x1F,0x20,0x20,0x20,0x10,0x3F,0x20},/*"u",85*/ ++{0x80,0x80,0x80,0x00,0x00,0x80,0x80,0x80,0x00,0x01,0x0E,0x30,0x08,0x06,0x01,0x00},/*"v",86*/ ++{0x80,0x80,0x00,0x80,0x00,0x80,0x80,0x80,0x0F,0x30,0x0C,0x03,0x0C,0x30,0x0F,0x00},/*"w",87*/ ++{0x00,0x80,0x80,0x00,0x80,0x80,0x80,0x00,0x00,0x20,0x31,0x2E,0x0E,0x31,0x20,0x00},/*"x",88*/ ++{0x80,0x80,0x80,0x00,0x00,0x80,0x80,0x80,0x80,0x81,0x8E,0x70,0x18,0x06,0x01,0x00},/*"y",89*/ ++{0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x21,0x30,0x2C,0x22,0x21,0x30,0x00},/*"z",90*/ ++{0x00,0x00,0x00,0x00,0x80,0x7C,0x02,0x02,0x00,0x00,0x00,0x00,0x00,0x3F,0x40,0x40},/*"{",91*/ ++{0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00},/*"|",92*/ ++{0x00,0x02,0x02,0x7C,0x80,0x00,0x00,0x00,0x00,0x40,0x40,0x3F,0x00,0x00,0x00,0x00},/*"}",93*/ ++{0x00,0x06,0x01,0x01,0x02,0x02,0x04,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"~",94*/ ++}; ++ ++ ++#ifdef __cplusplus ++#if __cplusplus ++} ++#endif ++#endif /* End of #ifdef __cplusplus */ ++ ++#endif /* End of #ifndef __OLED_FOMAT_H__*/ +diff --git a/sample/test_mmf/maix_mmf.h b/sample/test_mmf/maix_mmf.h +new file mode 100644 +index 0000000..d12747d +--- /dev/null ++++ b/sample/test_mmf/maix_mmf.h +@@ -0,0 +1,282 @@ ++#ifndef __MAIX_MMF_HPP__ ++#define __MAIX_MMF_HPP__ ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++#include "cvi_buffer.h" ++#include "cvi_ae_comm.h" ++#include "cvi_awb_comm.h" ++#include "cvi_comm_isp.h" ++#include "cvi_comm_sns.h" ++#include "cvi_ae.h" ++#include "cvi_awb.h" ++#include "cvi_isp.h" ++#include "cvi_sns_ctrl.h" ++#include "cvi_ive.h" ++#include "cvi_sys.h" ++#include "sample_comm.h" ++#ifdef __cplusplus ++} ++#endif ++ ++#define MMF_FUNC_SET_PARAM(method, num) ((uint32_t)((((uint32_t)method) << 24) | (num & 0xff))) ++#define MMF_FUNC_GET_PARAM_METHOD(x) ((x >> 24) & 0xffffff) ++#define MMF_FUNC_GET_PARAM_NUM(x) ((x & 0xff)) ++ ++#define MMF_VI_PIXEL_FORMAT PIXEL_FORMAT_NV21 // PIXEL_FORMAT_NV21, PIXEL_FORMAT_YUYV or PIXEL_FORMAT_UYVY ++ ++typedef struct { ++ uint8_t *data[8]; ++ int data_size[8]; ++ int count; ++} mmf_stream_t; ++ ++// old struct, must keep same as mmf_stream_t ++typedef struct { ++ uint8_t *data[8]; ++ int data_size[8]; ++ int count; ++} mmf_h265_stream_t; ++ ++typedef struct { ++ uint8_t type; // 0, jpg; 1, h265; 2, h264 ++ int w; ++ int h; ++ int fmt; ++ uint8_t jpg_quality; // jpeg ++ int gop; // h264/h265 ++ int intput_fps; // h264/h265 ++ int output_fps; // h264/h265 ++ int bitrate; // h264/h265 ++} mmf_venc_cfg_t; ++ ++typedef struct { ++ uint8_t type; // 0, jpg; 1, h265; 2, h264 ++ int w; ++ int h; ++ int fmt; ++ int buffer_num; ++} mmf_vdec_cfg_t; ++ ++typedef struct { ++ void *data; ++ int len; ++ int w; ++ int h; ++ int fmt; ++} mmf_frame_info_t; ++ ++typedef struct { ++ int chn; ++ int w; ++ int h; ++ int fmt; ++ int fps; ++ int depth; ++} mmf_vi_cfg_t; ++ ++typedef struct { ++ struct { ++ int size; ++ int count; ++ /* ++ VB_REMAP_MODE_NONE = 0, ++ VB_REMAP_MODE_NOCACHE = 1, ++ VB_REMAP_MODE_CACHED = 2, ++ VB_REMAP_MODE_BUTT ++ */ ++ int map; ++ } vb_pool[16]; ++ int max_pool_cnt; ++} mmf_sys_cfg_t; ++ ++// init sys ++int mmf_init(void); ++int mmf_deinit(void); ++int mmf_try_deinit(bool force); ++bool mmf_is_init(void); ++void mmf_pre_config_sys(mmf_sys_cfg_t *cfg); ++ ++// manage vi channels(vi->vpssgroup->vpss->frame) ++int mmf_get_vi_unused_channel(void); ++int mmf_vi_init(void); ++int mmf_vi_init2(mmf_vi_cfg_t *vi_info); ++int mmf_vi_deinit(void); ++int mmf_vi_get_max_size(int *width, int *height); ++int mmf_add_vi_channel(int ch, int width, int height, int format); ++int mmf_del_vi_channel(int ch); ++int mmf_del_vi_channel_all(void); ++int mmf_vi_channel_set_windowing(int ch, int x, int y, int w, int h); ++int mmf_reset_vi_channel(int ch, int width, int height, int format); ++bool mmf_vi_chn_is_open(int ch); ++int mmf_vi_aligned_width(int ch); ++void mmf_set_vi_hmirror(int ch, bool en); ++void mmf_set_vi_vflip(int ch, bool en); ++void mmf_get_vi_hmirror(int ch, bool *en); ++void mmf_get_vi_vflip(int ch, bool *en); ++void mmf_vi_set_pop_timeout(int ms); ++ ++// get vi frame ++int mmf_vi_frame_pop(int ch, void **data, int *len, int *width, int *height, int *format); ++void mmf_vi_frame_free(int ch); ++int mmf_vi_frame_pop2(int ch, void **frame_info, mmf_frame_info_t *frame_info_mmap); ++void mmf_vi_frame_free2(int ch, void **frame_info); ++ ++// manage vo channels ++int mmf_get_vo_unused_channel(int layer); ++int mmf_add_vo_channel(int layer, int ch, int width, int height, int format); ++int mmf_add_vo_channel_with_fit(int layer, int ch, int width, int height, int format, int fit); ++int mmf_del_vo_channel(int layer, int ch); ++int mmf_del_vo_channel_all(int layer); ++bool mmf_vo_channel_is_open(int layer, int ch); ++void mmf_set_vo_video_hmirror(int ch, bool en); ++void mmf_set_vo_video_flip(int ch, bool en); ++void mmf_get_vo_video_hmirror(int ch, bool *en); ++void mmf_get_vo_video_flip(int ch, bool *en); ++ ++// flush vo ++int mmf_vo_frame_push_with_fit(int layer, int ch, void *data, int len, int width, int height, int format, int fit); ++int mmf_vo_frame_push(int layer, int ch, void *data, int len, int width, int height, int format); ++int mmf_vo_frame_push2(int layer, int ch, int fit, void *frame_info); ++ ++// rgn ++int mmf_get_region_unused_channel(void); ++int mmf_add_region_channel(int ch, int type, int mod_id, int dev_id, int chn_id, int x, int y, int width, int height, int format); ++int mmf_del_region_channel(int ch); ++int mmf_del_region_channel_all(void); ++int mmf_region_frame_push(int ch, void *data, int len); ++int mmf_region_get_canvas(int ch, void **data, int *width, int *height, int *format); ++int mmf_region_update_canvas(int ch); ++ ++// enc jpg ++bool mmf_enc_jpg_is_init(void); ++int mmf_enc_jpg_init(int ch, int w, int h, int format, int quality); ++int mmf_enc_jpg_deinit(int ch); ++int mmf_enc_jpg_push(int ch, uint8_t *data, int w, int h, int format); ++int mmf_enc_jpg_push_with_quality(int ch, uint8_t *data, int w, int h, int format, int quality); ++int mmf_enc_jpg_pop(int ch, uint8_t **data, int *size); ++int mmf_enc_jpg_free(int ch); ++ ++// enc h265 ++int mmf_enc_h265_init(int ch, int w, int h); ++int mmf_enc_h265_deinit(int ch); ++int mmf_enc_h265_push(int ch, uint8_t *data, int w, int h, int format); ++int mmf_enc_h265_push2(int ch, void *frame_info); ++int mmf_enc_h265_pop(int ch, mmf_h265_stream_t *stream); ++#ifdef __cplusplus ++int mmf_enc_h265_pop(int ch, mmf_stream_t *stream); ++#endif ++int mmf_enc_h265_free(int ch); ++ ++// invert format ++int mmf_invert_format_to_maix(int mmf_format); ++int mmf_invert_format_to_mmf(int maix_format); ++ ++// config vb ++int mmf_vb_config_of_vi(uint32_t size, uint32_t count); // must be run before mmf_init() ++int mmf_vb_config_of_vo(uint32_t size, uint32_t count); // must be run before mmf_init() ++int mmf_vb_config_of_private(uint32_t size, uint32_t count); // must be run before mmf_init() ++ ++// config isp ++int mmf_set_exp_mode(int ch, int mode); ++int mmf_get_exp_mode(int ch); ++int mmf_get_exptime(int ch, uint32_t *exptime); ++int mmf_set_exptime(int ch, uint32_t exptime); ++int mmf_get_iso_num(int ch, uint32_t *iso_num); ++int mmf_set_iso_num(int ch, uint32_t iso_num); ++int mmf_get_again(int ch, uint32_t *gain); ++int mmf_set_again(int ch, uint32_t gain); // gain = [0x400, 0x7FFFFFFF] ++int mmf_get_dgain(int ch, uint32_t *gain); ++int mmf_set_dgain(int ch, uint32_t gain); // gain = [0x400, 0x7FFFFFFF] ++int mmf_get_ispdgain(int ch, uint32_t *gain); ++int mmf_set_ispdgain(int ch, uint32_t gain); // gain = [0x400, 0x7FFFFFFF] ++int mmf_get_exptime_and_iso(int ch, uint32_t *exptime, uint32_t *iso_num); ++int mmf_set_exptime_and_iso(int ch, uint32_t exptime, uint32_t iso_num); ++void mmf_set_constrast(int ch, uint32_t val); ++void mmf_set_saturation(int ch, uint32_t val); ++void mmf_set_luma(int ch, uint32_t val); ++int mmf_get_constrast(int ch, uint32_t *value); ++int mmf_get_saturation(int ch, uint32_t *value); ++int mmf_get_luma(int ch, uint32_t *value); ++int mmf_set_wb_mode(int ch, int mode); ++int mmf_get_wb_mode(int ch); ++ ++// sensor info ++int mmf_get_sensor_id(void); ++char* mmf_get_sensor_name(void); ++ ++// venc ++int mmf_venc_unused_channel(void); ++int mmf_venc_is_used(int ch); ++int mmf_add_venc_channel(int ch, mmf_venc_cfg_t *cfg); ++int mmf_del_venc_channel(int ch); ++int mmf_del_venc_channel_all(); ++int mmf_venc_push(int ch, uint8_t *data, int w, int h, int format); ++int mmf_venc_push2(int ch, void *frame_info); ++int mmf_venc_pop(int ch, mmf_stream_t *stream); ++int mmf_venc_free(int ch); ++int mmf_venc_get_cfg(int ch, mmf_venc_cfg_t *cfg); ++ ++// vdec ++int mmf_vdec_unused_channel(void); ++int mmf_vdec_is_used(int ch); ++int mmf_add_vdec_channel(int ch, mmf_vdec_cfg_t *cfg); ++int mmf_del_vdec_channel(int ch); ++int mmf_del_vdec_channel_all(); ++int mmf_vdec_push(int ch, uint8_t *data, int size, uint8_t is_start, uint8_t is_end); ++int mmf_vdec_pop(int ch, void **data, int *len, int *width, int *height, int *format); ++int mmf_vdec_free(int ch); ++int mmf_vdec_get_cfg(int ch, mmf_vdec_cfg_t *cfg); ++ ++int mmf_init0(uint32_t param, ...); ++int mmf_deinit0(uint32_t param, ...); ++int mmf_vi_init0(uint32_t param, ...); ++int mmf_add_vi_channel0(uint32_t param, ...); ++int mmf_add_vo_channel0(uint32_t param, ...); ++int mmf_add_region_channel0(uint32_t param, ...); ++int mmf_add_venc_channel0(uint32_t param, ...); ++int mmf_add_vdec_channel0(uint32_t param, ...); ++int mmf_vdec_push0(uint32_t param, ...); ++int mmf_vdec_pop0(uint32_t param, ...); ++ ++static inline int mmf_init_v2(int reload_kmod) { ++ return mmf_init0(MMF_FUNC_SET_PARAM(0, 1), reload_kmod); ++} ++ ++static inline int mmf_deinit_v2(int force) { ++ return mmf_deinit0(MMF_FUNC_SET_PARAM(0, 1), force); ++} ++ ++static inline int mmf_vi_init_v2(int width, int height, int vi_format, int vpss_format, int fps, int pool_num, SAMPLE_VI_CONFIG_S *vi_cfg) { ++ return mmf_vi_init0(MMF_FUNC_SET_PARAM(0, 8), width, height, vi_format, vpss_format, fps, pool_num, vi_cfg); ++} ++ ++static inline int mmf_add_vi_channel_v2(int ch, int width, int height, int format, int fps, int depth, int mirror, int vflip, int fit, int pool_num) { ++ return mmf_add_vi_channel0(MMF_FUNC_SET_PARAM(0, 10), ch, width, height, format, fps, depth, mirror, vflip, fit, pool_num); ++} ++ ++static inline int mmf_add_vo_channel_v2(int layer, int ch, int width, int height, int format_in, int format_out, int fps, int depth, int mirror, int vflip, int fit, int rotate, int pool_num_in, int pool_num_out) { ++ return mmf_add_vo_channel0(MMF_FUNC_SET_PARAM(0, 14), layer, ch, width, height, format_in, format_out, fps, depth, mirror, vflip, fit, rotate, pool_num_in, pool_num_out); ++} ++ ++static inline int mmf_add_region_channel_v2(int ch, int type, int mod_id, int dev_id, int chn_id, int x, int y, int width, int height, int format) { ++ return mmf_add_region_channel0(MMF_FUNC_SET_PARAM(0, 10), ch, type, mod_id, dev_id, chn_id, x, y, width, height, format); ++} ++ ++static inline int mmf_add_venc_channel_v2(int ch, void *cfg) { ++ return mmf_add_venc_channel0(MMF_FUNC_SET_PARAM(0, 2), ch, cfg); ++} ++ ++static inline int mmf_add_vdec_channel_v2(int ch, int format_out, int pool_num, VDEC_CHN_ATTR_S *cfg) { ++ return mmf_add_vdec_channel0(MMF_FUNC_SET_PARAM(0, 4), ch, format_out, pool_num, cfg); ++} ++ ++static inline int mmf_vdec_push_v2(int ch, VDEC_STREAM_S *stStream) { ++ return mmf_vdec_push0(MMF_FUNC_SET_PARAM(0, 2), ch, stStream); ++} ++ ++static inline int mmf_vdec_pop_v2(int ch, VIDEO_FRAME_INFO_S *frame) { ++ return mmf_vdec_pop0(MMF_FUNC_SET_PARAM(0, 2), ch, frame); ++} ++#endif // __SOPHGO_MIDDLEWARE_HPP__ +diff --git a/sample/test_mmf/maix_mmf/Makefile b/sample/test_mmf/maix_mmf/Makefile +new file mode 100644 +index 0000000..41e3ac1 +--- /dev/null ++++ b/sample/test_mmf/maix_mmf/Makefile +@@ -0,0 +1,58 @@ ++SHELL = /bin/bash ++ifeq ($(PARAM_FILE), ) ++ PARAM_FILE:=../../../Makefile.param ++ include $(PARAM_FILE) ++endif ++ ++PWD:=$(shell pwd) ++ROOT:=$(PWD)/.. ++ ++#--------------------------------Output------------------------------ ++# OUTTYPE: 0-exe, 1-dll, 2-static ++#-------------------------------------------------------------------- ++OUTTYPE = 2 ++OUTFILE = libmaix_mmf.a ++ ++#-------------------------------Include------------------------------ ++# ++# INCLUDES = $(addprefix -I,$(INCLUDES)) # add -I prefix ++#-------------------------------------------------------------------- ++INCLUDES = . \ ++ $(MW_INC) \ ++ $(ISP_INC) \ ++ ../../common/ \ ++ $(KERNEL_INC) \ ++ $(SENSOR_LIST_INC) \ ++ $(ROOT) ++ ++#-------------------------------Source------------------------------- ++# ++#-------------------------------------------------------------------- ++SOURCE_PATHS = . ++#source source/client source/server source/utils source/sdp ++SOURCE_FILES = $(foreach dir,$(SOURCE_PATHS),$(wildcard $(dir)/*.cpp)) ++SOURCE_FILES += $(foreach dir,$(SOURCE_PATHS),$(wildcard $(dir)/*.c)) ++ ++#-----------------------------Library-------------------------------- ++# ++# LIBPATHS = $(addprefix -L,$(LIBPATHS)) # add -L prefix ++#-------------------------------------------------------------------- ++LIBPATHS = ++ifdef RELEASE ++# relase library path ++LIBPATHS += ++else ++LIBPATHS += ++endif ++ ++LIBS = ++ ++STATIC_LIBS = ++ ++#-----------------------------DEFINES-------------------------------- ++# ++# DEFINES := $(addprefix -D,$(DEFINES)) # add -L prefix ++#-------------------------------------------------------------------- ++DEFINES = ++ ++include gcc.mk +diff --git a/sample/test_mmf/maix_mmf/gcc.mk b/sample/test_mmf/maix_mmf/gcc.mk +new file mode 100644 +index 0000000..5936d96 +--- /dev/null ++++ b/sample/test_mmf/maix_mmf/gcc.mk +@@ -0,0 +1,103 @@ ++RELEASE ?= 0 # default debug ++UNICODE ?= 0 # default ansi ++ ++ifdef PLATFORM ++ #CROSS:=$(PLATFORM)- ++else ++ #CROSS:= ++ PLATFORM:=linux ++endif ++ ++ifeq ($(RELEASE),1) ++ BUILD:=release ++else ++ BUILD:=debug ++endif ++ ++KERNEL := Linux ++ifeq ($(KERNEL),Linux) ++ DEFINES += OS_LINUX ++endif ++ifeq ($(KERNEL),Darwin) ++ DEFINES += OS_MAC ++endif ++ ++#--------------------------------Compile----------------------------- ++# ++#-------------------------------------------------------------------- ++#AR := $(CROSS)ar ++#CC := $(CROSS)gcc ++#CXX := $(CROSS)g++ ++CFLAGS += -Wall -fPIC ++CXXFLAGS += -Wall ++DEPFLAGS = -MMD -MP -MF $(OUTPATH)/$(*F).d ++ ++ifeq ($(RELEASE),1) ++ CFLAGS += -Wall -O2 ++ CXXFLAGS += $(CFLAGS) ++ DEFINES += NDEBUG ++else ++ CFLAGS += -g -Wall ++# CFLAGS += -fsanitize=address ++ CXXFLAGS += $(CFLAGS) ++ DEFINES += DEBUG _DEBUG ++endif ++ ++# default don't export anything ++CFLAGS += -fvisibility=hidden ++ ++COMPILE.CC = $(CC) $(addprefix -I,$(INCLUDES)) $(addprefix -D,$(DEFINES)) $(CFLAGS) ++COMPILE.CXX = $(CXX) $(addprefix -I,$(INCLUDES)) $(addprefix -D,$(DEFINES)) $(CXXFLAGS) ++ ++#-------------------------Link--------------------------- ++# ++#-------------------------------------------------------------------- ++ifeq ($(STATIC_LINK),1) ++ LDFLAGS += -static ++endif ++ ++#-------------------------Compile Output--------------------------- ++# ++#-------------------------------------------------------------------- ++ifeq ($(UNICODE),1) ++ OUTPATH += unicode.$(BUILD).$(PLATFORM) ++else ++ OUTPATH += $(BUILD).$(PLATFORM) ++endif ++ ++# make output dir ++$(shell mkdir -p $(OUTPATH) > /dev/null) ++ ++OBJECT_FILES := $(patsubst %.c,%.o,$(patsubst %.cpp,%.o,$(SOURCE_FILES))) ++DEPENDENCE_FILES := $(OBJECT_FILES:%.o=%.d) ++DEPENDENCE_FILES := $(foreach file,$(DEPENDENCE_FILES),$(OUTPATH)/$(notdir $(file))) ++ ++#--------------------------Makefile Rules---------------------------- ++# ++#-------------------------------------------------------------------- ++$(OUTPATH)/$(OUTFILE): $(OBJECT_FILES) $(STATIC_LIBS) ++ifeq ($(OUTTYPE),0) ++ $(CXX) -o $@ -Wl,-rpath . $(LDFLAGS) $^ $(addprefix -L,$(LIBPATHS)) $(addprefix -l,$(LIBS)) ++else ++ifeq ($(OUTTYPE),1) ++ $(CXX) -o $@ -shared -fpic -rdynamic -Wl,-rpath . $(LDFLAGS) $^ $(addprefix -L,$(LIBPATHS)) $(addprefix -l,$(LIBS)) ++else ++ $(AR) -rc $@ $^ ++endif ++endif ++ @echo make ok, output: $(OUTPATH)/$(OUTFILE) ++ ++%.o : %.c ++ $(COMPILE.CC) -c $(DEPFLAGS) -o $@ $< ++ ++%.o : %.cpp ++ $(COMPILE.CXX) -c $(DEPFLAGS) -o $@ $< ++ ++-include $(DEPENDENCE_FILES) ++ ++version.h : version.ver ++ $(ROOT)/svnver.sh version.ver version.h ++ ++.PHONY: clean ++clean: ++ rm -f $(OBJECT_FILES) $(OUTPATH)/$(OUTFILE) $(DEPENDENCE_FILES) +diff --git a/sample/test_mmf/maix_mmf/sophgo_middleware.c b/sample/test_mmf/maix_mmf/sophgo_middleware.c +new file mode 100644 +index 0000000..db370d0 +--- /dev/null ++++ b/sample/test_mmf/maix_mmf/sophgo_middleware.c +@@ -0,0 +1,5585 @@ ++#ifdef __cplusplus ++#include ++#else ++#include ++#endif ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include "math.h" ++#include ++ ++#include /* low-level i/o */ ++#ifdef __cplusplus ++extern "C" { ++#endif ++#include ++#include ++#include ++#include ++extern int ionFree(struct sys_ion_data *para); ++#ifdef __cplusplus ++} ++#endif ++#include "cvi_buffer.h" ++#include "cvi_ae_comm.h" ++#include "cvi_awb_comm.h" ++#include "cvi_comm_isp.h" ++#include "cvi_comm_sns.h" ++#include "cvi_ae.h" ++#include "cvi_awb.h" ++#include "cvi_isp.h" ++#include "cvi_sns_ctrl.h" ++#include "cvi_ive.h" ++#include "sample_comm.h" ++#ifdef __cplusplus ++#include "sophgo_middleware.hpp" ++#else ++#include "maix_mmf.h" ++#endif ++ ++ ++ ++#ifndef MMF_FUNC_GET_PARAM_METHOD ++#define MMF_FUNC_GET_PARAM_METHOD(x) ((x >> 24) & 0xffffff) ++#endif ++#ifndef MMF_FUNC_GET_PARAM_NUM ++#define MMF_FUNC_GET_PARAM_NUM(x) ((x & 0xff)) ++#endif ++ ++#define MMF_DEC_MAX_CHN 2 ++#define MMF_ENC_MAX_CHN 2 ++#define MMF_VI_MAX_CHN 2 // manually limit the max channel number of vi ++#define MMF_VO_VIDEO_MAX_CHN 1 // manually limit the max channel number of vo ++#define MMF_VO_OSD_MAX_CHN 1 ++#define MMF_VO_VIDEO_LAYER 0 ++#define MMF_VO_OSD_LAYER 1 ++#define MMF_VO_USE_NV21_ONLY 0 ++#define MMF_RGN_MAX_NUM 16 ++ ++#if VPSS_MAX_PHY_CHN_NUM < MMF_VI_MAX_CHN ++#error "VPSS_MAX_PHY_CHN_NUM < MMF_VI_MAX_CHN" ++#endif ++typedef struct { ++ int mmf_used_cnt; ++ ++ PIXEL_FORMAT_E vi_format; ++ PIXEL_FORMAT_E vi_vpss_format; ++ int vi_pop_timeout; ++ int vi_vpss; ++ bool vi_is_inited; ++ bool vi_chn_is_inited[MMF_VI_MAX_CHN]; ++ SIZE_S vi_max_size; ++ SIZE_S vi_size; ++ VIDEO_FRAME_INFO_S vi_frame[MMF_VI_MAX_CHN]; ++ ++#ifndef KVM_MMF ++ int vo_rotate; // 90, 180, 270 ++ int vo_vpss; ++ bool vo_video_chn_is_inited[MMF_VO_VIDEO_MAX_CHN]; ++ bool vo_osd_chn_is_inited[MMF_VO_OSD_MAX_CHN]; ++ SIZE_S vo_vpss_in_size[MMF_VO_VIDEO_MAX_CHN]; ++ SIZE_S vo_vpss_out_size[MMF_VO_VIDEO_MAX_CHN]; ++ int vo_vpss_out_fps[MMF_VO_VIDEO_MAX_CHN]; ++ int vo_vpss_out_depth[MMF_VO_VIDEO_MAX_CHN]; ++ int vo_vpss_in_format[MMF_VO_VIDEO_MAX_CHN]; ++ int vo_vpss_fit[MMF_VO_VIDEO_MAX_CHN]; ++ VIDEO_FRAME_INFO_S *vo_video_pre_frame[MMF_VO_VIDEO_MAX_CHN]; ++ int vo_video_pre_frame_width[MMF_VO_VIDEO_MAX_CHN]; ++ int vo_video_pre_frame_height[MMF_VO_VIDEO_MAX_CHN]; ++ int vo_video_pre_frame_format[MMF_VO_VIDEO_MAX_CHN]; ++ SAMPLE_VO_CONFIG_S vo_video_cfg[MMF_VO_VIDEO_MAX_CHN]; ++#endif ++ ++ int ive_is_init; ++ IVE_HANDLE ive_handle; ++ IVE_IMAGE_S ive_rgb2yuv_rgb_img; ++ IVE_IMAGE_S ive_rgb2yuv_yuv_img; ++ int ive_rgb2yuv_w; ++ int ive_rgb2yuv_h; ++ ++ bool rgn_is_init[MMF_RGN_MAX_NUM]; ++ bool rgn_is_bind[MMF_RGN_MAX_NUM]; ++ RGN_TYPE_E rgn_type[MMF_RGN_MAX_NUM]; ++ int rgn_id[MMF_RGN_MAX_NUM]; ++ MOD_ID_E rgn_mod_id[MMF_RGN_MAX_NUM]; ++ CVI_S32 rgn_dev_id[MMF_RGN_MAX_NUM]; ++ CVI_S32 rgn_chn_id[MMF_RGN_MAX_NUM]; ++ uint8_t* rgn_canvas_data[MMF_RGN_MAX_NUM]; ++ int rgn_canvas_w[MMF_RGN_MAX_NUM]; ++ int rgn_canvas_h[MMF_RGN_MAX_NUM]; ++ int rgn_canvas_format[MMF_RGN_MAX_NUM]; ++ ++ PAYLOAD_TYPE_E enc_chn_type[MMF_ENC_MAX_CHN]; ++ int enc_chn_vb_id[MMF_ENC_MAX_CHN]; ++ int enc_chn_vpss[MMF_ENC_MAX_CHN]; ++ int enc_chn_is_init[MMF_ENC_MAX_CHN]; ++ int enc_chn_running[MMF_ENC_MAX_CHN]; ++ VIDEO_FRAME_INFO_S *enc_chn_frame[MMF_ENC_MAX_CHN]; ++ VENC_STREAM_S enc_chn_stream[MMF_ENC_MAX_CHN]; ++ mmf_venc_cfg_t enc_chn_cfg[MMF_ENC_MAX_CHN]; ++ ++#ifndef KVM_MMF ++ int dec_pop_timeout; ++ PAYLOAD_TYPE_E dec_chn_type[MMF_DEC_MAX_CHN]; ++ int dec_chn_vb_id[MMF_DEC_MAX_CHN]; ++ int dec_chn_vpss[MMF_DEC_MAX_CHN]; ++ int dec_chn_is_init[MMF_DEC_MAX_CHN]; ++ int dec_chn_running[MMF_DEC_MAX_CHN]; ++ VIDEO_FRAME_INFO_S dec_chn_frame[MMF_DEC_MAX_CHN]; ++ VIDEO_FRAME_INFO_S *dec_pst_frame[MMF_DEC_MAX_CHN]; ++ VDEC_STREAM_S dec_chn_stream[MMF_DEC_MAX_CHN]; ++ SIZE_S dec_chn_size_in[MMF_DEC_MAX_CHN]; ++ mmf_vdec_cfg_t dec_chn_cfg[MMF_DEC_MAX_CHN]; ++#endif ++ ++ VB_CONFIG_S vb_conf; ++ int vb_of_vi_is_config : 1; ++#ifndef KVM_MMF ++ int vb_of_vo_is_config : 1; ++ int vb_of_private_is_config : 1; ++#endif ++ int vb_size_of_vi; ++ int vb_count_of_vi; ++ int vb_size_of_vo; ++ int vb_count_of_vo; ++ int vb_size_of_private; ++ int vb_count_of_private; ++ VB_POOL vb_vi_id; ++#ifndef KVM_MMF ++ VB_POOL vb_vo_id; ++ VB_POOL vb_user_id; ++#endif ++ VB_POOL vb_enc_h26x_id; ++ VB_POOL vb_enc_jpeg_id; ++#ifndef KVM_MMF ++ VB_POOL vb_dec_h26x_id; ++ VB_POOL vb_dec_jpeg_id; ++#endif ++ CVI_U32 vb_max_pool_cnt; ++ ++ SAMPLE_SNS_TYPE_E sensor_type; ++} priv_t; ++ ++typedef struct { ++ int enc_h26x_enable : 1; ++ int enc_jpg_enable : 1; ++ int dec_h26x_enable : 1; ++ int dec_jpg_enable : 1; ++ bool vi_hmirror[MMF_VI_MAX_CHN]; ++ bool vi_vflip[MMF_VI_MAX_CHN]; ++ bool vo_video_hmirror[MMF_VO_VIDEO_MAX_CHN]; ++ bool vo_video_vflip[MMF_VO_VIDEO_MAX_CHN]; ++ bool vo_osd_hmirror[MMF_VO_OSD_MAX_CHN]; ++ bool vo_osd_vflip[MMF_VO_OSD_MAX_CHN]; ++} g_priv_t; ++ ++static priv_t priv; ++static g_priv_t g_priv; ++ ++static CVI_S64 _get_ion_size_info(const char *path); ++ ++#ifndef KVM_MMF ++static int mmf_region_frame_push2(int ch, void *frame_info); ++#endif ++ ++static int mmf_venc_deinit(int ch); ++static int _mmf_venc_push(int ch, uint8_t *data, int w, int h, int format, int quality); ++static int mmf_rst_venc_channel(int ch, int w, int h, int format, int quality); ++ ++#ifndef KVM_MMF ++static int mmf_vdec_deinit(int ch); ++static int _mmf_vdec_push(int ch, VDEC_STREAM_S *stStream); ++static int mmf_rst_vdec_channel(int ch, mmf_vdec_cfg_t *cfg, SIZE_S size_in); ++#endif ++ ++#define DISP_W 640 ++#define DISP_H 480 ++static void priv_param_init(void) ++{ ++ CVI_S64 ion_total_mem = _get_ion_size_info("/sys/kernel/debug/ion/cvi_carveout_heap_dump/total_mem"); ++ ++ priv.vi_pop_timeout = 100; ++ priv.vi_vpss = VPSS_INVALID_GRP; ++#ifndef KVM_MMF ++ priv.vo_rotate = 90; ++ priv.vo_vpss = VPSS_INVALID_GRP; ++ priv.dec_pop_timeout = 1000; ++#endif ++ ++ priv.vb_conf.u32MaxPoolCnt = 0; ++ priv.vb_vi_id = priv.vb_conf.u32MaxPoolCnt; ++ priv.vb_conf.u32MaxPoolCnt ++; ++ ++#ifndef KVM_MMF ++ if (ion_total_mem > 0 && ion_total_mem < 40 * 1024 * 1024) { ++ priv.vb_vo_id = VB_INVALID_POOLID; ++ priv.vb_user_id = VB_INVALID_POOLID; ++ } else { ++ priv.vb_vo_id = priv.vb_conf.u32MaxPoolCnt; ++ priv.vb_conf.astCommPool[priv.vb_vo_id].u32BlkSize = ALIGN(DISP_W, DEFAULT_ALIGN) * ALIGN(DISP_H, DEFAULT_ALIGN) * 3; ++ priv.vb_conf.astCommPool[priv.vb_vo_id].u32BlkCnt = 8; ++ priv.vb_conf.astCommPool[priv.vb_vo_id].enRemapMode = VB_REMAP_MODE_CACHED; ++ priv.vb_conf.u32MaxPoolCnt ++; ++ ++ priv.vb_user_id = priv.vb_conf.u32MaxPoolCnt; ++ priv.vb_conf.astCommPool[priv.vb_user_id].u32BlkSize = ALIGN(2560, DEFAULT_ALIGN) * ALIGN(1440, DEFAULT_ALIGN) * 3 / 2; ++ priv.vb_conf.astCommPool[priv.vb_user_id].u32BlkCnt = 2; ++ priv.vb_conf.astCommPool[priv.vb_user_id].enRemapMode = VB_REMAP_MODE_CACHED; ++ priv.vb_conf.u32MaxPoolCnt ++; ++ } ++#endif ++ ++ priv.vb_enc_h26x_id = priv.vb_conf.u32MaxPoolCnt; ++ priv.vb_enc_jpeg_id = priv.vb_conf.u32MaxPoolCnt + 1; ++#ifndef KVM_MMF ++ priv.vb_dec_h26x_id = priv.vb_conf.u32MaxPoolCnt + 2; ++ priv.vb_dec_jpeg_id = priv.vb_conf.u32MaxPoolCnt + 3; ++#endif ++ ++ printf("ion heap total size: %llu KiB\n", ion_total_mem / 1024); ++ if (priv.vb_max_pool_cnt < priv.vb_conf.u32MaxPoolCnt) { ++ if (ion_total_mem > 0 && ion_total_mem < 40 * 1024 * 1024) { ++ priv.vb_max_pool_cnt = 2; ++ } else if (ion_total_mem > 0 && ion_total_mem < 64 * 1024 * 1024) { ++ priv.vb_max_pool_cnt = 4; ++ } else { ++ priv.vb_max_pool_cnt = 7; ++ } ++ } ++ ++ g_priv.enc_h26x_enable = (priv.vb_max_pool_cnt > priv.vb_conf.u32MaxPoolCnt) ? 1 : 0; ++ if (g_priv.enc_h26x_enable) { ++ priv.vb_conf.astCommPool[priv.vb_enc_h26x_id].u32BlkSize = ALIGN(2560, DEFAULT_ALIGN) * ALIGN(1440, DEFAULT_ALIGN) * 3 / 2; ++ priv.vb_conf.astCommPool[priv.vb_enc_h26x_id].u32BlkCnt = 1; ++ priv.vb_conf.astCommPool[priv.vb_enc_h26x_id].enRemapMode = VB_REMAP_MODE_CACHED; ++ priv.vb_conf.u32MaxPoolCnt ++; ++ } ++ ++ g_priv.enc_jpg_enable = (priv.vb_max_pool_cnt > priv.vb_conf.u32MaxPoolCnt) ? 1 : 0; ++ if (g_priv.enc_jpg_enable) { ++ priv.vb_conf.astCommPool[priv.vb_enc_jpeg_id].u32BlkSize = ALIGN(2560, DEFAULT_ALIGN) * ALIGN(1440, DEFAULT_ALIGN) * 3 / 2; ++ priv.vb_conf.astCommPool[priv.vb_enc_jpeg_id].u32BlkCnt = 1; ++ priv.vb_conf.astCommPool[priv.vb_enc_jpeg_id].enRemapMode = VB_REMAP_MODE_CACHED; ++ priv.vb_conf.u32MaxPoolCnt ++; ++ } else { ++ priv.vb_enc_jpeg_id = priv.vb_enc_h26x_id; ++ } ++ ++#ifndef KVM_MMF ++ g_priv.dec_h26x_enable = (priv.vb_max_pool_cnt > priv.vb_conf.u32MaxPoolCnt) ? 1 : 0; ++ if (g_priv.dec_h26x_enable) { ++ priv.vb_conf.astCommPool[priv.vb_dec_h26x_id].u32BlkSize = ALIGN(2560, DEFAULT_ALIGN) * ALIGN(1440, DEFAULT_ALIGN) * 3; ++ priv.vb_conf.astCommPool[priv.vb_dec_h26x_id].u32BlkCnt = 1; ++ priv.vb_conf.astCommPool[priv.vb_dec_h26x_id].enRemapMode = VB_REMAP_MODE_CACHED; ++ priv.vb_conf.u32MaxPoolCnt ++; ++ } ++ ++ g_priv.dec_jpg_enable = (priv.vb_max_pool_cnt > priv.vb_conf.u32MaxPoolCnt) ? 1 : 0; ++ if (g_priv.dec_jpg_enable) { ++ priv.vb_conf.astCommPool[priv.vb_dec_jpeg_id].u32BlkSize = ALIGN(2560, DEFAULT_ALIGN) * ALIGN(1440, DEFAULT_ALIGN) * 3; ++ priv.vb_conf.astCommPool[priv.vb_dec_jpeg_id].u32BlkCnt = 1; ++ priv.vb_conf.astCommPool[priv.vb_dec_jpeg_id].enRemapMode = VB_REMAP_MODE_CACHED; ++ priv.vb_conf.u32MaxPoolCnt ++; ++ } else { ++ priv.vb_dec_jpeg_id = priv.vb_dec_h26x_id; ++ } ++#endif ++ ++ if (priv.vb_of_vi_is_config) { ++ priv.vb_conf.astCommPool[priv.vb_vi_id].u32BlkSize = priv.vb_size_of_vi; ++ priv.vb_conf.astCommPool[priv.vb_vi_id].u32BlkCnt = priv.vb_count_of_vi; ++ priv.vb_conf.astCommPool[priv.vb_vi_id].enRemapMode = VB_REMAP_MODE_CACHED; ++ } ++ ++#ifndef KVM_MMF ++ if (priv.vb_of_vo_is_config) { ++ priv.vb_conf.astCommPool[priv.vb_vo_id].u32BlkSize = priv.vb_size_of_vo; ++ priv.vb_conf.astCommPool[priv.vb_vo_id].u32BlkCnt = priv.vb_count_of_vo; ++ priv.vb_conf.astCommPool[priv.vb_vo_id].enRemapMode = VB_REMAP_MODE_CACHED; ++ } ++ ++ if (priv.vb_of_private_is_config) { ++ priv.vb_conf.astCommPool[priv.vb_user_id].u32BlkSize = priv.vb_size_of_private; ++ priv.vb_conf.astCommPool[priv.vb_user_id].u32BlkCnt = priv.vb_count_of_private; ++ priv.vb_conf.astCommPool[priv.vb_user_id].enRemapMode = VB_REMAP_MODE_CACHED; ++ } ++#endif ++} ++ ++static SAMPLE_VI_CONFIG_S g_stViConfig; ++static SAMPLE_INI_CFG_S g_stIniCfg; ++ ++void mmf_dump_grpattr(VPSS_GRP_ATTR_S *GrpAttr) { ++ printf("GrpAttr->u32MaxW: %d, GrpAttr->u32MaxH: %d\r\n", GrpAttr->u32MaxW, GrpAttr->u32MaxH); ++ printf("GrpAttr->enPixelFormat:%d \r\n", GrpAttr->enPixelFormat); ++ printf("GrpAttr->stFrameRate.s32SrcFrameRate:%d \r\n", GrpAttr->stFrameRate.s32SrcFrameRate); ++ printf("GrpAttr->stFrameRate.s32DstFrameRate:%d \r\n", GrpAttr->stFrameRate.s32DstFrameRate); ++ printf("GrpAttr->u8VpssDev:%d\n", GrpAttr->u8VpssDev); ++} ++ ++void mmf_dump_venc_chn_status(VENC_CHN_STATUS_S *status) { ++ if (status == NULL) { ++ printf("status is null\n"); ++ return; ++ } ++ ++ printf("u32LeftPics:\t\t%d\n", status->u32LeftPics); ++ printf("u32LeftStreamBytes:\t\t%d\n", status->u32LeftStreamBytes); ++ printf("u32LeftStreamFrames:\t\t%d\n", status->u32LeftStreamFrames); ++ printf("u32CurPacks:\t\t%d\n", status->u32CurPacks); ++ printf("u32LeftRecvPics:\t\t%d\n", status->u32LeftRecvPics); ++ printf("u32LeftEncPics:\t\t%d\n", status->u32LeftEncPics); ++ printf("bJpegSnapEnd:\t\t%d\n", status->bJpegSnapEnd); ++ printf("stVencStrmInfo:\t\tnone\n"); // status->stVencStrmInfo ++} ++ ++void mmf_dump_chnattr(VPSS_CHN_ATTR_S *ChnAttr) { ++ printf("ChnAttr->u32Width:%d \r\n", ChnAttr->u32Width); ++ printf("ChnAttr->u32Height:%d \r\n", ChnAttr->u32Height); ++ printf("ChnAttr->enVideoFormat:%d \r\n", ChnAttr->enVideoFormat); ++ printf("ChnAttr->enPixelFormat:%d \r\n", ChnAttr->enPixelFormat); ++ printf("ChnAttr->stFrameRate.s32SrcFrameRate:%d \r\n", ChnAttr->stFrameRate.s32SrcFrameRate); ++ printf("ChnAttr->stFrameRate.s32DstFrameRate:%d \r\n", ChnAttr->stFrameRate.s32DstFrameRate); ++ printf("ChnAttr->bMirror:%d \r\n", ChnAttr->bMirror); ++ printf("ChnAttr->bFlip:%d \r\n", ChnAttr->bFlip); ++ printf("ChnAttr->u32Depth:%d \r\n", ChnAttr->u32Depth); ++ printf("ChnAttr->stAspectRatio.bEnable:%d \r\n", ChnAttr->stAspectRatio.enMode); ++ printf("ChnAttr->stAspectRatio.u32BgColor:%d \r\n", ChnAttr->stAspectRatio.u32BgColor); ++ printf("ChnAttr->stAspectRatio.bEnableBgColor:%d \r\n", ChnAttr->stAspectRatio.bEnableBgColor); ++ printf("ChnAttr->stAspectRatio.stVideoRect.s32X:%d \r\n", ChnAttr->stAspectRatio.stVideoRect.s32X); ++ printf("ChnAttr->stAspectRatio.stVideoRect.s32Y:%d \r\n", ChnAttr->stAspectRatio.stVideoRect.s32Y); ++ printf("ChnAttr->stAspectRatio.stVideoRect.u32Width:%d \r\n", ChnAttr->stAspectRatio.stVideoRect.u32Width); ++ printf("ChnAttr->stAspectRatio.stVideoRect.u32Height:%d \r\n", ChnAttr->stAspectRatio.stVideoRect.u32Height); ++ printf("ChnAttr->stNormalize.bEnable:%d \r\n", ChnAttr->stNormalize.bEnable); ++ for (int i = 0; i < 3; i ++) ++ printf("ChnAttr->stLumaScale.factor[%d]:%f \r\n", i, ChnAttr->stNormalize.factor[i]); ++ for (int i = 0; i < 3; i ++) ++ printf("ChnAttr->stLumaScale.mean[%d]:%f \r\n", i, ChnAttr->stNormalize.mean[i]); ++ printf("ChnAttr->stNormalize.rounding:%d \r\n", ChnAttr->stNormalize.rounding); ++} ++ ++void mmf_dump_frame(VIDEO_FRAME_INFO_S *frame) { ++ if (frame == NULL) { ++ printf("frame is null\n"); ++ return; ++ } ++ ++ VIDEO_FRAME_S *vframe = &frame->stVFrame; ++ printf("u32Width:\t\t%d\n", vframe->u32Width); ++ printf("u32Height:\t\t%d\n", vframe->u32Height); ++ printf("u32Stride[0]:\t\t%d\n", vframe->u32Stride[0]); ++ printf("u32Stride[1]:\t\t%d\n", vframe->u32Stride[1]); ++ printf("u32Stride[2]:\t\t%d\n", vframe->u32Stride[2]); ++ printf("u32Length[0]:\t\t%d\n", vframe->u32Length[0]); ++ printf("u32Length[1]:\t\t%d\n", vframe->u32Length[1]); ++ printf("u32Length[2]:\t\t%d\n", vframe->u32Length[2]); ++ printf("u64PhyAddr[0]:\t\t%#llx\n", vframe->u64PhyAddr[0]); ++ printf("u64PhyAddr[1]:\t\t%#llx\n", vframe->u64PhyAddr[1]); ++ printf("u64PhyAddr[2]:\t\t%#llx\n", vframe->u64PhyAddr[2]); ++ printf("pu8VirAddr[0]:\t\t%p\n", vframe->pu8VirAddr[0]); ++ printf("pu8VirAddr[1]:\t\t%p\n", vframe->pu8VirAddr[1]); ++ printf("pu8VirAddr[2]:\t\t%p\n", vframe->pu8VirAddr[2]); ++ ++ printf("enPixelFormat:\t\t%d\n", vframe->enPixelFormat); ++ printf("enBayerFormat:\t\t%d\n", vframe->enBayerFormat); ++ printf("enVideoFormat:\t\t%d\n", vframe->enVideoFormat); ++ printf("enCompressMode:\t\t%d\n", vframe->enCompressMode); ++ printf("enDynamicRange:\t\t%d\n", vframe->enDynamicRange); ++ printf("enColorGamut:\t\t%d\n", vframe->enColorGamut); ++ ++ printf("s16OffsetTop:\t\t%d\n", vframe->s16OffsetTop); ++ printf("s16OffsetBottom:\t\t%d\n", vframe->s16OffsetBottom); ++ printf("s16OffsetLeft:\t\t%d\n", vframe->s16OffsetLeft); ++ printf("s16OffsetRight:\t\t%d\n", vframe->s16OffsetRight); ++} ++ ++static CVI_S64 _get_ion_size_info(const char *path) ++{ ++ FILE *fd = NULL; ++ char val[256] = {0}; ++ ++ fd = fopen(path, "r"); ++ ++ if (fd == NULL) { ++ fprintf(stderr, "Error opening file %s\n", path); ++ return 0; ++ } ++ ++ memset(val, 0, 128); ++ ++ fgets(val, 128, fd); ++ ++ pclose(fd); ++ ++ return atol(val); ++} ++ ++static int _free_leak_memory_of_ion(void) ++{ ++ #define MAX_LINE_LENGTH 256 ++ FILE *fp; ++ char line[MAX_LINE_LENGTH]; ++ char alloc_buf_size_str[20], phy_addr_str[20], buffer_name[20]; ++ int alloc_buf_size; ++ uint64_t phy_addr; ++ ++ fp = fopen("/sys/kernel/debug/ion/cvi_carveout_heap_dump/summary", "r"); ++ if (fp == NULL) { ++ fprintf(stderr, "Error opening file\n"); ++ return 1; ++ } ++ ++ while (fgets(line, MAX_LINE_LENGTH, fp) != NULL) { ++ if (sscanf(line, "%*d %s %s %*d %s", alloc_buf_size_str, phy_addr_str, buffer_name) == 3) { ++ if (strcmp(buffer_name, "VI_DMA_BUF") ++ && strcmp(buffer_name, "ISP_SHARED_BUFFER_0")) ++ continue; ++ struct sys_ion_data2 ion_data; ++ ++ alloc_buf_size = atoi(alloc_buf_size_str); ++ phy_addr = (unsigned int)strtol(phy_addr_str, NULL, 16); ++ ++ memset(&ion_data, 0, sizeof(ion_data)); ++ ion_data.cached = 1; ++ ion_data.dmabuf_fd = (uint32_t)-1; ++ ion_data.size = alloc_buf_size; ++ ion_data.addr_p = phy_addr; ++ memset(ion_data.name, 0, sizeof(ion_data.name)); ++ strcpy((char *)ion_data.name, buffer_name); ++ ++ printf("alloc_buf_size(%s): %d, phy_addr(%s): %#lx, buffer_name: %s\n", ++ alloc_buf_size_str, alloc_buf_size, phy_addr_str, phy_addr, buffer_name); ++ ++ printf("ion_data.size:%d, ion_data.addr_p:%#x, ion_data.name:%s\r\n", ion_data.size, (int)ion_data.addr_p, ion_data.name); ++ ++ int res = ionFree((struct sys_ion_data *)&ion_data); ++ if (res) { ++ printf("ionFree2 failed! res:%#x\r\n", res); ++ mmf_deinit(); ++ return -1; ++ } ++ } ++ } ++ ++ fclose(fp); ++ ++ return 0; ++} ++ ++static CVI_S32 _mmf_init_frame(VB_POOL id, SIZE_S stSize, PIXEL_FORMAT_E enPixelFormat, VIDEO_FRAME_INFO_S *pstVideoFrame, VB_CAL_CONFIG_S *pstVbCfg) ++{ ++ VIDEO_FRAME_S *pstVFrame; ++ VB_BLK blk; ++ ++ if (id == VB_INVALID_POOLID || (CVI_U32)id >= priv.vb_conf.u32MaxPoolCnt) { ++ printf("Invalid vb pool. id: %d\n", id); ++ return CVI_FAILURE; ++ } ++ if (!pstVideoFrame || !pstVbCfg) { ++ return CVI_FAILURE; ++ } ++ ++ pstVFrame = &pstVideoFrame->stVFrame; ++ ++ pstVFrame->enCompressMode = COMPRESS_MODE_NONE; ++ pstVFrame->enPixelFormat = enPixelFormat; ++ pstVFrame->enVideoFormat = VIDEO_FORMAT_LINEAR; ++ pstVFrame->enColorGamut = COLOR_GAMUT_BT709; ++ pstVFrame->u32Width = stSize.u32Width; ++ pstVFrame->u32Height = stSize.u32Height; ++ pstVFrame->u32TimeRef = 0; ++ pstVFrame->u64PTS = 0; ++ pstVFrame->enDynamicRange = DYNAMIC_RANGE_SDR8; ++ ++ int retry_cnt = 0; ++_retry: ++ blk = CVI_VB_GetBlock(id, pstVbCfg->u32VBSize); ++ if (blk == VB_INVALID_HANDLE) { ++ if (retry_cnt ++ < 5) { ++ usleep(1000); ++ goto _retry; ++ } ++ printf("Can't acquire vb block. id: %d size:%d\n", id, pstVbCfg->u32VBSize); ++ return CVI_FAILURE; ++ } ++ ++ pstVideoFrame->u32PoolId = CVI_VB_Handle2PoolId(blk); ++ pstVFrame->u64PhyAddr[0] = CVI_VB_Handle2PhysAddr(blk); ++ pstVFrame->u32Stride[0] = pstVbCfg->u32MainStride; ++ pstVFrame->u32Length[0] = pstVbCfg->u32MainYSize; ++ pstVFrame->pu8VirAddr[0] = (CVI_U8 *)CVI_SYS_MmapCache(pstVFrame->u64PhyAddr[0], pstVbCfg->u32VBSize); ++ ++ if (pstVbCfg->plane_num == 2) { ++ pstVFrame->u64PhyAddr[1] = pstVFrame->u64PhyAddr[0] + ALIGN(pstVbCfg->u32MainYSize, pstVbCfg->u16AddrAlign); ++ pstVFrame->u32Stride[1] = pstVbCfg->u32CStride; ++ pstVFrame->u32Length[1] = pstVbCfg->u32MainCSize; ++ pstVFrame->pu8VirAddr[1] = (CVI_U8 *)pstVFrame->pu8VirAddr[0] + pstVFrame->u32Length[0]; ++ } ++ if (pstVbCfg->plane_num == 3) { ++ pstVFrame->u64PhyAddr[2] = pstVFrame->u64PhyAddr[1] + ALIGN(pstVbCfg->u32MainCSize, pstVbCfg->u16AddrAlign); ++ pstVFrame->u32Stride[2] = pstVbCfg->u32CStride; ++ pstVFrame->u32Length[2] = pstVbCfg->u32MainCSize; ++ pstVFrame->pu8VirAddr[2] = (CVI_U8 *)pstVFrame->pu8VirAddr[1] + pstVFrame->u32Length[1]; ++ } ++ ++ CVI_U32 total_size = pstVFrame->u32Length[0] + pstVFrame->u32Length[1] + pstVFrame->u32Length[2]; ++ if (total_size > pstVbCfg->u32VBSize) ++ printf("vb block. id: %d size:%d < %d\n", pstVideoFrame->u32PoolId, pstVbCfg->u32VBSize, total_size); ++ ++ // CVI_VENC_TRACE("pool id: %u\n", pstVideoFrame->u32PoolId); ++ // CVI_VENC_TRACE("phy addr(%#llx, %#llx, %#llx), Size %x\n", (long long)pstVFrame->u64PhyAddr[0] ++ // , (long long)pstVFrame->u64PhyAddr[1], (long long)pstVFrame->u64PhyAddr[2], pstVbCfg->u32VBSize); ++ // CVI_VENC_TRACE("vir addr(%p, %p, %p), Size %x\n", pstVFrame->pu8VirAddr[0] ++ // , pstVFrame->pu8VirAddr[1], pstVFrame->pu8VirAddr[2], pstVbCfg->u32MainSize); ++ ++ return CVI_SUCCESS; ++} ++ ++static VIDEO_FRAME_INFO_S *_mmf_alloc_frame(int id, SIZE_S stSize, PIXEL_FORMAT_E enPixelFormat) ++{ ++ VIDEO_FRAME_INFO_S *pstVideoFrame; ++ VB_CAL_CONFIG_S stVbCfg; ++ ++ pstVideoFrame = (VIDEO_FRAME_INFO_S *)calloc(sizeof(*pstVideoFrame), 1); ++ if (pstVideoFrame == NULL) { ++ printf("Failed to allocate VIDEO_FRAME_INFO_S\n"); ++ return NULL; ++ } ++ ++ memset(&stVbCfg, 0, sizeof(stVbCfg)); ++ VENC_GetPicBufferConfig(stSize.u32Width, ++ stSize.u32Height, ++ enPixelFormat, ++ DATA_BITWIDTH_8, ++ COMPRESS_MODE_NONE, ++ &stVbCfg); ++ ++ if (_mmf_init_frame(id, stSize, enPixelFormat, pstVideoFrame, &stVbCfg) != CVI_SUCCESS) ++ { ++ free(pstVideoFrame); ++ return NULL; ++ } ++ ++ return pstVideoFrame; ++} ++ ++static CVI_S32 _mmf_deinit_frame(VIDEO_FRAME_INFO_S *pstVideoFrame) ++{ ++ VIDEO_FRAME_S *pstVFrame; ++ VB_BLK blk; ++ ++ if (!pstVideoFrame) ++ return CVI_FAILURE; ++ ++ pstVFrame = &pstVideoFrame->stVFrame; ++ ++ if (pstVFrame->pu8VirAddr[2] == (CVI_U8 *)pstVFrame->pu8VirAddr[1] + pstVFrame->u32Length[1]) ++ { ++ pstVFrame->u32Length[1] += pstVFrame->u32Length[2]; ++ pstVFrame->u32Length[2] = 0; ++ pstVFrame->pu8VirAddr[2] = NULL; ++ pstVFrame->u64PhyAddr[2] = 0; ++ } ++ if (pstVFrame->pu8VirAddr[1] == (CVI_U8 *)pstVFrame->pu8VirAddr[0] + pstVFrame->u32Length[0]) ++ { ++ pstVFrame->u32Length[0] += pstVFrame->u32Length[1]; ++ pstVFrame->u32Length[1] = 0; ++ pstVFrame->pu8VirAddr[1] = NULL; ++ pstVFrame->u64PhyAddr[1] = 0; ++ } ++ ++ for (int b = 0; b < 3; b++) { ++ if (pstVFrame->pu8VirAddr[b]) { ++ CVI_SYS_Munmap((CVI_VOID *)pstVFrame->pu8VirAddr[b], pstVFrame->u32Length[b]); ++ pstVFrame->u32Length[b] = 0; ++ pstVFrame->pu8VirAddr[b] = NULL; ++ } ++ ++ if (pstVFrame->u64PhyAddr[b]) { ++ blk = CVI_VB_PhysAddr2Handle(pstVFrame->u64PhyAddr[b]); ++ if (blk != VB_INVALID_HANDLE) { ++ CVI_VB_ReleaseBlock(blk); ++ } ++ pstVFrame->u64PhyAddr[b] = 0; ++ } ++ } ++ ++ return CVI_SUCCESS; ++} ++ ++static CVI_S32 _mmf_free_frame(VIDEO_FRAME_INFO_S *pstVideoFrame) ++{ ++ if (_mmf_deinit_frame(pstVideoFrame) != CVI_SUCCESS) { ++ return CVI_FAILURE; ++ } ++ ++ free(pstVideoFrame); ++ ++ return CVI_SUCCESS; ++} ++ ++static int cvi_ive_init(void) ++{ ++ CVI_S32 s32Ret; ++ if (priv.ive_is_init) ++ return 0; ++ ++ priv.ive_rgb2yuv_w = 640; ++ priv.ive_rgb2yuv_h = 480; ++ priv.ive_handle = CVI_IVE_CreateHandle(); ++ if (priv.ive_handle == NULL) { ++ printf("CVI_IVE_CreateHandle failed!\n"); ++ return -1; ++ } ++ ++ s32Ret = CVI_IVE_CreateImage_Cached(priv.ive_handle, &priv.ive_rgb2yuv_rgb_img, IVE_IMAGE_TYPE_U8C3_PACKAGE, priv.ive_rgb2yuv_w, priv.ive_rgb2yuv_h); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("Create src image failed!\n"); ++ CVI_IVE_DestroyHandle(priv.ive_handle); ++ return -1; ++ } ++ ++ s32Ret = CVI_IVE_CreateImage_Cached(priv.ive_handle, &priv.ive_rgb2yuv_yuv_img, IVE_IMAGE_TYPE_YUV420SP, priv.ive_rgb2yuv_w, priv.ive_rgb2yuv_h); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("Create src image failed!\n"); ++ CVI_IVE_DestroyHandle(priv.ive_handle); ++ return -1; ++ } ++ ++ priv.ive_is_init = 1; ++ return 0; ++} ++ ++static int cvi_ive_deinit(void) ++{ ++ if (priv.ive_is_init == 0) ++ return 0; ++ ++ CVI_SYS_FreeI(priv.ive_handle, &priv.ive_rgb2yuv_rgb_img); ++ CVI_SYS_FreeI(priv.ive_handle, &priv.ive_rgb2yuv_yuv_img); ++ CVI_IVE_DestroyHandle(priv.ive_handle); ++ ++ priv.ive_is_init = 0; ++ return 0; ++} ++ ++#ifndef KVM_MMF ++ ++static int cvi_rgb2nv21(uint8_t *src, int input_w, int input_h) ++{ ++ CVI_S32 s32Ret; ++ ++ int width = ALIGN(input_w, DEFAULT_ALIGN); ++ int height = input_h; ++ ++ if (width != priv.ive_rgb2yuv_w || height != priv.ive_rgb2yuv_h) { ++ CVI_SYS_FreeI(priv.ive_handle, &priv.ive_rgb2yuv_rgb_img); ++ CVI_SYS_FreeI(priv.ive_handle, &priv.ive_rgb2yuv_yuv_img); ++ priv.ive_rgb2yuv_w = width; ++ priv.ive_rgb2yuv_h = height; ++ printf("reinit rgb2nv21 buffer, buff w:%d h:%d\n", priv.ive_rgb2yuv_w, priv.ive_rgb2yuv_h); ++ s32Ret = CVI_IVE_CreateImage_Cached(priv.ive_handle, &priv.ive_rgb2yuv_rgb_img, IVE_IMAGE_TYPE_U8C3_PACKAGE, priv.ive_rgb2yuv_w, priv.ive_rgb2yuv_h); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("Create src image failed!\n"); ++ return -1; ++ } ++ ++ s32Ret = CVI_IVE_CreateImage_Cached(priv.ive_handle, &priv.ive_rgb2yuv_yuv_img, IVE_IMAGE_TYPE_YUV420SP, priv.ive_rgb2yuv_w, priv.ive_rgb2yuv_h); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("Create src image failed!\n"); ++ return -1; ++ } ++ } ++ ++ if (width != input_w) { ++ for (int h = 0; h < height; h++) { ++ memcpy((uint8_t *)priv.ive_rgb2yuv_rgb_img.u64VirAddr[0] + width * h * 3, (uint8_t *)src + input_w * h * 3, input_w * 3); ++ } ++ } else { ++ memcpy((uint8_t *)priv.ive_rgb2yuv_rgb_img.u64VirAddr[0], (uint8_t *)src, width * height * 3); ++ } ++ ++ IVE_CSC_CTRL_S stCtrl; ++ stCtrl.enMode = IVE_CSC_MODE_VIDEO_BT601_RGB2YUV; ++ s32Ret = CVI_IVE_CSC(priv.ive_handle, &priv.ive_rgb2yuv_rgb_img, &priv.ive_rgb2yuv_yuv_img, &stCtrl, 1); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("Run HW IVE CSC YUV2RGB failed!\n"); ++ return -1; ++ } ++ return 0; ++} ++ ++#endif // !KVM_MMF ++ ++static int _try_release_sys(void) ++{ ++ CVI_S32 s32Ret = CVI_FAILURE; ++ SAMPLE_INI_CFG_S stIniCfg; ++ SAMPLE_VI_CONFIG_S stViConfig; ++ if (SAMPLE_COMM_VI_ParseIni(&stIniCfg)) { ++ printf("Parse complete\n"); ++ return s32Ret; ++ } ++ ++ priv.sensor_type = stIniCfg.enSnsType[0]; ++ ++ s32Ret = CVI_VI_SetDevNum(stIniCfg.devNum); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("VI_SetDevNum failed with %#x\n", s32Ret); ++ return s32Ret; ++ } ++ ++ s32Ret = SAMPLE_COMM_VI_IniToViCfg(&stIniCfg, &stViConfig); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("SAMPLE_COMM_VI_IniToViCfg failed with %#x\n", s32Ret); ++ return s32Ret; ++ } ++ ++ s32Ret = SAMPLE_COMM_VI_DestroyIsp(&stViConfig); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("SAMPLE_COMM_VI_DestroyIsp failed with %#x\n", s32Ret); ++ return s32Ret; ++ } ++ ++ s32Ret = SAMPLE_COMM_VI_DestroyVi(&stViConfig); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("SAMPLE_COMM_VI_DestroyVi failed with %#x\n", s32Ret); ++ return s32Ret; ++ } ++ ++ SAMPLE_COMM_SYS_Exit(); ++ return s32Ret; ++} ++ ++int _try_release_vio_all(void) ++{ ++ CVI_S32 s32Ret = CVI_FAILURE; ++ s32Ret = mmf_del_vi_channel_all(); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("mmf_del_vi_channel_all failed with %#x\n", s32Ret); ++ return s32Ret; ++ } ++ ++#ifndef KVM_MMF ++ s32Ret = mmf_del_vo_channel_all(0); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("mmf_del_vo_channel_all failed with %#x\n", s32Ret); ++ return s32Ret; ++ } ++#endif ++ return s32Ret; ++} ++ ++void mmf_pre_config_sys(mmf_sys_cfg_t *cfg) ++{ ++ // TODO support custom buffer pools ++ priv.vb_max_pool_cnt = cfg->max_pool_cnt; ++} ++ ++static void _mmf_sys_exit(void) ++{ ++ if (g_stViConfig.s32WorkingViNum != 0) { ++ SAMPLE_COMM_VI_DestroyIsp(&g_stViConfig); ++ SAMPLE_COMM_VI_DestroyVi(&g_stViConfig); ++ } ++ SAMPLE_COMM_SYS_Exit(); ++} ++ ++static CVI_S32 _mmf_sys_init(SIZE_S stSize) ++{ ++ VB_CONFIG_S stVbConf; ++ CVI_U32 u32BlkSize, u32BlkRotSize; ++ CVI_U32 u32TotalSize; ++ CVI_S32 s32Ret = CVI_SUCCESS; ++ COMPRESS_MODE_E enCompressMode = COMPRESS_MODE_NONE; ++ ++ memset(&stVbConf, 0, sizeof(VB_CONFIG_S)); ++ memcpy(&stVbConf, &priv.vb_conf, sizeof(VB_CONFIG_S)); ++ // stVbConf.u32MaxPoolCnt = 3; ++ ++ u32BlkSize = COMMON_GetPicBufferSize(stSize.u32Width, stSize.u32Height, priv.vi_format, ++ DATA_BITWIDTH_8, enCompressMode, DEFAULT_ALIGN); ++ u32BlkRotSize = COMMON_GetPicBufferSize(stSize.u32Height, stSize.u32Width, priv.vi_format, ++ DATA_BITWIDTH_8, enCompressMode, DEFAULT_ALIGN); ++ u32BlkSize = MAX(u32BlkSize, u32BlkRotSize); ++ ++ stVbConf.astCommPool[priv.vb_vi_id].u32BlkSize = u32BlkSize; ++ stVbConf.astCommPool[priv.vb_vi_id].u32BlkCnt = 3; ++ stVbConf.astCommPool[priv.vb_vi_id].enRemapMode = VB_REMAP_MODE_CACHED; ++#if 0 ++{ ++ VB_CONFIG_S vb_config; ++ s32Ret = CVI_VB_GetConfig(&vb_config); ++ if (s32Ret != CVI_SUCCESS) { ++ CVI_TRACE_LOG(CVI_DBG_ERR, "CVI_VB_GetConfig NG\n"); ++ return CVI_FAILURE; ++ } ++ printf(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[%s[%d]\r\n", __func__, __LINE__); ++ printf("vb_config.u32MaxPoolCnt :%d\r\n", stVbConf.u32MaxPoolCnt); ++ for (int i = 0; i < stVbConf.u32MaxPoolCnt; ++i) { ++ printf("common pool[%d] BlkSize(%d) BlkCnt(%d) Remap(%d)\n", \ ++ i, \ ++ stVbConf.astCommPool[i].u32BlkSize, \ ++ stVbConf.astCommPool[i].u32BlkCnt, \ ++ stVbConf.astCommPool[i].enRemapMode); ++ } ++ printf(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[%s[%d]\r\n", __func__, __LINE__); ++ printf("vb_config.u32MaxPoolCnt :%d\r\n", vb_config.u32MaxPoolCnt); ++ for (int i = 0; i < vb_config.u32MaxPoolCnt; ++i) { ++ printf("common pool[%d] BlkSize(%d) BlkCnt(%d) Remap(%d)\n", \ ++ i, \ ++ vb_config.astCommPool[i].u32BlkSize, \ ++ vb_config.astCommPool[i].u32BlkCnt, \ ++ vb_config.astCommPool[i].enRemapMode); ++ } ++} ++#endif ++ u32TotalSize = 0; ++ for (CVI_U32 i = 0; i < stVbConf.u32MaxPoolCnt; ++i) { ++ u32TotalSize += stVbConf.astCommPool[i].u32BlkSize * stVbConf.astCommPool[i].u32BlkCnt; ++ } ++ printf("common pools count: %u\n", stVbConf.u32MaxPoolCnt); ++ printf("common pools total size: %u KiB\n", u32TotalSize / 1024); ++ ++ s32Ret = SAMPLE_COMM_SYS_Init(&stVbConf); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("system init failed with %#x\n", s32Ret); ++ goto error; ++ } ++#if 0 ++{ ++ VB_CONFIG_S vb_config; ++ s32Ret = CVI_VB_GetConfig(&vb_config); ++ if (s32Ret != CVI_SUCCESS) { ++ CVI_TRACE_LOG(CVI_DBG_ERR, "CVI_VB_GetConfig NG\n"); ++ return CVI_FAILURE; ++ } ++ printf(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>[%s[%d]\r\n", __func__, __LINE__); ++ for (int i = 0; i < vb_config.u32MaxPoolCnt; ++i) { ++ printf("vb_config.u32MaxPoolCnt :%d\r\n", vb_config.u32MaxPoolCnt); ++ printf("common pool[%d] BlkSize(%d) BlkCnt(%d) Remap(%d)\n", \ ++ i, \ ++ vb_config.astCommPool[i].u32BlkSize, \ ++ vb_config.astCommPool[i].u32BlkCnt, \ ++ vb_config.astCommPool[i].enRemapMode); ++ } ++} ++#endif ++ return s32Ret; ++error: ++ _mmf_sys_exit(); ++ return s32Ret; ++} ++ ++static CVI_S32 _mmf_vpss_deinit(VPSS_GRP VpssGrp, VPSS_CHN VpssChn) ++{ ++ CVI_BOOL abChnEnable[VPSS_MAX_PHY_CHN_NUM] = {0}; ++ CVI_S32 s32Ret = CVI_SUCCESS; ++ ++ /*stop vpss*/ ++ abChnEnable[VpssChn] = CVI_TRUE; ++ s32Ret = SAMPLE_COMM_VPSS_Stop(VpssGrp, abChnEnable); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("stop vpss group failed. s32Ret: 0x%x !\n", s32Ret); ++ } ++ ++ return s32Ret; ++} ++ ++static CVI_S32 _mmf_vpss_deinit_new(VPSS_GRP VpssGrp) ++{ ++ CVI_S32 s32Ret = CVI_SUCCESS; ++ ++ s32Ret = CVI_VPSS_StopGrp(VpssGrp); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("Vpss Stop Grp %d failed! Please check param\n", VpssGrp); ++ return CVI_FAILURE; ++ } ++ ++ s32Ret = CVI_VPSS_DestroyGrp(VpssGrp); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("Vpss Destroy Grp %d failed! Please check\n", VpssGrp); ++ return CVI_FAILURE; ++ } ++ ++ return s32Ret; ++} ++ ++// fit = 0, width to new width, height to new height, may be stretch ++// fit = 1, keep aspect ratio, fill blank area with black color ++// fit = other, keep aspect ratio, crop image to fit new size ++static CVI_S32 _mmf_vpss_init(VPSS_GRP VpssGrp, VPSS_CHN VpssChn, SIZE_S stSizeIn, SIZE_S stSizeOut, PIXEL_FORMAT_E formatIn, PIXEL_FORMAT_E formatOut, ++int fps, int depth, bool mirror, bool flip, int fit) ++{ ++ VPSS_GRP_ATTR_S stVpssGrpAttr; ++ VPSS_CROP_INFO_S stGrpCropInfo; ++ CVI_BOOL abChnEnable[VPSS_MAX_PHY_CHN_NUM] = {0}; ++ VPSS_CHN_ATTR_S astVpssChnAttr[VPSS_MAX_PHY_CHN_NUM]; ++ CVI_S32 s32Ret = CVI_SUCCESS; ++ ++ memset(&stVpssGrpAttr, 0, sizeof(VPSS_GRP_ATTR_S)); ++ stVpssGrpAttr.stFrameRate.s32SrcFrameRate = -1; ++ stVpssGrpAttr.stFrameRate.s32DstFrameRate = -1; ++ stVpssGrpAttr.enPixelFormat = formatIn; ++ stVpssGrpAttr.u32MaxW = stSizeIn.u32Width; ++ stVpssGrpAttr.u32MaxH = stSizeIn.u32Height; ++ stVpssGrpAttr.u8VpssDev = 0; ++ ++ CVI_FLOAT corp_scale_w = (CVI_FLOAT)stSizeIn.u32Width / stSizeOut.u32Width; ++ CVI_FLOAT corp_scale_h = (CVI_FLOAT)stSizeIn.u32Height / stSizeOut.u32Height; ++ CVI_U32 crop_w = -1, crop_h = -1; ++ if (fit == 0) { ++ memset(astVpssChnAttr, 0, sizeof(VPSS_CHN_ATTR_S) * VPSS_MAX_PHY_CHN_NUM); ++ astVpssChnAttr[VpssChn].u32Width = stSizeOut.u32Width; ++ astVpssChnAttr[VpssChn].u32Height = stSizeOut.u32Height; ++ astVpssChnAttr[VpssChn].enVideoFormat = VIDEO_FORMAT_LINEAR; ++ astVpssChnAttr[VpssChn].enPixelFormat = formatOut; ++ astVpssChnAttr[VpssChn].stFrameRate.s32SrcFrameRate = fps; ++ astVpssChnAttr[VpssChn].stFrameRate.s32DstFrameRate = fps; ++ astVpssChnAttr[VpssChn].u32Depth = depth; ++ astVpssChnAttr[VpssChn].bMirror = mirror; ++ astVpssChnAttr[VpssChn].bFlip = flip; ++ astVpssChnAttr[VpssChn].stAspectRatio.enMode = ASPECT_RATIO_MANUAL; ++ astVpssChnAttr[VpssChn].stAspectRatio.stVideoRect.s32X = 0; ++ astVpssChnAttr[VpssChn].stAspectRatio.stVideoRect.s32Y = 0; ++ astVpssChnAttr[VpssChn].stAspectRatio.stVideoRect.u32Width = stSizeOut.u32Width; ++ astVpssChnAttr[VpssChn].stAspectRatio.stVideoRect.u32Height = stSizeOut.u32Height; ++ astVpssChnAttr[VpssChn].stAspectRatio.bEnableBgColor = CVI_TRUE; ++ astVpssChnAttr[VpssChn].stAspectRatio.u32BgColor = COLOR_RGB_BLACK; ++ astVpssChnAttr[VpssChn].stNormalize.bEnable = CVI_FALSE; ++ ++ stGrpCropInfo.bEnable = false; ++ } else if (fit == 1) { ++ memset(astVpssChnAttr, 0, sizeof(VPSS_CHN_ATTR_S) * VPSS_MAX_PHY_CHN_NUM); ++ astVpssChnAttr[VpssChn].u32Width = stSizeOut.u32Width; ++ astVpssChnAttr[VpssChn].u32Height = stSizeOut.u32Height; ++ astVpssChnAttr[VpssChn].enVideoFormat = VIDEO_FORMAT_LINEAR; ++ astVpssChnAttr[VpssChn].enPixelFormat = formatOut; ++ astVpssChnAttr[VpssChn].stFrameRate.s32SrcFrameRate = fps; ++ astVpssChnAttr[VpssChn].stFrameRate.s32DstFrameRate = fps; ++ astVpssChnAttr[VpssChn].u32Depth = depth; ++ astVpssChnAttr[VpssChn].bMirror = mirror; ++ astVpssChnAttr[VpssChn].bFlip = flip; ++ astVpssChnAttr[VpssChn].stAspectRatio.enMode = ASPECT_RATIO_AUTO; ++ astVpssChnAttr[VpssChn].stAspectRatio.bEnableBgColor = CVI_TRUE; ++ astVpssChnAttr[VpssChn].stAspectRatio.u32BgColor = COLOR_RGB_BLACK; ++ astVpssChnAttr[VpssChn].stNormalize.bEnable = CVI_FALSE; ++ ++ stGrpCropInfo.bEnable = false; ++ } else { ++ memset(astVpssChnAttr, 0, sizeof(VPSS_CHN_ATTR_S) * VPSS_MAX_PHY_CHN_NUM); ++ astVpssChnAttr[VpssChn].u32Width = stSizeOut.u32Width; ++ astVpssChnAttr[VpssChn].u32Height = stSizeOut.u32Height; ++ astVpssChnAttr[VpssChn].enVideoFormat = VIDEO_FORMAT_LINEAR; ++ astVpssChnAttr[VpssChn].enPixelFormat = formatOut; ++ astVpssChnAttr[VpssChn].stFrameRate.s32SrcFrameRate = fps; ++ astVpssChnAttr[VpssChn].stFrameRate.s32DstFrameRate = fps; ++ astVpssChnAttr[VpssChn].u32Depth = depth; ++ astVpssChnAttr[VpssChn].bMirror = mirror; ++ astVpssChnAttr[VpssChn].bFlip = flip; ++ astVpssChnAttr[VpssChn].stAspectRatio.enMode = ASPECT_RATIO_AUTO; ++ astVpssChnAttr[VpssChn].stAspectRatio.bEnableBgColor = CVI_TRUE; ++ astVpssChnAttr[VpssChn].stAspectRatio.u32BgColor = COLOR_RGB_BLACK; ++ astVpssChnAttr[VpssChn].stNormalize.bEnable = CVI_FALSE; ++ ++ crop_w = corp_scale_w < corp_scale_h ? stSizeOut.u32Width * corp_scale_w: stSizeOut.u32Width * corp_scale_h; ++ crop_h = corp_scale_w < corp_scale_h ? stSizeOut.u32Height * corp_scale_w: stSizeOut.u32Height * corp_scale_h; ++ if (corp_scale_h < 0 || corp_scale_w < 0) { ++ printf("crop scale error. corp_scale_w: %f, corp_scale_h: %f\n", corp_scale_w, corp_scale_h); ++ goto error; ++ } ++ ++ stGrpCropInfo.bEnable = true; ++ stGrpCropInfo.stCropRect.s32X = (stSizeIn.u32Width - crop_w) / 2; ++ stGrpCropInfo.stCropRect.s32Y = (stSizeIn.u32Height - crop_h) / 2; ++ stGrpCropInfo.stCropRect.u32Width = crop_w; ++ stGrpCropInfo.stCropRect.u32Height = crop_h; ++ } ++ ++ /*start vpss*/ ++ abChnEnable[0] = CVI_TRUE; ++ s32Ret = SAMPLE_COMM_VPSS_Init(VpssGrp, abChnEnable, &stVpssGrpAttr, astVpssChnAttr); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("init vpss group failed. s32Ret: 0x%x ! retry!!!\n", s32Ret); ++ s32Ret = SAMPLE_COMM_VPSS_Stop(VpssGrp, abChnEnable); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("stop vpss group failed. s32Ret: 0x%x !\n", s32Ret); ++ } ++ s32Ret = SAMPLE_COMM_VPSS_Init(VpssGrp, abChnEnable, &stVpssGrpAttr, astVpssChnAttr); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("retry to init vpss group failed. s32Ret: 0x%x !\n", s32Ret); ++ return s32Ret; ++ } else { ++ printf("retry to init vpss group ok!\n"); ++ } ++ } ++ ++ if (crop_w != 0 && crop_h != 0) { ++ s32Ret = CVI_VPSS_SetChnCrop(VpssGrp, VpssChn, &stGrpCropInfo); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("set vpss group crop failed. s32Ret: 0x%x !\n", s32Ret); ++ goto error; ++ } ++ } ++ ++ s32Ret = SAMPLE_COMM_VPSS_Start(VpssGrp, abChnEnable, &stVpssGrpAttr, astVpssChnAttr); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("start vpss group failed. s32Ret: 0x%x !\n", s32Ret); ++ goto error; ++ } ++ ++ return s32Ret; ++error: ++ _mmf_vpss_deinit(VpssGrp, VpssChn); ++ return s32Ret; ++} ++ ++static CVI_S32 _mmf_init(void) ++{ ++ MMF_VERSION_S stVersion; ++ SAMPLE_INI_CFG_S stIniCfg; ++ SAMPLE_VI_CONFIG_S stViConfig; ++ ++ PIC_SIZE_E enPicSize; ++ SIZE_S stSize; ++ CVI_S32 s32Ret = CVI_SUCCESS; ++ LOG_LEVEL_CONF_S log_conf; ++ ++ CVI_SYS_GetVersion(&stVersion); ++ printf("maix multi-media version:%s\n", stVersion.version); ++ ++ log_conf.enModId = CVI_ID_LOG; ++ log_conf.s32Level = CVI_DBG_DEBUG; ++ CVI_LOG_SetLevelConf(&log_conf); ++ ++ // Get config from ini if found. ++ if (SAMPLE_COMM_VI_ParseIni(&stIniCfg)) { ++ printf("Parse complete\n"); ++ } ++ ++ //Set sensor number ++ CVI_VI_SetDevNum(stIniCfg.devNum); ++ ++ /************************************************ ++ * step1: Config VI ++ ************************************************/ ++ s32Ret = SAMPLE_COMM_VI_IniToViCfg(&stIniCfg, &stViConfig); ++ if (s32Ret != CVI_SUCCESS) ++ return s32Ret; ++ ++ memcpy(&g_stViConfig, &stViConfig, sizeof(SAMPLE_VI_CONFIG_S)); ++ memcpy(&g_stIniCfg, &stIniCfg, sizeof(SAMPLE_INI_CFG_S)); ++ ++ /************************************************ ++ * step2: Get input size ++ ************************************************/ ++ s32Ret = SAMPLE_COMM_VI_GetSizeBySensor(stIniCfg.enSnsType[0], &enPicSize); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("SAMPLE_COMM_VI_GetSizeBySensor failed with %#x\n", s32Ret); ++ return s32Ret; ++ } ++ ++ s32Ret = SAMPLE_COMM_SYS_GetPicSize(enPicSize, &stSize); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("SAMPLE_COMM_SYS_GetPicSize failed with %#x\n", s32Ret); ++ return s32Ret; ++ } ++ ++ /************************************************ ++ * step3: Init modules ++ ************************************************/ ++ if (0 != _free_leak_memory_of_ion()) { ++ printf("free leak memory error\n"); ++ } ++ ++ s32Ret = _mmf_sys_init(stSize); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("sys init failed. s32Ret: 0x%x !\n", s32Ret); ++ goto _need_exit_sys_and_deinit_vi; ++ } ++ ++ s32Ret = SAMPLE_PLAT_VI_INIT(&stViConfig); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("vi init failed. s32Ret: 0x%x !\n", s32Ret); ++ printf("Please try to check if the camera is working.\n"); ++ goto _need_exit_sys_and_deinit_vi; ++ } ++ ++ priv.vi_max_size.u32Width = stSize.u32Width; ++ priv.vi_max_size.u32Height = stSize.u32Height; ++ priv.vi_size.u32Width = stSize.u32Width; ++ priv.vi_size.u32Height = stSize.u32Height; ++ ++ return s32Ret; ++ ++_need_exit_sys_and_deinit_vi: ++ _mmf_sys_exit(); ++ ++ return s32Ret; ++} ++ ++static void _mmf_deinit(void) ++{ ++ _mmf_sys_exit(); ++} ++ ++static int _vi_get_unused_ch() { ++ for (int i = 0; i < MMF_VI_MAX_CHN; i++) { ++ if (priv.vi_chn_is_inited[i] == false) { ++ return i; ++ } ++ } ++ return -1; ++} ++ ++char* mmf_get_sensor_name(void) ++{ ++ static char name[30]; ++ ++ switch (priv.sensor_type) { ++ case GCORE_GC2083_MIPI_2M_30FPS_10BIT: ++ snprintf(name, sizeof(name), "gcore_gc2083"); ++ return name; ++ case GCORE_GC4653_MIPI_4M_30FPS_10BIT: ++ case GCORE_GC4653_MIPI_720P_60FPS_10BIT: ++ snprintf(name, sizeof(name), "gcore_gc4653"); ++ return name; ++ case SMS_SC035GS_MIPI_480P_120FPS_12BIT: ++ snprintf(name, sizeof(name), "sms_sc035gs"); ++ return name; ++ case LONTIUM_LT6911_2M_60FPS_8BIT: ++ snprintf(name, sizeof(name), "lt6911"); ++ return name; ++ case OV_OS04A10_MIPI_4M_1440P_30FPS_12BIT: ++ snprintf(name, sizeof(name), "ov_os04a10"); ++ return name; ++ case GCORE_OV2685_MIPI_1600x1200_30FPS_10BIT: ++ snprintf(name, sizeof(name), "ov_ov2685"); ++ return name; ++ case OV_OV5647_MIPI_2M_30FPS_10BIT: ++ snprintf(name, sizeof(name), "ov_ov5647"); ++ return name; ++ default: ++ break; ++ } ++ ++ snprintf(name, sizeof(name), "gcore_gc4653"); ++ return name; ++} ++ ++int mmf_vi_format_init(void) ++{ ++ PIXEL_FORMAT_E vi_format = MMF_VI_PIXEL_FORMAT; ++ PIXEL_FORMAT_E vi_vpss_format = MMF_VI_PIXEL_FORMAT; ++ ++ // config vi param ++ char *sensor_name = mmf_get_sensor_name(); ++ ++ if (!strcmp(sensor_name, "sms_sc035gs")) { ++ vi_format = PIXEL_FORMAT_NV21; ++ vi_vpss_format = PIXEL_FORMAT_YUV_400; ++ } else if (!strcmp(sensor_name, "ov_ov2685")) { ++ vi_format = PIXEL_FORMAT_NV21; ++ vi_vpss_format = PIXEL_FORMAT_NV21; ++ } else if (!strcmp(sensor_name, "lt6911")) { ++ vi_format = PIXEL_FORMAT_UYVY; ++ vi_vpss_format = PIXEL_FORMAT_UYVY; ++ } else if (!strcmp(sensor_name, "ov_os04a10")) { ++ vi_format = PIXEL_FORMAT_NV21; ++ vi_vpss_format = PIXEL_FORMAT_NV21; ++ } else { // default is gcore_gc4653 ++ vi_format = PIXEL_FORMAT_NV21; ++ vi_vpss_format = PIXEL_FORMAT_NV21; ++ } ++ ++ priv.vi_format = vi_format; ++ priv.vi_vpss_format = vi_vpss_format; ++ ++ return 0; ++} ++ ++int mmf_init(void) ++{ ++ if (priv.mmf_used_cnt) { ++ priv.mmf_used_cnt ++; ++ printf("maix multi-media already inited(cnt:%d)\n", priv.mmf_used_cnt); ++ return 0; ++ } ++ ++ priv_param_init(); ++ ++ if (_try_release_sys() != CVI_SUCCESS) { ++ printf("try release sys failed\n"); ++ return -1; ++ } else { ++ printf("try release sys ok\n"); ++ } ++ ++ mmf_vi_format_init(); ++ ++ if (_mmf_init() != CVI_SUCCESS) { ++ printf("maix multi-media init failed\n"); ++ return -1; ++ } else { ++ printf("maix multi-media init ok\n"); ++ } ++ ++#if MMF_VO_USE_NV21_ONLY ++ if (cvi_ive_init() != CVI_SUCCESS) { ++ printf("cvi_ive_init failed\n"); ++ return -1; ++ } else { ++ printf("cvi_ive_init ok\n"); ++ } ++#else ++ UNUSED(cvi_ive_init); ++#endif ++ priv.mmf_used_cnt = 1; ++ ++ if (_try_release_vio_all() != CVI_SUCCESS) { ++ printf("try release vio failed\n"); ++ return -1; ++ } else { ++ printf("try release vio ok\n"); ++ } ++ ++ return 0; ++} ++ ++bool mmf_is_init(void) ++{ ++ return priv.mmf_used_cnt > 0 ? true : false; ++} ++ ++int mmf_deinit(void) { ++ if (!priv.mmf_used_cnt) { ++ return 0; ++ } ++ ++ priv.mmf_used_cnt --; ++ ++ if (priv.mmf_used_cnt) { ++ return 0; ++ } else { ++ printf("maix multi-media driver destroyed.\n"); ++#if MMF_VO_USE_NV21_ONLY ++ cvi_ive_deinit(); ++#else ++ UNUSED(cvi_ive_deinit); ++#endif ++ ++ mmf_del_vi_channel_all(); ++#ifndef KVM_MMF ++ mmf_del_vo_channel_all(0); ++#endif ++ mmf_del_venc_channel_all(); ++ mmf_vi_deinit(); ++ mmf_del_region_channel_all(); ++ _mmf_deinit(); ++ } ++ ++ return 0; ++} ++ ++int mmf_try_deinit(bool force) ++{ ++ UNUSED(force); ++ return mmf_deinit(); ++} ++ ++int mmf_get_vi_unused_channel(void) { ++ return _vi_get_unused_ch(); ++} ++ ++static CVI_S32 _mmf_vpss_chn_init(VPSS_GRP VpssGrp, VPSS_CHN VpssChn, int width, int height, PIXEL_FORMAT_E format, int fps, int depth, bool mirror, bool flip, int fit) ++{ ++#if 1 ++ VPSS_GRP_ATTR_S stGrpAttr; ++ VPSS_CROP_INFO_S stChnCropInfo; ++ VPSS_CHN_ATTR_S chn_attr; ++ CVI_S32 s32Ret = CVI_SUCCESS; ++ ++ memset(&chn_attr, 0, sizeof(chn_attr)); ++ s32Ret = CVI_VPSS_GetGrpAttr(VpssGrp, &stGrpAttr); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("CVI_VPSS_GetGrpAttr failed. s32Ret: 0x%x !\n", s32Ret); ++ return s32Ret; ++ } ++ CVI_FLOAT corp_scale_w = (CVI_FLOAT)stGrpAttr.u32MaxW / width; ++ CVI_FLOAT corp_scale_h = (CVI_FLOAT)stGrpAttr.u32MaxH / height; ++ CVI_U32 crop_w = -1, crop_h = -1; ++ if (fit == 0) { ++ chn_attr.u32Width = width; ++ chn_attr.u32Height = height; ++ chn_attr.enVideoFormat = VIDEO_FORMAT_LINEAR; ++ chn_attr.enPixelFormat = format; ++ chn_attr.stFrameRate.s32SrcFrameRate = fps; ++ chn_attr.stFrameRate.s32DstFrameRate = fps; ++ chn_attr.u32Depth = depth; ++ chn_attr.bMirror = mirror; ++ chn_attr.bFlip = flip; ++ chn_attr.stAspectRatio.enMode = ASPECT_RATIO_MANUAL; ++ chn_attr.stAspectRatio.stVideoRect.s32X = 0; ++ chn_attr.stAspectRatio.stVideoRect.s32Y = 0; ++ chn_attr.stAspectRatio.stVideoRect.u32Width = width; ++ chn_attr.stAspectRatio.stVideoRect.u32Height = height; ++ chn_attr.stAspectRatio.bEnableBgColor = CVI_TRUE; ++ chn_attr.stAspectRatio.u32BgColor = COLOR_RGB_BLACK; ++ chn_attr.stNormalize.bEnable = CVI_FALSE; ++ ++ stChnCropInfo.bEnable = false; ++ } else if (fit == 1) { ++ chn_attr.u32Width = width; ++ chn_attr.u32Height = height; ++ chn_attr.enVideoFormat = VIDEO_FORMAT_LINEAR; ++ chn_attr.enPixelFormat = format; ++ chn_attr.stFrameRate.s32SrcFrameRate = fps; ++ chn_attr.stFrameRate.s32DstFrameRate = fps; ++ chn_attr.u32Depth = depth; ++ chn_attr.bMirror = mirror; ++ chn_attr.bFlip = flip; ++ chn_attr.stAspectRatio.enMode = ASPECT_RATIO_AUTO; ++ chn_attr.stAspectRatio.bEnableBgColor = CVI_TRUE; ++ chn_attr.stAspectRatio.u32BgColor = COLOR_RGB_BLACK; ++ chn_attr.stNormalize.bEnable = CVI_FALSE; ++ ++ stChnCropInfo.bEnable = false; ++ } else { ++ chn_attr.u32Width = width; ++ chn_attr.u32Height = height; ++ chn_attr.enVideoFormat = VIDEO_FORMAT_LINEAR; ++ chn_attr.enPixelFormat = format; ++ chn_attr.stFrameRate.s32SrcFrameRate = fps; ++ chn_attr.stFrameRate.s32DstFrameRate = fps; ++ chn_attr.u32Depth = depth; ++ chn_attr.bMirror = mirror; ++ chn_attr.bFlip = flip; ++ chn_attr.stAspectRatio.enMode = ASPECT_RATIO_AUTO; ++ chn_attr.stAspectRatio.bEnableBgColor = CVI_TRUE; ++ chn_attr.stAspectRatio.u32BgColor = COLOR_RGB_BLACK; ++ chn_attr.stNormalize.bEnable = CVI_FALSE; ++ ++ crop_w = corp_scale_w < corp_scale_h ? width * corp_scale_w: width * corp_scale_h; ++ crop_h = corp_scale_w < corp_scale_h ? height * corp_scale_w: height * corp_scale_h; ++ if (corp_scale_h < 0 || corp_scale_w < 0) { ++ printf("crop scale error. corp_scale_w: %f, corp_scale_h: %f\n", corp_scale_w, corp_scale_h); ++ return -1; ++ } ++ ++ stChnCropInfo.bEnable = true; ++ stChnCropInfo.stCropRect.s32X = (stGrpAttr.u32MaxW - crop_w) / 2; ++ stChnCropInfo.stCropRect.s32Y = (stGrpAttr.u32MaxH - crop_h) / 2; ++ stChnCropInfo.stCropRect.u32Width = crop_w; ++ stChnCropInfo.stCropRect.u32Height = crop_h; ++ } ++ ++ if (crop_w != 0 && crop_h != 0) { ++ s32Ret = CVI_VPSS_SetChnCrop(VpssGrp, VpssChn, &stChnCropInfo); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("set vpss group crop failed. s32Ret: 0x%x !\n", s32Ret); ++ return -1; ++ } ++ } ++ ++ s32Ret = CVI_VPSS_SetChnAttr(VpssGrp, VpssChn, &chn_attr); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("CVI_VPSS_SetChnAttr failed with %#x\n", s32Ret); ++ return CVI_FAILURE; ++ } ++ ++ s32Ret = CVI_VPSS_EnableChn(VpssGrp, VpssChn); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("CVI_VPSS_EnableChn failed with %#x\n", s32Ret); ++ return CVI_FAILURE; ++ } ++ ++ return s32Ret; ++#else ++ CVI_S32 s32Ret; ++ VPSS_CHN_ATTR_S chn_attr = {0}; ++ chn_attr.u32Width = width; ++ chn_attr.u32Height = height; ++ chn_attr.enVideoFormat = VIDEO_FORMAT_LINEAR; ++ chn_attr.enPixelFormat = format; ++ chn_attr.stFrameRate.s32SrcFrameRate = fps; ++ chn_attr.stFrameRate.s32DstFrameRate = fps; ++ chn_attr.u32Depth = depth; ++ chn_attr.bMirror = mirror; ++ chn_attr.bFlip = flip; ++ chn_attr.stAspectRatio.enMode = ASPECT_RATIO_MANUAL; ++ chn_attr.stAspectRatio.stVideoRect.s32X = 0; ++ chn_attr.stAspectRatio.stVideoRect.s32Y = 0; ++ chn_attr.stAspectRatio.stVideoRect.u32Width = width; ++ chn_attr.stAspectRatio.stVideoRect.u32Height = height; ++ chn_attr.stAspectRatio.bEnableBgColor = CVI_TRUE; ++ chn_attr.stAspectRatio.u32BgColor = COLOR_RGB_BLACK; ++ chn_attr.stNormalize.bEnable = CVI_FALSE; ++ ++ s32Ret = CVI_VPSS_SetChnAttr(VpssGrp, VpssChn, &chn_attr); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("CVI_VPSS_SetChnAttr failed with %#x\n", s32Ret); ++ return CVI_FAILURE; ++ } ++ ++ s32Ret = CVI_VPSS_EnableChn(VpssGrp, VpssChn); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("CVI_VPSS_EnableChn failed with %#x\n", s32Ret); ++ return CVI_FAILURE; ++ } ++ ++ return CVI_SUCCESS; ++#endif ++} ++ ++static CVI_S32 _mmf_vpss_chn_deinit(VPSS_GRP VpssGrp, VPSS_CHN VpssChn) ++{ ++ return CVI_VPSS_DisableChn(VpssGrp, VpssChn); ++} ++ ++static CVI_S32 _mmf_vpss_init_new_with_fps(VPSS_GRP VpssGrp, CVI_U32 width, CVI_U32 height, PIXEL_FORMAT_E format, int fps) ++{ ++ VPSS_GRP_ATTR_S stVpssGrpAttr; ++ CVI_S32 s32Ret = CVI_SUCCESS; ++ VPSS_CHN_ATTR_S astVpssChnAttr; ++ ++ memset(&stVpssGrpAttr, 0, sizeof(VPSS_GRP_ATTR_S)); ++ stVpssGrpAttr.stFrameRate.s32SrcFrameRate = -1; ++ stVpssGrpAttr.stFrameRate.s32DstFrameRate = -1; ++ stVpssGrpAttr.enPixelFormat = format; ++ stVpssGrpAttr.u32MaxW = width; ++ stVpssGrpAttr.u32MaxH = height; ++ stVpssGrpAttr.u8VpssDev = 0; ++ ++ astVpssChnAttr.stFrameRate.s32SrcFrameRate = fps; ++ astVpssChnAttr.stFrameRate.s32DstFrameRate = fps; ++ ++ ++ s32Ret = CVI_VPSS_CreateGrp(VpssGrp, &stVpssGrpAttr); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("CVI_VPSS_CreateGrp(grp:%d) failed with %#x, retry!\n", VpssGrp, s32Ret); ++ CVI_VPSS_DestroyGrp(VpssGrp); ++ ++ s32Ret = CVI_VPSS_CreateGrp(VpssGrp, &stVpssGrpAttr); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("CVI_VPSS_CreateGrp(grp:%d) failed with %#x!\n", VpssGrp, s32Ret); ++ return CVI_FAILURE; ++ } ++ } ++ ++ CVI_VPSS_SetChnAttr(VpssGrp, VPSS_CHN0, &astVpssChnAttr); ++ ++ s32Ret = CVI_VPSS_ResetGrp(VpssGrp); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("CVI_VPSS_ResetGrp(grp:%d) failed with %#x!%d\n", VpssGrp, s32Ret, CVI_ERR_VPSS_ILLEGAL_PARAM); ++ return CVI_FAILURE; ++ } ++ ++ s32Ret = CVI_VPSS_StartGrp(VpssGrp); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("CVI_VPSS_StartGrp failed with %#x\n", s32Ret); ++ return CVI_FAILURE; ++ } ++ return s32Ret; ++} ++ ++static CVI_S32 _mmf_vi_init(CVI_U32 width, CVI_U32 height, PIXEL_FORMAT_E format, int fps) ++{ ++ VPSS_GRP out_grp; ++ CVI_S32 s32Ret = CVI_SUCCESS; ++ if (priv.vi_is_inited) { ++ return s32Ret; ++ } ++ ++ out_grp = CVI_VPSS_GetAvailableGrp(); ++ ++ s32Ret = _mmf_vpss_init_new_with_fps(out_grp, width, height, format, fps); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("_mmf_vpss_init_new failed. s32Ret: 0x%x !\n", s32Ret); ++ return s32Ret; ++ } ++ ++ priv.vi_vpss = out_grp; ++ priv.vi_is_inited = true; ++ ++ return s32Ret; ++} ++ ++int mmf_vi_init2(mmf_vi_cfg_t *vi_info) ++{ ++ CVI_S32 s32Ret = CVI_SUCCESS; ++ if (priv.vi_is_inited) { ++ return s32Ret; ++ } ++ ++ priv.vi_format = (PIXEL_FORMAT_E)vi_info->fmt; ++ priv.vi_size.u32Width = vi_info->w; ++ priv.vi_size.u32Height = vi_info->h; ++ ++ s32Ret = _mmf_vi_init(priv.vi_size.u32Width, priv.vi_size.u32Height, priv.vi_vpss_format, vi_info->fps); ++ ++ return s32Ret; ++} ++ ++int mmf_vi_init(void) ++{ ++ return _mmf_vi_init(priv.vi_size.u32Width, priv.vi_size.u32Height, priv.vi_vpss_format, 60); ++} ++ ++int mmf_vi_deinit(void) ++{ ++ if (!priv.vi_is_inited) { ++ return 0; ++ } ++ ++ CVI_S32 s32Ret = CVI_SUCCESS; ++ if (priv.vi_vpss != VPSS_INVALID_GRP) { ++ s32Ret = _mmf_vpss_deinit_new(priv.vi_vpss); ++ } ++ if (s32Ret != CVI_SUCCESS) { ++ printf("_mmf_vpss_deinit_new failed with %#x!\n", s32Ret); ++ return CVI_FAILURE; ++ } ++ ++ priv.vi_vpss = VPSS_INVALID_GRP; ++ priv.vi_is_inited = false; ++ ++ return s32Ret; ++} ++ ++static int _mmf_add_vi_channel(int ch, int width, int height, int format, int fps, int depth, bool mirror, bool flip, int fit) { ++ if (!priv.mmf_used_cnt || !priv.vi_is_inited) { ++ printf("%s: maix multi-media or vi not inited\n", __func__); ++ return -1; ++ } ++ ++ if (width <= 0 || height <= 0) { ++ printf("invalid width or height\n"); ++ return -1; ++ } ++ ++ if (format != PIXEL_FORMAT_NV21 ++ && format != PIXEL_FORMAT_RGB_888) { ++ printf("invalid format\n"); ++ return -1; ++ } ++ ++ if ((format == PIXEL_FORMAT_RGB_888 && width * height * 3 > 640 * 480 * 3) ++ || (format == PIXEL_FORMAT_NV21 && width * height * 3 / 2 > 2560 * 1440 * 3 / 2)) { ++ printf("image size is too large, for NV21, maximum resolution 2560x1440, for RGB888, maximum resolution 640x480!\n"); ++ return -1; ++ } ++ ++ if (mmf_vi_chn_is_open(ch)) { ++ printf("vi ch %d already open\n", ch); ++ return -1; ++ } ++ ++#if 0 ++ CVI_S32 s32Ret = CVI_SUCCESS; ++ SIZE_S stSizeIn, stSizeOut; ++ int fps = 30; ++ int depth = 2; ++ PIXEL_FORMAT_E formatIn = (PIXEL_FORMAT_E)PIXEL_FORMAT_NV21; ++ PIXEL_FORMAT_E formatOut = (PIXEL_FORMAT_E)format; ++ stSizeIn.u32Width = priv.vi_size.u32Width; ++ stSizeIn.u32Height = priv.vi_size.u32Height; ++ stSizeOut.u32Width = ALIGN(width, DEFAULT_ALIGN); ++ stSizeOut.u32Height = height; ++ bool mirror = !g_priv.vi_hmirror[ch]; ++ bool flip = !g_priv.vi_vflip[ch]; ++ s32Ret = _mmf_vpss_init(priv.vi_vpss, ch, stSizeIn, stSizeOut, formatIn, formatOut, fps, depth, mirror, flip, 2); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("vpss init failed. s32Ret: 0x%x. try again..\r\n", s32Ret); ++ s32Ret = _mmf_vpss_deinit(priv.vi_vpss, ch); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("vpss deinit failed. s32Ret: 0x%x !\n", s32Ret); ++ return -1; ++ } ++ ++ s32Ret = _mmf_vpss_init(priv.vi_vpss, ch, stSizeIn, stSizeOut, formatIn, formatOut, fps, depth, mirror, flip, 2); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("vpss init failed. s32Ret: 0x%x !\n", s32Ret); ++ return -1; ++ } ++ } ++ ++ priv.vi_chn_is_inited[ch] = true; ++ return 0; ++_need_deinit_vpss: ++ _mmf_vpss_deinit(priv.vi_vpss, ch); ++ return -1; ++#else ++ CVI_S32 s32Ret = CVI_SUCCESS; ++ int width_out = ALIGN(width, DEFAULT_ALIGN); ++ int height_out = height; ++ PIXEL_FORMAT_E format_out = (PIXEL_FORMAT_E)format; ++ s32Ret = _mmf_vpss_chn_deinit(priv.vi_vpss, ch); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("_mmf_vpss_chn_deinit failed with %#x!\n", s32Ret); ++ return CVI_FAILURE; ++ } ++ ++ s32Ret = _mmf_vpss_chn_init(priv.vi_vpss, ch, width_out, height_out, format_out, fps, depth, mirror, flip, fit); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("_mmf_vpss_chn_init failed with %#x!\n", s32Ret); ++ return CVI_FAILURE; ++ } ++ ++ s32Ret = SAMPLE_COMM_VI_Bind_VPSS(priv.vi_vpss, ch, 0); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("vi bind vpss failed. s32Ret: 0x%x !\n", s32Ret); ++ goto _need_deinit_vpss_chn; ++ } ++ ++ priv.vi_chn_is_inited[ch] = true; ++ ++ return 0; ++_need_deinit_vpss_chn: ++ _mmf_vpss_chn_deinit(priv.vi_vpss, ch); ++ return -1; ++#endif ++} ++ ++int mmf_add_vi_channel(int ch, int width, int height, int format) { ++ return _mmf_add_vi_channel(ch, width, height, format, 30, 2, !g_priv.vi_hmirror[ch], !g_priv.vi_vflip[ch], 2); ++} ++ ++int mmf_del_vi_channel(int ch) { ++ if (ch < 0 || ch >= MMF_VI_MAX_CHN) { ++ printf("invalid ch %d\n", ch); ++ return -1; ++ } ++ ++ if (priv.vi_chn_is_inited[ch] == false) { ++ printf("vi ch %d not open\n", ch); ++ return -1; ++ } ++ ++ CVI_S32 s32Ret = CVI_SUCCESS; ++ s32Ret = SAMPLE_COMM_VI_UnBind_VPSS(priv.vi_vpss, ch, 0); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("vi unbind vpss failed. s32Ret: 0x%x !\n", s32Ret); ++ // return -1; // continue to deinit vpss ++ } ++ ++ if (0 != _mmf_vpss_chn_deinit(priv.vi_vpss, ch)) { ++ printf("_mmf_vpss_chn_deinit failed. s32Ret: 0x%x !\n", s32Ret); ++ } ++ ++ priv.vi_chn_is_inited[ch] = false; ++ return s32Ret; ++} ++ ++int mmf_del_vi_channel_all() { ++ for (int i = 0; i < MMF_VI_MAX_CHN; i++) { ++ if (priv.vi_chn_is_inited[i] == true) { ++ mmf_del_vi_channel(i); ++ } ++ } ++ return 0; ++} ++ ++bool mmf_vi_chn_is_open(int ch) { ++ if (ch < 0 || ch >= MMF_VI_MAX_CHN) { ++ printf("invalid ch %d\n", ch); ++ return false; ++ } ++ ++ return priv.vi_chn_is_inited[ch]; ++} ++ ++int mmf_reset_vi_channel(int ch, int width, int height, int format) ++{ ++ mmf_del_vi_channel(ch); ++ return mmf_add_vi_channel(ch, width, height, format); ++} ++ ++int mmf_vi_aligned_width(int ch) { ++ UNUSED(ch); ++ return DEFAULT_ALIGN; ++} ++ ++int mmf_vi_frame_pop2(int ch, void **frame_info, mmf_frame_info_t *frame_info_mmap) { ++ if (ch < 0 || ch >= MMF_VI_MAX_CHN) { ++ printf("invalid ch %d\n", ch); ++ return -1; ++ } ++ if (!priv.vi_chn_is_inited[ch]) { ++ printf("vi ch %d not open\n", ch); ++ return -1; ++ } ++ if (frame_info == NULL) { ++ printf("invalid param\n"); ++ return -1; ++ } ++ ++ int ret = -1; ++ VIDEO_FRAME_INFO_S *frame = &priv.vi_frame[ch]; ++ if (CVI_VPSS_GetChnFrame(priv.vi_vpss, ch, frame, priv.vi_pop_timeout) == 0) { ++ int image_size = frame->stVFrame.u32Length[0] ++ + frame->stVFrame.u32Length[1] ++ + frame->stVFrame.u32Length[2]; ++ CVI_VOID *vir_addr; ++ vir_addr = CVI_SYS_MmapCache(frame->stVFrame.u64PhyAddr[0], image_size); ++ CVI_SYS_IonInvalidateCache(frame->stVFrame.u64PhyAddr[0], vir_addr, image_size); ++ ++ frame->stVFrame.pu8VirAddr[0] = (CVI_U8 *)vir_addr; // save virtual address for munmap ++ // printf("width: %d, height: %d, total_buf_length: %d, phy:%#lx vir:%p\n", ++ // frame->stVFrame.u32Width, ++ // frame->stVFrame.u32Height, image_size, ++ // frame->stVFrame.u64PhyAddr[0], vir_addr); ++ ++ *frame_info = frame; ++ ++ if (!frame_info_mmap) ++ return 0; ++ frame_info_mmap->data = vir_addr; ++ frame_info_mmap->len = image_size; ++ frame_info_mmap->w = frame->stVFrame.u32Width; ++ frame_info_mmap->h = frame->stVFrame.u32Height; ++ frame_info_mmap->fmt = frame->stVFrame.enPixelFormat; ++ ++ return 0; ++ } ++ ++ return ret; ++} ++ ++int mmf_vi_frame_pop(int ch, void **data, int *len, int *width, int *height, int *format) { ++ int ret; ++ void *frame; ++ mmf_frame_info_t frame_mmap; ++ ++ if (data == NULL || len == NULL || width == NULL || height == NULL || format == NULL) { ++ printf("invalid param\n"); ++ return -1; ++ } ++ ++ ret = mmf_vi_frame_pop2(ch, &frame, &frame_mmap); ++ if (ret != 0) ++ return ret; ++ ++ *data = frame_mmap.data; ++ *len = frame_mmap.len; ++ *width = frame_mmap.w; ++ *height = frame_mmap.h; ++ *format = frame_mmap.fmt; ++ ++ return 0; ++} ++ ++void mmf_vi_frame_free2(int ch, void **frame_info) ++{ ++ if (ch < 0 || ch >= MMF_VI_MAX_CHN) { ++ printf("invalid ch %d\n", ch); ++ return; ++ } ++ if (!frame_info) ++ return; ++ VIDEO_FRAME_INFO_S *frame = &priv.vi_frame[ch]; ++ if (*frame_info != frame) ++ return; ++ ++ mmf_vi_frame_free(ch); ++} ++ ++void mmf_vi_frame_free(int ch) { ++ if (ch < 0 || ch >= MMF_VI_MAX_CHN) { ++ printf("invalid ch %d\n", ch); ++ return; ++ } ++ ++ VIDEO_FRAME_INFO_S *frame = &priv.vi_frame[ch]; ++ int image_size = frame->stVFrame.u32Length[0] ++ + frame->stVFrame.u32Length[1] ++ + frame->stVFrame.u32Length[2]; ++ if (frame->stVFrame.pu8VirAddr[0]) { ++ CVI_SYS_Munmap(frame->stVFrame.pu8VirAddr[0], image_size); ++ frame->stVFrame.pu8VirAddr[0] = NULL; ++ } ++ if (CVI_VPSS_ReleaseChnFrame(priv.vi_vpss, ch, frame) != 0) ++ printf("CVI_VI_ReleaseChnFrame failed\n"); ++} ++ ++#ifndef KVM_MMF ++ ++// manage vo channels ++int mmf_get_vo_unused_channel(int layer) { ++ switch (layer) { ++ case MMF_VO_VIDEO_LAYER: ++ for (int i = 0; i < MMF_VO_VIDEO_MAX_CHN; i++) { ++ if (priv.vo_video_chn_is_inited[i] == false) { ++ return i; ++ } ++ } ++ break; ++ case MMF_VO_OSD_LAYER: ++ return mmf_get_region_unused_channel(); ++ default: ++ printf("invalid layer %d\n", layer); ++ return -1; ++ } ++ ++ return -1; ++} ++ ++static CVI_S32 _mmf_vo_vpss_init(CVI_U32 width, CVI_U32 height, PIXEL_FORMAT_E format) ++{ ++ VPSS_GRP out_grp = CVI_VPSS_GetAvailableGrp(); ++ CVI_S32 s32Ret = CVI_SUCCESS; ++ ++ s32Ret = _mmf_vpss_init_new_with_fps(out_grp, width, height, format, 60); ++ if (s32Ret != CVI_SUCCESS) { ++ return s32Ret; ++ } ++ ++ priv.vo_vpss = out_grp; ++ ++ return s32Ret; ++} ++ ++static CVI_S32 _mmf_vo_vpss_deinit(void) ++{ ++ CVI_S32 s32Ret = CVI_SUCCESS; ++ ++ if (priv.vo_vpss != VPSS_INVALID_GRP) { ++ s32Ret = _mmf_vpss_deinit_new(priv.vo_vpss); ++ } ++ if (s32Ret != CVI_SUCCESS) { ++ return s32Ret; ++ } ++ ++ priv.vo_vpss = VPSS_INVALID_GRP; ++ ++ return s32Ret; ++} ++ ++// fit = 0, width to new width, height to new height, may be stretch ++// fit = 1, keep aspect ratio, fill blank area with black color ++// fit = 2, keep aspect ratio, crop image to fit new size ++static int _mmf_add_vo_channel(int layer, int ch, int width, int height, int format_in, int format_out, int fps, int depth, bool mirror, bool flip, int fit) { ++ if (layer == MMF_VO_VIDEO_LAYER) { ++ if (ch < 0 || ch >= MMF_VO_VIDEO_MAX_CHN) { ++ printf("invalid ch %d\n", ch); ++ return false; ++ } ++ ++ SAMPLE_VO_CONFIG_S stVoConfig; ++ RECT_S stDefDispRect = {0, 0, (CVI_U32)width, (CVI_U32)height}; ++ SIZE_S stDefImageSize = {(CVI_U32)width, (CVI_U32)height}; ++ CVI_S32 s32Ret = CVI_SUCCESS; ++ CVI_U32 panel_init = false; ++ VO_PUB_ATTR_S stVoPubAttr; ++ ++ #if !MMF_VO_USE_NV21_ONLY ++ if (priv.vo_rotate == 90 || priv.vo_rotate == 270) { ++ stDefDispRect.u32Width = (CVI_U32)height; ++ stDefDispRect.u32Height = (CVI_U32)width; ++ stDefImageSize.u32Width = (CVI_U32)height; ++ stDefImageSize.u32Height = (CVI_U32)width; ++ } ++ #else ++ if (format_in == PIXEL_FORMAT_NV21 && (priv.vo_rotate == 90 || priv.vo_rotate == 270)) { ++ stDefDispRect.u32Width = (CVI_U32)height; ++ stDefDispRect.u32Height = (CVI_U32)width; ++ stDefImageSize.u32Width = (CVI_U32)height; ++ stDefImageSize.u32Height = (CVI_U32)width; ++ } ++ #endif ++ SIZE_S stSizeIn, stSizeOut; ++ PIXEL_FORMAT_E formatIn = (PIXEL_FORMAT_E)format_in; ++ PIXEL_FORMAT_E formatOut = (PIXEL_FORMAT_E)format_out; ++ ++ CVI_VO_Get_Panel_Status(0, ch, &panel_init); ++ if (panel_init) { ++ CVI_VO_GetPubAttr(0, &stVoPubAttr); ++ printf("Panel w=%d, h=%d.\n",\ ++ stVoPubAttr.stSyncInfo.u16Hact, stVoPubAttr.stSyncInfo.u16Vact); ++ stDefDispRect.u32Width = stVoPubAttr.stSyncInfo.u16Hact; ++ stDefDispRect.u32Height = stVoPubAttr.stSyncInfo.u16Vact; ++ stDefImageSize.u32Width = stVoPubAttr.stSyncInfo.u16Hact; ++ stDefImageSize.u32Height = stVoPubAttr.stSyncInfo.u16Vact; ++ } ++ s32Ret = SAMPLE_COMM_VO_GetDefConfig(&stVoConfig); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("SAMPLE_COMM_VO_GetDefConfig failed with %#x\n", s32Ret); ++ return -1; ++ } ++ ++ stVoConfig.VoDev = 0; ++ stVoConfig.stVoPubAttr.enIntfType = VO_INTF_MIPI; ++ stVoConfig.stVoPubAttr.enIntfSync = VO_OUTPUT_720x1280_60; ++ stVoConfig.stDispRect = stDefDispRect; ++ stVoConfig.stImageSize = stDefImageSize; ++ stVoConfig.enPixFormat = (PIXEL_FORMAT_E)PIXEL_FORMAT_NV21; ++ stVoConfig.enVoMode = VO_MODE_1MUX; ++ s32Ret = SAMPLE_COMM_VO_StartVO(&stVoConfig); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("SAMPLE_COMM_VO_StartVO failed with %#x\n", s32Ret); ++ return -1; ++ } ++ ++ memcpy(&priv.vo_video_cfg[ch], &stVoConfig, sizeof(SAMPLE_VO_CONFIG_S)); ++ ++ switch (priv.vo_rotate) { ++ case 0:break; ++ case 90: ++ CVI_VO_SetChnRotation(layer, ch, ROTATION_90); ++ break; ++ case 180: ++ CVI_VO_SetChnRotation(layer, ch, ROTATION_180); ++ break; ++ case 270: ++ CVI_VO_SetChnRotation(layer, ch, ROTATION_270); ++ break; ++ default: ++ break; ++ } ++ ++ stSizeIn.u32Width = width; ++ stSizeIn.u32Height = height; ++ stSizeOut.u32Width = width; ++ stSizeOut.u32Height = height; ++ priv.vo_vpss_in_format[ch] = format_in; ++ priv.vo_vpss_in_size[ch].u32Width = stSizeIn.u32Width; ++ priv.vo_vpss_in_size[ch].u32Height = stSizeIn.u32Height; ++ priv.vo_vpss_out_size[ch].u32Width = stSizeOut.u32Width; ++ priv.vo_vpss_out_size[ch].u32Height = stSizeOut.u32Height; ++ priv.vo_vpss_fit[ch] = fit; ++#if 1 ++ s32Ret = _mmf_vo_vpss_deinit(); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("_mmf_vpss_deinit_new failed. s32Ret: 0x%x !\n", s32Ret); ++ goto error_and_stop_vo; ++ } ++ ++ s32Ret = _mmf_vo_vpss_init(stSizeIn.u32Width, stSizeIn.u32Height, formatIn); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("_mmf_vpss_init_new failed. s32Ret: 0x%x !\n", s32Ret); ++ goto error_and_stop_vo; ++ } ++ ++ s32Ret = _mmf_vpss_chn_deinit(priv.vo_vpss, ch); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("_mmf_vpss_chn_deinit failed with %#x!\n", s32Ret); ++ goto error_and_deinit_vpss; ++ } ++ ++ s32Ret = _mmf_vpss_chn_init(priv.vo_vpss, ch, stSizeOut.u32Width, stSizeOut.u32Height, formatOut, fps, depth, mirror, flip, fit); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("_mmf_vpss_chn_init failed with %#x!\n", s32Ret); ++ goto error_and_deinit_vpss; ++ } ++ ++ s32Ret = SAMPLE_COMM_VPSS_Bind_VO(priv.vo_vpss, ch, layer, ch); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("vo bind vpss failed. s32Ret: 0x%x !\n", s32Ret); ++ goto error_and_deinit_vpss_chn; ++ } ++ ++ // if (priv.vo_video_pre_frame[ch]) { ++ // _mmf_free_frame(priv.vo_video_pre_frame[ch]); ++ // priv.vo_video_pre_frame[ch] = NULL; ++ // priv.vo_video_pre_frame_width[ch] = -1; ++ // priv.vo_video_pre_frame_height[ch] = -1; ++ // priv.vo_video_pre_frame_format[ch] = -1; ++ // } ++ ++ priv.vo_video_pre_frame_width[ch] = width; ++ priv.vo_video_pre_frame_height[ch] = height; ++ priv.vo_video_pre_frame_format[ch] = format_in; ++ // priv.vo_video_pre_frame[ch] = (VIDEO_FRAME_INFO_S *)_mmf_alloc_frame(priv.vb_user_id, (SIZE_S){(CVI_U32)width, (CVI_U32)height}, (PIXEL_FORMAT_E)format_in); ++ // if (!priv.vo_video_pre_frame[ch]) { ++ // printf("Alloc frame failed!\r\n"); ++ // goto error_and_unbind; ++ // } ++ ++ priv.vo_video_chn_is_inited[ch] = true; ++ ++ return s32Ret; ++// error_and_unbind: ++// s32Ret = SAMPLE_COMM_VPSS_UnBind_VO(priv.vo_vpss, ch, layer, ch); ++// if (s32Ret != CVI_SUCCESS) { ++// printf("vo unbind vpss failed. s32Ret: 0x%x !\n", s32Ret); ++// } ++error_and_deinit_vpss: ++ s32Ret = _mmf_vo_vpss_deinit(); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("_mmf_vpss_deinit_new failed. s32Ret: 0x%x !\n", s32Ret); ++ } ++error_and_deinit_vpss_chn: ++ s32Ret = _mmf_vpss_chn_deinit(priv.vo_vpss, ch); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("vpss deinit failed. s32Ret: 0x%x !\n", s32Ret); ++ } ++error_and_stop_vo: ++ s32Ret = SAMPLE_COMM_VO_StopVO(&stVoConfig); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("vo stop failed. s32Ret: 0x%x !\n", s32Ret); ++ } ++ return -1; ++#else ++ priv.vo_vpss = 1; ++ s32Ret = _mmf_vpss_init(priv.vo_vpss, ch, stSizeIn, stSizeOut, formatIn, formatOut, fps, depth, mirror, flip, fit); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("vpss init failed. s32Ret: 0x%x. try again..\r\n", s32Ret); ++ s32Ret = _mmf_vpss_deinit(priv.vo_vpss, ch); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("vpss deinit failed. s32Ret: 0x%x !\n", s32Ret); ++ goto error_and_stop_vo; ++ } ++ ++ s32Ret = _mmf_vpss_init(priv.vo_vpss, ch, stSizeIn, stSizeOut, formatIn, formatOut, fps, depth, mirror, flip, fit); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("vpss init failed. s32Ret: 0x%x !\n", s32Ret); ++ goto error_and_stop_vo; ++ } ++ } ++ ++ s32Ret = SAMPLE_COMM_VPSS_Bind_VO(priv.vo_vpss, ch, layer, ch); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("vo bind vpss failed. s32Ret: 0x%x !\n", s32Ret); ++ goto error_and_deinit_vpss; ++ } ++ ++ if (priv.vo_video_pre_frame[ch]) { ++ _mmf_free_frame(priv.vo_video_pre_frame[ch]); ++ priv.vo_video_pre_frame[ch] = NULL; ++ priv.vo_video_pre_frame_width[ch] = -1; ++ priv.vo_video_pre_frame_height[ch] = -1; ++ priv.vo_video_pre_frame_format[ch] = -1; ++ } ++ ++ priv.vo_video_pre_frame_width[ch] = width; ++ priv.vo_video_pre_frame_height[ch] = height; ++ priv.vo_video_pre_frame_format[ch] = format_in; ++ priv.vo_video_pre_frame[ch] = (VIDEO_FRAME_INFO_S *)_mmf_alloc_frame(priv.vb_user_id, (SIZE_S){(CVI_U32)width, (CVI_U32)height}, (PIXEL_FORMAT_E)format_in); ++ if (!priv.vo_video_pre_frame[ch]) { ++ printf("Alloc frame failed!\r\n"); ++ goto error_and_unbind; ++ } ++ ++ priv.vo_video_chn_is_inited[ch] = true; ++ ++ return s32Ret; ++error_and_stop_vo: ++ s32Ret = SAMPLE_COMM_VO_StopVO(&stVoConfig); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("vo stop failed. s32Ret: 0x%x !\n", s32Ret); ++ } ++error_and_unbind: ++ s32Ret = SAMPLE_COMM_VPSS_UnBind_VO(priv.vo_vpss, ch, layer, ch); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("vo unbind vpss failed. s32Ret: 0x%x !\n", s32Ret); ++ } ++error_and_deinit_vpss: ++ s32Ret = _mmf_vpss_deinit(priv.vo_vpss, ch); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("vpss deinit failed. s32Ret: 0x%x !\n", s32Ret); ++ } ++ return -1; ++#endif ++ } else if (layer == MMF_VO_OSD_LAYER) { ++ if (fit != 0) { ++ printf("region support fit = 0 only!\r\n"); ++ return false; ++ } ++ ++ if (ch < 0 || ch >= MMF_VO_OSD_MAX_CHN) { ++ printf("invalid ch %d\n", ch); ++ return false; ++ } ++ ++ if (priv.vo_osd_chn_is_inited[ch]) { ++ printf("vo osd ch %d already open\n", ch); ++ return -1; ++ } ++ ++ if (format_in != PIXEL_FORMAT_ARGB_8888) { ++ printf("only support ARGB format.\n"); ++ return -1; ++ } ++ ++ if (0 != mmf_add_region_channel(ch, OVERLAY_RGN, CVI_ID_VPSS, priv.vo_vpss, ch, 0, 0, width, height, format_in)) { ++ printf("mmf_add_region_channel failed!\r\n"); ++ return -1; ++ } ++ ++ priv.vo_osd_chn_is_inited[ch] = true; ++ ++ return 0; ++ } else { ++ printf("invalid layer %d\n", layer); ++ return -1; ++ } ++ ++ return -1; ++} ++ ++int mmf_add_vo_channel_with_fit(int layer, int ch, int width, int height, int format, int fit) ++{ ++ return _mmf_add_vo_channel(layer, ch, width, height, format, PIXEL_FORMAT_NV21, 30, 0, !g_priv.vo_video_hmirror[ch], !g_priv.vo_video_vflip[ch], fit); ++} ++ ++int mmf_add_vo_channel(int layer, int ch, int width, int height, int format) ++{ ++ return mmf_add_vo_channel_with_fit(layer, ch, width, height, format, priv.vo_vpss_fit[ch]); ++} ++ ++int mmf_del_vo_channel(int layer, int ch) { ++ if (layer == MMF_VO_VIDEO_LAYER) { ++ if (ch < 0 || ch >= MMF_VO_VIDEO_MAX_CHN) { ++ printf("invalid ch %d\n", ch); ++ return CVI_FALSE; ++ } ++ ++ if (priv.vo_video_chn_is_inited[ch] == false) { ++ return CVI_SUCCESS; ++ } ++ ++ if (CVI_SUCCESS != SAMPLE_COMM_VPSS_UnBind_VO(priv.vo_vpss, ch, layer, ch)) { ++ printf("vo unbind vpss failed.!\n"); ++ } ++#if 0 ++ if (0 != _mmf_vpss_deinit(priv.vo_vpss, ch)) { ++ printf("vpss deinit failed.!\n"); ++ } ++#else ++ if (0 != _mmf_vpss_chn_deinit(priv.vo_vpss, ch)) { ++ printf("_mmf_vpss_chn_deinit failed!\n"); ++ } ++ ++ if (0 != _mmf_vo_vpss_deinit()) { ++ printf("_mmf_vpss_deinit_new failed!\n"); ++ } ++#endif ++ if (CVI_SUCCESS != SAMPLE_COMM_VO_StopVO(&priv.vo_video_cfg[ch])) { ++ printf("SAMPLE_COMM_VO_StopVO failed with %#x\n", CVI_FAILURE); ++ return CVI_FAILURE; ++ } ++ ++ // if (priv.vo_video_pre_frame[ch]) { ++ // _mmf_free_frame(priv.vo_video_pre_frame[ch]); ++ // priv.vo_video_pre_frame_width[ch] = -1; ++ // priv.vo_video_pre_frame_height[ch] = -1; ++ // priv.vo_video_pre_frame_format[ch] = -1; ++ // priv.vo_video_pre_frame[ch] = NULL; ++ // } ++ ++ priv.vo_video_chn_is_inited[ch] = false; ++ return CVI_SUCCESS; ++ } else if (layer == MMF_VO_OSD_LAYER) { ++ if (ch < 0 || ch >= MMF_VO_OSD_MAX_CHN) { ++ printf("invalid ch %d\n", ch); ++ return CVI_FALSE; ++ } ++ ++ if (priv.vo_osd_chn_is_inited[ch] == false) { ++ return CVI_SUCCESS; ++ } ++ ++ if (0 != mmf_del_region_channel(ch)) { ++ printf("mmf_del_region_channel failed!\r\n"); ++ } ++ ++ priv.vo_osd_chn_is_inited[ch] = false; ++ return CVI_SUCCESS; ++ } else { ++ printf("invalid layer %d\n", layer); ++ return CVI_FAILURE; ++ } ++ ++ return CVI_FAILURE; ++} ++ ++int mmf_del_vo_channel_all(int layer) { ++ CVI_S32 s32Ret = CVI_SUCCESS; ++ switch (layer) { ++ case MMF_VO_VIDEO_LAYER: ++ for (int i = 0; i < MMF_VO_VIDEO_MAX_CHN; i++) { ++ if (priv.vo_video_chn_is_inited[i] == true) { ++ s32Ret = mmf_del_vo_channel(layer, i); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("mmf_del_vo_channel failed with %#x\n", s32Ret); ++ // return s32Ret; // continue to del other chn ++ } ++ } ++ } ++ break; ++ case MMF_VO_OSD_LAYER: ++ for (int i = 0; i < MMF_VO_OSD_MAX_CHN; i++) { ++ if (priv.vo_osd_chn_is_inited[i] == true) { ++ s32Ret = mmf_del_vo_channel(layer, i); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("mmf_del_vo_channel failed with %#x\n", s32Ret); ++ // return s32Ret; // continue to del other chn ++ } ++ } ++ } ++ break; ++ default: ++ printf("invalid layer %d\n", layer); ++ return CVI_FAILURE; ++ } ++ return CVI_SUCCESS; ++} ++ ++bool mmf_vo_channel_is_open(int layer, int ch) { ++ ++ switch (layer) { ++ case MMF_VO_VIDEO_LAYER: ++ if (ch < 0 || ch >= MMF_VO_VIDEO_MAX_CHN) { ++ printf("invalid ch %d\n", ch); ++ return false; ++ } ++ return priv.vo_video_chn_is_inited[ch]; ++ case MMF_VO_OSD_LAYER: ++ if (ch < 0 || ch >= MMF_VO_OSD_MAX_CHN) { ++ printf("invalid ch %d\n", ch); ++ return false; ++ } ++ return priv.vo_osd_chn_is_inited[ch]; ++ default: ++ printf("invalid layer %d\n", layer); ++ return false; ++ } ++ ++ return false; ++} ++ ++int mmf_vo_frame_push2(int layer, int ch, int fit, void *frame_info) { ++ CVI_S32 s32Ret = CVI_SUCCESS; ++ VIDEO_FRAME_INFO_S *frame = (VIDEO_FRAME_INFO_S *)frame_info; ++ ++ if (!frame) { ++ return -1; ++ } ++ ++ int width = frame->stVFrame.u32Width; ++ int height = frame->stVFrame.u32Height; ++ int format = frame->stVFrame.enPixelFormat; ++ ++ if (layer == MMF_VO_VIDEO_LAYER) { ++ if (fit != priv.vo_vpss_fit[ch] ++ || width != (int)priv.vo_vpss_in_size[ch].u32Width ++ || height != (int)priv.vo_vpss_in_size[ch].u32Height ++ || format != (int)priv.vo_vpss_in_format[ch]) { ++ priv.vo_vpss_in_format[ch] = format; ++ priv.vo_vpss_in_size[ch].u32Width = width; ++ priv.vo_vpss_in_size[ch].u32Height = height; ++ priv.vo_vpss_fit[ch] = fit; ++ int width_out = priv.vo_vpss_out_size[ch].u32Width; ++ int height_out = priv.vo_vpss_out_size[ch].u32Height; ++ int fps_out = priv.vo_vpss_out_fps[ch]; ++ int depth_out = priv.vo_vpss_out_depth[ch]; ++ int mirror_out = !g_priv.vo_video_hmirror[ch]; ++ int flip_out = !g_priv.vo_video_vflip[ch]; ++ s32Ret = SAMPLE_COMM_VPSS_UnBind_VO(priv.vo_vpss, ch, layer, ch); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("vo unbind vpss failed. s32Ret: 0x%x !\n", s32Ret); ++ return -1; ++ } ++ ++ s32Ret = _mmf_vo_vpss_deinit(); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("_mmf_vpss_deinit_new failed. s32Ret: 0x%x !\n", s32Ret); ++ return -1; ++ } ++ ++ s32Ret = _mmf_vo_vpss_init(width, height, (PIXEL_FORMAT_E)format); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("_mmf_vpss_init_new failed. s32Ret: 0x%x !\n", s32Ret); ++ return -1; ++ } ++ ++ s32Ret = _mmf_vpss_chn_deinit(priv.vo_vpss, ch); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("_mmf_vpss_chn_deinit failed with %#x!\n", s32Ret); ++ return -1; ++ } ++ ++ s32Ret = _mmf_vpss_chn_init(priv.vo_vpss, ch, width_out, height_out, PIXEL_FORMAT_NV21, fps_out, depth_out, mirror_out, flip_out, fit); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("_mmf_vpss_chn_init failed with %#x!\n", s32Ret); ++ return -1; ++ } ++ ++ s32Ret = SAMPLE_COMM_VPSS_Bind_VO(priv.vo_vpss, ch, layer, ch); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("vo bind vpss failed. s32Ret: 0x%x !\n", s32Ret); ++ return -1; ++ } ++ } ++ ++ // if (priv.vo_video_cfg[ch].enPixFormat != (PIXEL_FORMAT_E)format) { ++ // printf("vo ch %d format not match. input:%d need:%d\n", ch, format, priv.vo_video_cfg[ch].enPixFormat); ++ // return CVI_FAILURE; ++ // } ++ ++ // mmf_vo_frame_push ++ s32Ret = CVI_VPSS_SendFrame(priv.vo_vpss, frame, 1000); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("CVI_VO_SendFrame failed >< with %#x\n", s32Ret); ++ return s32Ret; ++ } ++ } else if (layer == MMF_VO_OSD_LAYER) { ++ if (ch < 0 || ch >= MMF_VO_OSD_MAX_CHN) { ++ printf("invalid ch %d\n", ch); ++ return -1; ++ } ++ ++ if (priv.vo_osd_chn_is_inited[ch] == false) { ++ printf("vo osd ch %d not open\n", ch); ++ return -1; ++ } ++ ++ if (format != PIXEL_FORMAT_ARGB_8888) { ++ printf("only support ARGB format.\n"); ++ return -1; ++ } ++ ++ if (0 != mmf_region_frame_push2(ch, frame)) { ++ printf("mmf_region_flush failed!\r\n"); ++ return -1; ++ } ++ } else { ++ printf("invalid layer %d\n", layer); ++ return -1; ++ } ++ ++ return CVI_SUCCESS; ++} ++ ++// flush vo ++int mmf_vo_frame_push_with_fit(int layer, int ch, void *data, int len, int width, int height, int format, int fit) { ++ CVI_S32 s32Ret = CVI_SUCCESS; ++ UNUSED(len); ++ UNUSED(layer); ++ UNUSED(cvi_rgb2nv21); ++ ++ if (layer == MMF_VO_VIDEO_LAYER) { ++ if (fit != priv.vo_vpss_fit[ch] ++ || width != (int)priv.vo_vpss_in_size[ch].u32Width ++ || height != (int)priv.vo_vpss_in_size[ch].u32Height ++ || format != (int)priv.vo_vpss_in_format[ch]) { ++#if 1 ++ priv.vo_vpss_in_format[ch] = format; ++ priv.vo_vpss_in_size[ch].u32Width = width; ++ priv.vo_vpss_in_size[ch].u32Height = height; ++ priv.vo_vpss_fit[ch] = fit; ++ int width_out = priv.vo_vpss_out_size[ch].u32Width; ++ int height_out = priv.vo_vpss_out_size[ch].u32Height; ++ int fps_out = priv.vo_vpss_out_fps[ch]; ++ int depth_out = priv.vo_vpss_out_depth[ch]; ++ int mirror_out = !g_priv.vo_video_hmirror[ch]; ++ int flip_out = !g_priv.vo_video_vflip[ch]; ++ s32Ret = SAMPLE_COMM_VPSS_UnBind_VO(priv.vo_vpss, ch, layer, ch); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("vo unbind vpss failed. s32Ret: 0x%x !\n", s32Ret); ++ return -1; ++ } ++ ++ s32Ret = _mmf_vo_vpss_deinit(); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("_mmf_vpss_deinit_new failed. s32Ret: 0x%x !\n", s32Ret); ++ return -1; ++ } ++ ++ s32Ret = _mmf_vo_vpss_init(width, height, (PIXEL_FORMAT_E)format); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("_mmf_vpss_init_new failed. s32Ret: 0x%x !\n", s32Ret); ++ return -1; ++ } ++ ++ s32Ret = _mmf_vpss_chn_deinit(priv.vo_vpss, ch); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("_mmf_vpss_chn_deinit failed with %#x!\n", s32Ret); ++ return -1; ++ } ++ ++ s32Ret = _mmf_vpss_chn_init(priv.vo_vpss, ch, width_out, height_out, PIXEL_FORMAT_NV21, fps_out, depth_out, mirror_out, flip_out, fit); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("_mmf_vpss_chn_init failed with %#x!\n", s32Ret); ++ return -1; ++ } ++ ++ s32Ret = SAMPLE_COMM_VPSS_Bind_VO(priv.vo_vpss, ch, layer, ch); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("vo bind vpss failed. s32Ret: 0x%x !\n", s32Ret); ++ return -1; ++ } ++#else ++ s32Ret = SAMPLE_COMM_VPSS_UnBind_VO(priv.vo_vpss, ch, layer, ch); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("vo unbind vpss failed. s32Ret: 0x%x !\n", s32Ret); ++ return -1; ++ } ++ ++ SIZE_S stSizeIn, stSizeOut; ++ int fps = 30; ++ int depth = 0; ++ PIXEL_FORMAT_E formatIn = (PIXEL_FORMAT_E)format; ++ PIXEL_FORMAT_E formatOut = (PIXEL_FORMAT_E)PIXEL_FORMAT_NV21; ++ stSizeIn.u32Width = width; ++ stSizeIn.u32Height = height; ++ stSizeOut.u32Width = priv.vo_vpss_out_size[ch].u32Width; ++ stSizeOut.u32Height = priv.vo_vpss_out_size[ch].u32Height; ++ priv.vo_vpss_in_size[ch].u32Width = stSizeIn.u32Width; ++ priv.vo_vpss_in_size[ch].u32Height = stSizeIn.u32Height; ++ priv.vo_vpss_fit[ch] = fit; ++ _mmf_vpss_deinit(priv.vo_vpss, ch); ++ bool mirror = !g_priv.vo_video_hmirror[ch]; ++ bool flip = !g_priv.vo_video_vflip[ch]; ++ int fit = priv.vo_vpss_fit[ch]; ++ s32Ret = _mmf_vpss_init(priv.vo_vpss, ch, stSizeIn, stSizeOut, formatIn, formatOut, fps, depth, mirror, flip, fit); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("vpss init failed. s32Ret: 0x%x !\n", s32Ret); ++ return -1; ++ } ++ ++ // printf("vpss vo reinit.\r\n"); ++ // printf("stSizeIn.u32Width: %d, stSizeIn.u32Height: %d, stSizeOut.u32Width: %d, stSizeOut.u32Height: %d formatOut:%d\n", ++ // stSizeIn.u32Width, stSizeIn.u32Height, stSizeOut.u32Width, stSizeOut.u32Height, formatOut); ++ s32Ret = SAMPLE_COMM_VPSS_Bind_VO(priv.vo_vpss, ch, layer, ch); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("vo bind vpss failed. s32Ret: 0x%x !\n", s32Ret); ++ _mmf_vpss_deinit(priv.vo_vpss, ch); ++ return -1; ++ } ++#endif ++ } ++ ++#if 0 ++ if (!priv.vo_video_pre_frame[ch] ++ || priv.vo_video_pre_frame_width[ch] != width ++ || priv.vo_video_pre_frame_height[ch] != height ++ || priv.vo_video_pre_frame_format[ch] != format) { ++ if (priv.vo_video_pre_frame[ch]) { ++ _mmf_free_frame(priv.vo_video_pre_frame[ch]); ++ priv.vo_video_pre_frame[ch] = NULL; ++ } ++ priv.vo_video_pre_frame[ch] = (VIDEO_FRAME_INFO_S *)_mmf_alloc_frame(priv.vb_user_id, (SIZE_S){(CVI_U32)width, (CVI_U32)height}, (PIXEL_FORMAT_E)format); ++ if (!priv.vo_video_pre_frame[ch]) { ++ printf("Alloc frame failed!\r\n"); ++ return -1; ++ } ++ priv.vo_video_pre_frame_width[ch] = width; ++ priv.vo_video_pre_frame_height[ch] = height; ++ priv.vo_video_pre_frame_format[ch] = format; ++ } ++ ++ VIDEO_FRAME_INFO_S *frame = (VIDEO_FRAME_INFO_S *)priv.vo_video_pre_frame[ch]; ++ switch (format) { ++ case PIXEL_FORMAT_RGB_888: ++ // if (fit == 2) { // crop image and keep aspect ratio ++ // CVI_FLOAT corp_scale_w = (CVI_FLOAT)priv.vo_vpss_in_size[ch].u32Width / priv.vo_vpss_out_size[ch].u32Width; ++ // CVI_FLOAT corp_scale_h = (CVI_FLOAT)priv.vo_vpss_in_size[ch].u32Height / priv.vo_vpss_out_size[ch].u32Height; ++ // CVI_U32 crop_w = corp_scale_w < corp_scale_h ? priv.vo_vpss_out_size[ch].u32Width * corp_scale_w: priv.vo_vpss_out_size[ch].u32Width * corp_scale_h; ++ // CVI_U32 crop_h = corp_scale_w < corp_scale_h ? priv.vo_vpss_out_size[ch].u32Height * corp_scale_w: priv.vo_vpss_out_size[ch].u32Height * corp_scale_h; ++ // if (corp_scale_h < 0 || corp_scale_w < 0) { ++ // printf("crop scale error. corp_scale_w: %d, corp_scale_h: %d\n", corp_scale_w, corp_scale_h); ++ // return -1; ++ // } ++ // } else ++ { ++ if (frame->stVFrame.u32Stride[0] != (CVI_U32)width * 3) { ++ for (int h = 0; h < height; h++) { ++ memcpy((uint8_t *)frame->stVFrame.pu8VirAddr[0] + frame->stVFrame.u32Stride[0] * h, ((uint8_t *)data) + width * h * 3, width * 3); ++ } ++ } else { ++ memcpy(frame->stVFrame.pu8VirAddr[0], ((uint8_t *)data), width * height * 3); ++ } ++ CVI_SYS_IonFlushCache(frame->stVFrame.u64PhyAddr[0], ++ frame->stVFrame.pu8VirAddr[0], ++ width * height * 3); ++ } ++ break; ++ case PIXEL_FORMAT_NV21: ++ if (frame->stVFrame.u32Stride[0] != (CVI_U32)width) { ++ for (int h = 0; h < height * 3 / 2; h ++) { ++ memcpy((uint8_t *)frame->stVFrame.pu8VirAddr[0] + frame->stVFrame.u32Stride[0] * h, ++ ((uint8_t *)data) + width * h, width); ++ } ++ } else { ++ memcpy(frame->stVFrame.pu8VirAddr[0], ((uint8_t *)data), width * height * 3 / 2); ++ } ++ ++ CVI_SYS_IonFlushCache(frame->stVFrame.u64PhyAddr[0], ++ frame->stVFrame.pu8VirAddr[0], ++ width * height * 3 / 2); ++ break; ++ default: ++ printf("format not support\n"); ++ return CVI_FAILURE; ++ } ++ ++ s32Ret = CVI_VPSS_SendFrame(priv.vo_vpss, frame, 1000); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("CVI_VO_SendFrame failed, ret:%#x\n", s32Ret); ++ return s32Ret; ++ } ++#else ++ VIDEO_FRAME_INFO_S stVideoFrame; ++ VB_CAL_CONFIG_S stVbCalConfig; ++ UNUSED(len); ++ COMMON_GetPicBufferConfig(width, height, (PIXEL_FORMAT_E)format, DATA_BITWIDTH_8 ++ , COMPRESS_MODE_NONE, DEFAULT_ALIGN, &stVbCalConfig); ++ ++ // if (priv.vo_video_cfg[ch].enPixFormat != (PIXEL_FORMAT_E)format) { ++ // printf("vo ch %d format not match. input:%d need:%d\n", ch, format, priv.vo_video_cfg[ch].enPixFormat); ++ // return CVI_FAILURE; ++ // } ++ ++ memset(&stVideoFrame, 0, sizeof(stVideoFrame)); ++ ++ if (_mmf_init_frame(priv.vb_user_id, (SIZE_S){(CVI_U32)width, (CVI_U32)height}, (PIXEL_FORMAT_E)format, &stVideoFrame, &stVbCalConfig) != CVI_SUCCESS) { ++ return CVI_FAILURE; ++ } ++ ++ switch (format) { ++ case PIXEL_FORMAT_RGB_888: ++ if (stVideoFrame.stVFrame.u32Stride[0] != (CVI_U32)width * 3) { ++ for (int h = 0; h < height; h++) { ++ memcpy((uint8_t *)stVideoFrame.stVFrame.pu8VirAddr[0] + stVideoFrame.stVFrame.u32Stride[0] * h, ((uint8_t *)data) + width * h * 3, width * 3); ++ } ++ } else { ++ memcpy(stVideoFrame.stVFrame.pu8VirAddr[0], ((uint8_t *)data), width * height * 3); ++ } ++ CVI_SYS_IonFlushCache(stVideoFrame.stVFrame.u64PhyAddr[0], ++ stVideoFrame.stVFrame.pu8VirAddr[0], ++ width * height * 3); ++ break; ++ case PIXEL_FORMAT_NV21: ++ if (stVideoFrame.stVFrame.u32Stride[0] != (CVI_U32)width) { ++ for (int h = 0; h < height * 3 / 2; h ++) { ++ memcpy((uint8_t *)stVideoFrame.stVFrame.pu8VirAddr[0] + stVideoFrame.stVFrame.u32Stride[0] * h, ++ ((uint8_t *)data) + width * h, width); ++ } ++ } else { ++ memcpy(stVideoFrame.stVFrame.pu8VirAddr[0], ((uint8_t *)data), width * height * 3 / 2); ++ } ++ ++ CVI_SYS_IonFlushCache(stVideoFrame.stVFrame.u64PhyAddr[0], ++ stVideoFrame.stVFrame.pu8VirAddr[0], ++ width * height * 3 / 2); ++ break; ++ default: ++ printf("format not support\n"); ++ _mmf_deinit_frame(&stVideoFrame); ++ return CVI_FAILURE; ++ } ++ ++ #if 0 ++ VPSS_GRP_ATTR_S GrpAttr; ++ CVI_VPSS_GetGrpAttr(priv.vo_vpss, &GrpAttr); ++ mmf_dump_grpattr(&GrpAttr); ++ ++ VPSS_CHN_ATTR_S ChnAttr; ++ CVI_VPSS_GetChnAttr(priv.vo_vpss, ch, &ChnAttr); ++ mmf_dump_chnattr(&ChnAttr); ++ ++ mmf_dump_frame(&stVideoFrame); ++ #endif ++ // UNUSED(layer); ++ // mmf_vo_frame_push ++ s32Ret = CVI_VPSS_SendFrame(priv.vo_vpss, &stVideoFrame, 1000); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("CVI_VO_SendFrame failed >< with %#x\n", s32Ret); ++ _mmf_deinit_frame(&stVideoFrame); ++ return s32Ret; ++ } ++ ++ _mmf_deinit_frame(&stVideoFrame); ++#endif ++ } else if (layer == MMF_VO_OSD_LAYER) { ++ if (ch < 0 || ch >= MMF_VO_OSD_MAX_CHN) { ++ printf("invalid ch %d\n", ch); ++ return -1; ++ } ++ ++ if (priv.vo_osd_chn_is_inited[ch] == false) { ++ printf("vo osd ch %d not open\n", ch); ++ return -1; ++ } ++ ++ if (format != PIXEL_FORMAT_ARGB_8888) { ++ printf("only support ARGB format.\n"); ++ return -1; ++ } ++ ++ if (0 != mmf_region_frame_push(ch, data, len)) { ++ printf("mmf_region_flush failed!\r\n"); ++ return -1; ++ } ++ } else { ++ printf("invalid layer %d\n", layer); ++ return -1; ++ } ++ ++ return CVI_SUCCESS; ++} ++ ++int mmf_vo_frame_push(int layer, int ch, void *data, int len, int width, int height, int format) { ++ return mmf_vo_frame_push_with_fit(layer, ch, data, len, width, height, format, priv.vo_vpss_fit[ch]); ++} ++ ++#endif // !KVM_MMF ++ ++static CVI_S32 _mmf_region_attach_to_channel(CVI_S32 ch, int x, int y, RGN_TYPE_E enType, MMF_CHN_S *pstChn) ++{ ++#define OverlayMinHandle 0 ++#define OverlayExMinHandle 20 ++#define CoverMinHandle 40 ++#define CoverExMinHandle 60 ++#define MosaicMinHandle 80 ++#define OdecHandle 100 ++ CVI_S32 s32Ret = CVI_SUCCESS; ++ RGN_CHN_ATTR_S stChnAttr; ++ ++ if (ch < 0 || ch >= MMF_RGN_MAX_NUM) { ++ printf("HandleId is illegal %d!\n", ch); ++ return CVI_FAILURE; ++ } ++ ++ if (enType != OVERLAY_RGN) { ++ printf("enType is illegal %d!\n", enType); ++ return CVI_FAILURE; ++ } ++ ++ if (pstChn == CVI_NULL) { ++ printf("pstChn is NULL !\n"); ++ return CVI_FAILURE; ++ } ++ memset(&stChnAttr, 0, sizeof(stChnAttr)); ++ ++ /*set the chn config*/ ++ stChnAttr.bShow = CVI_TRUE; ++ switch (enType) { ++ case OVERLAY_RGN: ++ stChnAttr.bShow = CVI_TRUE; ++ stChnAttr.enType = OVERLAY_RGN; ++ stChnAttr.unChnAttr.stOverlayChn.stInvertColor.bInvColEn = CVI_FALSE; ++ break; ++ case OVERLAYEX_RGN: ++ stChnAttr.bShow = CVI_TRUE; ++ stChnAttr.enType = OVERLAYEX_RGN; ++ stChnAttr.unChnAttr.stOverlayExChn.stInvertColor.bInvColEn = CVI_FALSE; ++ break; ++ case COVER_RGN: ++ stChnAttr.bShow = CVI_TRUE; ++ stChnAttr.enType = COVER_RGN; ++ stChnAttr.unChnAttr.stCoverChn.enCoverType = AREA_RECT; ++ ++ stChnAttr.unChnAttr.stCoverChn.stRect.u32Height = 100; ++ stChnAttr.unChnAttr.stCoverChn.stRect.u32Width = 100; ++ ++ stChnAttr.unChnAttr.stCoverChn.u32Color = 0x0000ffff; ++ ++ stChnAttr.unChnAttr.stCoverChn.enCoordinate = RGN_ABS_COOR; ++ break; ++ case COVEREX_RGN: ++ stChnAttr.bShow = CVI_TRUE; ++ stChnAttr.enType = COVEREX_RGN; ++ stChnAttr.unChnAttr.stCoverExChn.enCoverType = AREA_RECT; ++ ++ stChnAttr.unChnAttr.stCoverExChn.stRect.u32Height = 100; ++ stChnAttr.unChnAttr.stCoverExChn.stRect.u32Width = 100; ++ ++ stChnAttr.unChnAttr.stCoverExChn.u32Color = 0x0000ffff; ++ break; ++ case MOSAIC_RGN: ++ stChnAttr.enType = MOSAIC_RGN; ++ stChnAttr.unChnAttr.stMosaicChn.enBlkSize = MOSAIC_BLK_SIZE_8; ++ stChnAttr.unChnAttr.stMosaicChn.stRect.u32Height = 96; // 8 pixel align ++ stChnAttr.unChnAttr.stMosaicChn.stRect.u32Width = 96; ++ break; ++ default: ++ return CVI_FAILURE; ++ } ++ ++ if (enType == OVERLAY_RGN) { ++ stChnAttr.unChnAttr.stOverlayChn.stPoint.s32X = x; ++ stChnAttr.unChnAttr.stOverlayChn.stPoint.s32Y = y; ++ stChnAttr.unChnAttr.stOverlayChn.u32Layer = ch; ++ } ++ s32Ret = CVI_RGN_AttachToChn(ch, pstChn, &stChnAttr); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("CVI_RGN_AttachToChn failed!\n"); ++ return s32Ret; ++ } ++ ++ return s32Ret; ++} ++ ++static int _mmf_region_init(int ch, int type, int width, int height, int format) ++{ ++ CVI_S32 s32Ret = CVI_SUCCESS; ++ RGN_ATTR_S stRegion; ++ ++ if (ch < 0 || ch >= MMF_RGN_MAX_NUM) { ++ printf("Handle ch is illegal %d!\n", ch); ++ return CVI_FAILURE; ++ } ++ if (type != OVERLAY_RGN) { ++ printf("enType is illegal %d!\n", type); ++ return CVI_FAILURE; ++ } ++ ++ if (priv.rgn_is_init[ch]) { ++ return 0; ++ } ++ ++ stRegion.enType = (RGN_TYPE_E)type; ++ stRegion.unAttr.stOverlay.enPixelFormat = (PIXEL_FORMAT_E)format; ++ stRegion.unAttr.stOverlay.stSize.u32Height = height; ++ stRegion.unAttr.stOverlay.stSize.u32Width = width; ++ stRegion.unAttr.stOverlay.u32BgColor = 0x00000000; // ARGB1555 transparent ++ stRegion.unAttr.stOverlay.u32CanvasNum = 1; ++ stRegion.unAttr.stOverlay.stCompressInfo.enOSDCompressMode = OSD_COMPRESS_MODE_NONE; ++ s32Ret = CVI_RGN_Create(ch, &stRegion); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("CVI_RGN_Create failed with %#x!\n", s32Ret); ++ return CVI_FAILURE; ++ } ++ ++ priv.rgn_type[ch] = (RGN_TYPE_E)type; ++ priv.rgn_id[ch] = ch; ++ priv.rgn_is_init[ch] = true; ++ ++ return s32Ret; ++} ++ ++ ++static int _mmf_region_bind(int ch, int mod_id, int dev_id, int chn_id, int x, int y) ++{ ++ CVI_S32 s32Ret; ++ ++ MMF_CHN_S stChn = { ++ .enModId = (MOD_ID_E)mod_id, ++ .s32DevId = (CVI_S32)dev_id, ++ .s32ChnId = (CVI_S32)chn_id ++ }; ++ ++ if (ch < 0 || ch >= MMF_RGN_MAX_NUM) { ++ printf("Handle ch is illegal %d!\n", ch); ++ return CVI_FAILURE; ++ } ++ ++ if (!priv.rgn_is_init[ch]) { ++ return 0; ++ } ++ ++ if (priv.rgn_is_bind[ch]) { ++ return 0; ++ } ++ ++ RGN_TYPE_E type = (RGN_TYPE_E)priv.rgn_type[ch]; ++ s32Ret = _mmf_region_attach_to_channel(ch, x, y, type, &stChn); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("_mmf_region_attach_to_channel failed!\n"); ++ return s32Ret; ++ } ++ ++ priv.rgn_mod_id[ch] = (MOD_ID_E)mod_id; ++ priv.rgn_dev_id[ch] = (CVI_S32)dev_id; ++ priv.rgn_chn_id[ch] = (CVI_S32)chn_id; ++ priv.rgn_is_bind[ch] = true; ++ ++ return s32Ret; ++} ++ ++static int _mmf_region_unbind(int ch) ++{ ++ CVI_S32 s32Ret; ++ ++ if (ch < 0 || ch >= MMF_RGN_MAX_NUM) { ++ printf("Handle ch is illegal %d!\n", ch); ++ return CVI_FAILURE; ++ } ++ ++ MMF_CHN_S stChn = { ++ .enModId = (MOD_ID_E)priv.rgn_mod_id[ch], ++ .s32DevId = (CVI_S32)priv.rgn_dev_id[ch], ++ .s32ChnId = (CVI_S32)priv.rgn_chn_id[ch] ++ }; ++ ++ if (!priv.rgn_is_init[ch]) { ++ return 0; ++ } ++ ++ if (!priv.rgn_is_bind[ch]) { ++ return 0; ++ } ++ ++ s32Ret = CVI_RGN_DetachFromChn(ch, &stChn); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("CVI_RGN_DetachFromChn %d failed!\n", ch); ++ } ++ ++ priv.rgn_is_bind[ch] = false; ++ ++ return s32Ret; ++} ++ ++static int _mmf_region_deinit(int ch) ++{ ++ if (ch < 0 || ch >= MMF_RGN_MAX_NUM) { ++ printf("Handle ch is illegal %d!\n", ch); ++ return CVI_FAILURE; ++ } ++ ++ if (!priv.rgn_is_init[ch]) { ++ return 0; ++ } ++ ++ if (priv.rgn_is_bind[ch]) { ++ _mmf_region_unbind(ch); ++ } ++ ++ CVI_S32 s32Ret = CVI_RGN_Destroy(ch); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("CVI_RGN_Destroy failed with %#x!\n", s32Ret); ++ return CVI_FAILURE; ++ } ++ ++ priv.rgn_is_init[ch] = false; ++ ++ return s32Ret; ++} ++ ++int mmf_get_region_unused_channel(void) ++{ ++ for (int i = 0; i < MMF_RGN_MAX_NUM; i++) { ++ if (priv.rgn_is_init[i] == false) { ++ return i; ++ } ++ } ++ return -1; ++} ++ ++int mmf_add_region_channel(int ch, int type, int mod_id, int dev_id, int chn_id, int x, int y, int width, int height, int format) ++{ ++ if (0 != _mmf_region_init(ch, type, width, height, format)) { ++ return -1; ++ } ++ ++ if (0 != _mmf_region_bind(ch, mod_id, dev_id, chn_id, x, y)) { ++ _mmf_region_deinit(ch); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++int mmf_del_region_channel(int ch) ++{ ++ if (0 != _mmf_region_deinit(ch)) { ++ return -1; ++ } ++ ++ return 0; ++} ++ ++int mmf_del_region_channel_all(void) ++{ ++ for (int ch = 0; ch < MMF_RGN_MAX_NUM; ch ++) { ++ _mmf_region_deinit(ch); ++ } ++ ++ return 0; ++} ++ ++int mmf_region_get_canvas(int ch, void **data, int *width, int *height, int *format) ++{ ++ CVI_S32 s32Ret; ++ RGN_CANVAS_INFO_S stCanvasInfo; ++ ++ if (ch < 0 || ch >= MMF_RGN_MAX_NUM) { ++ printf("Handle ch is illegal %d!\n", ch); ++ return CVI_FAILURE; ++ } ++ ++ if (!priv.rgn_is_init[ch]) { ++ return 0; ++ } ++ ++ if (!priv.rgn_is_bind[ch]) { ++ return 0; ++ } ++ ++ s32Ret = CVI_RGN_GetCanvasInfo(ch, &stCanvasInfo); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("CVI_RGN_GetCanvasInfo failed with %#x!\n", s32Ret); ++ return CVI_FAILURE; ++ } ++ ++ if (data) *data = stCanvasInfo.pu8VirtAddr; ++ if (width) *width = (int)stCanvasInfo.stSize.u32Width; ++ if (height) *height = (int)stCanvasInfo.stSize.u32Height; ++ if (format) *format = (int)stCanvasInfo.enPixelFormat; ++ ++ return s32Ret; ++} ++ ++int mmf_region_update_canvas(int ch) ++{ ++ CVI_S32 s32Ret; ++ ++ if (ch < 0 || ch >= MMF_RGN_MAX_NUM) { ++ printf("Handle ch is illegal %d!\n", ch); ++ return CVI_FAILURE; ++ } ++ ++ if (!priv.rgn_is_init[ch]) { ++ return 0; ++ } ++ ++ if (!priv.rgn_is_bind[ch]) { ++ return 0; ++ } ++ ++ s32Ret = CVI_RGN_UpdateCanvas(ch); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("CVI_RGN_UpdateCanvas failed with %#x!\n", s32Ret); ++ return CVI_FAILURE; ++ } ++ return s32Ret; ++} ++ ++#ifndef KVM_MMF ++ ++static int mmf_region_frame_push2(int ch, void *frame_info) ++{ ++ void *data; ++ int len = 0; ++ VIDEO_FRAME_INFO_S *frame = (VIDEO_FRAME_INFO_S *)frame_info; ++ ++ if (!frame) { ++ return CVI_FAILURE; ++ } ++ ++ data = frame->stVFrame.pu8VirAddr[0]; ++ ++ if (frame->stVFrame.pu8VirAddr[2] == (CVI_U8 *)frame->stVFrame.pu8VirAddr[1] + frame->stVFrame.u32Length[1]) { ++ len += frame->stVFrame.u32Length[2]; ++ } ++ if (frame->stVFrame.pu8VirAddr[1] == (CVI_U8 *)frame->stVFrame.pu8VirAddr[0] + frame->stVFrame.u32Length[0]) { ++ len += frame->stVFrame.u32Length[1]; ++ } ++ if (frame->stVFrame.pu8VirAddr[0]) { ++ len += frame->stVFrame.u32Length[0]; ++ } ++ ++ if (!data || !len) { ++ return CVI_FAILURE; ++ } ++ ++ return mmf_region_frame_push(ch, data, len); ++} ++ ++#endif // !KVM_MMF ++ ++int mmf_region_frame_push(int ch, void *data, int len) ++{ ++ CVI_S32 s32Ret; ++ RGN_CANVAS_INFO_S stCanvasInfo; ++ ++ if (ch < 0 || ch >= MMF_RGN_MAX_NUM) { ++ printf("Handle ch is illegal %d!\n", ch); ++ return CVI_FAILURE; ++ } ++ ++ if (!priv.rgn_is_init[ch]) { ++ return 0; ++ } ++ ++ if (!priv.rgn_is_bind[ch]) { ++ return 0; ++ } ++ ++ s32Ret = CVI_RGN_GetCanvasInfo(ch, &stCanvasInfo); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("CVI_RGN_GetCanvasInfo failed with %#x!\n", s32Ret); ++ return CVI_FAILURE; ++ } ++ ++ if (stCanvasInfo.enPixelFormat == PIXEL_FORMAT_ARGB_8888) { ++ if (!data || (CVI_U32)len != stCanvasInfo.stSize.u32Width * stCanvasInfo.stSize.u32Height * 4) { ++ printf("Param is error!\r\n"); ++ return CVI_FAILURE; ++ } ++ memcpy(stCanvasInfo.pu8VirtAddr, data, len); ++ } else { ++ printf("Not support format!\r\n"); ++ return CVI_FAILURE; ++ } ++ ++ s32Ret = CVI_RGN_UpdateCanvas(ch); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("CVI_RGN_UpdateCanvas failed with %#x!\n", s32Ret); ++ return CVI_FAILURE; ++ } ++ return s32Ret; ++} ++ ++#ifndef KVM_MMF ++static int mmf_invert_codec_to_maix(PAYLOAD_TYPE_E mmf_codec) { ++ switch (mmf_codec) { ++ case PT_JPEG: ++ return 0; ++ case PT_H265: ++ return 1; ++ case PT_H264: ++ return 2; ++ case PT_MJPEG: ++ return 4; ++ default: ++ return 0xFF; ++ } ++} ++#endif ++ ++static PAYLOAD_TYPE_E mmf_invert_codec_to_mmf(int maix_codec) { ++ switch (maix_codec) { ++ case 0: ++ return PT_JPEG; ++ case 1: ++ return PT_H265; ++ case 2: ++ return PT_H264; ++ case 3: ++ return PT_JPEG; ++ case 4: ++ return PT_MJPEG; ++ default: ++ return PT_BUTT; ++ } ++} ++ ++static CVI_S32 _mmf_venc_vpss_init(int ch, mmf_venc_cfg_t *cfg) ++{ ++ CVI_S32 s32Ret = CVI_SUCCESS; ++ ++ priv.enc_chn_vpss[ch] = VPSS_INVALID_GRP; ++ switch (cfg->fmt) { ++ case PIXEL_FORMAT_RGB_888: ++ { ++ VPSS_GRP out_grp = CVI_VPSS_GetAvailableGrp(); ++ ++ s32Ret = _mmf_vpss_init(out_grp, ch, (SIZE_S){(CVI_U32)cfg->w, (CVI_U32)cfg->h}, (SIZE_S){(CVI_U32)cfg->w, (CVI_U32)cfg->h}, (PIXEL_FORMAT_E)cfg->fmt, PIXEL_FORMAT_YUV_PLANAR_420, cfg->output_fps, 0, CVI_FALSE, CVI_FALSE, 0); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("VPSS init failed with %d\n", s32Ret); ++ return s32Ret; ++ } ++ ++ s32Ret = SAMPLE_COMM_VPSS_Bind_VENC(out_grp, ch, ch); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("VPSS bind VENC failed with %#x\n", s32Ret); ++ _mmf_vpss_deinit(out_grp, ch); ++ return s32Ret; ++ } ++ ++ priv.enc_chn_vpss[ch] = out_grp; ++ break; ++ } ++ case PIXEL_FORMAT_NV21: ++ break; ++ default: ++ printf("unknown format!\n"); ++ s32Ret = CVI_FAILURE; ++ return s32Ret; ++ } ++ ++ return s32Ret; ++} ++ ++static CVI_S32 _mmf_venc_vpss_deinit(int ch) ++{ ++ CVI_S32 s32Ret = CVI_SUCCESS; ++ ++ if (priv.enc_chn_vpss[ch] != VPSS_INVALID_GRP) { ++ VPSS_GRP out_grp = priv.enc_chn_vpss[ch]; ++ ++ s32Ret = SAMPLE_COMM_VPSS_UnBind_VENC(out_grp, ch, ch); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("VPSS unbind VENC failed with %d\n", s32Ret); ++ } ++ ++ s32Ret = _mmf_vpss_deinit(out_grp, ch); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("VPSS deinit failed with %d\n", s32Ret); ++ } ++ ++ priv.enc_chn_vpss[ch] = VPSS_INVALID_GRP; ++ } ++ ++ return s32Ret; ++} ++ ++static int _mmf_enc_jpg_init(int ch, mmf_venc_cfg_t *cfg) ++{ ++ if (ch < 0 || ch >= MMF_ENC_MAX_CHN) { ++ return -1; ++ } ++ if (priv.enc_chn_is_init[ch]) { ++ return 0; ++ } ++ ++ if ((int8_t)cfg->jpg_quality < 50) { ++ printf("quality range is (50, 100]\n"); ++ return -1; ++ } ++ ++ if ((cfg->fmt == PIXEL_FORMAT_RGB_888 && cfg->w * cfg->h * 3 > 640 * 480 * 3) ++ || (cfg->fmt == PIXEL_FORMAT_NV21 && cfg->w * cfg->h * 3 / 2 > 2560 * 1440 * 3 / 2)) { ++ printf("image size is too large, for NV21, maximum resolution 2560x1440, for RGB888, maximum resolution 640x480!\n"); ++ return -1; ++ } ++ ++ CVI_S32 s32Ret = CVI_SUCCESS; ++ ++ VENC_CHN_ATTR_S stVencChnAttr; ++ memset(&stVencChnAttr, 0, sizeof(VENC_CHN_ATTR_S)); ++ stVencChnAttr.stVencAttr.enType = PT_JPEG; ++ stVencChnAttr.stVencAttr.u32MaxPicWidth = cfg->w; ++ stVencChnAttr.stVencAttr.u32MaxPicHeight = cfg->h; ++ stVencChnAttr.stVencAttr.u32PicWidth = cfg->w; ++ stVencChnAttr.stVencAttr.u32PicHeight = cfg->h; ++ stVencChnAttr.stVencAttr.bEsBufQueueEn = CVI_FALSE; ++ stVencChnAttr.stVencAttr.bIsoSendFrmEn = CVI_FALSE; ++ stVencChnAttr.stVencAttr.bByFrame = 1; ++ stVencChnAttr.stRcAttr.enRcMode = VENC_RC_MODE_MJPEGFIXQP; ++ ++ s32Ret = CVI_VENC_CreateChn(ch, &stVencChnAttr); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("CVI_VENC_CreateChn [%d] failed with %#x\n", ch, s32Ret); ++ return s32Ret; ++ } ++ ++ s32Ret = CVI_VENC_ResetChn(ch); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("CVI_VENC_ResetChn [%d] failed with %#x\n", ch, s32Ret); ++ return s32Ret; ++ } ++ ++ s32Ret = CVI_VENC_DestroyChn(ch); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("CVI_VENC_DestoryChn [%d] failed with %#x\n", ch, s32Ret); ++ } ++ ++ s32Ret = CVI_VENC_CreateChn(ch, &stVencChnAttr); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("CVI_VENC_CreateChn [%d] failed with %#x\n", ch, s32Ret); ++ return s32Ret; ++ } ++ ++ VENC_JPEG_PARAM_S stJpegParam; ++ memset(&stJpegParam, 0, sizeof(VENC_JPEG_PARAM_S)); ++ s32Ret = CVI_VENC_GetJpegParam(ch, &stJpegParam); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("CVI_VENC_GetJpegParam failed with %#x\n", s32Ret); ++ goto out_chn; ++ } ++ stJpegParam.u32Qfactor = (cfg->jpg_quality <= 50) ? 51 : (cfg->jpg_quality >= 100) ? 99 : cfg->jpg_quality; ++ s32Ret = CVI_VENC_SetJpegParam(ch, &stJpegParam); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("CVI_VENC_SetJpegParam failed with %#x\n", s32Ret); ++ goto out_chn; ++ } ++ ++ s32Ret = _mmf_venc_vpss_init(ch, cfg); ++ if (s32Ret != CVI_SUCCESS) { ++ goto out_chn; ++ } ++ ++ VENC_RECV_PIC_PARAM_S stRecvParam; ++ stRecvParam.s32RecvPicNum = -1; ++ s32Ret = CVI_VENC_StartRecvFrame(ch, &stRecvParam); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("CVI_VENC_StartRecvFrame failed with %#x\n", s32Ret); ++ s32Ret = CVI_FAILURE; ++ goto out_vpss; ++ } ++ ++ if (priv.enc_chn_frame[ch]) { ++ _mmf_free_frame(priv.enc_chn_frame[ch]); ++ priv.enc_chn_frame[ch] = NULL; ++ } ++ ++ priv.enc_chn_type[ch] = PT_JPEG; ++ priv.enc_chn_vb_id[ch] = priv.vb_enc_jpeg_id; ++ ++ memcpy(&priv.enc_chn_cfg[ch], cfg, sizeof(priv.enc_chn_cfg[ch])); ++ priv.enc_chn_cfg[ch].w = cfg->w; ++ priv.enc_chn_cfg[ch].h = cfg->h; ++ priv.enc_chn_cfg[ch].fmt = cfg->fmt; ++ priv.enc_chn_cfg[ch].jpg_quality = cfg->jpg_quality; ++ priv.enc_chn_is_init[ch] = 1; ++ priv.enc_chn_running[ch] = 0; ++ ++ return s32Ret; ++ ++out_vpss: ++ _mmf_venc_vpss_deinit(ch); ++out_chn: ++ CVI_VENC_DestroyChn(ch); ++ return s32Ret; ++} ++ ++int mmf_enc_jpg_init(int ch, int w, int h, int format, int quality) ++{ ++ mmf_venc_cfg_t cfg = { ++ .type = 4, //1, h265, 2, h264, 3, mjpeg, 4, jpeg ++ .w = w, ++ .h = h, ++ .fmt = format, ++ .jpg_quality = (uint8_t)quality, ++ .gop = 0, // unused ++ .intput_fps = 30, ++ .output_fps = 30, ++ .bitrate = 0, // unused ++ }; ++ ++ return _mmf_enc_jpg_init(ch, &cfg); ++} ++ ++int mmf_enc_jpg_deinit(int ch) ++{ ++ return mmf_venc_deinit(ch); ++} ++ ++int mmf_enc_jpg_push_with_quality(int ch, uint8_t *data, int w, int h, int format, int quality) ++{ ++ CVI_S32 s32Ret = CVI_SUCCESS; ++ if (ch < 0 || ch >= MMF_ENC_MAX_CHN) { ++ return -1; ++ } ++ if (!priv.enc_chn_is_init[ch]) { ++ s32Ret = mmf_enc_jpg_init(ch, w, h, format, quality); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("mmf_enc_jpg_init failed with %d\n", s32Ret); ++ return s32Ret; ++ } ++ } ++ ++ return _mmf_venc_push(ch, data, w, h, format, quality); ++} ++ ++int mmf_enc_jpg_push(int ch, uint8_t *data, int w, int h, int format) ++{ ++ if (ch < 0 || ch >= MMF_ENC_MAX_CHN) { ++ return -1; ++ } ++ if (!priv.enc_chn_cfg[ch].jpg_quality) { ++ priv.enc_chn_cfg[ch].jpg_quality = 80; ++ } ++ ++ return mmf_enc_jpg_push_with_quality(ch, data, w,h, format, priv.enc_chn_cfg[ch].jpg_quality); ++} ++ ++int mmf_enc_jpg_pop(int ch, uint8_t **data, int *size) ++{ ++ CVI_S32 s32Ret = mmf_venc_pop(ch, NULL); ++ if (s32Ret != CVI_SUCCESS) { ++ return s32Ret; ++ } ++ ++ if (!priv.enc_chn_stream[ch].pstPack) ++ return -1; ++ if (data) ++ *data = priv.enc_chn_stream[ch].pstPack[0].pu8Addr; ++ if (size) ++ *size = priv.enc_chn_stream[ch].pstPack[0].u32Len; ++ ++ return s32Ret; ++} ++ ++int mmf_enc_jpg_free(int ch) ++{ ++ return mmf_venc_free(ch); ++} ++ ++static int _mmf_enc_h265_init(int ch, mmf_venc_cfg_t *cfg) ++{ ++ if (ch < 0 || ch >= MMF_ENC_MAX_CHN) { ++ return -1; ++ } ++ if (priv.enc_chn_is_init[ch]) { ++ return 0; ++ } ++ ++ CVI_S32 s32Ret = CVI_SUCCESS; ++ ++ VENC_CHN_ATTR_S stVencChnAttr; ++ memset(&stVencChnAttr, 0, sizeof(VENC_CHN_ATTR_S)); ++ stVencChnAttr.stVencAttr.enType = PT_H265; ++ stVencChnAttr.stVencAttr.u32MaxPicWidth = cfg->w; ++ stVencChnAttr.stVencAttr.u32MaxPicHeight = cfg->h; ++ stVencChnAttr.stVencAttr.u32BufSize = 1024 * 1024; // 1024Kb ++ stVencChnAttr.stVencAttr.bByFrame = 1; ++ stVencChnAttr.stVencAttr.u32PicWidth = cfg->w; ++ stVencChnAttr.stVencAttr.u32PicHeight = cfg->h; ++ stVencChnAttr.stVencAttr.bEsBufQueueEn = CVI_TRUE; ++ stVencChnAttr.stVencAttr.bIsoSendFrmEn = CVI_TRUE; ++ stVencChnAttr.stGopAttr.enGopMode = VENC_GOPMODE_NORMALP; ++ stVencChnAttr.stGopAttr.stNormalP.s32IPQpDelta = 2; ++ ++ stVencChnAttr.stRcAttr.enRcMode = VENC_RC_MODE_H265CBR; ++ stVencChnAttr.stRcAttr.stH265Cbr.u32Gop = cfg->gop; ++ stVencChnAttr.stRcAttr.stH265Cbr.u32StatTime = 2; ++ stVencChnAttr.stRcAttr.stH265Cbr.u32SrcFrameRate = cfg->intput_fps; ++ stVencChnAttr.stRcAttr.stH265Cbr.fr32DstFrameRate = cfg->output_fps; ++ stVencChnAttr.stRcAttr.stH265Cbr.u32BitRate = cfg->bitrate; ++ stVencChnAttr.stRcAttr.stH265Cbr.bVariFpsEn = 0; ++ ++ s32Ret = CVI_VENC_CreateChn(ch, &stVencChnAttr); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("CVI_VENC_CreateChn [%d] failed with %d\n", ch, s32Ret); ++ return s32Ret; ++ } ++ ++ s32Ret = _mmf_venc_vpss_init(ch, cfg); ++ if (s32Ret != CVI_SUCCESS) { ++ goto out_chn; ++ } ++ ++ VENC_RECV_PIC_PARAM_S stRecvParam; ++ stRecvParam.s32RecvPicNum = -1; ++ s32Ret = CVI_VENC_StartRecvFrame(ch, &stRecvParam); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("CVI_VENC_StartRecvFrame failed with %d\n", s32Ret); ++ goto out_vpss; ++ } ++ ++ { ++ VENC_H265_TRANS_S h265Trans; ++ memset(&h265Trans, 0, sizeof(h265Trans)); ++ s32Ret = CVI_VENC_GetH265Trans(ch, &h265Trans); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("CVI_VENC_GetH265Trans failed with %d\n", s32Ret); ++ goto out_vpss; ++ } ++ h265Trans.cb_qp_offset = 0; ++ h265Trans.cr_qp_offset = 0; ++ s32Ret = CVI_VENC_SetH265Trans(ch, &h265Trans); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("CVI_VENC_SetH265Trans failed with %d\n", s32Ret); ++ goto out_vpss; ++ } ++ } ++ ++ { ++ VENC_H265_VUI_S h265Vui; ++ memset(&h265Vui, 0, sizeof(h265Vui)); ++ s32Ret = CVI_VENC_GetH265Vui(ch, &h265Vui); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("CVI_VENC_GetH265Vui failed with %d\n", s32Ret); ++ goto out_vpss; ++ } ++ ++ h265Vui.stVuiAspectRatio.aspect_ratio_info_present_flag = 0; ++ h265Vui.stVuiAspectRatio.aspect_ratio_idc = 1; ++ h265Vui.stVuiAspectRatio.overscan_info_present_flag = 0; ++ h265Vui.stVuiAspectRatio.overscan_appropriate_flag = 0; ++ h265Vui.stVuiAspectRatio.sar_width = 1; ++ h265Vui.stVuiAspectRatio.sar_height = 1; ++ h265Vui.stVuiTimeInfo.timing_info_present_flag = 1; ++ h265Vui.stVuiTimeInfo.num_units_in_tick = 1; ++ h265Vui.stVuiTimeInfo.time_scale = 30; ++ h265Vui.stVuiTimeInfo.num_ticks_poc_diff_one_minus1 = 1; ++ h265Vui.stVuiVideoSignal.video_signal_type_present_flag = 0; ++ h265Vui.stVuiVideoSignal.video_format = 5; ++ h265Vui.stVuiVideoSignal.video_full_range_flag = 0; ++ h265Vui.stVuiVideoSignal.colour_description_present_flag = 0; ++ h265Vui.stVuiVideoSignal.colour_primaries = 2; ++ h265Vui.stVuiVideoSignal.transfer_characteristics = 2; ++ h265Vui.stVuiVideoSignal.matrix_coefficients = 2; ++ h265Vui.stVuiBitstreamRestric.bitstream_restriction_flag = 0; ++ ++ // _mmf_dump_venc_h265_vui(&h265Vui); ++ ++ s32Ret = CVI_VENC_SetH265Vui(ch, &h265Vui); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("CVI_VENC_SetH265Vui failed with %d\n", s32Ret); ++ goto out_vpss; ++ } ++ } ++ ++ // rate control ++ { ++ VENC_RC_PARAM_S stRcParam; ++ s32Ret = CVI_VENC_GetRcParam(ch, &stRcParam); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("CVI_VENC_GetRcParam failed with %d\n", s32Ret); ++ goto out_vpss; ++ } ++ stRcParam.s32FirstFrameStartQp = 35; ++ stRcParam.stParamH265Cbr.u32MinIprop = 1; ++ stRcParam.stParamH265Cbr.u32MaxIprop = 10; ++ stRcParam.stParamH265Cbr.u32MaxQp = 51; ++ stRcParam.stParamH265Cbr.u32MinQp = 20; ++ stRcParam.stParamH265Cbr.u32MaxIQp = 51; ++ stRcParam.stParamH265Cbr.u32MinIQp = 20; ++ ++ // _mmf_dump_venc_rc_param(&stRcParam); ++ ++ s32Ret = CVI_VENC_SetRcParam(ch, &stRcParam); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("CVI_VENC_SetRcParam failed with %d\n", s32Ret); ++ goto out_vpss; ++ } ++ } ++ ++ // frame lost set ++ { ++ VENC_FRAMELOST_S stFL; ++ s32Ret = CVI_VENC_GetFrameLostStrategy(ch, &stFL); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("CVI_VENC_GetFrameLostStrategy failed with %d\n", s32Ret); ++ goto out_vpss; ++ } ++ stFL.enFrmLostMode = FRMLOST_PSKIP; ++ ++ // _mmf_dump_venc_framelost(&stFL); ++ ++ s32Ret = CVI_VENC_SetFrameLostStrategy(ch, &stFL); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("CVI_VENC_SetFrameLostStrategy failed with %d\n", s32Ret); ++ goto out_vpss; ++ } ++ } ++ ++ if (priv.enc_chn_frame[ch]) { ++ _mmf_free_frame(priv.enc_chn_frame[ch]); ++ priv.enc_chn_frame[ch] = NULL; ++ } ++ ++ priv.enc_chn_type[ch] = PT_H265; ++ priv.enc_chn_vb_id[ch] = priv.vb_enc_h26x_id; ++ ++ memcpy(&priv.enc_chn_cfg[ch], cfg, sizeof(priv.enc_chn_cfg[ch])); ++ priv.enc_chn_cfg[ch].w = cfg->w; ++ priv.enc_chn_cfg[ch].h = cfg->h; ++ priv.enc_chn_cfg[ch].fmt = cfg->fmt; ++ priv.enc_chn_cfg[ch].jpg_quality = cfg->jpg_quality; ++ priv.enc_chn_running[ch] = 0; ++ priv.enc_chn_is_init[ch] = 1; ++ ++ return s32Ret; ++ ++out_vpss: ++ _mmf_venc_vpss_deinit(ch); ++out_chn: ++ CVI_VENC_DestroyChn(ch); ++ return s32Ret; ++} ++ ++int mmf_enc_h265_init(int ch, int w, int h) ++{ ++ mmf_venc_cfg_t cfg = { ++ .type = 1, //1, h265, 2, h264, 3, mjpeg, 4, jpeg ++ .w = w, ++ .h = h, ++ .fmt = PIXEL_FORMAT_NV21, ++ .jpg_quality = 0, // unused ++ .gop = 50, ++ .intput_fps = 30, ++ .output_fps = 30, ++ .bitrate = 3000, ++ }; ++ ++ return _mmf_enc_h265_init(ch, &cfg); ++} ++ ++static int _mmf_enc_h264_init(int ch, mmf_venc_cfg_t *cfg) ++{ ++ if (ch < 0 || ch >= MMF_ENC_MAX_CHN) { ++ return -1; ++ } ++ if (priv.enc_chn_is_init[ch]) { ++ return 0; ++ } ++ ++ CVI_S32 s32Ret = CVI_SUCCESS; ++ ++ VENC_CHN_ATTR_S stVencChnAttr; ++ memset(&stVencChnAttr, 0, sizeof(VENC_CHN_ATTR_S)); ++ stVencChnAttr.stVencAttr.enType = PT_H264; ++ stVencChnAttr.stVencAttr.u32MaxPicWidth = cfg->w; ++ stVencChnAttr.stVencAttr.u32MaxPicHeight = cfg->h; ++ stVencChnAttr.stVencAttr.u32BufSize = 1024 * 1024; // 1024Kb ++ stVencChnAttr.stVencAttr.bByFrame = 1; ++ stVencChnAttr.stVencAttr.u32PicWidth = cfg->w; ++ stVencChnAttr.stVencAttr.u32PicHeight = cfg->h; ++ stVencChnAttr.stVencAttr.bEsBufQueueEn = CVI_TRUE; ++ stVencChnAttr.stVencAttr.bIsoSendFrmEn = CVI_TRUE; // ??? ++ stVencChnAttr.stGopAttr.enGopMode = VENC_GOPMODE_NORMALP; ++ stVencChnAttr.stGopAttr.stNormalP.s32IPQpDelta = 2; ++ ++ VENC_H264_CBR_S *pstH264Cbr = &stVencChnAttr.stRcAttr.stH264Cbr; ++ ++ stVencChnAttr.stRcAttr.enRcMode = VENC_RC_MODE_H264CBR; ++ pstH264Cbr->u32Gop = cfg->gop; ++ pstH264Cbr->u32StatTime = 2; ++ pstH264Cbr->u32SrcFrameRate = cfg->intput_fps; ++ pstH264Cbr->fr32DstFrameRate = cfg->output_fps; ++ pstH264Cbr->u32BitRate = cfg->bitrate; ++ pstH264Cbr->bVariFpsEn = 0; ++ ++ s32Ret = CVI_VENC_CreateChn(ch, &stVencChnAttr); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("CVI_VENC_CreateChn [%d] failed with %d\n", ch, s32Ret); ++ return s32Ret; ++ } ++ ++ VENC_PARAM_MOD_S stModParam; ++ CVI_VENC_GetModParam(&stModParam); ++ stModParam.stH264eModParam.enH264eVBSource = VB_SOURCE_COMMON; ++ stModParam.stH264eModParam.bSingleEsBuf = true; ++ stModParam.stH264eModParam.u32SingleEsBufSize = 1024 * 1024; ++ stModParam.stH264eModParam.u32UserDataMaxLen = 3072; ++ CVI_VENC_SetModParam(&stModParam); ++ ++ s32Ret = _mmf_venc_vpss_init(ch, cfg); ++ if (s32Ret != CVI_SUCCESS) { ++ goto out_chn; ++ } ++ ++ VENC_RECV_PIC_PARAM_S stRecvParam; ++ stRecvParam.s32RecvPicNum = -1; ++ s32Ret = CVI_VENC_StartRecvFrame(ch, &stRecvParam); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("CVI_VENC_StartRecvFrame failed with %d\n", s32Ret); ++ goto out_vpss; ++ } ++ ++ { ++ VENC_H264_TRANS_S h264Trans; ++ memset(&h264Trans, 0, sizeof(h264Trans)); ++ s32Ret = CVI_VENC_GetH264Trans(ch, &h264Trans); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("CVI_VENC_GetH264Trans failed with %d\n", s32Ret); ++ goto out_vpss; ++ } ++ ++ //h264Trans.cb_qp_offset = 0; ++ //h264Trans.cr_qp_offset = 0; ++ h264Trans.chroma_qp_index_offset = 0; ++ ++ s32Ret = CVI_VENC_SetH264Trans(ch, &h264Trans); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("CVI_VENC_SetH264Trans failed with %d\n", s32Ret); ++ goto out_vpss; ++ } ++ } ++ ++ { ++ VENC_H264_VUI_S h264Vui; ++ memset(&h264Vui, 0, sizeof(h264Vui)); ++ s32Ret = CVI_VENC_GetH264Vui(ch, &h264Vui); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("CVI_VENC_GetH264Vui failed with %d\n", s32Ret); ++ goto out_vpss; ++ } ++ ++ h264Vui.stVuiAspectRatio.aspect_ratio_info_present_flag = 0; ++ h264Vui.stVuiAspectRatio.aspect_ratio_idc = 1; ++ h264Vui.stVuiAspectRatio.overscan_info_present_flag = 0; ++ h264Vui.stVuiAspectRatio.overscan_appropriate_flag = 0; ++ h264Vui.stVuiAspectRatio.sar_width = 1; ++ h264Vui.stVuiAspectRatio.sar_height = 1; ++ h264Vui.stVuiTimeInfo.timing_info_present_flag = 1; ++ h264Vui.stVuiTimeInfo.num_units_in_tick = 1; ++ h264Vui.stVuiTimeInfo.time_scale = 30; ++ //h264Vui.stVuiTimeInfo.num_ticks_poc_diff_one_minus1 = 1; ++ h264Vui.stVuiVideoSignal.video_signal_type_present_flag = 0; ++ h264Vui.stVuiVideoSignal.video_format = 5; ++ h264Vui.stVuiVideoSignal.video_full_range_flag = 0; ++ h264Vui.stVuiVideoSignal.colour_description_present_flag = 0; ++ h264Vui.stVuiVideoSignal.colour_primaries = 2; ++ h264Vui.stVuiVideoSignal.transfer_characteristics = 2; ++ h264Vui.stVuiVideoSignal.matrix_coefficients = 2; ++ h264Vui.stVuiBitstreamRestric.bitstream_restriction_flag = 0; ++ ++ // _mmf_dump_venc_h264_vui(&h264Vui); ++ ++ s32Ret = CVI_VENC_SetH264Vui(ch, &h264Vui); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("CVI_VENC_SetH264Vui failed with %d\n", s32Ret); ++ goto out_vpss; ++ } ++ } ++ ++ // rate control ++ { ++ VENC_RC_PARAM_S stRcParam; ++ s32Ret = CVI_VENC_GetRcParam(ch, &stRcParam); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("CVI_VENC_GetRcParam failed with %d\n", s32Ret); ++ goto out_vpss; ++ } ++ stRcParam.s32FirstFrameStartQp = 35; ++ stRcParam.stParamH264Cbr.u32MinIprop = 1; ++ stRcParam.stParamH264Cbr.u32MaxIprop = 10; ++ stRcParam.stParamH264Cbr.u32MaxQp = 51; ++ stRcParam.stParamH264Cbr.u32MinQp = 20; ++ stRcParam.stParamH264Cbr.u32MaxIQp = 51; ++ stRcParam.stParamH264Cbr.u32MinIQp = 20; ++ ++ // _mmf_dump_venc_rc_param(&stRcParam); ++ ++ s32Ret = CVI_VENC_SetRcParam(ch, &stRcParam); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("CVI_VENC_SetRcParam failed with %d\n", s32Ret); ++ goto out_vpss; ++ } ++ } ++ ++ // frame lost set ++ { ++ VENC_FRAMELOST_S stFL; ++ s32Ret = CVI_VENC_GetFrameLostStrategy(ch, &stFL); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("CVI_VENC_GetFrameLostStrategy failed with %d\n", s32Ret); ++ goto out_vpss; ++ } ++ stFL.enFrmLostMode = FRMLOST_PSKIP; ++ ++ // _mmf_dump_venc_framelost(&stFL); ++ ++ s32Ret = CVI_VENC_SetFrameLostStrategy(ch, &stFL); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("CVI_VENC_SetFrameLostStrategy failed with %d\n", s32Ret); ++ goto out_vpss; ++ } ++ } ++ ++ if (priv.enc_chn_frame[ch]) { ++ _mmf_free_frame(priv.enc_chn_frame[ch]); ++ priv.enc_chn_frame[ch] = NULL; ++ } ++ ++ priv.enc_chn_type[ch] = PT_H264; ++ priv.enc_chn_vb_id[ch] = priv.vb_enc_h26x_id; ++ ++ memcpy(&priv.enc_chn_cfg[ch], cfg, sizeof(priv.enc_chn_cfg[ch])); ++ priv.enc_chn_cfg[ch].w = cfg->w; ++ priv.enc_chn_cfg[ch].h = cfg->h; ++ priv.enc_chn_cfg[ch].fmt = cfg->fmt; ++ priv.enc_chn_cfg[ch].jpg_quality = cfg->jpg_quality; ++ priv.enc_chn_running[ch] = 0; ++ priv.enc_chn_is_init[ch] = 1; ++ ++ return s32Ret; ++ ++out_vpss: ++ _mmf_venc_vpss_deinit(ch); ++out_chn: ++ CVI_VENC_DestroyChn(ch); ++ return s32Ret; ++} ++ ++#if 0 ++int mmf_enc_h264_init(int ch, int w, int h) ++{ ++ mmf_venc_cfg_t cfg = { ++ .type = 2, //1, h265, 2, h264, 3, mjpeg, 4, jpeg ++ .w = w, ++ .h = h, ++ .fmt = PIXEL_FORMAT_NV21, ++ .jpg_quality = 0, // unused ++ .gop = 50, ++ .intput_fps = 30, ++ .output_fps = 30, ++ .bitrate = 3000, ++ }; ++ ++ return _mmf_enc_h264_init(ch, &cfg); ++} ++#endif ++ ++static int mmf_venc_deinit(int ch) ++{ ++ CVI_S32 s32Ret = CVI_SUCCESS; ++ if (ch < 0 || ch >= MMF_ENC_MAX_CHN) { ++ return -1; ++ } ++ if (!priv.enc_chn_is_init[ch]) { ++ return 0; ++ } ++ ++ mmf_stream_t stream; ++ if (!mmf_venc_pop(ch, &stream)) { ++ mmf_venc_free(ch); ++ } ++ ++ _mmf_venc_vpss_deinit(ch); ++ ++ s32Ret = CVI_VENC_StopRecvFrame(ch); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("CVI_VENC_StopRecvFrame failed with %d\n", s32Ret); ++ } ++ ++ s32Ret = CVI_VENC_ResetChn(ch); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("CVI_VENC_ResetChn vechn[%d] failed with %#x!\n", ch, s32Ret); ++ } ++ ++ s32Ret = CVI_VENC_DestroyChn(ch); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("CVI_VENC_DestroyChn [%d] failed with %d\n", ch, s32Ret); ++ } ++ ++ if (priv.enc_chn_frame[ch]) { ++ _mmf_free_frame(priv.enc_chn_frame[ch]); ++ priv.enc_chn_frame[ch] = NULL; ++ } ++ ++ priv.enc_chn_cfg[ch].w = 0; ++ priv.enc_chn_cfg[ch].h = 0; ++ priv.enc_chn_cfg[ch].fmt = 0; ++ priv.enc_chn_running[ch] = 0; ++ priv.enc_chn_is_init[ch] = 0; ++ ++ return s32Ret; ++} ++ ++int mmf_venc_push2(int ch, void *frame_info) ++{ ++ int out_ch = ch; ++ CVI_S32 s32Ret = CVI_SUCCESS; ++ VIDEO_FRAME_INFO_S *frame = (VIDEO_FRAME_INFO_S *)frame_info; ++ if (ch < 0 || ch >= MMF_ENC_MAX_CHN) { ++ return -1; ++ } ++ if (priv.enc_chn_running[ch]) { ++ return s32Ret; ++ } ++ if (!frame) { ++ return -1; ++ } ++ ++ int w = frame->stVFrame.u32Width; ++ int h = frame->stVFrame.u32Height; ++ int format = frame->stVFrame.enPixelFormat; ++ int quality = priv.enc_chn_cfg[ch].jpg_quality; ++ ++ if (priv.enc_chn_cfg[ch].w != w || priv.enc_chn_cfg[ch].h != h || priv.enc_chn_cfg[ch].fmt != format || priv.enc_chn_cfg[ch].jpg_quality != quality) { ++ s32Ret = mmf_rst_venc_channel(ch, w, h, format, quality); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("mmf_rst_venc_channel failed with %d\n", s32Ret); ++ return s32Ret; ++ } ++ ++ priv.enc_chn_cfg[ch].w = w; ++ priv.enc_chn_cfg[ch].h = h; ++ priv.enc_chn_cfg[ch].fmt = format; ++ } ++ ++ if (priv.enc_chn_vpss[ch] != VPSS_INVALID_GRP) { ++ out_ch = priv.enc_chn_vpss[ch]; ++ } ++ ++ s32Ret = CVI_VENC_SendFrame(out_ch, frame, 1000); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("CVI_VENC_SendFrame failed with %d\n", s32Ret); ++ return s32Ret; ++ } ++ ++ priv.enc_chn_running[ch] = 1; ++ ++ return s32Ret; ++} ++ ++static int _mmf_venc_push(int ch, uint8_t *data, int w, int h, int format, int quality) ++{ ++ int out_ch = ch; ++ CVI_S32 s32Ret = CVI_SUCCESS; ++ if (ch < 0 || ch >= MMF_ENC_MAX_CHN) { ++ return -1; ++ } ++ if (priv.enc_chn_running[ch]) { ++ return s32Ret; ++ } ++ ++ SIZE_S stSize = {(CVI_U32)w, (CVI_U32)h}; ++ if (priv.enc_chn_frame[ch] == NULL || priv.enc_chn_cfg[ch].w != w || priv.enc_chn_cfg[ch].h != h || priv.enc_chn_cfg[ch].fmt != format || priv.enc_chn_cfg[ch].jpg_quality != quality) { ++ s32Ret = mmf_rst_venc_channel(ch, w, h, format, quality); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("mmf_rst_venc_channel failed with %d\n", s32Ret); ++ return s32Ret; ++ } ++ ++ priv.enc_chn_cfg[ch].w = w; ++ priv.enc_chn_cfg[ch].h = h; ++ priv.enc_chn_cfg[ch].fmt = format; ++ priv.enc_chn_frame[ch] = (VIDEO_FRAME_INFO_S *)_mmf_alloc_frame(priv.enc_chn_vb_id[ch], stSize, (PIXEL_FORMAT_E)format); ++ if (!priv.enc_chn_frame[ch]) { ++ printf("Alloc frame failed!\r\n"); ++ return -1; ++ } ++ } ++ ++ switch (format) { ++ case PIXEL_FORMAT_RGB_888: ++ { ++ if (priv.enc_chn_frame[ch]->stVFrame.u32Stride[0] != (CVI_U32)w * 3) { ++ for (int h0 = 0; h0 < h; h0 ++) { ++ memcpy((uint8_t *)priv.enc_chn_frame[ch]->stVFrame.pu8VirAddr[0] + priv.enc_chn_frame[ch]->stVFrame.u32Stride[0] * h0, ++ ((uint8_t *)data) + w * h0 * 3, w * 3); ++ } ++ } else { ++ memcpy(priv.enc_chn_frame[ch]->stVFrame.pu8VirAddr[0], data, w * h * 3); ++ } ++ } ++ break; ++ case PIXEL_FORMAT_NV21: ++ { ++ if (priv.enc_chn_frame[ch]->stVFrame.u32Stride[0] != (CVI_U32)w) { ++ for (int h0 = 0; h0 < h * 3 / 2; h0 ++) { ++ memcpy((uint8_t *)priv.enc_chn_frame[ch]->stVFrame.pu8VirAddr[0] + priv.enc_chn_frame[ch]->stVFrame.u32Stride[0] * h0, ++ ((uint8_t *)data) + w * h0, w); ++ } ++ } else { ++ uint32_t p0_size = w * h; ++ uint32_t p1_size = w * h / 2; ++ memcpy(priv.enc_chn_frame[ch]->stVFrame.pu8VirAddr[0], ((uint8_t *)data), p0_size); ++ memcpy(priv.enc_chn_frame[ch]->stVFrame.pu8VirAddr[1], ((uint8_t *)data) + p0_size, p1_size); ++ } ++ } ++ break; ++ default: return -1; ++ } ++ ++ if (priv.enc_chn_vpss[ch] != VPSS_INVALID_GRP) { ++ out_ch = priv.enc_chn_vpss[ch]; ++ } ++ ++ s32Ret = CVI_VENC_SendFrame(out_ch, priv.enc_chn_frame[ch], 1000); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("CVI_VENC_SendFrame failed with %d\n", s32Ret); ++ return s32Ret; ++ } ++ ++ priv.enc_chn_running[ch] = 1; ++ ++ return s32Ret; ++} ++ ++int mmf_venc_push(int ch, uint8_t *data, int w, int h, int format) ++{ ++ if (ch < 0 || ch >= MMF_ENC_MAX_CHN) { ++ return -1; ++ } ++ ++ return _mmf_venc_push(ch, data, w, h, format, priv.enc_chn_cfg[ch].jpg_quality); ++} ++ ++int mmf_venc_pop(int ch, mmf_stream_t *stream) ++{ ++ CVI_S32 s32Ret = CVI_SUCCESS; ++ if (ch < 0 || ch >= MMF_ENC_MAX_CHN) { ++ return -1; ++ } ++ if (!priv.enc_chn_running[ch]) { ++ return s32Ret; ++ } ++ ++ int fd = CVI_VENC_GetFd(ch); ++ if (fd < 0) { ++ printf("CVI_VENC_GetFd failed with %d\n", fd); ++ return -1; ++ } ++ ++ fd_set readFds; ++ struct timeval timeoutVal; ++ FD_ZERO(&readFds); ++ FD_SET(fd, &readFds); ++ timeoutVal.tv_sec = 0; ++ timeoutVal.tv_usec = 80*1000; ++ s32Ret = select(fd + 1, &readFds, NULL, NULL, &timeoutVal); ++ if (s32Ret < 0) { ++ if (errno == EINTR) { ++ printf("VencChn(%d) select failed!\n", ch); ++ return -1; ++ } ++ } else if (s32Ret == 0) { ++ printf("VencChn(%d) select timeout!\n", ch); ++ return -1; ++ } ++ ++ priv.enc_chn_stream[ch].pstPack = (VENC_PACK_S *)malloc(sizeof(VENC_PACK_S) * 8); ++ if (!priv.enc_chn_stream[ch].pstPack) { ++ printf("Malloc failed!\r\n"); ++ return -1; ++ } ++ ++ VENC_CHN_STATUS_S stStatus; ++ s32Ret = CVI_VENC_QueryStatus(ch, &stStatus); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("CVI_VENC_QueryStatus failed with %#x\n", s32Ret); ++ return s32Ret; ++ } ++ ++ if (stStatus.u32CurPacks > 0) { ++ s32Ret = CVI_VENC_GetStream(ch, &priv.enc_chn_stream[ch], 1000); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("CVI_VENC_GetStream failed with %#x\n", s32Ret); ++ free(priv.enc_chn_stream[ch].pstPack); ++ priv.enc_chn_stream[ch].pstPack = NULL; ++ return s32Ret; ++ } ++ } else { ++ printf("CVI_VENC_QueryStatus find not pack\r\n"); ++ free(priv.enc_chn_stream[ch].pstPack); ++ priv.enc_chn_stream[ch].pstPack = NULL; ++ return -1; ++ } ++ ++ if (stream) { ++ stream->count = priv.enc_chn_stream[ch].u32PackCount; ++ if (stream->count > 8) { ++ printf("pack count is too large! cnt:%d\r\n", stream->count); ++ mmf_venc_free(ch); ++ return -1; ++ } ++ for (int i = 0; i < stream->count; i++) { ++ stream->data[i] = priv.enc_chn_stream[ch].pstPack[i].pu8Addr + priv.enc_chn_stream[ch].pstPack[i].u32Offset; ++ stream->data_size[i] = priv.enc_chn_stream[ch].pstPack[i].u32Len - priv.enc_chn_stream[ch].pstPack[i].u32Offset; ++ } ++ } ++ ++ return s32Ret; ++} ++ ++int mmf_venc_free(int ch) ++{ ++ CVI_S32 s32Ret = CVI_SUCCESS; ++ if (ch < 0 || ch >= MMF_ENC_MAX_CHN) { ++ return -1; ++ } ++ if (!priv.enc_chn_running[ch]) { ++ return s32Ret; ++ } ++ ++ if (priv.enc_chn_stream[ch].pstPack) { ++ s32Ret = CVI_VENC_ReleaseStream(ch, &priv.enc_chn_stream[ch]); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("CVI_VENC_ReleaseStream failed with %#x\n", s32Ret); ++ return s32Ret; ++ } ++ ++ free(priv.enc_chn_stream[ch].pstPack); ++ priv.enc_chn_stream[ch].pstPack = NULL; ++ } ++ ++ priv.enc_chn_running[ch] = 0; ++ return s32Ret; ++} ++ ++int mmf_enc_h265_deinit(int ch) ++{ ++ return mmf_venc_deinit(ch); ++} ++ ++int mmf_enc_h265_push2(int ch, void *frame_info) ++{ ++ return mmf_venc_push2(ch, frame_info); ++} ++ ++int mmf_enc_h265_push(int ch, uint8_t *data, int w, int h, int format) ++{ ++ CVI_S32 s32Ret = CVI_SUCCESS; ++ if (ch < 0 || ch >= MMF_ENC_MAX_CHN) { ++ return -1; ++ } ++ if (!priv.enc_chn_is_init[ch]) { ++ s32Ret = mmf_enc_h265_init(ch, w, h); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("mmf_enc_h265_init failed with %d\n", s32Ret); ++ return s32Ret; ++ } ++ } ++ ++ return _mmf_venc_push(ch, data, w, h, format, 0); ++} ++ ++int mmf_enc_h265_pop(int ch, mmf_h265_stream_t *stream) ++{ ++ return mmf_venc_pop(ch, (mmf_stream_t *)stream); ++} ++ ++#ifdef __cplusplus ++int mmf_enc_h265_pop(int ch, mmf_stream_t *stream) ++{ ++ return mmf_venc_pop(ch, stream); ++} ++#endif ++ ++int mmf_enc_h265_free(int ch) ++{ ++ return mmf_venc_free(ch); ++} ++ ++int mmf_venc_unused_channel(void) { ++ for (int i = 0; i < MMF_ENC_MAX_CHN; i++) { ++ if (!priv.enc_chn_is_init[i]) { ++ return i; ++ } ++ } ++ return -1; ++} ++ ++int mmf_venc_is_used(int ch) ++{ ++ if (ch < 0 || ch >= MMF_ENC_MAX_CHN) { ++ return -1; ++ } ++ ++ return priv.enc_chn_running[ch]; ++} ++ ++int mmf_venc_get_cfg(int ch, mmf_venc_cfg_t *cfg) ++{ ++ if (ch < 0 || ch >= MMF_ENC_MAX_CHN) { ++ printf("%s: channel %d is out of range.\n", __func__, ch); ++ return -1; ++ } ++ if (!priv.enc_chn_is_init[ch]) { ++ printf("%s: channel %d is not initialized.\n", __func__, ch); ++ return -1; ++ } ++ if (!cfg) { ++ printf("%s: cfg is not set.\n", __func__); ++ return -1; ++ } ++ ++ memcpy(cfg, &priv.enc_chn_cfg[ch], sizeof(priv.enc_chn_cfg[ch])); ++ ++ return 0; ++} ++ ++int mmf_add_venc_channel(int ch, mmf_venc_cfg_t *cfg) ++{ ++ if (ch < 0 || ch >= MMF_ENC_MAX_CHN) { ++ printf("%s: channel %d is out of range.\n", __func__, ch); ++ return -1; ++ } ++ if (!cfg) { ++ printf("%s: cfg is not set.\n", __func__); ++ return -1; ++ } ++ if (mmf_invert_codec_to_mmf(cfg->type) == PT_H265) ++ return _mmf_enc_h265_init(ch, cfg); ++ if (mmf_invert_codec_to_mmf(cfg->type) == PT_H264) ++ return _mmf_enc_h264_init(ch, cfg); ++ if (mmf_invert_codec_to_mmf(cfg->type) == PT_JPEG || ++ mmf_invert_codec_to_mmf(cfg->type) == PT_MJPEG) ++ return _mmf_enc_jpg_init(ch, cfg); ++ ++ printf("%s: type %d not supported.\n", __func__, cfg->type); ++ return -1; ++} ++ ++int mmf_del_venc_channel(int ch) ++{ ++ return mmf_venc_deinit(ch); ++} ++ ++int mmf_del_venc_channel_all() ++{ ++ for (int i = 0; i < MMF_ENC_MAX_CHN; i++) ++ mmf_del_venc_channel(i); ++ ++ return 0; ++} ++ ++static int mmf_rst_venc_channel(int ch, int w, int h, int format, int quality) ++{ ++ mmf_venc_cfg_t cfg; ++ ++ if (ch < 0 || ch >= MMF_ENC_MAX_CHN) { ++ printf("%s: channel %d is out of range.\n", __func__, ch); ++ return -1; ++ } ++ if (!priv.enc_chn_is_init[ch]) { ++ printf("%s: channel %d is not initialized.\n", __func__, ch); ++ return -1; ++ } ++ ++ memcpy(&cfg, &priv.enc_chn_cfg[ch], sizeof(cfg)); ++ mmf_del_venc_channel(ch); ++ cfg.w = w; ++ cfg.h = h; ++ cfg.fmt = format; ++ cfg.jpg_quality = quality; ++ ++ return mmf_add_venc_channel(ch, &cfg); ++} ++ ++#ifndef KVM_MMF ++ ++static int _mmf_vdec_init(int ch, int format_out, VDEC_CHN_ATTR_S *chn_attr_out, SIZE_S size_in, int vb_id) ++{ ++ int format_in = PIXEL_FORMAT_YUV_PLANAR_444; //PIXEL_FORMAT_YUV_PLANAR_420; ++ CVI_U32 w_in = size_in.u32Width; ++ CVI_U32 h_in = size_in.u32Height; ++ CVI_U32 w_out = chn_attr_out->u32PicWidth; ++ CVI_U32 h_out = chn_attr_out->u32PicHeight; ++ int fps_out = 30; ++ ++ if (ch < 0 || ch >= MMF_DEC_MAX_CHN) { ++ return -1; ++ } ++ if (priv.dec_chn_is_init[ch]) ++ return 0; ++ ++ if ((format_out == PIXEL_FORMAT_RGB_888 && w_out * h_out * 3 > 640 * 480 * 3) ++ || (format_out == PIXEL_FORMAT_NV21 && w_out * h_out * 3 / 2 > 2560 * 1440 * 3 / 2)) { ++ printf("image size is too large, for NV21, maximum resolution 2560x1440, for RGB888, maximum resolution 640x480!\n"); ++ return -1; ++ } ++ ++ CVI_S32 s32Ret = CVI_SUCCESS; ++ VDEC_CHN_ATTR_S *chn_attr = (VDEC_CHN_ATTR_S *)malloc(sizeof(VDEC_CHN_ATTR_S)); ++ if (!chn_attr) { ++ return -1; ++ } ++ memcpy(chn_attr, chn_attr_out, sizeof(VDEC_CHN_ATTR_S)); ++ chn_attr->u32PicWidth = w_in; ++ chn_attr->u32PicHeight = h_in; ++ chn_attr->u32FrameBufCnt = 1; ++ chn_attr->u32FrameBufSize = VDEC_GetPicBufferSize( ++ chn_attr->enType, w_in, h_in, ++ (PIXEL_FORMAT_E)format_in, DATA_BITWIDTH_8, COMPRESS_MODE_NONE); ++ chn_attr->u32StreamBufSize = w_in * h_in; //ALIGN(w * h, 0x4000); ++ ++ s32Ret = CVI_VDEC_CreateChn(ch, chn_attr); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("CVI_VDEC_CreateChn [%d] failed with %#x\n", ch, s32Ret); ++ goto out_chn_attr; ++ } ++ ++ s32Ret = CVI_VDEC_ResetChn(ch); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("CVI_VDEC_ResetChn [%d] failed with %#x\n", ch, s32Ret); ++ goto out_chn_attr; ++ } ++ ++ s32Ret = CVI_VDEC_DestroyChn(ch); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("CVI_VDEC_DestoryChn [%d] failed with %#x\n", ch, s32Ret); ++ } ++ ++ s32Ret = CVI_VDEC_CreateChn(ch, chn_attr); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("CVI_VDEC_CreateChn [%d] failed with %#x\n", ch, s32Ret); ++ goto out_chn_attr; ++ } ++ ++#if 0 ++ VDEC_MOD_PARAM_S stModParam; ++ CVI_VDEC_GetModParam(&stModParam); ++ stModParam.enVdecVBSource = VB_SOURCE_COMMON; ++ CVI_VDEC_SetModParam(&stModParam); ++#endif ++ ++ priv.dec_chn_vpss[ch] = VPSS_INVALID_GRP; ++ ++ switch (format_out) { ++ case PIXEL_FORMAT_RGB_888: ++ //fallthrough; ++ case PIXEL_FORMAT_NV21: ++ { ++ VPSS_GRP out_grp = CVI_VPSS_GetAvailableGrp(); ++ ++ if (out_grp == VPSS_INVALID_GRP) { ++ printf("VPSS get group failed\n"); ++ CVI_VDEC_DestroyChn(ch); ++ s32Ret = CVI_FAILURE; ++ goto out_chn_attr; ++ } ++ ++ s32Ret = _mmf_vpss_init(out_grp, ch, (SIZE_S){w_in, h_in}, (SIZE_S){w_out, h_out}, (PIXEL_FORMAT_E)format_in, (PIXEL_FORMAT_E)format_out, fps_out, 0, CVI_FALSE, CVI_FALSE, 0); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("VPSS init failed with %d\n", s32Ret); ++ CVI_VDEC_DestroyChn(ch); ++ goto out_chn_attr; ++ } ++ ++ s32Ret = SAMPLE_COMM_VDEC_Bind_VPSS(ch, out_grp); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("VPSS bind VDEC failed with %#x\n", s32Ret); ++ _mmf_vpss_deinit(out_grp, ch); ++ CVI_VDEC_StopRecvStream(ch); ++ CVI_VDEC_DestroyChn(ch); ++ goto out_chn_attr; ++ } ++ ++ priv.dec_chn_vpss[ch] = out_grp; ++ break; ++ } ++ case PIXEL_FORMAT_YUV_PLANAR_420: ++ case PIXEL_FORMAT_YUV_PLANAR_444: ++ break; ++ default: ++ printf("unknown format %d (want %d)!\n", format_out, PIXEL_FORMAT_NV21); ++ CVI_VDEC_StopRecvStream(ch); ++ CVI_VDEC_DestroyChn(ch); ++ s32Ret = CVI_FAILURE; ++ goto out_chn_attr; ++ } ++ ++ VDEC_CHN_PARAM_S stChnParam; ++ s32Ret = CVI_VDEC_GetChnParam(ch, &stChnParam); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("CVI_VDEC_GetChnParam failed with %#x\n", s32Ret); ++ s32Ret = CVI_FAILURE; ++ goto out_vpss; ++ } ++ ++ stChnParam.enPixelFormat = (PIXEL_FORMAT_E)format_in; //(PIXEL_FORMAT_E)format_out; ++ stChnParam.u32DisplayFrameNum = chn_attr->u32FrameBufCnt - 1; ++ ++ s32Ret = CVI_VDEC_SetChnParam(ch, &stChnParam); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("CVI_VDEC_SetChnParam failed with %#x\n", s32Ret); ++ s32Ret = CVI_FAILURE; ++ goto out_vpss; ++ } ++ ++ s32Ret = CVI_VDEC_StartRecvStream(ch); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("CVI_VDEC_StartRecvStream failed with %#x\n", s32Ret); ++ s32Ret = CVI_FAILURE; ++ goto out_vpss; ++ } ++ ++ priv.dec_chn_type[ch] = chn_attr->enType; ++ priv.dec_chn_vb_id[ch] = vb_id; ++ ++ priv.dec_chn_size_in[ch] = (SIZE_S){w_in, h_in}; ++ priv.dec_chn_cfg[ch].type = mmf_invert_codec_to_maix(priv.dec_chn_type[ch]); ++ priv.dec_chn_cfg[ch].w = w_out; ++ priv.dec_chn_cfg[ch].h = h_out; ++ priv.dec_chn_cfg[ch].fmt = format_out; ++ priv.dec_chn_cfg[ch].buffer_num = chn_attr->u32FrameBufCnt; ++ priv.dec_chn_is_init[ch] = 1; ++ priv.dec_chn_running[ch] = 0; ++ ++ goto out_chn_attr; ++ ++out_vpss: ++ if (priv.dec_chn_vpss[ch] != VPSS_INVALID_GRP) ++ { ++ VPSS_GRP out_grp = priv.dec_chn_vpss[ch]; ++ SAMPLE_COMM_VDEC_UnBind_VPSS(ch, out_grp); ++ _mmf_vpss_deinit(out_grp, ch); ++ priv.dec_chn_vpss[ch] = VPSS_INVALID_GRP; ++ } ++out_chn_attr: ++ free(chn_attr); ++ return s32Ret; ++} ++ ++#if 0 ++int mmf_dec_jpg_init(int ch, int w, int h, int format) ++{ ++ mmf_vdec_cfg_t cfg = { ++ .type = 4, //1, h265, 2, h264, 3, mjpeg, 4, jpeg ++ .w = w, ++ .h = h, ++ .fmt = format, ++ .buffer_num = 1, ++ }; ++ ++ return mmf_add_vdec_channel(ch, &cfg); ++} ++ ++int mmf_dec_jpg_deinit(int ch) ++{ ++ return mmf_vdec_deinit(ch); ++} ++#endif ++ ++static int _mmf_dec_jpg_get_frame_info(uint8_t *data, uint32_t size, uint32_t *width, uint32_t *height, int *format) ++{ ++ uint8_t *j_ptr = data; ++ uint8_t jpeg_b = 0, jpeg_c = 0; ++ uint32_t jpeg_w = 0, jpeg_h = 0; ++ ++ if (data == NULL || size < 1024 || width == NULL || height == NULL || format == NULL) { ++ printf("invalid param\n"); ++ return -1; ++ } ++ ++ // Start of Image (SoI) marker and Application x (APPx) segment ++ if (j_ptr[0] == 0xFF && j_ptr[1] == 0xD8 && ++ j_ptr[2] == 0xFF && (j_ptr[3] & 0xF0) == 0xE0) { ++ j_ptr += 2; ++ while (j_ptr < data + 1024 - 2 - 8) { ++ // segment length ++ uint32_t jm_len = (j_ptr[2] << 8) | j_ptr[3]; ++ // Start of Frame (SoF) segment ++ if (j_ptr[0] == 0xFF && j_ptr[1] == 0xC0 && ++ j_ptr[2] == 0x00 && j_ptr[3] >= 0x08 && j_ptr[3] < 0x12) { ++ // bits per sample ++ jpeg_b = j_ptr[4]; ++ // image height ++ jpeg_h = (j_ptr[5] << 8) | j_ptr[6]; ++ // image width ++ jpeg_w = (j_ptr[7] << 8) | j_ptr[8]; ++ // component count ++ jpeg_c = j_ptr[9]; ++ break; ++ } ++ j_ptr += 2; ++ j_ptr += jm_len; ++ } ++ } ++ ++ if (jpeg_w && jpeg_h && jpeg_b && jpeg_c) { ++#ifdef DEBUG_EN ++ printf("%s: %dx%d %d bps %d components\n", __func__, jpeg_w, jpeg_h, jpeg_b, jpeg_c); ++#endif ++ *width = jpeg_w; ++ *height = jpeg_h; ++ } ++ ++ return 0; ++} ++ ++#if 0 ++int mmf_dec_h265_init(int ch, int w, int h) ++{ ++ mmf_vdec_cfg_t cfg = { ++ .type = 1, //1, h265, 2, h264, 3, mjpeg, 4, jpeg ++ .w = w, ++ .h = h, ++ .fmt = PIXEL_FORMAT_NV21, ++ .buffer_num = 1, ++ }; ++ ++ return mmf_add_vdec_channel(ch, &cfg); ++} ++#endif ++ ++#if 0 ++int mmf_dec_h264_init(int ch, int w, int h) ++{ ++ mmf_vdec_cfg_t cfg = { ++ .type = 2, //1, h265, 2, h264, 3, mjpeg, 4, jpeg ++ .w = w, ++ .h = h, ++ .fmt = PIXEL_FORMAT_NV21, ++ .buffer_num = 1, ++ }; ++ ++ return mmf_add_vdec_channel(ch, &cfg); ++} ++#endif ++ ++static int mmf_vdec_deinit(int ch) ++{ ++ CVI_S32 s32Ret = CVI_SUCCESS; ++ if (ch < 0 || ch >= MMF_DEC_MAX_CHN) { ++ return -1; ++ } ++ if (!priv.dec_chn_is_init[ch]) { ++ return 0; ++ } ++ ++#if 0 ++ VIDEO_FRAME_INFO_S frame; ++ if (!mmf_vdec_pop(ch, &frame)) { ++ mmf_vdec_free(ch); ++ } ++#endif ++ ++ if (priv.dec_chn_vpss[ch] != VPSS_INVALID_GRP) { ++ VPSS_GRP out_grp = priv.dec_chn_vpss[ch]; ++ ++ s32Ret = SAMPLE_COMM_VDEC_UnBind_VPSS(ch, out_grp); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("VPSS unbind VDEC failed with %d\n", s32Ret); ++ } ++ ++ s32Ret = _mmf_vpss_deinit(out_grp, ch); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("VPSS deinit failed with %d\n", s32Ret); ++ } ++ ++ priv.dec_chn_vpss[ch] = VPSS_INVALID_GRP; ++ } ++ ++ s32Ret = CVI_VDEC_StopRecvStream(ch); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("CVI_VDEC_StopRecvStream failed with %d\n", s32Ret); ++ } ++ ++ s32Ret = CVI_VDEC_ResetChn(ch); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("CVI_VDEC_ResetChn vechn[%d] failed with %#x!\n", ch, s32Ret); ++ } ++ ++ s32Ret = CVI_VDEC_DestroyChn(ch); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("CVI_VDEC_DestroyChn [%d] failed with %d\n", ch, s32Ret); ++ } ++ ++ priv.dec_chn_size_in[ch] = (SIZE_S){0, 0}; ++ priv.dec_chn_cfg[ch].w = 0; ++ priv.dec_chn_cfg[ch].h = 0; ++ priv.dec_chn_cfg[ch].fmt = 0; ++ priv.dec_chn_cfg[ch].buffer_num = 0; ++ priv.dec_chn_running[ch] = 0; ++ priv.dec_chn_is_init[ch] = 0; ++ ++ return s32Ret; ++} ++ ++static int _mmf_vdec_push(int ch, VDEC_STREAM_S *stStream) ++{ ++ int out_ch = ch; ++ CVI_S32 s32Ret = CVI_SUCCESS; ++ if (ch < 0 || ch >= MMF_DEC_MAX_CHN) { ++ return -1; ++ } ++ if (priv.dec_chn_running[ch]) { ++ return s32Ret; ++ } ++ ++ uint32_t stream_w = priv.dec_chn_size_in[ch].u32Width; ++ uint32_t stream_h = priv.dec_chn_size_in[ch].u32Height; ++ int stream_fmt = 0; ++ if (priv.dec_chn_type[ch] == PT_JPEG) { ++ _mmf_dec_jpg_get_frame_info(stStream->pu8Addr, stStream->u32Len, &stream_w, &stream_h, &stream_fmt); ++ } ++ if (stream_w != priv.dec_chn_size_in[ch].u32Width || stream_h != priv.dec_chn_size_in[ch].u32Height) ++ { ++ s32Ret = mmf_rst_vdec_channel(ch, &priv.dec_chn_cfg[ch], (SIZE_S){stream_w, stream_h}); ++ if (s32Ret != CVI_SUCCESS) { ++ return s32Ret; ++ } ++ } ++ ++ s32Ret = CVI_VDEC_SendStream(out_ch, stStream, 1000); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("CVI_VDEC_SendStream failed with %d\n", s32Ret); ++ return s32Ret; ++ } ++ ++ if (stStream->bDisplay) ++ priv.dec_chn_running[ch] = 1; ++ ++ return s32Ret; ++} ++ ++int mmf_vdec_push(int ch, uint8_t *data, int size, uint8_t is_start, uint8_t is_end) ++{ ++ VDEC_STREAM_S *stStream; ++ UNUSED(is_start); ++ ++ if (ch < 0 || ch >= MMF_DEC_MAX_CHN) { ++ return -1; ++ } ++ if (!data && (size != 0)) { ++ return -1; ++ } ++ ++ stStream = &priv.dec_chn_stream[ch]; ++ memset(stStream, 0, sizeof(*stStream)); ++ ++ stStream->u64PTS = 0; ++ stStream->pu8Addr = data; ++ stStream->u32Len = size; ++ stStream->bEndOfFrame = (size != 0) ? CVI_TRUE : CVI_FALSE; ++ stStream->bEndOfStream = is_end ? CVI_TRUE : CVI_FALSE; ++ stStream->bDisplay = (size != 0) ? 1 : 0; ++ ++ return _mmf_vdec_push(ch, &priv.dec_chn_stream[ch]); ++} ++ ++static int _mmf_vdec_pop(int ch, VIDEO_FRAME_INFO_S *frame) ++{ ++ VPSS_GRP out_grp = 0; ++ ++ CVI_S32 s32Ret = CVI_SUCCESS; ++ if (ch < 0 || ch >= MMF_DEC_MAX_CHN) { ++ printf("invalid ch %d\n", ch); ++ return -1; ++ } ++ if (!priv.dec_chn_is_init[ch]) { ++ printf("dec ch %d not open\n", ch); ++ return -1; ++ } ++ if (!priv.dec_chn_running[ch]) { ++ return -1; ++ } ++ if (frame == NULL) { ++ printf("invalid param\n"); ++ return -1; ++ } ++ ++ int fd = CVI_VDEC_GetFd(ch); ++ if (fd < 0) { ++ printf("CVI_VDEC_GetFd failed with %d\n", fd); ++ return -1; ++ } ++ ++ fd_set readFds; ++ struct timeval timeoutVal; ++ FD_ZERO(&readFds); ++ FD_SET(fd, &readFds); ++ timeoutVal.tv_sec = 0; ++ timeoutVal.tv_usec = 80*1000; ++ s32Ret = select(fd + 1, &readFds, NULL, NULL, &timeoutVal); ++ if (s32Ret < 0) { ++ if (errno == EINTR) { ++ printf("VdecChn(%d) select failed!\n", ch); ++ return -1; ++ } ++ } else if (s32Ret == 0) { ++ printf("VdecChn(%d) select timeout!\n", ch); ++ return -1; ++ } ++ ++ if (priv.dec_chn_vpss[ch] != VPSS_INVALID_GRP) { ++ out_grp = priv.dec_chn_vpss[ch]; ++ ++ s32Ret = CVI_VPSS_GetChnFrame(out_grp, ch, frame, 1000); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("CVI_VPSS_GetChnFrame failed, grp:%d\n", out_grp); ++ return -1; ++ } ++ ++ int image_size = 0; ++ for (int b = 0; b < 3; b++) if (frame->stVFrame.u64PhyAddr[b]) ++ { ++ CVI_VOID *vir_addr; ++ CVI_U32 vir_size = frame->stVFrame.u32Length[b]; ++ vir_addr = CVI_SYS_MmapCache(frame->stVFrame.u64PhyAddr[b], vir_size); ++ CVI_SYS_IonInvalidateCache(frame->stVFrame.u64PhyAddr[b], vir_addr, vir_size); ++ frame->stVFrame.pu8VirAddr[b] = (CVI_U8 *)vir_addr; ++ image_size += vir_size; ++ } ++ ++ // printf("width: %d, height: %d, total_buf_length: %d, phy:%#lx vir:%p\n", ++ // frame->stVFrame.u32Width, ++ // frame->stVFrame.u32Height, image_size, ++ // frame->stVFrame.u64PhyAddr[0], vir_addr); ++ ++ } else { ++ s32Ret = CVI_VDEC_GetFrame(ch, frame, priv.dec_pop_timeout); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("CVI_VDEC_GetFrame failed\n"); ++ return -1; ++ } ++ ++ // map already done by CVI_VDEC_GetFrame ++ } ++ ++ if (s32Ret == 0) { ++ priv.dec_pst_frame[ch] = frame; ++ ++ return 0; ++ } ++ ++ return s32Ret; ++} ++ ++int mmf_vdec_pop(int ch, void **data, int *len, int *width, int *height, int *format) ++{ ++ if (ch < 0 || ch >= MMF_DEC_MAX_CHN) { ++ printf("invalid ch %d\n", ch); ++ return -1; ++ } ++ if (data == NULL || len == NULL || width == NULL || height == NULL || format == NULL) { ++ printf("invalid param\n"); ++ return -1; ++ } ++ ++ VIDEO_FRAME_INFO_S *frame = &priv.dec_chn_frame[ch]; ++ CVI_S32 s32Ret = _mmf_vdec_pop(ch, frame); ++ if (s32Ret != 0) { ++ return s32Ret; ++ } ++ ++ int image_size = frame->stVFrame.u32Length[0] ++ + frame->stVFrame.u32Length[1] ++ + frame->stVFrame.u32Length[2]; ++ ++ *data = frame->stVFrame.pu8VirAddr[0]; ++ *len = image_size; ++ *width = frame->stVFrame.u32Width; ++ *height = frame->stVFrame.u32Height; ++ *format = frame->stVFrame.enPixelFormat; ++ ++ return s32Ret; ++} ++ ++int mmf_vdec_free(int ch) ++{ ++ int out_grp = 0; ++ CVI_S32 s32Ret = CVI_SUCCESS; ++ if (ch < 0 || ch >= MMF_DEC_MAX_CHN) { ++ printf("invalid ch %d\n", ch); ++ return -1; ++ } ++ if (!priv.dec_chn_is_init[ch]) { ++ printf("dec ch %d not open\n", ch); ++ return -1; ++ } ++ if (!priv.dec_chn_running[ch]) { ++ return s32Ret; ++ } ++ ++ VIDEO_FRAME_INFO_S *frame = priv.dec_pst_frame[ch]; ++ if (!frame) ++ { ++ priv.dec_chn_running[ch] = 0; ++ return s32Ret; ++ } ++ ++ if (priv.dec_chn_vpss[ch] != VPSS_INVALID_GRP) { ++ out_grp = priv.dec_chn_vpss[ch]; ++ ++ for (int b = 0; b < 3; b++) if (frame->stVFrame.pu8VirAddr[b]) ++ { ++ CVI_VOID *vir_addr = frame->stVFrame.pu8VirAddr[b]; ++ CVI_U32 vir_size = frame->stVFrame.u32Length[b]; ++ CVI_SYS_Munmap(vir_addr, vir_size); ++ frame->stVFrame.pu8VirAddr[b] = NULL; ++ } ++ ++ s32Ret = CVI_VPSS_ReleaseChnFrame(out_grp, ch, frame); ++ } else { ++ // unmap will be done by CVI_VDEC_ReleaseFrame ++ ++ s32Ret = CVI_VDEC_ReleaseFrame(ch, frame); ++ } ++ ++ if (s32Ret != 0) { ++ printf("CVI_VDEC_ReleaseFrame failed\n"); ++ return -1; ++ } ++ ++ priv.dec_pst_frame[ch] = NULL; ++ priv.dec_chn_running[ch] = 0; ++ ++ return s32Ret; ++} ++ ++#if 0 ++int mmf_dec_h265_deinit(int ch) ++{ ++ return mmf_vdec_deinit(ch); ++} ++#endif ++ ++int mmf_vdec_unused_channel(void) { ++ for (int i = 0; i < MMF_DEC_MAX_CHN; i++) { ++ if (!priv.dec_chn_is_init[i]) { ++ return i; ++ } ++ } ++ return -1; ++} ++ ++int mmf_vdec_is_used(int ch) ++{ ++ if (ch < 0 || ch >= MMF_DEC_MAX_CHN) { ++ return -1; ++ } ++ ++ return priv.dec_chn_running[ch]; ++} ++ ++int mmf_vdec_get_cfg(int ch, mmf_vdec_cfg_t *cfg) ++{ ++ if (ch < 0 || ch >= MMF_DEC_MAX_CHN) { ++ printf("%s: channel %d is out of range.\n", __func__, ch); ++ return -1; ++ } ++ if (!priv.dec_chn_is_init[ch]) { ++ printf("%s: channel %d is not initialized.\n", __func__, ch); ++ return -1; ++ } ++ if (!cfg) { ++ printf("%s: cfg is not set.\n", __func__); ++ return -1; ++ } ++ ++ memcpy(cfg, &priv.dec_chn_cfg[ch], sizeof(priv.dec_chn_cfg[ch])); ++ ++ return 0; ++} ++ ++static int _mmf_add_vdec_channel(int ch, int format_out, VDEC_CHN_ATTR_S *chn_attr, SIZE_S size_in) ++{ ++ int vb_id = priv.vb_dec_jpeg_id; ++ ++ if (ch < 0 || ch >= MMF_DEC_MAX_CHN) { ++ printf("%s: channel %d is out of range.\n", __func__, ch); ++ return -1; ++ } ++ if (!chn_attr) { ++ printf("%s: cfg is not set.\n", __func__); ++ return -1; ++ } ++ ++ switch (chn_attr->enType) { ++ case PT_H265: ++ vb_id = priv.vb_dec_h26x_id; ++ break; ++ case PT_H264: ++ vb_id = priv.vb_dec_h26x_id; ++ break; ++ case PT_MJPEG: ++ //fallthrough; ++ case PT_JPEG: ++ vb_id = priv.vb_dec_jpeg_id; ++ break; ++ default: ++ printf("%s: type %d may not be supported.\n", __func__, chn_attr->enType); ++ //return -1; ++ break; ++ } ++ ++ return _mmf_vdec_init(ch, format_out, chn_attr, size_in, vb_id); ++} ++ ++int mmf_add_vdec_channel(int ch, mmf_vdec_cfg_t *cfg) ++{ ++ VDEC_CHN_ATTR_S vdec_chn_attr; ++ ++ if (!cfg) { ++ printf("%s: cfg is not set.\n", __func__); ++ return -1; ++ } ++ ++ memset(&vdec_chn_attr, 0, sizeof(VDEC_CHN_ATTR_S)); ++ vdec_chn_attr.enType = mmf_invert_codec_to_mmf(cfg->type); ++ vdec_chn_attr.enMode = VIDEO_MODE_FRAME; ++ vdec_chn_attr.u32PicWidth = cfg->w; ++ vdec_chn_attr.u32PicHeight = cfg->h; ++ vdec_chn_attr.u32FrameBufCnt = cfg->buffer_num; ++ vdec_chn_attr.u32FrameBufSize = VDEC_GetPicBufferSize( ++ vdec_chn_attr.enType, cfg->w, cfg->h, ++ (PIXEL_FORMAT_E)cfg->fmt, DATA_BITWIDTH_8, COMPRESS_MODE_NONE); ++ ++ return _mmf_add_vdec_channel(ch, cfg->fmt, &vdec_chn_attr, (SIZE_S){(CVI_U32)cfg->w, (CVI_U32)cfg->h}); ++} ++ ++int mmf_del_vdec_channel(int ch) ++{ ++ return mmf_vdec_deinit(ch); ++} ++ ++int mmf_del_vdec_channel_all() ++{ ++ for (int i = 0; i < MMF_DEC_MAX_CHN; i++) ++ mmf_del_vdec_channel(i); ++ ++ return 0; ++} ++ ++static int mmf_rst_vdec_channel(int ch, mmf_vdec_cfg_t *cfg, SIZE_S size_in) ++{ ++ int format_out; ++ VDEC_CHN_ATTR_S vdec_chn_attr; ++ ++ if (!cfg) { ++ printf("%s: cfg is not set.\n", __func__); ++ return -1; ++ } ++ ++ format_out = cfg->fmt; ++ memset(&vdec_chn_attr, 0, sizeof(VDEC_CHN_ATTR_S)); ++ vdec_chn_attr.enType = mmf_invert_codec_to_mmf(cfg->type); ++ vdec_chn_attr.enMode = VIDEO_MODE_FRAME; ++ vdec_chn_attr.u32PicWidth = cfg->w; ++ vdec_chn_attr.u32PicHeight = cfg->h; ++ vdec_chn_attr.u32FrameBufCnt = cfg->buffer_num; ++ vdec_chn_attr.u32FrameBufSize = VDEC_GetPicBufferSize( ++ vdec_chn_attr.enType, cfg->w, cfg->h, ++ (PIXEL_FORMAT_E)cfg->fmt, DATA_BITWIDTH_8, COMPRESS_MODE_NONE); ++ ++ if (0 != mmf_vdec_deinit(ch)) { ++ return -1; ++ } ++ ++ return _mmf_add_vdec_channel(ch, format_out, &vdec_chn_attr, size_in); ++} ++ ++#endif // !KVM_MMF ++ ++int mmf_invert_format_to_maix(int mmf_format) { ++ switch (mmf_format) { ++ case PIXEL_FORMAT_RGB_888: ++ return 0; ++ case PIXEL_FORMAT_BGR_888: ++ return 1; ++ case PIXEL_FORMAT_ARGB_8888: ++ return 3; ++ case PIXEL_FORMAT_NV21: ++ return 8; ++ default: ++ return 0xFF; ++ } ++} ++ ++int mmf_invert_format_to_mmf(int maix_format) { ++ switch (maix_format) { ++ case 0: ++ return PIXEL_FORMAT_RGB_888; ++ case 1: ++ return PIXEL_FORMAT_BGR_888; ++ case 3: ++ return PIXEL_FORMAT_ARGB_8888; ++ case 8: ++ return PIXEL_FORMAT_NV21; ++ default: ++ return -1; ++ } ++} ++ ++int mmf_vb_config_of_vi(uint32_t size, uint32_t count) ++{ ++ priv.vb_size_of_vi = size; ++ priv.vb_count_of_vi = count; ++ priv.vb_of_vi_is_config = 1; ++ return 0; ++} ++ ++#ifndef KVM_MMF ++ ++int mmf_vb_config_of_vo(uint32_t size, uint32_t count) ++{ ++ priv.vb_size_of_vo = size; ++ priv.vb_count_of_vo = count; ++ priv.vb_of_vo_is_config = 1; ++ return 0; ++} ++ ++int mmf_vb_config_of_private(uint32_t size, uint32_t count) ++{ ++ priv.vb_size_of_private = size; ++ priv.vb_count_of_private = count; ++ priv.vb_of_private_is_config = 1; ++ return 0; ++} ++ ++#endif // !KVM_MMF ++ ++int mmf_set_exp_mode(int ch, int mode) ++{ ++ ISP_EXPOSURE_ATTR_S stExpAttr; ++ ++ memset(&stExpAttr, 0, sizeof(ISP_EXPOSURE_ATTR_S)); ++ ++ CVI_ISP_GetExposureAttr(ch, &stExpAttr); ++ ++ stExpAttr.u8DebugMode = 0; ++ ++ if (mode == 0) { ++ stExpAttr.bByPass = 0; ++ stExpAttr.enOpType = OP_TYPE_AUTO; ++ stExpAttr.stManual.enExpTimeOpType = OP_TYPE_AUTO; ++ stExpAttr.stManual.enISONumOpType = OP_TYPE_AUTO; ++ printf("AE Auto!\n"); ++ } else if (mode == 1) { ++ stExpAttr.bByPass = 0; ++ stExpAttr.enOpType = OP_TYPE_MANUAL; ++ stExpAttr.stManual.enExpTimeOpType = OP_TYPE_MANUAL; ++ stExpAttr.stManual.enISONumOpType = OP_TYPE_MANUAL; ++ stExpAttr.stManual.enGainType = AE_TYPE_ISO; ++ printf("AE Manual!\n"); ++ } ++ ++ CVI_ISP_SetExposureAttr(ch, &stExpAttr); ++ ++ //usleep(100 * 1000); ++ return 0; ++} ++ ++// 0, auto; 1, manual ++int mmf_get_exp_mode(int ch) ++{ ++ ISP_EXPOSURE_ATTR_S stExpAttr; ++ memset(&stExpAttr, 0, sizeof(ISP_EXPOSURE_ATTR_S)); ++ CVI_ISP_GetExposureAttr(ch, &stExpAttr); ++ return stExpAttr.enOpType; ++} ++ ++int mmf_get_exptime(int ch, uint32_t *exptime) ++{ ++ ISP_EXP_INFO_S stExpInfo; ++ memset(&stExpInfo, 0, sizeof(ISP_EXP_INFO_S)); ++ CVI_ISP_QueryExposureInfo(ch, &stExpInfo); ++ if (exptime) { ++ *exptime = stExpInfo.u32ExpTime; ++ } ++ return 0; ++} ++ ++int mmf_set_exptime(int ch, uint32_t exptime) ++{ ++ ISP_EXPOSURE_ATTR_S stExpAttr; ++ memset(&stExpAttr, 0, sizeof(ISP_EXPOSURE_ATTR_S)); ++ CVI_ISP_GetExposureAttr(ch, &stExpAttr); ++ if (stExpAttr.enOpType == OP_TYPE_MANUAL) { ++ stExpAttr.stManual.u32ExpTime = exptime; ++ CVI_ISP_SetExposureAttr(ch, &stExpAttr); ++ //usleep(100 * 1000); ++ } else { ++ return -1; ++ } ++ ++ return 0; ++} ++ ++int mmf_get_iso_num(int ch, uint32_t *iso_num) ++{ ++ ISP_EXP_INFO_S stExpInfo; ++ memset(&stExpInfo, 0, sizeof(ISP_EXP_INFO_S)); ++ CVI_ISP_QueryExposureInfo(ch, &stExpInfo); ++ if (iso_num) { ++ *iso_num = stExpInfo.u32ISO; ++ } ++ return 0; ++} ++ ++int mmf_set_iso_num(int ch, uint32_t iso_num) ++{ ++ ISP_EXPOSURE_ATTR_S stExpAttr; ++ memset(&stExpAttr, 0, sizeof(ISP_EXPOSURE_ATTR_S)); ++ CVI_ISP_GetExposureAttr(ch, &stExpAttr); ++ if (stExpAttr.enOpType == OP_TYPE_MANUAL) { ++ stExpAttr.stManual.u32ISONum = iso_num; ++ CVI_ISP_SetExposureAttr(ch, &stExpAttr); ++ //usleep(100 * 1000); ++ } else { ++ return -1; ++ } ++ ++ return 0; ++} ++ ++int mmf_get_exptime_and_iso(int ch, uint32_t *exptime, uint32_t *iso_num) ++{ ++ ISP_EXP_INFO_S stExpInfo; ++ memset(&stExpInfo, 0, sizeof(ISP_EXP_INFO_S)); ++ CVI_ISP_QueryExposureInfo(ch, &stExpInfo); ++ ++ if (exptime) { ++ *exptime = stExpInfo.u32ExpTime; ++ } ++ ++ if (iso_num) { ++ *iso_num = stExpInfo.u32ISO; ++ } ++ return 0; ++} ++ ++int mmf_set_exptime_and_iso(int ch, uint32_t exptime, uint32_t iso_num) ++{ ++ ISP_EXPOSURE_ATTR_S stExpAttr; ++ memset(&stExpAttr, 0, sizeof(ISP_EXPOSURE_ATTR_S)); ++ CVI_ISP_GetExposureAttr(ch, &stExpAttr); ++ if (stExpAttr.enOpType == OP_TYPE_MANUAL) { ++ stExpAttr.stManual.u32ExpTime = exptime; ++ stExpAttr.stManual.u32ISONum = iso_num; ++ CVI_ISP_SetExposureAttr(ch, &stExpAttr); ++ //usleep(100 * 1000); ++ } else { ++ return -1; ++ } ++ ++ return 0; ++} ++ ++int mmf_get_sensor_id(void) ++{ ++ switch (priv.sensor_type) { ++ case GCORE_GC4653_MIPI_4M_30FPS_10BIT: return 0x4653; ++ case LONTIUM_LT6911_2M_60FPS_8BIT: return 0x6911; ++ default: return -1; ++ } ++ ++ return -1; ++} ++ ++void mmf_get_vi_hmirror(int ch, bool *en) ++{ ++ if (ch < 0 || ch >= MMF_VI_MAX_CHN) { ++ printf("invalid ch %d, must be >= 0 < %d\r\n", ch, MMF_VI_MAX_CHN); ++ return; ++ } ++ ++ if (!en) ++ return; ++ ++ *en = g_priv.vi_hmirror[ch]; ++} ++ ++void mmf_set_vi_hmirror(int ch, bool en) ++{ ++ if (ch < 0 || ch >= MMF_VI_MAX_CHN) { ++ printf("invalid ch %d, must be >= 0 < %d\r\n", ch, MMF_VI_MAX_CHN); ++ return; ++ } ++ ++ g_priv.vi_hmirror[ch] = en; ++} ++ ++void mmf_get_vi_vflip(int ch, bool *en) ++{ ++ if (ch < 0 || ch >= MMF_VI_MAX_CHN) { ++ printf("invalid ch %d, must be >= 0 < %d\r\n", ch, MMF_VI_MAX_CHN); ++ return; ++ } ++ ++ if (!en) ++ return; ++ ++ *en = g_priv.vi_vflip[ch]; ++} ++ ++void mmf_set_vi_vflip(int ch, bool en) ++{ ++ if (ch < 0 || ch >= MMF_VI_MAX_CHN) { ++ printf("invalid ch %d, must be >= 0 < %d\r\n", ch, MMF_VI_MAX_CHN); ++ return; ++ } ++ ++ g_priv.vi_vflip[ch] = en; ++} ++ ++#ifndef KVM_MMF ++ ++void mmf_get_vo_video_hmirror(int ch, bool *en) ++{ ++ if (ch < 0 || ch >= MMF_VO_VIDEO_MAX_CHN) { ++ printf("invalid ch %d, must be >= 0 < %d\r\n", ch, MMF_VO_VIDEO_MAX_CHN); ++ return; ++ } ++ ++ if (!en) ++ return; ++ ++ *en = g_priv.vo_video_hmirror[ch]; ++} ++ ++void mmf_set_vo_video_hmirror(int ch, bool en) ++{ ++ if (ch < 0 || ch >= MMF_VO_VIDEO_MAX_CHN) { ++ printf("invalid ch %d, must be >= 0 < %d\r\n", ch, MMF_VO_VIDEO_MAX_CHN); ++ return; ++ } ++ ++ g_priv.vo_video_hmirror[ch] = en; ++} ++ ++void mmf_get_vo_video_flip(int ch, bool *en) ++{ ++ if (ch < 0 || ch >= MMF_VO_VIDEO_MAX_CHN) { ++ printf("invalid ch %d, must be >= 0 < %d\r\n", ch, MMF_VO_VIDEO_MAX_CHN); ++ return; ++ } ++ ++ if (!en) ++ return; ++ ++ *en = g_priv.vo_video_vflip[ch]; ++} ++ ++void mmf_set_vo_video_flip(int ch, bool en) ++{ ++ if (ch < 0 || ch >= MMF_VO_VIDEO_MAX_CHN) { ++ printf("invalid ch %d, must be >= 0 < %d\r\n", ch, MMF_VO_VIDEO_MAX_CHN); ++ return; ++ } ++ ++ g_priv.vo_video_vflip[ch] = en; ++} ++ ++#endif // !KVM_MMF ++ ++int mmf_get_constrast(int ch, uint32_t *value) ++{ ++ if (ch < 0 || ch >= MMF_VI_MAX_CHN) { ++ printf("invalid ch %d, must be >= 0 < %d\r\n", ch, MMF_VI_MAX_CHN); ++ return -1; ++ } ++ ++ if (!value) ++ return -1; ++ ++ ISP_CSC_ATTR_S stCscAttr; ++ ++ memset(&stCscAttr, 0, sizeof(ISP_CSC_ATTR_S)); ++ ++ CVI_ISP_GetCSCAttr(ch, &stCscAttr); ++ *value = stCscAttr.Contrast; ++ ++ return 0; ++} ++ ++void mmf_set_constrast(int ch, uint32_t val) ++{ ++ if (ch < 0 || ch >= MMF_VI_MAX_CHN) { ++ printf("invalid ch %d, must be >= 0 < %d\r\n", ch, MMF_VI_MAX_CHN); ++ return; ++ } ++ ++ val = val > 0x64 ? 0x64 : val; ++ ++ ISP_CSC_ATTR_S stCscAttr; ++ ++ memset(&stCscAttr, 0, sizeof(ISP_CSC_ATTR_S)); ++ ++ CVI_ISP_GetCSCAttr(ch, &stCscAttr); ++ stCscAttr.Enable = true; ++ stCscAttr.Contrast = val; ++ CVI_ISP_SetCSCAttr(ch, &stCscAttr); ++} ++ ++int mmf_get_saturation(int ch, uint32_t *value) ++{ ++ if (ch < 0 || ch >= MMF_VI_MAX_CHN) { ++ printf("invalid ch %d, must be >= 0 < %d\r\n", ch, MMF_VI_MAX_CHN); ++ return -1; ++ } ++ ++ if (!value) ++ return -1; ++ ++ ISP_CSC_ATTR_S stCscAttr; ++ ++ memset(&stCscAttr, 0, sizeof(ISP_CSC_ATTR_S)); ++ ++ CVI_ISP_GetCSCAttr(ch, &stCscAttr); ++ *value = stCscAttr.Saturation; ++ ++ return 0; ++} ++ ++void mmf_set_saturation(int ch, uint32_t val) ++{ ++ if (ch < 0 || ch >= MMF_VI_MAX_CHN) { ++ printf("invalid ch %d, must be >= 0 < %d\r\n", ch, MMF_VI_MAX_CHN); ++ return; ++ } ++ ++ val = val > 0x64 ? 0x64 : val; ++ ++ ISP_CSC_ATTR_S stCscAttr; ++ ++ memset(&stCscAttr, 0, sizeof(ISP_CSC_ATTR_S)); ++ ++ CVI_ISP_GetCSCAttr(ch, &stCscAttr); ++ stCscAttr.Enable = true; ++ stCscAttr.Saturation = val; ++ ++ CVI_ISP_SetCSCAttr(ch, &stCscAttr); ++} ++ ++int mmf_get_luma(int ch, uint32_t *value) ++{ ++ if (ch < 0 || ch >= MMF_VI_MAX_CHN) { ++ printf("invalid ch %d, must be >= 0 < %d\r\n", ch, MMF_VI_MAX_CHN); ++ return -1; ++ } ++ ++ if (!value) ++ return -1; ++ ++ ISP_CSC_ATTR_S stCscAttr; ++ memset(&stCscAttr, 0, sizeof(ISP_CSC_ATTR_S)); ++ ++ CVI_ISP_GetCSCAttr(ch, &stCscAttr); ++ *value = stCscAttr.Luma; ++ ++ return 0; ++} ++ ++void mmf_set_luma(int ch, uint32_t val) ++{ ++ if (ch < 0 || ch >= MMF_VI_MAX_CHN) { ++ printf("invalid ch %d, must be >= 0 < %d\r\n", ch, MMF_VI_MAX_CHN); ++ return; ++ } ++ ++ val = val > 0x64 ? 0x64 : val; ++ ++ ISP_CSC_ATTR_S stCscAttr; ++ memset(&stCscAttr, 0, sizeof(ISP_CSC_ATTR_S)); ++ ++ CVI_ISP_GetCSCAttr(ch, &stCscAttr); ++ stCscAttr.Enable = true; ++ stCscAttr.Luma = val; ++ CVI_ISP_SetCSCAttr(ch, &stCscAttr); ++} ++ ++int mmf_vi_get_max_size(int *width, int *height) ++{ ++ if (!width) ++ return -1; ++ if (!height) ++ return -1; ++ ++ *width = priv.vi_max_size.u32Width; ++ *height = priv.vi_max_size.u32Height; ++ ++ return 0; ++} ++ ++void mmf_vi_set_pop_timeout(int ms) ++{ ++ priv.vi_pop_timeout = ms; ++} ++ ++int mmf_vi_channel_set_windowing(int ch, int x, int y, int w, int h) ++{ ++ return -1; ++} ++ ++int mmf_get_again(int ch, uint32_t *gain) ++{ ++ ISP_EXP_INFO_S stExpInfo; ++ memset(&stExpInfo, 0, sizeof(ISP_EXP_INFO_S)); ++ CVI_ISP_QueryExposureInfo(ch, &stExpInfo); ++ ++ if (gain) { ++ *gain = stExpInfo.u32AGain; ++ } ++ return 0; ++} ++ ++int mmf_set_again(int ch, uint32_t gain) ++{ ++ ISP_EXPOSURE_ATTR_S stExpAttr; ++ memset(&stExpAttr, 0, sizeof(ISP_EXPOSURE_ATTR_S)); ++ CVI_ISP_GetExposureAttr(ch, &stExpAttr); ++ if (stExpAttr.enOpType == OP_TYPE_MANUAL) { ++ stExpAttr.stManual.enAGainOpType = OP_TYPE_MANUAL; ++ stExpAttr.stManual.u32AGain = gain; ++ CVI_ISP_SetExposureAttr(ch, &stExpAttr); ++ //usleep(100 * 1000); ++ } else { ++ return -1; ++ } ++ ++ return 0; ++} ++ ++int mmf_get_dgain(int ch, uint32_t *gain) ++{ ++ ISP_EXP_INFO_S stExpInfo; ++ memset(&stExpInfo, 0, sizeof(ISP_EXP_INFO_S)); ++ CVI_ISP_QueryExposureInfo(ch, &stExpInfo); ++ ++ if (gain) { ++ *gain = stExpInfo.u32DGain; ++ } ++ return 0; ++} ++ ++int mmf_set_dgain(int ch, uint32_t gain) ++{ ++ ISP_EXPOSURE_ATTR_S stExpAttr; ++ memset(&stExpAttr, 0, sizeof(ISP_EXPOSURE_ATTR_S)); ++ CVI_ISP_GetExposureAttr(ch, &stExpAttr); ++ if (stExpAttr.enOpType == OP_TYPE_MANUAL) { ++ stExpAttr.stManual.enDGainOpType = OP_TYPE_MANUAL; ++ stExpAttr.stManual.u32DGain = gain; ++ CVI_ISP_SetExposureAttr(ch, &stExpAttr); ++ //usleep(100 * 1000); ++ } else { ++ return -1; ++ } ++ ++ return 0; ++} ++ ++int mmf_get_ispdgain(int ch, uint32_t *gain) ++{ ++ ISP_EXP_INFO_S stExpInfo; ++ memset(&stExpInfo, 0, sizeof(ISP_EXP_INFO_S)); ++ CVI_ISP_QueryExposureInfo(ch, &stExpInfo); ++ ++ if (gain) { ++ *gain = stExpInfo.u32ISPDGain; ++ } ++ return 0; ++} ++ ++int mmf_set_ispdgain(int ch, uint32_t gain) ++{ ++ ISP_EXPOSURE_ATTR_S stExpAttr; ++ memset(&stExpAttr, 0, sizeof(ISP_EXPOSURE_ATTR_S)); ++ CVI_ISP_GetExposureAttr(ch, &stExpAttr); ++ if (stExpAttr.enOpType == OP_TYPE_MANUAL) { ++ stExpAttr.stManual.enISPDGainOpType = OP_TYPE_MANUAL; ++ stExpAttr.stManual.u32ISPDGain = gain; ++ CVI_ISP_SetExposureAttr(ch, &stExpAttr); ++ //usleep(100 * 1000); ++ } else { ++ return -1; ++ } ++ ++ return 0; ++} ++ ++int mmf_set_wb_mode(int ch, int mode) ++{ ++ return -1; ++} ++ ++int mmf_get_wb_mode(int ch) ++{ ++ return 0; ++} ++ ++int mmf_init0(uint32_t param, ...) ++{ ++ int method = MMF_FUNC_GET_PARAM_METHOD(param); ++ int n_args = MMF_FUNC_GET_PARAM_NUM(param); ++ va_list ap; ++ ++ if ((method != 0) || (n_args < 1)) ++ return -1; ++ va_start(ap, param); ++ int reload_kmod = va_arg(ap, int); ++ va_end(ap); ++ ++ UNUSED(reload_kmod); ++ return mmf_init(); ++} ++ ++int mmf_deinit0(uint32_t param, ...) ++{ ++ int method = MMF_FUNC_GET_PARAM_METHOD(param); ++ int n_args = MMF_FUNC_GET_PARAM_NUM(param); ++ va_list ap; ++ ++ if ((method != 0) || (n_args < 1)) ++ return -1; ++ va_start(ap, param); ++ int force = va_arg(ap, int); ++ va_end(ap); ++ ++ UNUSED(force); ++ return mmf_deinit(); ++} ++ ++int mmf_vi_init0(uint32_t param, ...) ++{ ++ int method = MMF_FUNC_GET_PARAM_METHOD(param); ++ int n_args = MMF_FUNC_GET_PARAM_NUM(param); ++ va_list ap; ++ ++ if (priv.vi_is_inited) { ++ return 0; ++ } ++ ++ if ((method != 0) || (n_args < 8)) ++ return -1; ++ va_start(ap, param); ++ int width = va_arg(ap, int); ++ int height = va_arg(ap, int); ++ int vi_format = va_arg(ap, int); ++ int vpss_format = va_arg(ap, int); ++ int fps = va_arg(ap, int); ++ int pool_num = va_arg(ap, int); ++ SAMPLE_VI_CONFIG_S *vi_cfg = va_arg(ap, SAMPLE_VI_CONFIG_S*); ++ va_end(ap); ++ ++ CVI_S32 s32Ret = CVI_SUCCESS; ++ if (priv.vi_is_inited) { ++ return s32Ret; ++ } ++ ++ priv.vi_format = (PIXEL_FORMAT_E)vi_format; ++ priv.vi_size.u32Width = width; ++ priv.vi_size.u32Height = height; ++ UNUSED(pool_num); ++ UNUSED(vi_cfg); ++ return _mmf_vi_init(priv.vi_size.u32Width, priv.vi_size.u32Height, (PIXEL_FORMAT_E)vpss_format, fps); ++} ++ ++int mmf_add_vi_channel0(uint32_t param, ...) ++{ ++ int method = MMF_FUNC_GET_PARAM_METHOD(param); ++ int n_args = MMF_FUNC_GET_PARAM_NUM(param); ++ va_list ap; ++ ++ if ((method != 0) || (n_args < 10)) ++ return -1; ++ va_start(ap, param); ++ int ch = va_arg(ap, int); ++ int width = va_arg(ap, int); ++ int height = va_arg(ap, int); ++ int format = va_arg(ap, int); ++ int fps = va_arg(ap, int); ++ int depth = va_arg(ap, int); ++ int mirror = va_arg(ap, int); ++ int vflip = va_arg(ap, int); ++ int fit = va_arg(ap, int); ++ int pool_num = va_arg(ap, int); ++ va_end(ap); ++ ++ UNUSED(pool_num); ++ priv.vi_pop_timeout = 3000; ++ return _mmf_add_vi_channel(ch, width, height, format, fps, depth, mirror, vflip, fit); ++} ++ ++#ifndef KVM_MMF ++ ++int mmf_add_vo_channel0(uint32_t param, ...) ++{ ++ int method = MMF_FUNC_GET_PARAM_METHOD(param); ++ int n_args = MMF_FUNC_GET_PARAM_NUM(param); ++ va_list ap; ++ ++ if ((method != 0) || (n_args < 14)) ++ return -1; ++ va_start(ap, param); ++ int layer = va_arg(ap, int); ++ int ch = va_arg(ap, int); ++ int width = va_arg(ap, int); ++ int height = va_arg(ap, int); ++ int format_in = va_arg(ap, int); ++ int format_out = va_arg(ap, int); ++ int fps = va_arg(ap, int); ++ int depth = va_arg(ap, int); ++ int mirror = va_arg(ap, int); ++ int vflip = va_arg(ap, int); ++ int fit = va_arg(ap, int); ++ int rotate = va_arg(ap, int); ++ int pool_num_in = va_arg(ap, int); ++ int pool_num_out = va_arg(ap, int); ++ va_end(ap); ++ ++ priv.vo_rotate = rotate; ++ UNUSED(pool_num_in); ++ UNUSED(pool_num_out); ++ return _mmf_add_vo_channel(layer, ch, width, height, format_in, format_out, fps, depth, mirror, vflip, fit); ++} ++ ++#endif // !KVM_MMF ++ ++int mmf_add_region_channel0(uint32_t param, ...) ++{ ++ int method = MMF_FUNC_GET_PARAM_METHOD(param); ++ int n_args = MMF_FUNC_GET_PARAM_NUM(param); ++ va_list ap; ++ ++ if ((method != 0) || (n_args < 10)) ++ return -1; ++ va_start(ap, param); ++ int ch = va_arg(ap, int); ++ int type = va_arg(ap, int); ++ int mod_id = va_arg(ap, int); ++ int dev_id = va_arg(ap, int); ++ int chn_id = va_arg(ap, int); ++ int x = va_arg(ap, int); ++ int y = va_arg(ap, int); ++ int width = va_arg(ap, int); ++ int height = va_arg(ap, int); ++ int format = va_arg(ap, int); ++ va_end(ap); ++ ++ return mmf_add_region_channel(ch, type, mod_id, dev_id, chn_id, x, y, width, height, format); ++} ++ ++int mmf_add_venc_channel0(uint32_t param, ...) ++{ ++ int method = MMF_FUNC_GET_PARAM_METHOD(param); ++ int n_args = MMF_FUNC_GET_PARAM_NUM(param); ++ va_list ap; ++ ++ if ((method != 0) || (n_args < 2)) ++ return -1; ++ va_start(ap, param); ++ int ch = va_arg(ap, int); ++ void *cfg = va_arg(ap, void*); ++ va_end(ap); ++ ++ return mmf_add_venc_channel(ch, (mmf_venc_cfg_t*)cfg); ++} ++ ++#ifndef KVM_MMF ++ ++int mmf_add_vdec_channel0(uint32_t param, ...) ++{ ++ int method = MMF_FUNC_GET_PARAM_METHOD(param); ++ int n_args = MMF_FUNC_GET_PARAM_NUM(param); ++ int format_out = 0; ++ int pool_num = 0; ++ va_list ap; ++ ++ if ((method != 0) || (n_args < 2)) ++ return -1; ++ va_start(ap, param); ++ int ch = va_arg(ap, int); ++ if (n_args > 2) ++ format_out = va_arg(ap, int); ++ if (n_args > 3) ++ pool_num = va_arg(ap, int); ++ void *cfg = va_arg(ap, void*); ++ va_end(ap); ++ ++ UNUSED(pool_num); ++ if (!cfg) { ++ return -1; ++ } ++ if (n_args > 3) { ++ VDEC_CHN_ATTR_S *chn_attr = (VDEC_CHN_ATTR_S *)cfg; ++ return _mmf_add_vdec_channel(ch, format_out, chn_attr, (SIZE_S){chn_attr->u32PicWidth, chn_attr->u32PicHeight}); ++ } ++ return mmf_add_vdec_channel(ch, (mmf_vdec_cfg_t *)cfg); ++} ++ ++int mmf_vdec_push0(uint32_t param, ...) ++{ ++ int method = MMF_FUNC_GET_PARAM_METHOD(param); ++ int n_args = MMF_FUNC_GET_PARAM_NUM(param); ++ va_list ap; ++ ++ if ((method != 0) || (n_args < 2)) ++ return -1; ++ va_start(ap, param); ++ int ch = va_arg(ap, int); ++ void *stStream = va_arg(ap, void*); ++ va_end(ap); ++ ++ return _mmf_vdec_push(ch, (VDEC_STREAM_S *)stStream); ++} ++ ++int mmf_vdec_pop0(uint32_t param, ...) ++{ ++ int method = MMF_FUNC_GET_PARAM_METHOD(param); ++ int n_args = MMF_FUNC_GET_PARAM_NUM(param); ++ va_list ap; ++ ++ if ((method != 0) || (n_args < 2)) ++ return -1; ++ va_start(ap, param); ++ int ch = va_arg(ap, int); ++ void *frame = va_arg(ap, void*); ++ va_end(ap); ++ ++ return _mmf_vdec_pop(ch, (VIDEO_FRAME_INFO_S *)frame); ++} ++ ++#endif // !KVM_MMF +diff --git a/sample/test_mmf/rtsp_server/inc/h264-file-reader.h b/sample/test_mmf/rtsp_server/inc/h264-file-reader.h +new file mode 100644 +index 0000000..6ba3c5e +--- /dev/null ++++ b/sample/test_mmf/rtsp_server/inc/h264-file-reader.h +@@ -0,0 +1,51 @@ ++#ifndef _h264_file_reader_h_ ++#define _h264_file_reader_h_ ++ ++#include ++#include ++#include ++#include ++#include "ctypedef.h" ++ ++class H264FileReader ++{ ++public: ++ H264FileReader(const char* file); ++ ~H264FileReader(); ++ ++ bool IsOpened() const; ++ ++public: ++ const std::list > GetParameterSets() const { return m_sps; } ++ int GetDuration(int64_t& duration) const { duration = m_duration; return 0; } ++ int GetNextFrame(int64_t &dts, const uint8_t* &ptr, size_t &bytes); ++ int Seek(int64_t &dts); ++ ++private: ++ int Init(); ++ ++private: ++ struct vframe_t ++ { ++ const uint8_t* nalu; ++ int64_t time; ++ long bytes; ++ bool idr; // IDR frame ++ ++ bool operator < (const struct vframe_t &v) const ++ { ++ return time < v.time; ++ } ++ }; ++ typedef std::vector vframes_t; ++ vframes_t m_videos; ++ vframes_t::iterator m_vit; ++ ++ std::list > m_sps; ++ int64_t m_duration; ++ ++ uint8_t *m_ptr; ++ size_t m_capacity; ++}; ++ ++#endif /* !_h264_file_reader_h_ */ +diff --git a/sample/test_mmf/rtsp_server/inc/h264-file-source.h b/sample/test_mmf/rtsp_server/inc/h264-file-source.h +new file mode 100644 +index 0000000..3116286 +--- /dev/null ++++ b/sample/test_mmf/rtsp_server/inc/h264-file-source.h +@@ -0,0 +1,52 @@ ++#ifndef _h264_file_source_h_ ++#define _h264_file_source_h_ ++ ++#include "h264-file-reader.h" ++#include "media-source.h" ++#include "sys/process.h" ++#include "time64.h" ++#include "rtp.h" ++#include ++ ++class H264FileSource : public IMediaSource ++{ ++public: ++ H264FileSource(const char *file); ++ virtual ~H264FileSource(); ++ ++public: ++ virtual int Play(); ++ virtual int Pause(); ++ virtual int Seek(int64_t pos); ++ virtual int SetSpeed(double speed); ++ virtual int GetDuration(int64_t& duration) const; ++ virtual int GetSDPMedia(std::string& sdp) const; ++ virtual int GetRTPInfo(const char* uri, char *rtpinfo, size_t bytes) const; ++ virtual int SetTransport(const char* track, std::shared_ptr transport); ++ ++private: ++ static void OnRTCPEvent(void* param, const struct rtcp_msg_t* msg); ++ void OnRTCPEvent(const struct rtcp_msg_t* msg); ++ int SendRTCP(); ++ ++ static void* RTPAlloc(void* param, int bytes); ++ static void RTPFree(void* param, void *packet); ++ static int RTPPacket(void* param, const void *packet, int bytes, uint32_t timestamp, int flags); ++ ++private: ++ void* m_rtp; ++ uint32_t m_timestamp; ++ time64_t m_rtp_clock; ++ time64_t m_rtcp_clock; ++ H264FileReader m_reader; ++ std::shared_ptr m_transport; ++ ++ int m_status; ++ int64_t m_pos; ++ double m_speed; ++ ++ void *m_rtppacker; ++ unsigned char m_packet[MAX_UDP_PACKET+14]; ++}; ++ ++#endif /* !_h264_file_source_h_ */ +diff --git a/sample/test_mmf/rtsp_server/inc/h264-memory-reader.h b/sample/test_mmf/rtsp_server/inc/h264-memory-reader.h +new file mode 100644 +index 0000000..8b9fcc1 +--- /dev/null ++++ b/sample/test_mmf/rtsp_server/inc/h264-memory-reader.h +@@ -0,0 +1,59 @@ ++#ifndef _h264_memory_reader_h_ ++#define _h264_memory_reader_h_ ++ ++#include ++#include ++#include ++#include ++#include "ctypedef.h" ++#include "pthread.h" ++ ++class H264MemoryReader ++{ ++public: ++ H264MemoryReader(const char* file); ++ ~H264MemoryReader(); ++ ++ bool IsOpened() const; ++ ++public: ++ const std::list > GetParameterSets() const { return m_sps; } ++ int GetDuration(int64_t& duration) const { duration = m_duration; return 0; } ++ int GetNextFrame(int64_t &dts, const uint8_t* &ptr, size_t &bytes); ++ int FreeNextFrame(); ++ int PushNextFrame(int64_t time, const uint8_t* nalu, size_t bytes); ++ int SetPspFromFrame(const uint8_t* nalu, size_t bytes); ++ int Seek(int64_t &dts); ++ ++private: ++ int Init(); ++ ++private: ++ struct vframe_t ++ { ++ const uint8_t* nalu; ++ int64_t time; ++ long bytes; ++ bool idr; // IDR frame ++ ++ bool operator < (const struct vframe_t &v) const ++ { ++ return time < v.time; ++ } ++ }; ++ typedef std::list vframes_t; ++ vframes_t m_videos; ++ vframes_t::iterator m_vit; ++ pthread_mutex_t m_lock; ++ ++ std::list > m_sps; ++ int64_t m_duration; ++ ++ uint8_t *m_ptr; ++ size_t m_capacity; ++ uint8_t m_first_pop; ++ uint64_t m_first_time; ++ uint8_t m_sps_nalu[512]; ++}; ++ ++#endif /* !_h264_memory_reader_h_ */ +diff --git a/sample/test_mmf/rtsp_server/inc/h264-memory-source.h b/sample/test_mmf/rtsp_server/inc/h264-memory-source.h +new file mode 100644 +index 0000000..2071d54 +--- /dev/null ++++ b/sample/test_mmf/rtsp_server/inc/h264-memory-source.h +@@ -0,0 +1,53 @@ ++#ifndef _h264_memory_source_h_ ++#define _h264_memory_source_h_ ++ ++#include "h264-memory-reader.h" ++#include "media-source.h" ++#include "sys/process.h" ++#include "time64.h" ++#include "rtp.h" ++#include ++ ++class H264MemorySource : public IMediaSource ++{ ++public: ++ H264MemorySource(const char *file); ++ virtual ~H264MemorySource(); ++ ++public: ++ virtual int Play(); ++ virtual int Pause(); ++ virtual int Seek(int64_t pos); ++ virtual int SetSpeed(double speed); ++ virtual int GetDuration(int64_t& duration) const; ++ virtual int GetSDPMedia(std::string& sdp) const; ++ virtual int GetRTPInfo(const char* uri, char *rtpinfo, size_t bytes) const; ++ virtual int SetTransport(const char* track, std::shared_ptr transport); ++ int Push(int64_t time, const uint8_t* nalu, size_t bytes); ++ int SetPspFromFrame(const uint8_t* nalu, size_t bytes); ++private: ++ static void OnRTCPEvent(void* param, const struct rtcp_msg_t* msg); ++ void OnRTCPEvent(const struct rtcp_msg_t* msg); ++ int SendRTCP(); ++ ++ static void* RTPAlloc(void* param, int bytes); ++ static void RTPFree(void* param, void *packet); ++ static int RTPPacket(void* param, const void *packet, int bytes, uint32_t timestamp, int flags); ++ ++private: ++ void* m_rtp; ++ uint32_t m_timestamp; ++ time64_t m_rtp_clock; ++ time64_t m_rtcp_clock; ++ H264MemoryReader m_reader; ++ std::shared_ptr m_transport; ++ ++ int m_status; ++ int64_t m_pos; ++ double m_speed; ++ ++ void *m_rtppacker; ++ unsigned char m_packet[MAX_UDP_PACKET+14]; ++}; ++ ++#endif /* !_h264_memory_source_h_ */ +diff --git a/sample/test_mmf/rtsp_server/inc/h265-file-reader.h b/sample/test_mmf/rtsp_server/inc/h265-file-reader.h +new file mode 100644 +index 0000000..c6b0222 +--- /dev/null ++++ b/sample/test_mmf/rtsp_server/inc/h265-file-reader.h +@@ -0,0 +1,51 @@ ++#ifndef _h265_file_reader_h_ ++#define _h265_file_reader_h_ ++ ++#include ++#include ++#include ++#include ++#include "ctypedef.h" ++ ++class H265FileReader ++{ ++public: ++ H265FileReader(const char* file); ++ ~H265FileReader(); ++ ++ bool IsOpened() const; ++ ++public: ++ const std::list > GetParameterSets() const { return m_sps; } ++ int GetDuration(int64_t& duration) const { duration = m_duration; return 0; } ++ int GetNextFrame(int64_t &dts, const uint8_t* &ptr, size_t &bytes); ++ int Seek(int64_t &dts); ++ ++private: ++ int Init(); ++ ++private: ++ struct vframe_t ++ { ++ const uint8_t* nalu; ++ int64_t time; ++ long bytes; ++ bool idr; // IDR frame ++ ++ bool operator < (const struct vframe_t &v) const ++ { ++ return time < v.time; ++ } ++ }; ++ typedef std::vector vframes_t; ++ vframes_t m_videos; ++ vframes_t::iterator m_vit; ++ ++ std::list > m_sps; ++ int64_t m_duration; ++ ++ uint8_t *m_ptr; ++ size_t m_capacity; ++}; ++ ++#endif /* !_h265_file_reader_h_ */ +diff --git a/sample/test_mmf/rtsp_server/inc/h265-file-source.h b/sample/test_mmf/rtsp_server/inc/h265-file-source.h +new file mode 100644 +index 0000000..e3c7d06 +--- /dev/null ++++ b/sample/test_mmf/rtsp_server/inc/h265-file-source.h +@@ -0,0 +1,52 @@ ++#ifndef _h265_file_source_h_ ++#define _h265_file_source_h_ ++ ++#include "h265-file-reader.h" ++#include "media-source.h" ++#include "sys/process.h" ++#include "time64.h" ++#include "rtp.h" ++#include ++ ++class H265FileSource : public IMediaSource ++{ ++public: ++ H265FileSource(const char *file); ++ virtual ~H265FileSource(); ++ ++public: ++ virtual int Play(); ++ virtual int Pause(); ++ virtual int Seek(int64_t pos); ++ virtual int SetSpeed(double speed); ++ virtual int GetDuration(int64_t& duration) const; ++ virtual int GetSDPMedia(std::string& sdp) const; ++ virtual int GetRTPInfo(const char* uri, char *rtpinfo, size_t bytes) const; ++ virtual int SetTransport(const char* track, std::shared_ptr transport); ++ ++private: ++ static void OnRTCPEvent(void* param, const struct rtcp_msg_t* msg); ++ void OnRTCPEvent(const struct rtcp_msg_t* msg); ++ int SendRTCP(); ++ ++ static void* RTPAlloc(void* param, int bytes); ++ static void RTPFree(void* param, void *packet); ++ static int RTPPacket(void* param, const void *packet, int bytes, uint32_t timestamp, int flags); ++ ++private: ++ void* m_rtp; ++ uint32_t m_timestamp; ++ time64_t m_rtp_clock; ++ time64_t m_rtcp_clock; ++ H265FileReader m_reader; ++ std::shared_ptr m_transport; ++ ++ int m_status; ++ int64_t m_pos; ++ double m_speed; ++ ++ void *m_rtppacker; ++ unsigned char m_packet[MAX_UDP_PACKET+14]; ++}; ++ ++#endif /* !_h265_file_source_h_ */ +diff --git a/sample/test_mmf/rtsp_server/inc/media-source.h b/sample/test_mmf/rtsp_server/inc/media-source.h +new file mode 100644 +index 0000000..c63574b +--- /dev/null ++++ b/sample/test_mmf/rtsp_server/inc/media-source.h +@@ -0,0 +1,30 @@ ++#ifndef _media_source_h_ ++#define _media_source_h_ ++ ++#include ++#include ++ ++#ifndef MAX_UDP_PACKET ++#define MAX_UDP_PACKET (1450-16) ++#endif ++ ++struct IRTPTransport ++{ ++ virtual int Send(bool rtcp, const void* data, size_t bytes) = 0; ++}; ++ ++struct IMediaSource ++{ ++ virtual ~IMediaSource(){} ++ ++ virtual int Play() = 0; ++ virtual int Pause() = 0; ++ virtual int Seek(int64_t pos) = 0; ++ virtual int SetSpeed(double speed) = 0; ++ virtual int GetDuration(int64_t& duration) const = 0; ++ virtual int GetSDPMedia(std::string& sdp) const = 0; ++ virtual int GetRTPInfo(const char* uri, char *rtpinfo, size_t bytes) const = 0; ++ virtual int SetTransport(const char* track, std::shared_ptr transport) = 0; ++}; ++ ++#endif /* !_media_source_h_ */ +diff --git a/sample/test_mmf/rtsp_server/inc/rtp-tcp-transport.h b/sample/test_mmf/rtsp_server/inc/rtp-tcp-transport.h +new file mode 100644 +index 0000000..dbcc2a0 +--- /dev/null ++++ b/sample/test_mmf/rtsp_server/inc/rtp-tcp-transport.h +@@ -0,0 +1,35 @@ ++#ifndef _rtp_tcp_transport_h_ ++#define _rtp_tcp_transport_h_ ++ ++#include "media-source.h" ++ ++class RTPTcpTransport : public IRTPTransport ++{ ++public: ++ RTPTcpTransport(rtsp_server_t* rtsp, uint8_t rtp, uint8_t rtcp): m_rtp(rtp), m_rtcp(rtcp), m_rtsp(rtsp) {} ++ virtual ~RTPTcpTransport() {} ++ ++public: ++ virtual int Send(bool rtcp, const void* data, size_t bytes) ++ { ++ assert(bytes < (1 << 16)); ++ if (bytes >= (1 << 16)) ++ return -E2BIG; ++ ++ m_packet[0] = '$'; ++ m_packet[1] = rtcp ? m_rtcp : m_rtp; ++ m_packet[2] = (bytes >> 8) & 0xFF; ++ m_packet[3] = bytes & 0xff; ++ memcpy(m_packet + 4, data, bytes); ++ int r = rtsp_server_send_interleaved_data(m_rtsp, m_packet, bytes + 4); ++ return 0 == r ? bytes : r; ++ } ++ ++private: ++ uint8_t m_rtp; ++ uint8_t m_rtcp; ++ rtsp_server_t* m_rtsp; ++ uint8_t m_packet[4 + (1 << 16)]; ++}; ++ ++#endif /* !_rtp_tcp_transport_h_ */ +diff --git a/sample/test_mmf/rtsp_server/inc/rtp-udp-transport.h b/sample/test_mmf/rtsp_server/inc/rtp-udp-transport.h +new file mode 100644 +index 0000000..7ced2de +--- /dev/null ++++ b/sample/test_mmf/rtsp_server/inc/rtp-udp-transport.h +@@ -0,0 +1,26 @@ ++#ifndef _rtp_udp_transport_h_ ++#define _rtp_udp_transport_h_ ++ ++#include "sys/sock.h" ++#include "media-source.h" ++ ++class RTPUdpTransport : public IRTPTransport ++{ ++public: ++ RTPUdpTransport(); ++ virtual ~RTPUdpTransport(); ++ ++public: ++ virtual int Send(bool rtcp, const void* data, size_t bytes); ++ ++public: ++ int Init(const char* ip, unsigned short port[2]); ++ int Init(socket_t socket[2], const char* peer, unsigned short port[2]); ++ ++private: ++ socket_t m_socket[2]; ++ socklen_t m_addrlen[2]; ++ struct sockaddr_storage m_addr[2]; ++}; ++ ++#endif /* !_rtp_udp_transport_h_ */ +diff --git a/sample/test_mmf/rtsp_server/inc/rtsp-camera-reader.h b/sample/test_mmf/rtsp_server/inc/rtsp-camera-reader.h +new file mode 100644 +index 0000000..d4dc568 +--- /dev/null ++++ b/sample/test_mmf/rtsp_server/inc/rtsp-camera-reader.h +@@ -0,0 +1,59 @@ ++#ifndef _rtsp_camera_reader_h_ ++#define _rtsp_camera_reader_h_ ++ ++#include ++#include ++#include ++#include ++#include "ctypedef.h" ++#include "pthread.h" ++ ++class RtspCameraReader ++{ ++public: ++ RtspCameraReader(const char* file); ++ ~RtspCameraReader(); ++ ++ bool IsOpened() const; ++ ++public: ++ const std::list > GetParameterSets() const { return m_sps; } ++ int GetDuration(int64_t& duration) const { duration = m_duration; return 0; } ++ int GetNextFrame(int64_t &dts, const uint8_t* &ptr, size_t &bytes); ++ int FreeNextFrame(); ++ int PushNextFrame(int64_t time, const uint8_t* nalu, size_t bytes); ++ int SetPspFromFrame(const uint8_t* nalu, size_t bytes); ++ int Seek(int64_t &dts); ++ ++private: ++ int Init(); ++ ++private: ++ struct vframe_t ++ { ++ const uint8_t* nalu; ++ int64_t time; ++ long bytes; ++ bool idr; // IDR frame ++ ++ bool operator < (const struct vframe_t &v) const ++ { ++ return time < v.time; ++ } ++ }; ++ typedef std::list vframes_t; ++ vframes_t m_videos; ++ vframes_t::iterator m_vit; ++ pthread_mutex_t m_lock; ++ ++ std::list > m_sps; ++ int64_t m_duration; ++ ++ uint8_t *m_ptr; ++ size_t m_capacity; ++ uint8_t m_first_pop; ++ uint64_t m_first_time; ++ uint8_t m_sps_nalu[512]; ++}; ++ ++#endif /* !_rtsp_camera_reader_h_ */ +diff --git a/sample/test_mmf/rtsp_server/inc/rtsp-camera-source.h b/sample/test_mmf/rtsp_server/inc/rtsp-camera-source.h +new file mode 100644 +index 0000000..12dedd1 +--- /dev/null ++++ b/sample/test_mmf/rtsp_server/inc/rtsp-camera-source.h +@@ -0,0 +1,53 @@ ++#ifndef _rtsp_camera_source_h_ ++#define _rtsp_camera_source_h_ ++ ++#include "rtsp-camera-reader.h" ++#include "media-source.h" ++#include "sys/process.h" ++#include "time64.h" ++#include "rtp.h" ++#include ++ ++class RtspCameraSource : public IMediaSource ++{ ++public: ++ RtspCameraSource(const char *file); ++ virtual ~RtspCameraSource(); ++ ++public: ++ virtual int Play(); ++ virtual int Pause(); ++ virtual int Seek(int64_t pos); ++ virtual int SetSpeed(double speed); ++ virtual int GetDuration(int64_t& duration) const; ++ virtual int GetSDPMedia(std::string& sdp) const; ++ virtual int GetRTPInfo(const char* uri, char *rtpinfo, size_t bytes) const; ++ virtual int SetTransport(const char* track, std::shared_ptr transport); ++ int Push(int64_t time, const uint8_t* nalu, size_t bytes); ++ int SetPspFromFrame(const uint8_t* nalu, size_t bytes); ++private: ++ static void OnRTCPEvent(void* param, const struct rtcp_msg_t* msg); ++ void OnRTCPEvent(const struct rtcp_msg_t* msg); ++ int SendRTCP(); ++ ++ static void* RTPAlloc(void* param, int bytes); ++ static void RTPFree(void* param, void *packet); ++ static int RTPPacket(void* param, const void *packet, int bytes, uint32_t timestamp, int flags); ++ ++private: ++ void* m_rtp; ++ uint32_t m_timestamp; ++ time64_t m_rtp_clock; ++ time64_t m_rtcp_clock; ++ RtspCameraReader m_reader; ++ std::shared_ptr m_transport; ++ ++ int m_status; ++ int64_t m_pos; ++ double m_speed; ++ ++ void *m_rtppacker; ++ unsigned char m_packet[MAX_UDP_PACKET+14]; ++}; ++ ++#endif /* !_rtsp_camera_source_h_ */ +diff --git a/sample/test_mmf/rtsp_server/inc/rtsp_server.h b/sample/test_mmf/rtsp_server/inc/rtsp_server.h +new file mode 100644 +index 0000000..659a3df +--- /dev/null ++++ b/sample/test_mmf/rtsp_server/inc/rtsp_server.h +@@ -0,0 +1,28 @@ ++#ifndef __RTSP_SERVER_H ++#define __RTSP_SERVER_H ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++#include "stdlib.h" ++#include "stdint.h" ++ ++int rtsp_server_init(char *ip, int port); ++int rtsp_server_deinit(void); ++char *rtsp_get_server_ip(void); ++int rtsp_get_server_port(void); ++int rtsp_memory_server_start(int type); ++int rtsp_server_start(void); ++int rtsp_server_stop(void); ++void rtsp_send_h265_data(uint64_t time, uint8_t *asddata, size_t data_len); ++void rtsp_send_memory_data(uint64_t time, uint8_t *data, size_t data_len); ++#ifdef __cplusplus ++} ++#endif ++ ++#ifdef __cplusplus ++std::vector rtsp_get_server_urls(void); ++#endif ++ ++#endif // __RTSP_SERVER_H +diff --git a/sample/test_mmf/rtsp_server/src/h264-file-reader.cpp b/sample/test_mmf/rtsp_server/src/h264-file-reader.cpp +new file mode 100644 +index 0000000..32196e9 +--- /dev/null ++++ b/sample/test_mmf/rtsp_server/src/h264-file-reader.cpp +@@ -0,0 +1,166 @@ ++#include "h264-file-reader.h" ++#include ++#include ++#include ++ ++#define H264_NAL(v) (v & 0x1F) ++ ++enum { NAL_IDR = 5, NAL_SEI = 6, NAL_SPS = 7, NAL_PPS = 8 }; ++ ++H264FileReader::H264FileReader(const char* file) ++:m_ptr(NULL), m_capacity(0) ++{ ++ FILE* fp = fopen(file, "rb"); ++ if(fp) ++ { ++ fseek(fp, 0, SEEK_END); ++ m_capacity = ftell(fp); ++ fseek(fp, 0, SEEK_SET); ++ ++ m_ptr = (uint8_t*)malloc(m_capacity); ++ fread(m_ptr, 1, m_capacity, fp); ++ fclose(fp); ++ ++ Init(); ++ } ++ ++ m_vit = m_videos.begin(); ++} ++ ++H264FileReader::~H264FileReader() ++{ ++ if (m_ptr) ++ { ++ assert(m_capacity > 0); ++ free(m_ptr); ++ } ++} ++ ++bool H264FileReader::IsOpened() const ++{ ++ return !m_videos.empty(); ++} ++ ++int H264FileReader::GetNextFrame(int64_t &dts, const uint8_t* &ptr, size_t &bytes) ++{ ++ if(m_vit == m_videos.end()) ++ return -1; // file end ++ ++ ptr = m_vit->nalu; ++ dts = m_vit->time; ++ bytes = m_vit->bytes; ++ ++ ++m_vit; ++ return 0; ++} ++ ++int H264FileReader::Seek(int64_t &dts) ++{ ++ vframe_t frame; ++ frame.time = dts; ++ ++ vframes_t::iterator it; ++ it = std::lower_bound(m_videos.begin(), m_videos.end(), frame); ++ if(it == m_videos.end()) ++ return -1; ++ ++ while(it != m_videos.begin()) ++ { ++ if(it->idr) ++ { ++ m_vit = it; ++ return 0; ++ } ++ --it; ++ } ++ return 0; ++} ++ ++static inline const uint8_t* search_start_code(const uint8_t* ptr, const uint8_t* end) ++{ ++ for(const uint8_t *p = ptr; p + 3 < end; p++) ++ { ++ if(0x00 == p[0] && 0x00 == p[1] && (0x01 == p[2] || (0x00==p[2] && 0x01==p[3]))) ++ return p; ++ } ++ return end; ++} ++ ++static inline int h264_nal_type(const unsigned char* ptr) ++{ ++ int i = 2; ++ assert(0x00 == ptr[0] && 0x00 == ptr[1]); ++ if(0x00 == ptr[2]) ++ ++i; ++ assert(0x01 == ptr[i]); ++ return H264_NAL(ptr[i+1]); ++} ++ ++static inline int h264_nal_new_access(const unsigned char* ptr, const uint8_t* end) ++{ ++ int i = 2; ++ if (end - ptr < 4) ++ return 1; ++ assert(0x00 == ptr[0] && 0x00 == ptr[1]); ++ if (0x00 == ptr[2]) ++ ++i; ++ assert(0x01 == ptr[i]); ++ int nal_unit_type = H264_NAL(ptr[i + 1]); ++ if (nal_unit_type < 1 || nal_unit_type > 5) ++ return 1; ++ ++ if (ptr + i + 2 > end) ++ return 1; ++ ++ // Live555 H264or5VideoStreamParser::parse ++ // The high-order bit of the byte after the "nal_unit_header" tells us whether it's ++ // the start of a new 'access unit' (and thus the current NAL unit ends an 'access unit'): ++ return (ptr[i + 2] & 0x80) != 0 ? 1 : 0; ++} ++ ++int H264FileReader::Init() ++{ ++ size_t count = 0; ++ bool spspps = true; ++ ++ const uint8_t* end = m_ptr + m_capacity; ++ const uint8_t* nalu = search_start_code(m_ptr, end); ++ const uint8_t* p = nalu; ++ ++ while (p < end) ++ { ++ const unsigned char* pn = search_start_code(p + 4, end); ++ size_t bytes = pn - nalu; ++ ++ int nal_unit_type = h264_nal_type(p); ++ assert(0 != nal_unit_type); ++ if(nal_unit_type <= 5 && h264_nal_new_access(pn, end)) ++ { ++ if(m_sps.size() > 0) spspps = false; // don't need more sps/pps ++ ++ vframe_t frame; ++ frame.nalu = nalu; ++ frame.bytes = (long)bytes; ++ frame.time = 40 * count++; ++ frame.idr = 5 == nal_unit_type; // IDR-frame ++ m_videos.push_back(frame); ++ nalu = pn; ++ } ++ else if(NAL_SPS == nal_unit_type || NAL_PPS == nal_unit_type) ++ { ++ if(spspps) ++ { ++ size_t n = 0x01 == p[2] ? 3 : 4; ++ std::pair pr; ++ pr.first = p + n; ++ pr.second = bytes; ++ m_sps.push_back(pr); ++ } ++ } ++ ++ p = pn; ++ } ++ ++ m_duration = 40 * count; ++ return 0; ++} +diff --git a/sample/test_mmf/rtsp_server/src/h264-file-source.cpp b/sample/test_mmf/rtsp_server/src/h264-file-source.cpp +new file mode 100644 +index 0000000..135ca20 +--- /dev/null ++++ b/sample/test_mmf/rtsp_server/src/h264-file-source.cpp +@@ -0,0 +1,207 @@ ++#include "h264-file-source.h" ++#include "cstringext.h" ++#include "base64.h" ++#include "rtp-profile.h" ++#include "rtp-payload.h" ++#include ++ ++extern "C" uint32_t rtp_ssrc(void); ++ ++H264FileSource::H264FileSource(const char *file) ++:m_reader(file) ++{ ++ m_speed = 1.0; ++ m_status = 0; ++ m_rtp_clock = 0; ++ m_rtcp_clock = 0; ++ m_timestamp = 0; ++ ++ uint32_t ssrc = rtp_ssrc(); ++ static struct rtp_payload_t s_rtpfunc = { ++ H264FileSource::RTPAlloc, ++ H264FileSource::RTPFree, ++ H264FileSource::RTPPacket, ++ }; ++ m_rtppacker = rtp_payload_encode_create(RTP_PAYLOAD_H264, "H264", (uint16_t)ssrc, ssrc, &s_rtpfunc, this); ++ ++ struct rtp_event_t event; ++ event.on_rtcp = OnRTCPEvent; ++ m_rtp = rtp_create(&event, this, ssrc, m_timestamp, 90000, 4*1024, 1); ++ rtp_set_info(m_rtp, "RTSPServer", "szj.h264"); ++} ++ ++H264FileSource::~H264FileSource() ++{ ++ if(m_rtp) ++ rtp_destroy(m_rtp); ++ ++ if(m_rtppacker) ++ rtp_payload_encode_destroy(m_rtppacker); ++} ++ ++int H264FileSource::SetTransport(const char* /*track*/, std::shared_ptr transport) ++{ ++ m_transport = transport; ++ return 0; ++} ++ ++int H264FileSource::Play() ++{ ++ m_status = 1; ++ ++ //uint32_t timestamp = 0; ++ time64_t clock = time64_now(); ++ if (0 == m_rtp_clock) ++ m_rtp_clock = clock; ++ ++ if(m_rtp_clock + 40 < clock) ++ { ++ size_t bytes; ++ const uint8_t* ptr; ++ if(0 == m_reader.GetNextFrame(m_pos, ptr, bytes)) ++ { ++ rtp_payload_encode_input(m_rtppacker, ptr, (int)bytes, m_timestamp * 90 /*kHz*/); ++ m_rtp_clock += 40; ++ m_timestamp += 40; ++ ++ SendRTCP(); ++ return 1; ++ } ++ } ++ ++ return 0; ++} ++ ++int H264FileSource::Pause() ++{ ++ m_status = 2; ++ m_rtp_clock = 0; ++ return 0; ++} ++ ++int H264FileSource::Seek(int64_t pos) ++{ ++ m_pos = pos; ++ m_rtp_clock = 0; ++ return m_reader.Seek(m_pos); ++} ++ ++int H264FileSource::SetSpeed(double speed) ++{ ++ m_speed = speed; ++ return 0; ++} ++ ++int H264FileSource::GetDuration(int64_t& duration) const ++{ ++ return m_reader.GetDuration(duration); ++} ++ ++int H264FileSource::GetSDPMedia(std::string& sdp) const ++{ ++ static const char* pattern = ++ "m=video 0 RTP/AVP %d\n" ++ "a=control:track0\n" ++ "a=rtpmap:%d H264/90000\n" ++ "a=fmtp:%d profile-level-id=%02X%02X%02X;" ++ "packetization-mode=1;" ++ "sprop-parameter-sets="; ++ ++ char base64[512] = {0}; ++ std::string parameters; ++ ++ const std::list >& sps = m_reader.GetParameterSets(); ++ std::list >::const_iterator it; ++ for(it = sps.begin(); it != sps.end(); ++it) ++ { ++ if(parameters.empty()) ++ { ++ snprintf(base64, sizeof(base64), pattern, ++ RTP_PAYLOAD_H264, RTP_PAYLOAD_H264,RTP_PAYLOAD_H264, ++ (unsigned int)(it->first[1]), (unsigned int)(it->first[2]), (unsigned int)(it->first[3])); ++ sdp = base64; ++ } ++ else ++ { ++ parameters += ','; ++ } ++ ++ size_t bytes = it->second; ++ assert((bytes+2)/3*4 + bytes/57 + 1 < sizeof(base64)); ++ bytes = base64_encode(base64, it->first, bytes); ++ base64[bytes] = '\0'; ++ assert(strlen(base64) > 0); ++ parameters += base64; ++ } ++ ++ sdp += parameters; ++ sdp += '\n'; ++ return sps.empty() ? -1 : 0; ++} ++ ++int H264FileSource::GetRTPInfo(const char* uri, char *rtpinfo, size_t bytes) const ++{ ++ uint16_t seq; ++ uint32_t timestamp; ++ rtp_payload_encode_getinfo(m_rtppacker, &seq, ×tamp); ++ ++ // url=rtsp://video.example.com/twister/video;seq=12312232;rtptime=78712811 ++ snprintf(rtpinfo, bytes, "url=%s;seq=%hu;rtptime=%u", uri, seq, timestamp); ++ return 0; ++} ++ ++void H264FileSource::OnRTCPEvent(const struct rtcp_msg_t* msg) ++{ ++ msg; ++} ++ ++void H264FileSource::OnRTCPEvent(void* param, const struct rtcp_msg_t* msg) ++{ ++ H264FileSource *self = (H264FileSource *)param; ++ self->OnRTCPEvent(msg); ++} ++ ++int H264FileSource::SendRTCP() ++{ ++ // make sure have sent RTP packet ++ ++ time64_t clock = time64_now(); ++ int interval = rtp_rtcp_interval(m_rtp); ++ if(0 == m_rtcp_clock || m_rtcp_clock + interval < clock) ++ { ++ char rtcp[1024] = {0}; ++ size_t n = rtp_rtcp_report(m_rtp, rtcp, sizeof(rtcp)); ++ ++ // send RTCP packet ++ m_transport->Send(true, rtcp, n); ++ ++ m_rtcp_clock = clock; ++ } ++ ++ return 0; ++} ++ ++void* H264FileSource::RTPAlloc(void* param, int bytes) ++{ ++ H264FileSource *self = (H264FileSource*)param; ++ assert(bytes <= sizeof(self->m_packet)); ++ return self->m_packet; ++} ++ ++void H264FileSource::RTPFree(void* param, void *packet) ++{ ++ H264FileSource *self = (H264FileSource*)param; ++ assert(self->m_packet == packet); ++} ++ ++int H264FileSource::RTPPacket(void* param, const void *packet, int bytes, uint32_t /*timestamp*/, int /*flags*/) ++{ ++ H264FileSource *self = (H264FileSource*)param; ++ assert(self->m_packet == packet); ++ ++ int r = self->m_transport->Send(false, packet, bytes); ++ if (r != bytes) ++ return -1; ++ ++ return rtp_onsend(self->m_rtp, packet, bytes/*, time*/); ++} +diff --git a/sample/test_mmf/rtsp_server/src/h264-memory-reader.cpp b/sample/test_mmf/rtsp_server/src/h264-memory-reader.cpp +new file mode 100644 +index 0000000..6145062 +--- /dev/null ++++ b/sample/test_mmf/rtsp_server/src/h264-memory-reader.cpp +@@ -0,0 +1,307 @@ ++#include "h264-memory-reader.h" ++#include ++#include ++#include ++#include ++#include ++#include "time64.h" ++ ++#define H264_NAL(v) (v & 0x1F) ++ ++enum { NAL_IDR = 5, NAL_SEI = 6, NAL_SPS = 7, NAL_PPS = 8 }; ++ ++H264MemoryReader::H264MemoryReader(const char* file) ++:m_ptr(NULL), m_capacity(0), m_first_time(0) ++{ ++ pthread_mutex_init(&m_lock, NULL); ++ pthread_mutex_unlock(&m_lock); ++ m_vit = m_videos.begin(); ++ m_first_pop = 1; ++} ++ ++H264MemoryReader::~H264MemoryReader() ++{ ++ if (m_ptr) ++ { ++ assert(m_capacity > 0); ++ free(m_ptr); ++ } ++ ++ pthread_mutex_destroy(&m_lock); ++} ++ ++bool H264MemoryReader::IsOpened() const ++{ ++ return true; ++} ++ ++int H264MemoryReader::Seek(int64_t &dts) ++{ ++ return 0; ++} ++ ++static inline const uint8_t* search_start_code(const uint8_t* ptr, const uint8_t* end) ++{ ++ for(const uint8_t *p = ptr; p + 3 < end; p++) ++ { ++ if(0x00 == p[0] && 0x00 == p[1] && (0x01 == p[2] || (0x00==p[2] && 0x01==p[3]))) ++ return p; ++ } ++ return end; ++} ++ ++static inline int h264_nal_type(const unsigned char* ptr) ++{ ++ int i = 2; ++ assert(0x00 == ptr[0] && 0x00 == ptr[1]); ++ if(0x00 == ptr[2]) ++ ++i; ++ assert(0x01 == ptr[i]); ++ return H264_NAL(ptr[i+1]); ++} ++ ++int H264MemoryReader::SetPspFromFrame(const uint8_t* nalu, size_t bytes) ++{ ++ if(m_sps.size() == 0) { ++ int nal_unit_type = h264_nal_type(nalu); ++ if (0 > nal_unit_type) { ++ return -1; ++ } ++ ++ const uint8_t *nalu2 = (uint8_t *)nalu; ++ const uint8_t* end = nalu2 + bytes; ++ const uint8_t* p = nalu2; ++ while (p < end) ++ { ++ const unsigned char* pn = search_start_code(p + 4, end); ++ size_t size = pn - nalu2; ++ ++ int nal_unit_type = h264_nal_type(p); ++ if (nal_unit_type < 0) { ++ return -1; ++ } ++ ++ if(NAL_SPS == nal_unit_type) ++ { ++ memcpy(m_sps_nalu, nalu2, size); ++ size_t n = 0x01 == nalu2[2] ? 3 : 4; ++ std::pair pr; ++ pr.first = m_sps_nalu + n; ++ pr.second = size; ++ m_sps.push_back(pr); ++ break; ++ } ++ ++ nalu2 = pn; ++ p = pn; ++ } ++ ++ PushNextFrame(0, nalu, bytes); ++ } ++ return 0; ++} ++ ++int H264MemoryReader::GetNextFrame(int64_t &dts, const uint8_t* &ptr, size_t &bytes) ++{ ++ pthread_mutex_lock(&m_lock); ++ vframes_t::iterator frame; ++ ++ if (m_first_pop) { ++ while (1) { ++ frame = m_videos.begin(); ++ if(frame == m_videos.end()) { ++ pthread_mutex_unlock(&m_lock); ++ return -1; ++ } ++ ++ int nal_unit_type = h264_nal_type(frame->nalu); ++ if (0 > nal_unit_type) { ++ m_videos.pop_front(); ++ continue; ++ } ++ ++ if(NAL_SPS == nal_unit_type || NAL_PPS == nal_unit_type) ++ { ++ m_first_pop = 0; ++ break; ++ } else { ++ m_videos.pop_front(); ++ continue; ++ } ++ } ++ } else { ++ frame = m_videos.begin(); ++ if(frame == m_videos.end()) { ++ pthread_mutex_unlock(&m_lock); ++ return -1; ++ } ++ } ++ ++ ptr = frame->nalu; ++ dts = frame->time; ++ bytes = frame->bytes; ++ ++ pthread_mutex_unlock(&m_lock); ++ return 0; ++} ++ ++int H264MemoryReader::PushNextFrame(int64_t time, const uint8_t* nalu, size_t bytes) ++{ ++ pthread_mutex_lock(&m_lock); ++ int nal_unit_type = h264_nal_type(nalu); ++ if (0 > nal_unit_type) { ++ pthread_mutex_unlock(&m_lock); ++ return -1; ++ } ++ ++ if(m_sps.size() == 0) { ++ const uint8_t *nalu2 = (uint8_t *)nalu; ++ const uint8_t* end = nalu2 + bytes; ++ const uint8_t* p = nalu2; ++ while (p < end) ++ { ++ const unsigned char* pn = search_start_code(p + 4, end); ++ size_t size = pn - nalu2; ++ ++ int nal_unit_type = h264_nal_type(p); ++ if (nal_unit_type < 0) { ++ return -1; ++ } ++ ++ if(NAL_SPS == nal_unit_type) ++ { ++ memcpy(m_sps_nalu, nalu2, size); ++ size_t n = 0x01 == nalu2[2] ? 3 : 4; ++ std::pair pr; ++ pr.first = m_sps_nalu + n; ++ pr.second = size; ++ m_sps.push_back(pr); ++ break; ++ } ++ ++ nalu2 = pn; ++ p = pn; ++ } ++ m_first_time = time; ++ } ++ ++ vframe_t frame; ++ frame.nalu = (const uint8_t*)malloc(bytes); ++ memcpy((uint8_t *)frame.nalu, nalu, bytes); ++ frame.bytes = bytes; ++ frame.time = (time == 0) ? 0 : time - m_first_time; ++ frame.idr = (NAL_IDR == nal_unit_type); // IDR-frame ++ m_videos.push_back(frame); ++ pthread_mutex_unlock(&m_lock); ++ ++ return 0; ++} ++ ++int H264MemoryReader::FreeNextFrame() ++{ ++ pthread_mutex_lock(&m_lock); ++ vframes_t::iterator frame = m_videos.begin(); ++ if(frame == m_videos.end()) { ++ pthread_mutex_unlock(&m_lock); ++ return -1; ++ } ++ ++ if (frame->nalu) { ++ free((uint8_t *)frame->nalu); ++ } ++ m_videos.pop_front(); ++ pthread_mutex_unlock(&m_lock); ++ ++ return 0; ++} ++ ++static inline int h264_nal_new_access(const unsigned char* ptr, const uint8_t* end) ++{ ++ int i = 2; ++ if (end - ptr < 4) ++ return 1; ++ assert(0x00 == ptr[0] && 0x00 == ptr[1]); ++ if (0x00 == ptr[2]) ++ ++i; ++ assert(0x01 == ptr[i]); ++ int nal_unit_type = H264_NAL(ptr[i + 1]); ++ if (nal_unit_type < 1 || nal_unit_type > 5) ++ return 1; ++ ++ if (ptr + i + 2 > end) ++ return 1; ++ ++ // Live555 H264or5VideoStreamParser::parse ++ // The high-order bit of the byte after the "nal_unit_header" tells us whether it's ++ // the start of a new 'access unit' (and thus the current NAL unit ends an 'access unit'): ++ return (ptr[i + 2] & 0x80) != 0 ? 1 : 0; ++} ++ ++int H264MemoryReader::Init() ++{ ++#if 0 ++ size_t count = 0; ++ bool spspps = true; ++ ++ const uint8_t* end = m_ptr + m_capacity; ++ const uint8_t* nalu = search_start_code(m_ptr, end); ++ const uint8_t* p = nalu; ++ ++ while (p < end) ++ { ++ const unsigned char* pn = search_start_code(p + 4, end); ++ size_t bytes = pn - nalu; ++ ++ int nal_unit_type = h264_nal_type(p); ++ assert(0 != nal_unit_type); ++ if(nal_unit_type <= 5 && h264_nal_new_access(pn, end)) ++ { ++ if(m_sps.size() > 0) spspps = false; // don't need more sps/pps ++ ++ vframe_t frame; ++ frame.nalu = nalu; ++ frame.bytes = (long)bytes; ++ frame.time = 40 * count++; ++ frame.idr = 5 == nal_unit_type; // IDR-frame ++ m_videos.push_back(frame); ++ nalu = pn; ++ } ++ else if(NAL_SPS == nal_unit_type || NAL_PPS == nal_unit_type) ++ { ++ if(spspps) ++ { ++ size_t n = 0x01 == p[2] ? 3 : 4; ++ std::pair pr; ++ pr.first = p + n; ++ pr.second = bytes; ++ m_sps.push_back(pr); ++ } ++ } ++ ++ p = pn; ++ } ++ ++ m_duration = 40 * count; ++ return 0; ++#else ++ // size_t count = 0; ++ ++ // const uint8_t* end = m_ptr + m_capacity; ++ // const uint8_t* nalu = search_start_code(m_ptr, end); ++ // const uint8_t* p = nalu; ++ ++ // while (p < end) ++ // { ++ // const unsigned char* pn = search_start_code(p + 4, end); ++ // size_t bytes = pn - nalu; ++ ++ // PushNextFrame(40 * count++, nalu, bytes); ++ ++ // nalu = pn; ++ // p = pn; ++ // } ++ ++ // m_duration = 40 * count; ++ return 0; ++#endif ++} +diff --git a/sample/test_mmf/rtsp_server/src/h264-memory-source.cpp b/sample/test_mmf/rtsp_server/src/h264-memory-source.cpp +new file mode 100644 +index 0000000..52c1f4f +--- /dev/null ++++ b/sample/test_mmf/rtsp_server/src/h264-memory-source.cpp +@@ -0,0 +1,221 @@ ++#include "h264-memory-source.h" ++#include "cstringext.h" ++#include "base64.h" ++#include "rtp-profile.h" ++#include "rtp-payload.h" ++#include ++ ++extern "C" uint32_t rtp_ssrc(void); ++ ++H264MemorySource::H264MemorySource(const char *file) ++:m_reader(file) ++{ ++ m_speed = 1.0; ++ m_status = 0; ++ m_rtp_clock = 0; ++ m_rtcp_clock = 0; ++ m_timestamp = 0; ++ ++ uint32_t ssrc = rtp_ssrc(); ++ static struct rtp_payload_t s_rtpfunc = { ++ H264MemorySource::RTPAlloc, ++ H264MemorySource::RTPFree, ++ H264MemorySource::RTPPacket, ++ }; ++ m_rtppacker = rtp_payload_encode_create(RTP_PAYLOAD_H264, "H264", (uint16_t)ssrc, ssrc, &s_rtpfunc, this); ++ ++ struct rtp_event_t event; ++ event.on_rtcp = OnRTCPEvent; ++ m_rtp = rtp_create(&event, this, ssrc, m_timestamp, 90000, 4*1024, 1); ++ rtp_set_info(m_rtp, "RTSPServer", "szj.h264"); ++} ++ ++H264MemorySource::~H264MemorySource() ++{ ++ if(m_rtp) ++ rtp_destroy(m_rtp); ++ ++ if(m_rtppacker) ++ rtp_payload_encode_destroy(m_rtppacker); ++} ++ ++int H264MemorySource::SetTransport(const char* /*track*/, std::shared_ptr transport) ++{ ++ m_transport = transport; ++ return 0; ++} ++ ++int H264MemorySource::Push(int64_t time, const uint8_t* nalu, size_t bytes) ++{ ++ return m_reader.PushNextFrame(time, nalu, bytes); ++} ++ ++int H264MemorySource::SetPspFromFrame(const uint8_t* nalu, size_t bytes) ++{ ++ return m_reader.SetPspFromFrame(nalu, bytes); ++} ++ ++int H264MemorySource::Play() ++{ ++ m_status = 1; ++ ++ //uint32_t timestamp = 0; ++ time64_t clock = time64_now(); ++ if (0 == m_rtp_clock) ++ m_rtp_clock = clock; ++ static int64_t last_m_pos = 0; ++ if(m_rtp_clock + 10 < clock) ++ { ++ size_t bytes; ++ const uint8_t* ptr; ++ if(0 == m_reader.GetNextFrame(m_pos, ptr, bytes)) ++ { ++ m_timestamp = m_pos; ++ rtp_payload_encode_input(m_rtppacker, ptr, bytes, m_timestamp * 90 /*kHz*/); ++ SendRTCP(); ++ m_reader.FreeNextFrame(); ++ return 1; ++ } ++ } ++ ++ return 0; ++} ++ ++int H264MemorySource::Pause() ++{ ++ m_status = 2; ++ m_rtp_clock = 0; ++ return 0; ++} ++ ++int H264MemorySource::Seek(int64_t pos) ++{ ++ m_pos = pos; ++ m_rtp_clock = 0; ++ return 0; ++} ++ ++int H264MemorySource::SetSpeed(double speed) ++{ ++ m_speed = speed; ++ return 0; ++} ++ ++int H264MemorySource::GetDuration(int64_t& duration) const ++{ ++ return m_reader.GetDuration(duration); ++} ++ ++int H264MemorySource::GetSDPMedia(std::string& sdp) const ++{ ++ static const char* pattern = ++ "m=video 0 RTP/AVP %d\n" ++ "a=rtpmap:%d H264/90000\n" ++ "a=fmtp:%d profile-level-id=%02X%02X%02X;" ++ "packetization-mode=1;" ++ "sprop-parameter-sets="; ++ ++ char base64[512] = {0}; ++ std::string parameters; ++ ++ const std::list >& sps = m_reader.GetParameterSets(); ++ std::list >::const_iterator it; ++ for(it = sps.begin(); it != sps.end(); ++it) ++ { ++ if(parameters.empty()) ++ { ++ snprintf(base64, sizeof(base64), pattern, ++ RTP_PAYLOAD_H264, RTP_PAYLOAD_H264,RTP_PAYLOAD_H264, ++ (unsigned int)(it->first[1]), (unsigned int)(it->first[2]), (unsigned int)(it->first[3])); ++ sdp = base64; ++ } ++ else ++ { ++ parameters += ','; ++ } ++ ++ size_t bytes = it->second; ++ assert((bytes+2)/3*4 + bytes/57 + 1 < sizeof(base64)); ++ bytes = base64_encode(base64, it->first, bytes); ++ base64[bytes] = '\0'; ++ assert(strlen(base64) > 0); ++ parameters += base64; ++ } ++ ++ sdp += parameters; ++ sdp += '\n'; ++ return sps.empty() ? -1 : 0; ++} ++ ++int H264MemorySource::GetRTPInfo(const char* uri, char *rtpinfo, size_t bytes) const ++{ ++ uint16_t seq; ++ uint32_t timestamp; ++ rtp_payload_encode_getinfo(m_rtppacker, &seq, ×tamp); ++ ++ // url=rtsp://video.example.com/twister/video;seq=12312232;rtptime=78712811 ++ snprintf(rtpinfo, bytes, "url=%s;seq=%hu;rtptime=%u", uri, seq, timestamp); ++ return 0; ++} ++ ++void H264MemorySource::OnRTCPEvent(const struct rtcp_msg_t* msg) ++{ ++ (void)msg; ++} ++ ++void H264MemorySource::OnRTCPEvent(void* param, const struct rtcp_msg_t* msg) ++{ ++ H264MemorySource *self = (H264MemorySource *)param; ++ self->OnRTCPEvent(msg); ++} ++ ++int H264MemorySource::SendRTCP() ++{ ++ // make sure have sent RTP packet ++ ++ time64_t clock = time64_now(); ++ int interval = rtp_rtcp_interval(m_rtp); ++ if(0 == m_rtcp_clock || m_rtcp_clock + interval < clock) ++ { ++ char rtcp[1024] = {0}; ++ size_t n = rtp_rtcp_report(m_rtp, rtcp, sizeof(rtcp)); ++ ++ // send RTCP packet ++ m_transport->Send(true, rtcp, n); ++ ++ m_rtcp_clock = clock; ++ } ++ ++ return 0; ++} ++ ++void* H264MemorySource::RTPAlloc(void* param, int bytes) ++{ ++ H264MemorySource *self = (H264MemorySource*)param; ++ assert(bytes <= (int)sizeof(self->m_packet)); ++ return self->m_packet; ++} ++ ++void H264MemorySource::RTPFree(void* param, void *packet) ++{ ++ H264MemorySource *self = (H264MemorySource*)param; ++ assert(self->m_packet == packet); ++} ++ ++int H264MemorySource::RTPPacket(void* param, const void *packet, int bytes, uint32_t /*timestamp*/, int /*flags*/) ++{ ++ H264MemorySource *self = (H264MemorySource*)param; ++ assert(self->m_packet == packet); ++ // const char* ptr = (const char*)packet; ++ // for(int i=0;i 4){ ++ // exit(-1); ++ // } ++ int r = self->m_transport->Send(false, packet, bytes); ++ if (r != bytes) ++ return -1; ++ ++ return rtp_onsend(self->m_rtp, packet, bytes/*, time*/); ++} +diff --git a/sample/test_mmf/rtsp_server/src/h265-file-reader.cpp b/sample/test_mmf/rtsp_server/src/h265-file-reader.cpp +new file mode 100644 +index 0000000..f777d8d +--- /dev/null ++++ b/sample/test_mmf/rtsp_server/src/h265-file-reader.cpp +@@ -0,0 +1,146 @@ ++#include "h265-file-reader.h" ++#include ++#include ++#include ++ ++#define H265_NAL(v) ((v>> 1) & 0x3f) ++ ++enum { NAL_IDR_W_RADL = 19, NAL_IDR_N_LP= 20, NAL_VPS = 32, NAL_SPS = 33, NAL_PPS = 34, NAL_SEI = 39}; ++ ++H265FileReader::H265FileReader(const char* file) ++:m_ptr(NULL), m_capacity(0) ++{ ++ FILE* fp = fopen(file, "rb"); ++ if(fp) ++ { ++ fseek(fp, 0, SEEK_END); ++ m_capacity = ftell(fp); ++ fseek(fp, 0, SEEK_SET); ++ ++ m_ptr = (uint8_t*)malloc(m_capacity); ++ fread(m_ptr, 1, m_capacity, fp); ++ fclose(fp); ++ ++ Init(); ++ } ++ ++ m_vit = m_videos.begin(); ++} ++ ++H265FileReader::~H265FileReader() ++{ ++ if (m_ptr) ++ { ++ assert(m_capacity > 0); ++ free(m_ptr); ++ } ++} ++ ++bool H265FileReader::IsOpened() const ++{ ++ return !m_videos.empty(); ++} ++ ++int H265FileReader::GetNextFrame(int64_t &dts, const uint8_t* &ptr, size_t &bytes) ++{ ++ if(m_vit == m_videos.end()) ++ return -1; // file end ++ ++ ptr = m_vit->nalu; ++ dts = m_vit->time; ++ bytes = m_vit->bytes; ++ ++ ++m_vit; ++ return 0; ++} ++ ++int H265FileReader::Seek(int64_t &dts) ++{ ++ vframe_t frame; ++ frame.time = dts; ++ ++ vframes_t::iterator it; ++ it = std::lower_bound(m_videos.begin(), m_videos.end(), frame); ++ if(it == m_videos.end()) ++ return -1; ++ ++ while(it != m_videos.begin()) ++ { ++ if(it->idr) ++ { ++ m_vit = it; ++ return 0; ++ } ++ --it; ++ } ++ return 0; ++} ++ ++static inline const uint8_t* search_start_code(const uint8_t* ptr, const uint8_t* end) ++{ ++ for(const uint8_t *p = ptr; p + 3 < end; p++) ++ { ++ if(0x00 == p[0] && 0x00 == p[1] && (0x01 == p[2] || (0x00==p[2] && 0x01==p[3]))) ++ return p; ++ } ++ return end; ++} ++ ++static inline int h265_nal_type(const unsigned char* ptr) ++{ ++ int i = 2; ++ assert(0x00 == ptr[0] && 0x00 == ptr[1]); ++ if(0x00 == ptr[2]) ++ ++i; ++ assert(0x01 == ptr[i]); ++ return H265_NAL(ptr[i+1]); ++} ++ ++ ++int H265FileReader::Init() ++{ ++ size_t count = 0; ++ bool vpsspspps = true; ++ ++ const uint8_t* end = m_ptr + m_capacity; ++ const uint8_t* nalu = search_start_code(m_ptr, end); ++ const uint8_t* p = nalu; ++ ++ while (p < end) ++ { ++ const unsigned char* pn = search_start_code(p + 4, end); ++ size_t bytes = pn - nalu; ++ ++ int nal_unit_type = h265_nal_type(p); ++ assert(0 <= nal_unit_type); ++ ++ if(NAL_VPS == nal_unit_type || NAL_SPS == nal_unit_type || NAL_PPS == nal_unit_type) ++ { ++ if(vpsspspps) ++ { ++ size_t n = 0x01 == p[2] ? 3 : 4; ++ std::pair pr; ++ pr.first = p + n; ++ pr.second = bytes; ++ m_sps.push_back(pr); ++ } ++ } ++ ++ { ++ if(m_sps.size() > 0) vpsspspps = false; // don't need more vps/sps/pps ++ ++ vframe_t frame; ++ frame.nalu = nalu; ++ frame.bytes = bytes; ++ frame.time = 40 * count++; ++ frame.idr = (NAL_IDR_N_LP == nal_unit_type || NAL_IDR_W_RADL == nal_unit_type); // IDR-frame ++ m_videos.push_back(frame); ++ nalu = pn; ++ } ++ ++ p = pn; ++ } ++ ++ m_duration = 40 * count; ++ return 0; ++} +diff --git a/sample/test_mmf/rtsp_server/src/h265-file-source.cpp b/sample/test_mmf/rtsp_server/src/h265-file-source.cpp +new file mode 100644 +index 0000000..c480171 +--- /dev/null ++++ b/sample/test_mmf/rtsp_server/src/h265-file-source.cpp +@@ -0,0 +1,216 @@ ++#include "h265-file-source.h" ++#include "cstringext.h" ++#include "base64.h" ++#include "rtp-profile.h" ++#include "rtp-payload.h" ++#include ++ ++extern "C" uint32_t rtp_ssrc(void); ++ ++H265FileSource::H265FileSource(const char *file) ++:m_reader(file) ++{ ++ m_speed = 1.0; ++ m_status = 0; ++ m_rtp_clock = 0; ++ m_rtcp_clock = 0; ++ m_timestamp = 0; ++ ++ uint32_t ssrc = rtp_ssrc(); ++ static struct rtp_payload_t s_rtpfunc = { ++ H265FileSource::RTPAlloc, ++ H265FileSource::RTPFree, ++ H265FileSource::RTPPacket, ++ }; ++ m_rtppacker = rtp_payload_encode_create(RTP_PAYLOAD_H265, "H265", (uint16_t)ssrc, ssrc, &s_rtpfunc, this); ++ ++ struct rtp_event_t event; ++ event.on_rtcp = OnRTCPEvent; ++ m_rtp = rtp_create(&event, this, ssrc, m_timestamp, 90000, 4*1024, 1); ++ rtp_set_info(m_rtp, "RTSPServer", "szj.h265"); ++} ++ ++H265FileSource::~H265FileSource() ++{ ++ if(m_rtp) ++ rtp_destroy(m_rtp); ++ ++ if(m_rtppacker) ++ rtp_payload_encode_destroy(m_rtppacker); ++} ++ ++int H265FileSource::SetTransport(const char* /*track*/, std::shared_ptr transport) ++{ ++ m_transport = transport; ++ return 0; ++} ++ ++int H265FileSource::Play() ++{ ++ m_status = 1; ++ ++ //uint32_t timestamp = 0; ++ time64_t clock = time64_now(); ++ if (0 == m_rtp_clock) ++ m_rtp_clock = clock; ++ ++ if(m_rtp_clock + 40 < clock) ++ { ++ size_t bytes; ++ const uint8_t* ptr; ++ if(0 == m_reader.GetNextFrame(m_pos, ptr, bytes)) ++ { ++ // for(int i=0;iOnRTCPEvent(msg); ++} ++ ++int H265FileSource::SendRTCP() ++{ ++ // make sure have sent RTP packet ++ ++ time64_t clock = time64_now(); ++ int interval = rtp_rtcp_interval(m_rtp); ++ if(0 == m_rtcp_clock || m_rtcp_clock + interval < clock) ++ { ++ char rtcp[1024] = {0}; ++ size_t n = rtp_rtcp_report(m_rtp, rtcp, sizeof(rtcp)); ++ ++ // send RTCP packet ++ m_transport->Send(true, rtcp, n); ++ ++ m_rtcp_clock = clock; ++ } ++ ++ return 0; ++} ++ ++void* H265FileSource::RTPAlloc(void* param, int bytes) ++{ ++ H265FileSource *self = (H265FileSource*)param; ++ assert(bytes <= sizeof(self->m_packet)); ++ return self->m_packet; ++} ++ ++void H265FileSource::RTPFree(void* param, void *packet) ++{ ++ H265FileSource *self = (H265FileSource*)param; ++ assert(self->m_packet == packet); ++} ++ ++static int i = 0; ++int H265FileSource::RTPPacket(void* param, const void *packet, int bytes, uint32_t /*timestamp*/, int /*flags*/) ++{ ++ H265FileSource *self = (H265FileSource*)param; ++ assert(self->m_packet == packet); ++ const char* ptr = (const char*)packet; ++ // for(int i=0;i 4){ ++ // exit(-1); ++ // } ++ int r = self->m_transport->Send(false, packet, bytes); ++ if (r != bytes) ++ return -1; ++ ++ return rtp_onsend(self->m_rtp, packet, bytes/*, time*/); ++} +diff --git a/sample/test_mmf/rtsp_server/src/rtp-udp-transport.cpp b/sample/test_mmf/rtsp_server/src/rtp-udp-transport.cpp +new file mode 100644 +index 0000000..0e406a3 +--- /dev/null ++++ b/sample/test_mmf/rtsp_server/src/rtp-udp-transport.cpp +@@ -0,0 +1,50 @@ ++#include "rtp-udp-transport.h" ++#include "sockpair.h" ++#include "ctypedef.h" ++#include "port/ip-route.h" ++ ++RTPUdpTransport::RTPUdpTransport() ++{ ++ m_socket[0] = socket_invalid; ++ m_socket[1] = socket_invalid; ++} ++ ++RTPUdpTransport::~RTPUdpTransport() ++{ ++ for (int i = 0; i < 2; i++) ++ { ++ if (socket_invalid != m_socket[i]) ++ socket_close(m_socket[i]); ++ m_socket[i] = socket_invalid; ++ } ++} ++ ++int RTPUdpTransport::Init(const char* ip, unsigned short port[2]) ++{ ++ char local[SOCKET_ADDRLEN]; ++ int r1 = socket_addr_from(&m_addr[0], &m_addrlen[0], ip, port[0]); ++ int r2 = socket_addr_from(&m_addr[1], &m_addrlen[1], ip, port[1]); ++ if (0 != r1 || 0 != r2) ++ return 0 != r1 ? r1 : r2; ++ ++ r1 = ip_route_get(ip, local); ++ return sockpair_create(0==r1 ? local : NULL, m_socket, port); ++} ++ ++int RTPUdpTransport::Init(socket_t socket[2], const char* peer, unsigned short port[2]) ++{ ++ int r1 = socket_addr_from(&m_addr[0], &m_addrlen[0], peer, port[0]); ++ int r2 = socket_addr_from(&m_addr[1], &m_addrlen[1], peer, port[1]); ++ if (0 != r1 || 0 != r2) ++ return 0 != r1 ? r1 : r2; ++ ++ m_socket[0] = socket[0]; ++ m_socket[1] = socket[1]; ++ return 0; ++} ++ ++int RTPUdpTransport::Send(bool rtcp, const void* data, size_t bytes) ++{ ++ int i = rtcp ? 1 : 0; ++ return socket_sendto(m_socket[i], data, bytes, 0, (sockaddr*)&m_addr[i], m_addrlen[i]); ++} +diff --git a/sample/test_mmf/rtsp_server/src/rtsp-camera-reader.cpp b/sample/test_mmf/rtsp_server/src/rtsp-camera-reader.cpp +new file mode 100644 +index 0000000..580e277 +--- /dev/null ++++ b/sample/test_mmf/rtsp_server/src/rtsp-camera-reader.cpp +@@ -0,0 +1,286 @@ ++#include "rtsp-camera-reader.h" ++#include ++#include ++#include ++#include ++#include ++#include "time64.h" ++ ++#define H265_NAL(v) ((v>> 1) & 0x3f) ++ ++enum { NAL_IDR_W_RADL = 19, NAL_IDR_N_LP= 20, NAL_VPS = 32, NAL_SPS = 33, NAL_PPS = 34, NAL_SEI = 39}; ++ ++RtspCameraReader::RtspCameraReader(const char* file) ++:m_ptr(NULL), m_capacity(0), m_first_time(0) ++{ ++ pthread_mutex_init(&m_lock, NULL); ++ pthread_mutex_unlock(&m_lock); ++ m_vit = m_videos.begin(); ++ m_first_pop = 1; ++} ++ ++RtspCameraReader::~RtspCameraReader() ++{ ++ if (m_ptr) ++ { ++ assert(m_capacity > 0); ++ free(m_ptr); ++ } ++ ++ pthread_mutex_destroy(&m_lock); ++} ++ ++bool RtspCameraReader::IsOpened() const ++{ ++ return true; ++} ++ ++int RtspCameraReader::Seek(int64_t &dts) ++{ ++ return 0; ++} ++ ++static inline const uint8_t* search_start_code(const uint8_t* ptr, const uint8_t* end) ++{ ++ for(const uint8_t *p = ptr; p + 3 < end; p++) ++ { ++ if(0x00 == p[0] && 0x00 == p[1] && (0x01 == p[2] || (0x00==p[2] && 0x01==p[3]))) ++ return p; ++ } ++ return end; ++} ++ ++static inline int h265_nal_type(const unsigned char* ptr) ++{ ++ int i = 2; ++ assert(0x00 == ptr[0] && 0x00 == ptr[1]); ++ if(0x00 == ptr[2]) ++ ++i; ++ assert(0x01 == ptr[i]); ++ return H265_NAL(ptr[i+1]); ++} ++ ++int RtspCameraReader::SetPspFromFrame(const uint8_t* nalu, size_t bytes) ++{ ++ if(m_sps.size() == 0) { ++ int nal_unit_type = h265_nal_type(nalu); ++ if (0 > nal_unit_type) { ++ return -1; ++ } ++ ++ const uint8_t *nalu2 = (uint8_t *)nalu; ++ const uint8_t* end = nalu2 + bytes; ++ const uint8_t* p = nalu2; ++ while (p < end) ++ { ++ const unsigned char* pn = search_start_code(p + 4, end); ++ size_t size = pn - nalu2; ++ ++ int nal_unit_type = h265_nal_type(p); ++ if (nal_unit_type < 0) { ++ return -1; ++ } ++ ++ if(NAL_SPS == nal_unit_type) ++ { ++ memcpy(m_sps_nalu, nalu2, size); ++ size_t n = 0x01 == nalu2[2] ? 3 : 4; ++ std::pair pr; ++ pr.first = m_sps_nalu + n; ++ pr.second = size; ++ m_sps.push_back(pr); ++ break; ++ } ++ ++ nalu2 = pn; ++ p = pn; ++ } ++ ++ PushNextFrame(0, nalu, bytes); ++ } ++ return 0; ++} ++ ++int RtspCameraReader::GetNextFrame(int64_t &dts, const uint8_t* &ptr, size_t &bytes) ++{ ++ pthread_mutex_lock(&m_lock); ++ vframes_t::iterator frame; ++ ++ if (m_first_pop) { ++ while (1) { ++ frame = m_videos.begin(); ++ if(frame == m_videos.end()) { ++ pthread_mutex_unlock(&m_lock); ++ return -1; ++ } ++ ++ int nal_unit_type = h265_nal_type(frame->nalu); ++ if (0 > nal_unit_type) { ++ m_videos.pop_front(); ++ continue; ++ } ++ ++ if(NAL_VPS == nal_unit_type || NAL_SPS == nal_unit_type || NAL_PPS == nal_unit_type) ++ { ++ m_first_pop = 0; ++ break; ++ } else { ++ m_videos.pop_front(); ++ continue; ++ } ++ } ++ } else { ++ frame = m_videos.begin(); ++ if(frame == m_videos.end()) { ++ pthread_mutex_unlock(&m_lock); ++ return -1; ++ } ++ } ++ ++ ptr = frame->nalu; ++ dts = frame->time; ++ bytes = frame->bytes; ++ ++ pthread_mutex_unlock(&m_lock); ++ return 0; ++} ++ ++int RtspCameraReader::PushNextFrame(int64_t time, const uint8_t* nalu, size_t bytes) ++{ ++ pthread_mutex_lock(&m_lock); ++ int nal_unit_type = h265_nal_type(nalu); ++ if (0 > nal_unit_type) { ++ pthread_mutex_unlock(&m_lock); ++ return -1; ++ } ++ ++ if(m_sps.size() == 0) { ++ const uint8_t *nalu2 = (uint8_t *)nalu; ++ const uint8_t* end = nalu2 + bytes; ++ const uint8_t* p = nalu2; ++ while (p < end) ++ { ++ const unsigned char* pn = search_start_code(p + 4, end); ++ size_t size = pn - nalu2; ++ ++ int nal_unit_type = h265_nal_type(p); ++ if (nal_unit_type < 0) { ++ return -1; ++ } ++ ++ if(NAL_SPS == nal_unit_type) ++ { ++ memcpy(m_sps_nalu, nalu2, size); ++ size_t n = 0x01 == nalu2[2] ? 3 : 4; ++ std::pair pr; ++ pr.first = m_sps_nalu + n; ++ pr.second = size; ++ m_sps.push_back(pr); ++ break; ++ } ++ ++ nalu2 = pn; ++ p = pn; ++ } ++ m_first_time = time; ++ } ++ ++ vframe_t frame; ++ frame.nalu = (const uint8_t*)malloc(bytes); ++ memcpy((uint8_t *)frame.nalu, nalu, bytes); ++ frame.bytes = bytes; ++ frame.time = (time == 0) ? 0 : time - m_first_time; ++ frame.idr = (NAL_IDR_N_LP == nal_unit_type || NAL_IDR_W_RADL == nal_unit_type); // IDR-frame ++ m_videos.push_back(frame); ++ pthread_mutex_unlock(&m_lock); ++ ++ return 0; ++} ++ ++int RtspCameraReader::FreeNextFrame() ++{ ++ pthread_mutex_lock(&m_lock); ++ vframes_t::iterator frame = m_videos.begin(); ++ if(frame == m_videos.end()) { ++ pthread_mutex_unlock(&m_lock); ++ return -1; ++ } ++ ++ if (frame->nalu) { ++ free((uint8_t *)frame->nalu); ++ } ++ m_videos.pop_front(); ++ pthread_mutex_unlock(&m_lock); ++ ++ return 0; ++} ++ ++int RtspCameraReader::Init() ++{ ++#if 0 ++ size_t count = 0; ++ bool vpsspspps = true; ++ ++ const uint8_t* end = m_ptr + m_capacity; ++ const uint8_t* nalu = search_start_code(m_ptr, end); ++ const uint8_t* p = nalu; ++ ++ while (p < end) ++ { ++ const unsigned char* pn = search_start_code(p + 4, end); ++ size_t bytes = pn - nalu; ++ ++ int nal_unit_type = h265_nal_type(p); ++ assert(0 <= nal_unit_type); ++ ++ if(NAL_VPS == nal_unit_type || NAL_SPS == nal_unit_type || NAL_PPS == nal_unit_type) ++ { ++ if(vpsspspps) ++ { ++ size_t n = 0x01 == p[2] ? 3 : 4; ++ std::pair pr; ++ pr.first = p + n; ++ pr.second = bytes; ++ m_sps.push_back(pr); ++ } ++ } ++ ++ { ++ if(m_sps.size() > 0) vpsspspps = false; // don't need more vps/sps/pps ++ ++ vframe_t frame; ++ frame.nalu = nalu; ++ frame.bytes = bytes; ++ frame.time = 40 * count++; ++ frame.idr = (NAL_IDR_N_LP == nal_unit_type || NAL_IDR_W_RADL == nal_unit_type); // IDR-frame ++ m_videos.push_back(frame); ++ nalu = pn; ++ } ++ ++ p = pn; ++ } ++ ++ m_duration = 40 * count; ++ return 0; ++#else ++ // size_t count = 0; ++ ++ // const uint8_t* end = m_ptr + m_capacity; ++ // const uint8_t* nalu = search_start_code(m_ptr, end); ++ // const uint8_t* p = nalu; ++ ++ // while (p < end) ++ // { ++ // const unsigned char* pn = search_start_code(p + 4, end); ++ // size_t bytes = pn - nalu; ++ ++ // PushNextFrame(40 * count++, nalu, bytes); ++ ++ // nalu = pn; ++ // p = pn; ++ // } ++ ++ // m_duration = 40 * count; ++ return 0; ++#endif ++} +diff --git a/sample/test_mmf/rtsp_server/src/rtsp-camera-source.cpp b/sample/test_mmf/rtsp_server/src/rtsp-camera-source.cpp +new file mode 100644 +index 0000000..bf62d3e +--- /dev/null ++++ b/sample/test_mmf/rtsp_server/src/rtsp-camera-source.cpp +@@ -0,0 +1,221 @@ ++#include "rtsp-camera-source.h" ++#include "cstringext.h" ++#include "base64.h" ++#include "rtp-profile.h" ++#include "rtp-payload.h" ++#include ++ ++extern "C" uint32_t rtp_ssrc(void); ++ ++RtspCameraSource::RtspCameraSource(const char *file) ++:m_reader(file) ++{ ++ m_speed = 1.0; ++ m_status = 0; ++ m_rtp_clock = 0; ++ m_rtcp_clock = 0; ++ m_timestamp = 0; ++ ++ uint32_t ssrc = rtp_ssrc(); ++ static struct rtp_payload_t s_rtpfunc = { ++ RtspCameraSource::RTPAlloc, ++ RtspCameraSource::RTPFree, ++ RtspCameraSource::RTPPacket, ++ }; ++ m_rtppacker = rtp_payload_encode_create(RTP_PAYLOAD_H265, "H265", (uint16_t)ssrc, ssrc, &s_rtpfunc, this); ++ ++ struct rtp_event_t event; ++ event.on_rtcp = OnRTCPEvent; ++ m_rtp = rtp_create(&event, this, ssrc, m_timestamp, 90000, 4*1024, 1); ++ rtp_set_info(m_rtp, "RTSPServer", "szj.h265"); ++} ++ ++RtspCameraSource::~RtspCameraSource() ++{ ++ if(m_rtp) ++ rtp_destroy(m_rtp); ++ ++ if(m_rtppacker) ++ rtp_payload_encode_destroy(m_rtppacker); ++} ++ ++int RtspCameraSource::SetTransport(const char* /*track*/, std::shared_ptr transport) ++{ ++ m_transport = transport; ++ return 0; ++} ++ ++int RtspCameraSource::Push(int64_t time, const uint8_t* nalu, size_t bytes) ++{ ++ return m_reader.PushNextFrame(time, nalu, bytes); ++} ++ ++int RtspCameraSource::SetPspFromFrame(const uint8_t* nalu, size_t bytes) ++{ ++ return m_reader.SetPspFromFrame(nalu, bytes); ++} ++ ++int RtspCameraSource::Play() ++{ ++ m_status = 1; ++ ++ //uint32_t timestamp = 0; ++ time64_t clock = time64_now(); ++ if (0 == m_rtp_clock) ++ m_rtp_clock = clock; ++ static int64_t last_m_pos = 0; ++ if(m_rtp_clock + 10 < clock) ++ { ++ size_t bytes; ++ const uint8_t* ptr; ++ if(0 == m_reader.GetNextFrame(m_pos, ptr, bytes)) ++ { ++ m_timestamp = m_pos; ++ rtp_payload_encode_input(m_rtppacker, ptr, bytes, m_timestamp * 90 /*kHz*/); ++ SendRTCP(); ++ m_reader.FreeNextFrame(); ++ return 1; ++ } ++ } ++ ++ return 0; ++} ++ ++int RtspCameraSource::Pause() ++{ ++ m_status = 2; ++ m_rtp_clock = 0; ++ return 0; ++} ++ ++int RtspCameraSource::Seek(int64_t pos) ++{ ++ m_pos = pos; ++ m_rtp_clock = 0; ++ return 0; ++} ++ ++int RtspCameraSource::SetSpeed(double speed) ++{ ++ m_speed = speed; ++ return 0; ++} ++ ++int RtspCameraSource::GetDuration(int64_t& duration) const ++{ ++ return m_reader.GetDuration(duration); ++} ++ ++int RtspCameraSource::GetSDPMedia(std::string& sdp) const ++{ ++ static const char* pattern = ++ "m=video 0 RTP/AVP %d\n" ++ "a=rtpmap:%d H265/90000\n" ++ "a=fmtp:%d profile-level-id=%02X%02X%02X;" ++ "packetization-mode=1;" ++ "sprop-parameter-sets="; ++ ++ char base64[512] = {0}; ++ std::string parameters; ++ ++ const std::list >& sps = m_reader.GetParameterSets(); ++ std::list >::const_iterator it; ++ for(it = sps.begin(); it != sps.end(); ++it) ++ { ++ if(parameters.empty()) ++ { ++ snprintf(base64, sizeof(base64), pattern, ++ RTP_PAYLOAD_H265, RTP_PAYLOAD_H265,RTP_PAYLOAD_H265, ++ (unsigned int)(it->first[1]), (unsigned int)(it->first[2]), (unsigned int)(it->first[3])); ++ sdp = base64; ++ } ++ else ++ { ++ parameters += ','; ++ } ++ ++ size_t bytes = it->second; ++ assert((bytes+2)/3*4 + bytes/57 + 1 < sizeof(base64)); ++ bytes = base64_encode(base64, it->first, bytes); ++ base64[bytes] = '\0'; ++ assert(strlen(base64) > 0); ++ parameters += base64; ++ } ++ ++ sdp += parameters; ++ sdp += '\n'; ++ return sps.empty() ? -1 : 0; ++} ++ ++int RtspCameraSource::GetRTPInfo(const char* uri, char *rtpinfo, size_t bytes) const ++{ ++ uint16_t seq; ++ uint32_t timestamp; ++ rtp_payload_encode_getinfo(m_rtppacker, &seq, ×tamp); ++ ++ // url=rtsp://video.example.com/twister/video;seq=12312232;rtptime=78712811 ++ snprintf(rtpinfo, bytes, "url=%s;seq=%hu;rtptime=%u", uri, seq, timestamp); ++ return 0; ++} ++ ++void RtspCameraSource::OnRTCPEvent(const struct rtcp_msg_t* msg) ++{ ++ (void)msg; ++} ++ ++void RtspCameraSource::OnRTCPEvent(void* param, const struct rtcp_msg_t* msg) ++{ ++ RtspCameraSource *self = (RtspCameraSource *)param; ++ self->OnRTCPEvent(msg); ++} ++ ++int RtspCameraSource::SendRTCP() ++{ ++ // make sure have sent RTP packet ++ ++ time64_t clock = time64_now(); ++ int interval = rtp_rtcp_interval(m_rtp); ++ if(0 == m_rtcp_clock || m_rtcp_clock + interval < clock) ++ { ++ char rtcp[1024] = {0}; ++ size_t n = rtp_rtcp_report(m_rtp, rtcp, sizeof(rtcp)); ++ ++ // send RTCP packet ++ m_transport->Send(true, rtcp, n); ++ ++ m_rtcp_clock = clock; ++ } ++ ++ return 0; ++} ++ ++void* RtspCameraSource::RTPAlloc(void* param, int bytes) ++{ ++ RtspCameraSource *self = (RtspCameraSource*)param; ++ assert(bytes <= (int)sizeof(self->m_packet)); ++ return self->m_packet; ++} ++ ++void RtspCameraSource::RTPFree(void* param, void *packet) ++{ ++ RtspCameraSource *self = (RtspCameraSource*)param; ++ assert(self->m_packet == packet); ++} ++ ++int RtspCameraSource::RTPPacket(void* param, const void *packet, int bytes, uint32_t /*timestamp*/, int /*flags*/) ++{ ++ RtspCameraSource *self = (RtspCameraSource*)param; ++ assert(self->m_packet == packet); ++ // const char* ptr = (const char*)packet; ++ // for(int i=0;i 4){ ++ // exit(-1); ++ // } ++ int r = self->m_transport->Send(false, packet, bytes); ++ if (r != bytes) ++ return -1; ++ ++ return rtp_onsend(self->m_rtp, packet, bytes/*, time*/); ++} +diff --git a/sample/test_mmf/rtsp_server/src/rtsp_server.cpp b/sample/test_mmf/rtsp_server/src/rtsp_server.cpp +new file mode 100644 +index 0000000..5a4b289 +--- /dev/null ++++ b/sample/test_mmf/rtsp_server/src/rtsp_server.cpp +@@ -0,0 +1,1005 @@ ++#include "cstringext.h" ++#include "sys/sock.h" ++#include "sys/thread.h" ++#include "sys/system.h" ++#include "sys/path.h" ++#include "sys/sync.hpp" ++#include "sockutil.h" ++// #include "aio-worker.h" ++#include "ctypedef.h" ++#include "ntp-time.h" ++#include "rtp-profile.h" ++#include "rtsp-server.h" ++// #include "media/ps-file-source.h" ++#include "h264-file-source.h" ++#include "h265-file-source.h" ++#include "h264-memory-source.h" ++#include "rtsp-camera-source.h" ++// #include "media/mp4-file-source.h" ++#include "rtp-udp-transport.h" ++#include "rtp-tcp-transport.h" ++#include "rtsp-server-aio.h" ++#include "uri-parse.h" ++#include "urlcodec.h" ++#include "path.h" ++#include ++#include ++#include "cpm/shared_ptr.h" ++ ++#include ++#include ++#include ++#include ++#include ++ ++#if defined(_HAVE_FFMPEG_) ++#include "media/ffmpeg-file-source.h" ++#include "media/ffmpeg-live-source.h" ++#endif ++ ++#define UDP_MULTICAST_ADDR "239.0.0.2" ++#define UDP_MULTICAST_PORT 6000 ++ ++// ffplay rtsp://127.0.0.1/vod/video/abc.mp4 ++// Windows --> d:\video\abc.mp4 ++// Linux --> ./video/abc.mp4 ++ ++#if defined(OS_WINDOWS) ++static const char* s_workdir = "d:\\"; ++#else ++static const char* s_workdir = "./"; ++#endif ++ ++static ThreadLocker s_locker; ++static int source_type = 1; ++static IMediaSource *camera_source = NULL; ++struct rtsp_media_t ++{ ++ std::shared_ptr media; ++ std::shared_ptr transport; ++ uint8_t channel; // rtp over rtsp interleaved channel ++ int status; // setup-init, 1-play, 2-pause ++ rtsp_server_t* rtsp; ++}; ++typedef std::map TSessions; ++static TSessions s_sessions; ++ ++struct TFileDescription ++{ ++ int64_t duration; ++ std::string sdpmedia; ++}; ++static std::map s_describes; ++ ++IMediaSource *newMemorySource(const char *file) ++{ ++ if (source_type == 2) ++ return new H264MemorySource(file); ++ else ++ return new RtspCameraSource(file); ++} ++ ++static int rtsp_uri_parse(const char* uri, std::string& path) ++{ ++ char path1[256]; ++ struct uri_t* r = uri_parse(uri, strlen(uri)); ++ if(!r) ++ return -1; ++ ++ url_decode(r->path, strlen(r->path), path1, sizeof(path1)); ++ path = path1; ++ uri_free(r); ++ return 0; ++} ++ ++static int rtsp_ondescribe(void* /*ptr*/, rtsp_server_t* rtsp, const char* uri) ++{ ++ // static const char* pattern_vod = ++ // "v=0\n" ++ // "o=- %llu %llu IN IP4 %s\n" ++ // "s=%s\n" ++ // "c=IN IP4 0.0.0.0\n" ++ // "t=0 0\n" ++ // "a=range:npt=0-%.1f\n" ++ // "a=recvonly\n" ++ // "a=control:*\n"; // aggregate control ++ ++ // static const char* pattern_live = ++ // "v=0\n" ++ // "o=- %llu %llu IN IP4 %s\n" ++ // "s=%s\n" ++ // "c=IN IP4 0.0.0.0\n" ++ // "t=0 0\n" ++ // "a=range:npt=now-\n" // live ++ // "a=recvonly\n" ++ // "a=control:*\n"; // aggregate control ++ ++ std::string filename; ++ std::map::const_iterator it; ++ ++ rtsp_uri_parse(uri, filename); ++ if (strstartswith(filename.c_str(), "/live")) ++ { ++ // living ++ filename = filename.c_str() + 5; ++ } ++ else if (strstartswith(filename.c_str(), "/live/")) ++ { ++ filename = filename.c_str() + 6; ++ } ++ else if (strstartswith(filename.c_str(), "/vod/")) ++ { ++ filename = path::join(s_workdir, filename.c_str() + 5); ++ } ++ else ++ { ++ assert(0); ++ return -1; ++ } ++ ++ char buffer[1024] = { 0 }; ++ { ++ AutoThreadLocker locker(s_locker); ++ it = s_describes.find(filename); ++ if(it == s_describes.end()) ++ { ++ // unlock ++ TFileDescription describe; ++ std::shared_ptr source; ++ if (0 == filename.size()) ++ { ++// #if defined(_HAVE_FFMPEG_) ++// source.reset(new FFLiveSource("video=Integrated Webcam")); ++// #endif ++ if (!camera_source) { ++ camera_source = newMemorySource("output.h26x"); ++ } ++ source.reset(camera_source); ++ // int offset = snprintf(buffer, sizeof(buffer), pattern_live, ntp64_now(), ntp64_now(), "0.0.0.0", uri); ++ // assert(offset > 0 && offset + 1 < sizeof(buffer)); ++ } ++ else ++ { ++ if (strendswith(filename.c_str(), ".ps")) ++ { ++ // source.reset(new PSFileSource(filename.c_str())); ++ } ++ else if (strendswith(filename.c_str(), ".h264")) ++ source.reset(new H264FileSource(filename.c_str())); ++ else if (strendswith(filename.c_str(), ".h265")) ++ source.reset(new H265FileSource(filename.c_str())); ++ else ++ { ++// #if defined(_HAVE_FFMPEG_) ++// source.reset(new FFFileSource(filename.c_str())); ++// #else ++// source.reset(new MP4FileSource(filename.c_str())); ++// #endif ++ } ++ source->GetDuration(describe.duration); ++ ++ // int offset = snprintf(buffer, sizeof(buffer), pattern_vod, ntp64_now(), ntp64_now(), "0.0.0.0", uri, describe.duration / 1000.0); ++ // assert(offset > 0 && offset + 1 < sizeof(buffer)); ++ } ++ ++ source->GetSDPMedia(describe.sdpmedia); ++ ++ // re-lock ++ it = s_describes.insert(std::make_pair(filename, describe)).first; ++ } ++ } ++ ++ std::string sdp = buffer; ++ sdp += it->second.sdpmedia; ++ return rtsp_server_reply_describe(rtsp, 200, sdp.c_str()); ++} ++ ++static int rtsp_onsetup(void* /*ptr*/, rtsp_server_t* rtsp, const char* uri, const char* session, const struct rtsp_header_transport_t transports[], size_t num) ++{ ++ std::string filename; ++ char rtsp_transport[256]; ++ const struct rtsp_header_transport_t *transport = NULL; ++ ++ rtsp_uri_parse(uri, filename); ++ if (strstartswith(filename.c_str(), "/live")) ++ { ++ // living ++ filename = filename.c_str() + 5; ++ } ++ else if (strstartswith(filename.c_str(), "/live/")) ++ { ++ filename = filename.c_str() + 6; ++ } ++ else if (strstartswith(filename.c_str(), "/vod/")) ++ { ++ filename = path::join(s_workdir, filename.c_str() + 5); ++ } ++ else ++ { ++ assert(0); ++ return -1; ++ } ++ ++ if ('\\' == *filename.rbegin() || '/' == *filename.rbegin()) ++ filename.erase(filename.end() - 1); ++ ++ if (filename.size() > 0) { ++ const char* basename = path_basename(filename.c_str()); ++ if (NULL == strchr(basename, '.')) // filter track1 ++ filename.erase(basename - filename.c_str() - 1, std::string::npos); ++ ++ } ++ ++ TSessions::iterator it; ++ if(session) ++ { ++ AutoThreadLocker locker(s_locker); ++ it = s_sessions.find(session); ++ if(it == s_sessions.end()) ++ { ++ // 454 Session Not Found ++ return rtsp_server_reply_setup(rtsp, 454, NULL, NULL); ++ } ++ else ++ { ++ // don't support aggregate control ++ if (0) ++ { ++ // 459 Aggregate Operation Not Allowed ++ return rtsp_server_reply_setup(rtsp, 459, NULL, NULL); ++ } ++ } ++ } ++ else ++ { ++ rtsp_media_t item; ++ item.rtsp = rtsp; ++ item.channel = 0; ++ item.status = 0; ++ ++ if (0 == filename.size()) ++ { ++// #if defined(_HAVE_FFMPEG_) ++// item.media.reset(new FFLiveSource("video=Integrated Webcam")); ++// #endif ++ camera_source = newMemorySource("output.h26x"); ++ item.media.reset(camera_source); ++ } ++ else ++ { ++ if (strendswith(filename.c_str(), ".ps")) ++ { ++ // item.media.reset(new PSFileSource(filename.c_str())); ++ } ++ else if (strendswith(filename.c_str(), ".h264")) ++ item.media.reset(new H264FileSource(filename.c_str())); ++ else if (strendswith(filename.c_str(), ".h265")) ++ item.media.reset(new H265FileSource(filename.c_str())); ++ else ++ { ++// #if defined(_HAVE_FFMPEG_) ++// item.media.reset(new FFFileSource(filename.c_str())); ++// #else ++// item.media.reset(new MP4FileSource(filename.c_str())); ++// #endif ++ } ++ } ++ ++ char rtspsession[32]; ++ snprintf(rtspsession, sizeof(rtspsession), "%p", item.media.get()); ++ ++ AutoThreadLocker locker(s_locker); ++ it = s_sessions.insert(std::make_pair(rtspsession, item)).first; ++ } ++ ++ assert(NULL == transport); ++ for(size_t i = 0; i < num && !transport; i++) ++ { ++ if(RTSP_TRANSPORT_RTP_UDP == transports[i].transport) ++ { ++ // RTP/AVP/UDP ++ transport = &transports[i]; ++ } ++ else if(RTSP_TRANSPORT_RTP_TCP == transports[i].transport) ++ { ++ // RTP/AVP/TCP ++ // 10.12 Embedded (Interleaved) Binary Data (p40) ++ transport = &transports[i]; ++ } ++ } ++ if(!transport) ++ { ++ // 461 Unsupported Transport ++ return rtsp_server_reply_setup(rtsp, 461, NULL, NULL); ++ } ++ ++ rtsp_media_t &item = it->second; ++ if (RTSP_TRANSPORT_RTP_TCP == transport->transport) ++ { ++ // 10.12 Embedded (Interleaved) Binary Data (p40) ++ int interleaved[2]; ++ if (transport->interleaved1 == transport->interleaved2) ++ { ++ interleaved[0] = item.channel++; ++ interleaved[1] = item.channel++; ++ } ++ else ++ { ++ interleaved[0] = transport->interleaved1; ++ interleaved[1] = transport->interleaved2; ++ } ++ ++ item.transport = std::make_shared(rtsp, interleaved[0], interleaved[1]); ++ item.media->SetTransport(path_basename(uri), item.transport); ++ ++ // RTP/AVP/TCP;interleaved=0-1 ++ snprintf(rtsp_transport, sizeof(rtsp_transport), "RTP/AVP/TCP;interleaved=%d-%d", interleaved[0], interleaved[1]); ++ } ++ else if(transport->multicast) ++ { ++ unsigned short port[2] = { transport->rtp.u.client_port1, transport->rtp.u.client_port2 }; ++ char multicast[100]; ++ // RFC 2326 1.6 Overall Operation p12 ++ ++ if(transport->destination[0]) ++ { ++ // Multicast, client chooses address ++ snprintf(multicast, sizeof(multicast), "%s", transport->destination); ++ port[0] = transport->rtp.m.port1; ++ port[1] = transport->rtp.m.port2; ++ } ++ else ++ { ++ // Multicast, server chooses address ++ snprintf(multicast, sizeof(multicast), "%s", UDP_MULTICAST_ADDR); ++ port[0] = UDP_MULTICAST_PORT; ++ port[1] = UDP_MULTICAST_PORT + 1; ++ } ++ ++ item.transport = std::make_shared(); ++ if(0 != ((RTPUdpTransport*)item.transport.get())->Init(multicast, port)) ++ { ++ // log ++ ++ // 500 Internal Server Error ++ return rtsp_server_reply_setup(rtsp, 500, NULL, NULL); ++ } ++ item.media->SetTransport(path_basename(uri), item.transport); ++ ++ // Transport: RTP/AVP;multicast;destination=224.2.0.1;port=3456-3457;ttl=16 ++ snprintf(rtsp_transport, sizeof(rtsp_transport), ++ "RTP/AVP;multicast;destination=%s;port=%hu-%hu;ttl=%d", ++ multicast, port[0], port[1], 16); ++ ++ // 461 Unsupported Transport ++ //return rtsp_server_reply_setup(rtsp, 461, NULL, NULL); ++ } ++ else ++ { ++ // unicast ++ item.transport = std::make_shared(); ++ ++ assert(transport->rtp.u.client_port1 && transport->rtp.u.client_port2); ++ unsigned short port[2] = { transport->rtp.u.client_port1, transport->rtp.u.client_port2 }; ++ const char *ip = transport->destination[0] ? transport->destination : rtsp_server_get_client(rtsp, NULL); ++ if(0 != ((RTPUdpTransport*)item.transport.get())->Init(ip, port)) ++ { ++ // log ++ ++ // 500 Internal Server Error ++ return rtsp_server_reply_setup(rtsp, 500, NULL, NULL); ++ } ++ item.media->SetTransport(path_basename(uri), item.transport); ++ ++ // RTP/AVP;unicast;client_port=4588-4589;server_port=6256-6257;destination=xxxx ++ snprintf(rtsp_transport, sizeof(rtsp_transport), ++ "RTP/AVP;unicast;client_port=%hu-%hu;server_port=%hu-%hu%s%s", ++ transport->rtp.u.client_port1, transport->rtp.u.client_port2, ++ port[0], port[1], ++ transport->destination[0] ? ";destination=" : "", ++ transport->destination[0] ? transport->destination : ""); ++ } ++ ++ return rtsp_server_reply_setup(rtsp, 200, it->first.c_str(), rtsp_transport); ++} ++ ++static int rtsp_onplay(void* /*ptr*/, rtsp_server_t* rtsp, const char* uri, const char* session, const int64_t *npt, const double *scale) ++{ ++ std::shared_ptr source; ++ TSessions::iterator it; ++ { ++ AutoThreadLocker locker(s_locker); ++ it = s_sessions.find(session ? session : ""); ++ if(it == s_sessions.end()) ++ { ++ // 454 Session Not Found ++ return rtsp_server_reply_play(rtsp, 454, NULL, NULL, NULL); ++ } ++ else ++ { ++ // uri with track ++ if (0) ++ { ++ // 460 Only aggregate operation allowed ++ return rtsp_server_reply_play(rtsp, 460, NULL, NULL, NULL); ++ } ++ } ++ ++ source = it->second.media; ++ } ++ if(npt && 0 != source->Seek(*npt)) ++ { ++ // 457 Invalid Range ++ return rtsp_server_reply_play(rtsp, 457, NULL, NULL, NULL); ++ } ++ ++ if(scale && 0 != source->SetSpeed(*scale)) ++ { ++ // set speed ++ assert(*scale > 0); ++ ++ // 406 Not Acceptable ++ return rtsp_server_reply_play(rtsp, 406, NULL, NULL, NULL); ++ } ++ ++ // RFC 2326 12.33 RTP-Info (p55) ++ // 1. Indicates the RTP timestamp corresponding to the time value in the Range response header. ++ // 2. A mapping from RTP timestamps to NTP timestamps (wall clock) is available via RTCP. ++ char rtpinfo[512] = { 0 }; ++ source->GetRTPInfo(uri, rtpinfo, sizeof(rtpinfo)); ++ ++ // for vlc 2.2.2 ++ // MP4FileSource* mp4 = dynamic_cast(source.get()); ++ // if(mp4) ++ // mp4->SendRTCP(system_clock()); ++ ++ it->second.status = 1; ++ return rtsp_server_reply_play(rtsp, 200, npt, NULL, rtpinfo); ++} ++ ++static int rtsp_onpause(void* /*ptr*/, rtsp_server_t* rtsp, const char* /*uri*/, const char* session, const int64_t* /*npt*/) ++{ ++ std::shared_ptr source; ++ TSessions::iterator it; ++ { ++ AutoThreadLocker locker(s_locker); ++ it = s_sessions.find(session ? session : ""); ++ if(it == s_sessions.end()) ++ { ++ // 454 Session Not Found ++ return rtsp_server_reply_pause(rtsp, 454); ++ } ++ else ++ { ++ // uri with track ++ if (0) ++ { ++ // 460 Only aggregate operation allowed ++ return rtsp_server_reply_pause(rtsp, 460); ++ } ++ } ++ ++ source = it->second.media; ++ it->second.status = 2; ++ } ++ ++ source->Pause(); ++ ++ // 457 Invalid Range ++ ++ return rtsp_server_reply_pause(rtsp, 200); ++} ++ ++static int rtsp_onteardown(void* /*ptr*/, rtsp_server_t* rtsp, const char* /*uri*/, const char* session) ++{ ++ std::shared_ptr source; ++ TSessions::iterator it; ++ { ++ AutoThreadLocker locker(s_locker); ++ it = s_sessions.find(session ? session : ""); ++ if(it == s_sessions.end()) ++ { ++ // 454 Session Not Found ++ return rtsp_server_reply_teardown(rtsp, 454); ++ } ++ ++ source = it->second.media; ++ s_sessions.erase(it); ++ } ++ ++ return rtsp_server_reply_teardown(rtsp, 200); ++} ++ ++static int rtsp_onannounce(void* /*ptr*/, rtsp_server_t* rtsp, const char* uri, const char* sdp, int len) ++{ ++ return rtsp_server_reply_announce(rtsp, 200); ++} ++ ++static int rtsp_onrecord(void* /*ptr*/, rtsp_server_t* rtsp, const char* uri, const char* session, const int64_t *npt, const double *scale) ++{ ++ return rtsp_server_reply_record(rtsp, 200, NULL, NULL); ++} ++ ++static int rtsp_onoptions(void* ptr, rtsp_server_t* rtsp, const char* uri) ++{ ++ __attribute__((unused)) const char* require = rtsp_server_get_header(rtsp, "Require"); ++ return rtsp_server_reply_options(rtsp, 200); ++} ++ ++static int rtsp_ongetparameter(void* ptr, rtsp_server_t* rtsp, const char* uri, const char* session, const void* content, int bytes) ++{ ++ __attribute__((unused)) const char* ctype = rtsp_server_get_header(rtsp, "Content-Type"); ++ __attribute__((unused)) const char* encoding = rtsp_server_get_header(rtsp, "Content-Encoding"); ++ __attribute__((unused)) const char* language = rtsp_server_get_header(rtsp, "Content-Language"); ++ return rtsp_server_reply_get_parameter(rtsp, 200, NULL, 0); ++} ++ ++static int rtsp_onsetparameter(void* ptr, rtsp_server_t* rtsp, const char* uri, const char* session, const void* content, int bytes) ++{ ++ __attribute__((unused)) const char* ctype = rtsp_server_get_header(rtsp, "Content-Type"); ++ __attribute__((unused)) const char* encoding = rtsp_server_get_header(rtsp, "Content-Encoding"); ++ __attribute__((unused)) const char* language = rtsp_server_get_header(rtsp, "Content-Language"); ++ return rtsp_server_reply_set_parameter(rtsp, 200); ++} ++ ++static int rtsp_onclose(void* /*ptr2*/) ++{ ++ // TODO: notify rtsp connection lost ++ // start a timer to check rtp/rtcp activity ++ // close rtsp media session on expired ++ printf("rtsp close\n"); ++ s_sessions.clear(); ++ camera_source = NULL; ++ return 0; ++} ++ ++// static void rtsp_onerror(void* /*param*/, rtsp_server_t* rtsp, int code) ++// { ++// printf("rtsp_onerror code=%d, rtsp=%p\n", code, rtsp); ++ ++// TSessions::iterator it; ++// AutoThreadLocker locker(s_locker); ++// for (it = s_sessions.begin(); it != s_sessions.end(); ++it) ++// { ++// if (rtsp == it->second.rtsp) ++// { ++// it->second.media->Pause(); ++// s_sessions.erase(it); ++// break; ++// } ++// } ++ ++// //return 0; ++// } ++ ++#if 1 ++static int rtsp_send(void* ptr, const void* data, size_t bytes) ++{ ++ socket_t socket = (socket_t)(intptr_t)ptr; ++ ++ // TODO: send multiple rtp packet once time ++ return (int)bytes == socket_send(socket, data, bytes, 0) ? 0 : -1; ++} ++ ++extern "C" void rtsp_example() ++{ ++ socket_t socket; ++ char buffer[512]; ++ ++ // create server socket ++ socket = socket_tcp_listen(0 /*AF_UNSPEC*/, "0.0.0.0", 8554, SOMAXCONN, 1, 0); ++ if (socket_invalid == socket) ++ return; ++ ++ while(1) ++ { ++ sockaddr_storage addr; ++ socklen_t len = sizeof(addr); ++ socket_t tcp = socket_accept(socket, &addr, &len); ++ if (socket_invalid == tcp) ++ continue; ++ ++ struct rtsp_handler_t handler; ++ memset(&handler, 0, sizeof(handler)); ++ handler.ondescribe = rtsp_ondescribe; ++ handler.onsetup = rtsp_onsetup; ++ handler.onplay = rtsp_onplay; ++ handler.onpause = rtsp_onpause; ++ handler.onteardown = rtsp_onteardown; ++ handler.onannounce = rtsp_onannounce; ++ handler.onrecord = rtsp_onrecord; ++ handler.onoptions = rtsp_onoptions; ++ handler.ongetparameter = rtsp_ongetparameter; ++ handler.onsetparameter = rtsp_onsetparameter; ++ handler.close = rtsp_onclose; ++ handler.send = rtsp_send; ++ ++ u_short port = 0; ++ socket_setnonblock(tcp, 0); // block io ++ socket_addr_to((const sockaddr*)&addr, len, buffer, &port); ++ struct rtsp_server_t* rtsp = rtsp_server_create(buffer, port, &handler, NULL, (void*)(intptr_t)tcp); // reuse-able, don't need create in every link ++ ++ while (1) ++ { ++ int r = socket_recv_by_time(tcp, buffer, sizeof(buffer), 0, 5); ++ if (r > 0) ++ { ++ size_t n = r; ++ r = rtsp_server_input(rtsp, buffer, &n); ++ assert(n == 0 && r == 0); ++ } ++ else if (r <= 0 && r != SOCKET_TIMEDOUT) ++ { ++ break; ++ } ++ ++ TSessions::iterator it; ++ AutoThreadLocker locker(s_locker); ++ ++ for (it = s_sessions.begin(); it != s_sessions.end(); ++it) ++ { ++ rtsp_media_t& session = it->second; ++ if (1 == session.status) { ++ session.media->Play(); ++ } ++ } ++ } ++ ++ rtsp_server_destroy(rtsp); ++ socket_close(tcp); ++ } ++ ++ socket_close(socket); ++} ++ ++#else ++// #define N_AIO_THREAD 4 ++// extern "C" void rtsp_example() ++// { ++// aio_worker_init(N_AIO_THREAD); ++// ++// struct aio_rtsp_handler_t handler; ++// memset(&handler, 0, sizeof(handler)); ++// handler.base.ondescribe = rtsp_ondescribe; ++// handler.base.onsetup = rtsp_onsetup; ++// handler.base.onplay = rtsp_onplay; ++// handler.base.onpause = rtsp_onpause; ++// handler.base.onteardown = rtsp_onteardown; ++// handler.base.close = rtsp_onclose; ++// handler.base.onannounce = rtsp_onannounce; ++// handler.base.onrecord = rtsp_onrecord; ++// handler.base.onoptions = rtsp_onoptions; ++// handler.base.ongetparameter = rtsp_ongetparameter; ++// handler.base.onsetparameter = rtsp_onsetparameter; ++// // handler.base.send; // ignore ++// handler.onerror = rtsp_onerror; ++ ++// // 1. check s_workdir, MUST be end with '/' or '\\' ++// // 2. url: rtsp://127.0.0.1:8554/vod/ ++// void* tcp = rtsp_server_listen("0.0.0.0", 8554, &handler, NULL); assert(tcp); ++// // void* udp = rtsp_transport_udp_create(NULL, 554, &handler, NULL); assert(udp); ++// ++// // test only ++// while(1) ++// { ++// system_sleep(5); ++ ++// TSessions::iterator it; ++// AutoThreadLocker locker(s_locker); ++// for(it = s_sessions.begin(); it != s_sessions.end(); ++it) ++// { ++// rtsp_media_t &session = it->second; ++// if(1 == session.status) ++// session.media->Play(); ++// } ++ ++// // TODO: check rtsp session activity ++// } ++ ++// aio_worker_clean(N_AIO_THREAD); ++// rtsp_server_unlisten(tcp); ++// // rtsp_transport_udp_destroy(udp); ++// } ++#endif // N_AIO_THREAD ++ ++// #if defined(RTSP_TEST_MAIN) ++ ++static int get_ip(char *hw, char ip[16]) ++{ ++ struct ifaddrs *ifaddr, *ifa; ++ int family, s; ++ char host[NI_MAXHOST]; ++ ++ if (getifaddrs(&ifaddr) == -1) { ++ perror("getifaddrs"); ++ return -1; ++ } ++ ++ for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) { ++ if (ifa->ifa_addr == NULL) { ++ continue; ++ } ++ ++ family = ifa->ifa_addr->sa_family; ++ ++ if (family == AF_INET) { ++ s = getnameinfo(ifa->ifa_addr, (family == AF_INET) ? sizeof(struct sockaddr_in) : ++ sizeof(struct sockaddr_in6), host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST); ++ if (s != 0) { ++ printf("getnameinfo() failed: %s\n", gai_strerror(s)); ++ return -1; ++ } ++ ++ if (!strcmp(ifa->ifa_name, hw)) { ++ strncpy(ip, host, 16); ++ freeifaddrs(ifaddr); ++ return 0; ++ } ++ } ++ } ++ ++ freeifaddrs(ifaddr); ++ return -1; ++} ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++typedef struct { ++ bool rtsp_is_init; ++ bool rtsp_is_start; ++ socket_t rtsp_socket; ++ pthread_t rtsp_id; ++ char ip[16]; ++ int port; ++} priv_t; ++ ++static priv_t priv; ++ ++int rtsp_server_init(char *ip, int port) ++{ ++ socket_t socket; ++ if (priv.rtsp_is_init) { ++ return 0; ++ } ++ ++ char new_ip[16] = {0}; ++ if (ip == NULL) { ++ // if (get_ip((char *)"eth0", new_ip) && get_ip((char *)"usb0", new_ip)) { ++ // strcpy(new_ip, "0.0.0.0"); ++ // } ++ if (get_ip((char *)"end0", new_ip) && get_ip((char *)"eth0", new_ip) && ++ get_ip((char *)"wlan0", new_ip) && get_ip((char *)"usb0", new_ip)) { ++ strcpy(new_ip, "0.0.0.0"); ++ } ++ } else { ++ strcpy(new_ip, ip); ++ } ++ ++ // create server socket ++ socket = socket_tcp_listen(0 /*AF_UNSPEC*/, new_ip, port, SOMAXCONN, 0, 0); ++ if (socket_invalid == socket) ++ return -1; ++ ++ strcpy(priv.ip, new_ip); ++ priv.port = port; ++ ++ priv.rtsp_socket = socket; ++ priv.rtsp_is_init = true; ++ return 0; ++} ++ ++int rtsp_server_deinit(void) ++{ ++ if (!priv.rtsp_is_init) { ++ return 0; ++ } ++ ++ socket_close(priv.rtsp_socket); ++ ++ priv.rtsp_is_init = true; ++ return 0; ++} ++ ++char *rtsp_get_server_ip(void) ++{ ++ return priv.ip; ++} ++ ++int rtsp_get_server_port(void) ++{ ++ return priv.port; ++} ++ ++void rtsp_send_h265_data(uint64_t time, uint8_t *data, size_t data_len) ++{ ++ TSessions::iterator it; ++ AutoThreadLocker locker(s_locker); ++ RtspCameraSource *media = (RtspCameraSource *)camera_source; ++ if (media) { ++ media->SetPspFromFrame(data, data_len); ++ } ++ ++ for (it = s_sessions.begin(); it != s_sessions.end(); ++it) ++ { ++ rtsp_media_t& session = it->second; ++ if(session.status == 1) { ++ media->Push(time, (uint8_t *)data, data_len); ++ } ++ } ++} ++ ++void rtsp_send_h264_data(uint64_t time, uint8_t *data, size_t data_len) ++{ ++ TSessions::iterator it; ++ AutoThreadLocker locker(s_locker); ++ H264MemorySource *media = (H264MemorySource *)camera_source; ++ if (media) { ++ media->SetPspFromFrame(data, data_len); ++ } ++ ++ for (it = s_sessions.begin(); it != s_sessions.end(); ++it) ++ { ++ rtsp_media_t& session = it->second; ++ if(session.status == 1) { ++ media->Push(time, (uint8_t *)data, data_len); ++ } ++ } ++} ++ ++void rtsp_send_memory_data(uint64_t time, uint8_t *data, size_t data_len) ++{ ++ if (source_type == 2) ++ rtsp_send_h264_data(time, data, data_len); ++ else ++ rtsp_send_h265_data(time, data, data_len); ++} ++ ++static void* _rtsp_server_thread(void *args) ++{ ++ (void)args; ++ socket_t socket; ++ char buffer[512]; ++ socket = priv.rtsp_socket; ++ while(1) ++ { ++ sockaddr_storage addr; ++ socklen_t len = sizeof(addr); ++ socket_t tcp = socket_accept(socket, &addr, &len); ++ if (socket_invalid == tcp) ++ continue; ++ ++ struct rtsp_handler_t handler; ++ memset(&handler, 0, sizeof(handler)); ++ handler.ondescribe = rtsp_ondescribe; ++ handler.onsetup = rtsp_onsetup; ++ handler.onplay = rtsp_onplay; ++ handler.onpause = rtsp_onpause; ++ handler.onteardown = rtsp_onteardown; ++ handler.onannounce = rtsp_onannounce; ++ handler.onrecord = rtsp_onrecord; ++ handler.onoptions = rtsp_onoptions; ++ handler.ongetparameter = rtsp_ongetparameter; ++ handler.onsetparameter = rtsp_onsetparameter; ++ handler.close = rtsp_onclose; ++ handler.send = rtsp_send; ++ ++ u_short port = 0; ++ socket_setnonblock(tcp, 0); // block io ++ socket_addr_to((const sockaddr*)&addr, len, buffer, &port); ++ struct rtsp_server_t* rtsp = rtsp_server_create(buffer, port, &handler, NULL, (void*)(intptr_t)tcp); // reuse-able, don't need create in every link ++ ++ while (1) ++ { ++ int r = socket_recv_by_time(tcp, buffer, sizeof(buffer), 0, 5); ++ if (r > 0) ++ { ++ size_t n = r; ++ r = rtsp_server_input(rtsp, buffer, &n); ++ continue; ++ } ++ else if (r <= 0 && r != SOCKET_TIMEDOUT) ++ { ++ break; ++ } ++ ++ TSessions::iterator it; ++ AutoThreadLocker locker(s_locker); ++ for (it = s_sessions.begin(); it != s_sessions.end(); ++it) ++ { ++ rtsp_media_t& session = it->second; ++ if (1 == session.status) { ++ session.media->Play(); ++ } ++ } ++ } ++ ++ rtsp_server_destroy(rtsp); ++ socket_close(tcp); ++ } ++ ++ return NULL; ++} ++ ++int rtsp_memory_server_start(int type) ++{ ++ if (!priv.rtsp_is_init) { ++ return -1; ++ } ++ ++ if (priv.rtsp_is_start) { ++ return 0; ++ } ++ ++ source_type = type; ++ camera_source = newMemorySource(NULL); ++ if (!camera_source) { ++ perror("create rtsp camera source failed!\r\n"); ++ return -1; ++ } ++ ++ if (0 != pthread_create(&priv.rtsp_id, NULL, _rtsp_server_thread, NULL)) { ++ return -1; ++ } ++ ++ priv.rtsp_is_start = true; ++ return 0; ++} ++ ++int rtsp_server_start(void) ++{ ++ return rtsp_memory_server_start(1); ++} ++ ++int rtsp_server_stop(void) ++{ ++ if (!priv.rtsp_is_init) { ++ return -1; ++ } ++ ++ if (!priv.rtsp_is_start) { ++ return 0; ++ } ++ ++ if (0 != pthread_cancel(priv.rtsp_id)) { ++ return -1; ++ } ++ ++ if (camera_source) { ++ delete camera_source; ++ } ++ ++ priv.rtsp_is_start = false; ++ ++ return 0; ++} ++ ++#ifdef __cplusplus ++} ++#endif ++ ++std::vector rtsp_get_server_urls(void) ++{ ++ char new_ip[16] = {0}; ++ ++ std::vector ip_list; ++ ++ if (!strcmp("0.0.0.0", priv.ip)) { ++ if (!get_ip((char *)"end0", new_ip)) { ++ ip_list.push_back("rtsp://" + std::string(new_ip) + ":" + std::to_string(priv.port) + "/live"); ++ } ++ if (!get_ip((char *)"eth0", new_ip)) { ++ ip_list.push_back("rtsp://" + std::string(new_ip) + ":" + std::to_string(priv.port) + "/live"); ++ } ++ if (!get_ip((char *)"usb0", new_ip)) { ++ ip_list.push_back("rtsp://" + std::string(new_ip) + ":" + std::to_string(priv.port) + "/live"); ++ } ++ if (!get_ip((char *)"wlan0", new_ip)) { ++ ip_list.push_back("rtsp://" + std::string(new_ip) + ":" + std::to_string(priv.port) + "/live"); ++ } ++ } else { ++ ip_list.push_back("rtsp://" + std::string(priv.ip) + ":" + std::to_string(priv.port) + "/live"); ++ } ++ ++ return ip_list; ++} +\ No newline at end of file +diff --git a/sample/test_mmf/sample_vio.c b/sample/test_mmf/sample_vio.c +new file mode 100644 +index 0000000..9c63827 +--- /dev/null ++++ b/sample/test_mmf/sample_vio.c +@@ -0,0 +1,3079 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "cvi_buffer.h" ++#include "cvi_ae_comm.h" ++#include "cvi_awb_comm.h" ++#include "cvi_comm_isp.h" ++#include "cvi_ive.h" ++#include "cvi_awb.h" ++ ++#include "sample_comm.h" ++#include "maix_mmf.h" ++// #include "vo_uapi.h" ++#include "rtsp_server.h" ++#include "fomat.h" ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++ ++static int rtsp_server_type = 1; //1, h265, 2, h264 ++ ++// #define DEBUG_EN ++#ifdef DEBUG_EN ++#define DEBUG(fmt, args...) printf("[%s][%d]: "fmt, __func__, __LINE__, ##args) ++#else ++#define DEBUG(fmt, args...) ++#endif ++ ++int exit_flag = 0; ++static void sig_handle(CVI_S32 signo) ++{ ++ UNUSED(signo); ++ signal(SIGINT, SIG_IGN); ++ signal(SIGTERM, SIG_IGN); ++ exit_flag = 1; ++} ++ ++static void exit_handle(CVI_S32 signo) ++{ ++ printf("exit handle! signo:%d\n", signo); ++ mmf_deinit(); ++ exit(0); ++} ++ ++static uint64_t _get_time_us(void) ++{ ++ struct timeval tv; ++ gettimeofday(&tv, NULL); ++ return tv.tv_usec + tv.tv_sec * 1000000; ++} ++ ++#define OLED_DISABLE 0 ++#define OLED_ENABLE 1 ++#define oled_i2c_bus 5 // 4.1.0 sdk: 3 ++#define oled_i2c_addr 0x3D ++#define OLED_CMD 0x00 ++#define OLED_DATA 0x40 ++ ++// int oled_dev; ++int oled_i2c_init(uint8_t _EN, int * oled_dev) ++{ ++ // PinMux ++ system("devmem 0x030010E0 32 0x2"); ++ system("devmem 0x030010E4 32 0x2"); ++ int ret; ++ if(_EN) { ++ char i2c_dev[12]; ++ sprintf(i2c_dev, "/dev/i2c-%hhd", oled_i2c_bus); ++ *oled_dev = open(i2c_dev, O_RDWR, 0600); ++ if (*oled_dev < 0) { ++ CVI_TRACE_SNS(CVI_DBG_ERR, "Open /dev/cvi_i2c_drv-3 error!\n"); ++ return CVI_FAILURE; ++ } ++ ++ ret = ioctl(*oled_dev, I2C_SLAVE_FORCE, oled_i2c_addr); ++ if (ret < 0) { ++ printf("I2C_SLAVE_FORCE error! = %d\n", ret); ++ close(*oled_dev); ++ *oled_dev = -1; ++ return ret; ++ } ++ printf("I2C_SLAVE_FORCE OK! = %d\n", ret); ++ return ret; ++ } else { ++ if (*oled_dev >= 0) { ++ close(*oled_dev); ++ *oled_dev = -1; ++ ret = 0; ++ return ret; ++ } ++ } ++ return -1; ++} ++ ++int oled_read_register(int _fb, uint8_t addr) ++{ ++ int ret, data; ++ CVI_U8 buf[2]; ++ ++ if (_fb < 0) ++ return CVI_FAILURE; ++ ++ buf[0] = addr; ++ ++ ret = write(_fb, buf, 1); ++ if (ret < 0) { ++ CVI_TRACE_SNS(CVI_DBG_ERR, "I2C_WRITE error!\n"); ++ return ret; ++ } ++ ++ buf[0] = 0; ++ buf[1] = 0; ++ ret = read(_fb, buf, 1); ++ if (ret < 0) { ++ CVI_TRACE_SNS(CVI_DBG_ERR, "I2C_READ error!\n"); ++ return ret; ++ } ++ ++ // pack read back data ++ data = buf[0]; ++ ++ DEBUG("i2c r 0x%x = 0x%x\n", addr, data); ++ return data; ++} ++ ++/* mode = OLED_CMD ++ * = OLED_DATA */ ++int oled_write_register(int _fb, uint8_t mode, uint8_t data) ++{ ++ int ret; ++ CVI_U8 buf[2]; ++ ++ if (_fb < 0) ++ return CVI_SUCCESS; ++ buf[0] = mode; ++ buf[1] = data; ++ ++ ret = write(_fb, buf, 2); ++ if (ret < 0) { ++ CVI_TRACE_SNS(CVI_DBG_ERR, "I2C_WRITE error!\n"); ++ return CVI_FAILURE; ++ } ++ syslog(LOG_DEBUG, "i2c w 0x%x 0x%x\n", mode, data); ++ return CVI_SUCCESS; ++} ++ ++// 坐标设置 ++void OLED_Set_Pos(int _fb, uint8_t x, uint8_t y) ++{ ++ oled_write_register(_fb, OLED_CMD, 0xb0+y); ++ oled_write_register(_fb, OLED_CMD, ((x&0xf0)>>4)|0x10); ++ oled_write_register(_fb, OLED_CMD, (x&0x0f)); ++} ++ ++//开启OLED显示 ++void OLED_Display_On(int _fb) ++{ ++ oled_write_register(_fb, OLED_CMD, 0X8D); ++ oled_write_register(_fb, OLED_CMD, 0X14); ++ oled_write_register(_fb, OLED_CMD, 0XAF); ++} ++ ++//关闭OLED显示 ++void OLED_Display_Off(int _fb) ++{ ++ oled_write_register(_fb, OLED_CMD, 0X8D); ++ oled_write_register(_fb, OLED_CMD, 0X10); ++ oled_write_register(_fb, OLED_CMD, 0XAE); ++} ++ ++//清屏函数,清完屏,整个屏幕是黑色的!和没点亮一样!!! ++void OLED_Clear(int _fb) ++{ ++ uint8_t i,n; ++ for(i=0;i<8;i++) ++ { ++ oled_write_register(_fb, OLED_CMD, 0xb0+i); ++ oled_write_register(_fb, OLED_CMD, 0x00); ++ oled_write_register(_fb, OLED_CMD, 0x10); ++ for(n=0;n<128;n++)oled_write_register(_fb, OLED_DATA, 0x00); ++ } //更新显示 ++} ++ ++//在指定位置显示一个字符,包括部分字符 ++//x:0~127 ++//y:0~63 ++//sizey:选择字体 6x8 8x16 ++void OLED_ShowChar(int _fb, uint8_t x,uint8_t y,uint8_t chr,uint8_t sizey) ++{ ++ uint8_t c=0,sizex=sizey/2; ++ uint16_t i=0,size1; ++ if(sizey==8)size1=6; ++ else size1=(sizey/8+((sizey%8)?1:0))*(sizey/2); ++ c=chr-' ';//得到偏移后的值 ++ OLED_Set_Pos(_fb, x, y); ++ for(i=0; i=254&&g>=254&&b>=254) ++ { ++ y_val=254; ++ *y++ = y_val; ++ continue; ++ } ++ y_val = (uint8_t)(((int)(299 * r) + (int)(597 * g) + (int)(114 * b)) / 1000); ++ *y++ = y_val; ++ } ++ } ++ //转换uv ++ for (i = 0; i > 7; ++// } ++// } ++// } ++ ++ ++static uint8_t *_prepare_image(int width, int height, int format) ++{ ++ switch (format) { ++ case PIXEL_FORMAT_RGB_888: ++ { ++ uint8_t *rgb_data = (uint8_t *)malloc(width * height * 3); ++ int x_oft = 0; ++ int remain_width = width; ++ int segment_width = width / 6; ++ int idx = 0; ++ while (remain_width > 0) { ++ int seg_w = (remain_width > segment_width) ? segment_width : remain_width; ++ uint8_t r,g,b; ++ switch (idx) { ++ case 0: r = 0xff, g = 0x00, b = 0x00; break; ++ case 1: r = 0x00, g = 0xff, b = 0x00; break; ++ case 2: r = 0x00, g = 0x00, b = 0xff; break; ++ case 3: r = 0xff, g = 0xff, b = 0x00; break; ++ case 4: r = 0xff, g = 0x00, b = 0xff; break; ++ case 5: r = 0x00, g = 0xff, b = 0xff; break; ++ default: r = 0x00, g = 0x00, b = 0x00; break; ++ } ++ idx ++; ++ for (int i = 0; i < height; i ++) { ++ for (int j = 0; j < seg_w; j ++) { ++ rgb_data[(i * width + x_oft + j) * 3 + 0] = r; ++ rgb_data[(i * width + x_oft + j) * 3 + 1] = g; ++ rgb_data[(i * width + x_oft + j) * 3 + 2] = b; ++ } ++ } ++ x_oft += seg_w; ++ remain_width -= seg_w; ++ } ++ ++ for (int i = 0; i < height; i ++) { ++ uint8_t *buff = &rgb_data[(i * width + i) * 3]; ++ buff[0] = 0xff; ++ buff[1] = 0xff; ++ buff[2] = 0xff; ++ } ++ for (int i = 0; i < height; i ++) { ++ uint8_t *buff = &rgb_data[(i * width + i + width - height) * 3]; ++ buff[0] = 0xff; ++ buff[1] = 0xff; ++ buff[2] = 0xff; ++ } ++ ++ return rgb_data; ++ } ++ case PIXEL_FORMAT_ARGB_8888: ++ { ++ uint8_t *rgb_data = (uint8_t *)malloc(width * height * 4); ++ memset(rgb_data, 0x00, width * height * 4); ++ int x_oft = 0; ++ int remain_width = width; ++ int segment_width = width / 6; ++ int idx = 0; ++ while (remain_width > 0) { ++ int seg_w = (remain_width > segment_width) ? segment_width : remain_width; ++ uint8_t r,g,b,a; ++ switch (idx) { ++ case 0: r = 0xff, g = 0x00, b = 0x00; a = 0x10; break; ++ case 1: r = 0x00, g = 0xff, b = 0x00; a = 0x20; break; ++ case 2: r = 0x00, g = 0x00, b = 0xff; a = 0x40; break; ++ case 3: r = 0xff, g = 0xff, b = 0x00; a = 0x60; break; ++ case 4: r = 0xff, g = 0x00, b = 0xff; a = 0x80; break; ++ case 5: r = 0x00, g = 0xff, b = 0xff; a = 0xA0; break; ++ default: r = 0x00, g = 0x00, b = 0x00; a = 0xC0; break; ++ } ++ idx ++; ++ for (int i = 0; i < height; i ++) { ++ for (int j = 0; j < seg_w; j ++) { ++ rgb_data[(i * width + x_oft + j) * 4 + 0] = r; ++ rgb_data[(i * width + x_oft + j) * 4 + 1] = g; ++ rgb_data[(i * width + x_oft + j) * 4 + 2] = b; ++ rgb_data[(i * width + x_oft + j) * 4 + 3] = a; ++ } ++ } ++ x_oft += seg_w; ++ remain_width -= seg_w; ++ } ++ ++ // for (int i = 0; i < height; i ++) { ++ // uint8_t *buff = &rgb_data[(i * width + i) * 4]; ++ // buff[0] = 0xff; ++ // buff[1] = 0xff; ++ // buff[2] = 0xff; ++ // } ++ // for (int i = 0; i < height; i ++) { ++ // uint8_t *buff = &rgb_data[(i * width + i + width - height) * 4]; ++ // buff[0] = 0xff; ++ // buff[1] = 0xff; ++ // buff[2] = 0xff; ++ // } ++ ++ return rgb_data; ++ } ++ case PIXEL_FORMAT_NV21: ++ { ++ uint8_t *rgb_data = _prepare_image(width, height, PIXEL_FORMAT_RGB_888); ++ uint8_t *nv21 = (uint8_t *)malloc(width * height * 3 / 2); ++ _rgb888_to_nv21(rgb_data, width, height, nv21); ++ free(rgb_data); ++ return nv21; ++ } ++ break; ++ default: ++ DEBUG("Only support PIXEL_FORMAT_RGB_888\r\n"); ++ break; ++ } ++ return NULL; ++} ++ ++static int _test_vo_only(void) ++{ ++ uint8_t *filebuf = NULL; ++ uint32_t filelen; ++ signal(SIGINT, sig_handle); ++ signal(SIGTERM, sig_handle); ++ ++#if 1 ++ int img_w = 320, img_h = 240, fit = 0, img_fmt = PIXEL_FORMAT_NV21; //PIXEL_FORMAT_NV21 or PIXEL_FORMAT_RGB_888 ++ // int img_w = 320, img_h = 240, fit = 0, img_fmt = PIXEL_FORMAT_RGB_888; //PIXEL_FORMAT_NV21 or PIXEL_FORMAT_RGB_888 ++ filebuf = _prepare_image(img_w, img_h, img_fmt); ++ if (img_fmt == PIXEL_FORMAT_RGB_888) ++ filelen = img_w * img_h * 3; ++ else ++ filelen = img_w * img_h * 3 / 2; ++ int show_w = 552, show_h = 368; ++ ++ DEBUG("in w:%d h:%d fmt:%d\r\n", img_w, img_h, img_fmt); ++ DEBUG("out w:%d h:%d fmt:%d\r\n", show_w, show_h, img_fmt); ++#endif ++ ++ mmf_init(); ++ ++ int layer = 0; ++ int vo_ch = mmf_get_vo_unused_channel(layer); ++ if (0 != mmf_add_vo_channel_with_fit(layer, vo_ch, show_w, show_h, img_fmt, fit)) { ++ DEBUG("mmf_add_vo_channel_with_fit failed!\r\n"); ++ exit_flag = 1; ++ } ++ ++ // save_buff_to_file("640_480_draw.rgb", filebuf, filelen); ++ // system("sync"); ++ ++ while (!exit_flag) { ++ struct timeval tv, tv2; ++ gettimeofday(&tv, NULL); ++ mmf_vo_frame_push_with_fit(layer, vo_ch, filebuf, filelen, img_w, img_h, img_fmt, fit); ++ gettimeofday(&tv2, NULL); ++ DEBUG("mmf vo frame push. %ld\r\n", (tv2.tv_usec + tv2.tv_sec * 1000000) - (tv.tv_usec + tv.tv_sec * 1000000)); ++ usleep(1000 * 1000); ++ } ++ ++ mmf_del_vo_channel(layer, vo_ch); ++ mmf_deinit(); ++ return 0; ++} ++ ++static int _test_vi_only(void) ++{ ++ signal(SIGINT, sig_handle); ++ signal(SIGTERM, sig_handle); ++ ++ if (0 != mmf_init()) { ++ DEBUG("mmf_init failed!\r\n"); ++ return -1; ++ } ++ ++ DEBUG("sensor id: %#x\n", mmf_get_sensor_id()); ++ ++ if (0 != mmf_vi_init()) { ++ DEBUG("mmf_vi_init failed!\r\n"); ++ mmf_deinit(); ++ return -1; ++ } ++ ++ int img_w = 2560, img_h = 1440, fit = 0, img_fmt = PIXEL_FORMAT_NV21; //PIXEL_FORMAT_NV21 or PIXEL_FORMAT_RGB_888 ++ (void)fit; ++ int vi_ch = mmf_get_vi_unused_channel(); ++ if (0 != mmf_add_vi_channel(vi_ch, img_w, img_h, img_fmt)) { ++ DEBUG("mmf_add_vi_channel failed!\r\n"); ++ mmf_deinit(); ++ return -1; ++ } ++ ++ mmf_del_vi_channel(vi_ch); ++ if (0 != mmf_add_vi_channel(vi_ch, img_w , img_h, img_fmt)) { ++ DEBUG("mmf_add_vi_channel failed!\r\n"); ++ mmf_deinit(); ++ return -1; ++ } ++ ++ struct timeval tv; ++ uint64_t last_loop = 0; ++#ifndef DEBUG_EN ++ UNUSED(last_loop); ++#endif ++ ++ void *data; ++ int data_size, width, height, format; ++ while (!exit_flag) { ++ if (0 == mmf_vi_frame_pop(vi_ch, &data, &data_size, &width, &height, &format)) { ++ gettimeofday(&tv, NULL); ++ DEBUG("Pop..width:%d height:%d data_size:%d format:%d\r\n", width, height, data_size, format); ++ DEBUG("data:%p loop: %ld\n", data, (tv.tv_usec + tv.tv_sec * 1000000 - last_loop) / 1000); ++ last_loop = tv.tv_usec + tv.tv_sec * 1000000; ++#if 0 ++ static int count = 0; ++ if (count++ > 10) { ++ save_buff_to_file("2560x1440.yuv", data, data_size); ++ system("sync"); ++ mmf_vi_frame_free(vi_ch); ++ break; ++ } ++#endif ++ mmf_vi_frame_free(vi_ch); ++ ++ // usleep(50 * 1000); ++ } ++ } ++ ++ mmf_del_vi_channel(vi_ch); ++ mmf_deinit(); ++ return 0; ++} ++ ++// static void dump_ae_attr(ISP_EXPOSURE_ATTR_S *ae_attr) ++// { ++// printf("ae_attr->u8DebugMode: %d\n", ae_attr->u8DebugMode); ++// printf("ae_attr->bByPass: %d\n", ae_attr->bByPass); ++// printf("ae_attr->enOpType: %s\n", ae_attr->enOpType ? "manual" : "auto"); ++// if (ae_attr->enOpType) { ++// printf("ae_attr->stManual.enExpTimeOpType: %s\n", ae_attr->stManual.enExpTimeOpType ? "manual" : "auto"); ++// printf("ae_attr->stManual.enISONumOpType: %s\n", ae_attr->stManual.enISONumOpType ? "manual" : "auto"); ++// printf("ae_attr->stManual.u32ExpTime: %d\n", ae_attr->stManual.u32ExpTime); ++// printf("ae_attr->stManual.enGainType: %d\n", ae_attr->stManual.enGainType); ++// printf("ae_attr->stManual.u32ISONum: %d\n", ae_attr->stManual.u32ISONum); ++// } else { ++// printf("ae_attr->stAuto.bManualExpValue: %d\n", ae_attr->stAuto.bManualExpValue); ++// printf("ae_attr->stAuto.u32ExpValue: %d\n", ae_attr->stAuto.u32ExpValue); ++// } ++// } ++ ++static void dump_wb_attr(ISP_WB_ATTR_S *wb_attr) ++{ ++ printf("wb_attr->bByPass: %d\n", wb_attr->bByPass); ++ printf("wb_attr->enOpType: %s\n", wb_attr->enOpType ? "manual" : "auto"); ++ if (wb_attr->enOpType == OP_TYPE_MANUAL) { ++ printf("wb_attr->stManual.u16Rgain: %d\n", wb_attr->stManual.u16Rgain); ++ printf("wb_attr->stManual.u16Grgain: %d\n", wb_attr->stManual.u16Grgain); ++ printf("wb_attr->stManual.u16Gbgain: %d\n", wb_attr->stManual.u16Gbgain); ++ printf("wb_attr->stManual.u16Bgain: %d\n", wb_attr->stManual.u16Bgain); ++ } else if (wb_attr->enOpType == OP_TYPE_AUTO){ ++ printf("wb_attr->stAuto.bEnable: %d\n", wb_attr->stAuto.bEnable); ++ printf("wb_attr->stAuto.u16RefColorTemp: %d\n", wb_attr->stAuto.u16RefColorTemp); ++ printf("wb_attr->stAuto.u16Speed: %d\n", wb_attr->stAuto.u16Speed); ++ printf("wb_attr->stAuto.u16HighColorTemp: %d\n", wb_attr->stAuto.u16HighColorTemp); ++ printf("wb_attr->stAuto.u16LowColorTemp: %d\n", wb_attr->stAuto.u16LowColorTemp); ++ } ++} ++ ++int mmf_get_wb(int ch, uint16_t *wb_value) ++{ ++ ISP_WB_Q_INFO_S wb_info; ++ memset(&wb_info, 0, sizeof(ISP_WB_Q_INFO_S)); ++ CVI_AWB_QueryInfo(ch, &wb_info); ++ if (wb_value) { ++ *wb_value = wb_info.u16ColorTemp; ++ } ++ return 0; ++} ++ ++int mmf_set_wb(int ch, uint16_t wb_value) ++{ ++ ISP_WB_ATTR_S stWbAttr; ++ CVI_ISP_GetWBAttr(ch, &stWbAttr); ++ dump_wb_attr(&stWbAttr); ++ stWbAttr.stAuto.u16RefColorTemp = wb_value; ++ stWbAttr.stAuto.u16HighColorTemp = wb_value + 500; ++ stWbAttr.stAuto.u16LowColorTemp = wb_value - 500; ++ printf("==========[%s][%d] set wb_value:%d\n", __func__, __LINE__, wb_value); ++ CVI_ISP_SetWBAttr(ch, &stWbAttr); ++ CVI_ISP_GetWBAttr(ch, &stWbAttr); ++ dump_wb_attr(&stWbAttr); ++ return 0; ++} ++ ++// static void _awb_test(void) ++// { ++// static uint16_t colortemp = 0; ++// static int up_flag = 1; ++// static int init = 0; ++// if (!init) { ++// mmf_get_wb(0, &colortemp); ++// printf("==========[%s][%d] get wb_value:%d\n", __func__, __LINE__, colortemp); ++ ++// mmf_set_wb(0, 1000); ++// init = 1; ++// } ++ ++// if (colortemp >= 9000) { ++// up_flag = 0; ++// colortemp = 9000; ++// } else if (colortemp <= 1000) { ++// up_flag = 1; ++// colortemp = 1000; ++// } ++ ++// if (up_flag) { ++// colortemp += 1000; ++// } else { ++// colortemp -= 1000; ++// } ++ ++// // mmf_set_wb(0, colortemp); ++ ++// uint16_t wb_value2 = 0; ++// mmf_get_wb(0, &wb_value2); ++// printf("==========[%s][%d] get wb_value2:%d\n", __func__, __LINE__, wb_value2); ++// } ++ ++static int _test_vio(void) ++{ ++ signal(SIGINT, sig_handle); ++ signal(SIGTERM, sig_handle); ++ ++ int img_w = 480, img_h = 640, fit = 2, img_fmt = PIXEL_FORMAT_NV21; //PIXEL_FORMAT_NV21 or PIXEL_FORMAT_RGB_888 ++ ++ // mmf_vb_config_of_vo(ALIGN(img_w, DEFAULT_ALIGN) * img_h * 3 / 2, 8); ++ // mmf_vb_config_of_private(ALIGN(img_w, DEFAULT_ALIGN) * img_h * 3 / 2, 1); ++ ++ if (0 != mmf_init()) { ++ DEBUG("mmf_init failed!\r\n"); ++ return -1; ++ } ++ ++ if (0 != mmf_vi_init()) { ++ DEBUG("mmf_vi_init failed!\r\n"); ++ mmf_deinit(); ++ return -1; ++ } ++ ++ int vi_ch = mmf_get_vi_unused_channel(); ++ // mmf_set_vi_hmirror(vi_ch, true); ++ // mmf_set_vi_vflip(vi_ch, true); ++ if (0 != mmf_add_vi_channel(vi_ch, img_w, img_h, img_fmt)) { ++ DEBUG("mmf_add_vi_channel failed!\r\n"); ++ mmf_vi_deinit(); ++ mmf_deinit(); ++ return -1; ++ } ++ ++ usleep(1000 * 1000); ++ uint32_t exptime = 0, iso_num = 0; ++ mmf_get_exptime_and_iso(0, &exptime, &iso_num); ++ printf("==========[%s][%d] get exp:%d iso:%d\n", ++ __func__, __LINE__, exptime, iso_num); ++ int layer = 0; ++ int vo_ch = mmf_get_vo_unused_channel(layer); ++ if (0 != mmf_add_vo_channel_with_fit(layer, vo_ch, 552, 368, img_fmt, fit)) { ++ DEBUG("mmf_add_vo_channel_with_fit failed!\r\n"); ++ mmf_del_vi_channel(vi_ch); ++ mmf_deinit(); ++ return -1; ++ } ++ ++ uint64_t start, start2 = 0; ++ void *data; ++ int data_size, width, height, format; ++#ifndef DEBUG_EN ++ UNUSED(start); UNUSED(start2); ++#endif ++ ++ // first snap, do nothing ++ if (0 == mmf_vi_frame_pop(vi_ch, &data, &data_size, &width, &height, &format)) { ++ mmf_vi_frame_free(vi_ch); ++ } ++ while (!exit_flag) { ++ int show_img_size = 0; ++ if (img_fmt == PIXEL_FORMAT_RGB_888) ++ show_img_size = img_w * img_h * 3; ++ else ++ show_img_size = img_w * img_h * 3 / 2; ++ ++ uint8_t *show_img = malloc(show_img_size); ++ if (!show_img) { ++ DEBUG("Malloc failed!\r\n"); ++ exit_flag = 1; ++ } ++ ++ start = _get_time_us(); ++ if (0 == mmf_vi_frame_pop(vi_ch, &data, &data_size, &width, &height, &format)) { ++ DEBUG(">>>>>> pop vi frame %ld us\n", _get_time_us() - start); ++ ++ DEBUG("Pop..width:%d height:%d data_size:%d format:%d\r\n", width, height, data_size, format); ++ ++ start = _get_time_us(); ++ if (img_w % DEFAULT_ALIGN != 0) { ++ switch (img_fmt) { ++ case PIXEL_FORMAT_RGB_888: ++ for (int h = 0; h < img_h; h ++) { ++ memcpy(show_img + h * img_w * 3, (uint8_t *)data + h * width * 3, img_w * 3); ++ } ++ break; ++ case PIXEL_FORMAT_NV21: ++ for (int h = 0; h < img_h * 3 / 2; h ++) { ++ memcpy(show_img + h * img_w, (uint8_t *)data + h * width, img_w); ++ } ++ break; ++ default:break; ++ } ++ } else { ++ memcpy(show_img, data, data_size); ++ } ++ ++ mmf_vi_frame_free(vi_ch); ++ ++ if (img_fmt == PIXEL_FORMAT_RGB_888) { ++ for (int i = 0; i < img_h; i ++) { ++ uint8_t *buff = &show_img[(i * img_w + i) * 3]; ++ buff[0] = 0xff; ++ buff[1] = 0x00; ++ buff[2] = 0x00; ++ } ++ for (int i = 0; i < img_h; i ++) { ++ uint8_t *buff = &show_img[(i * img_w + i + img_w - img_h) * 3]; ++ buff[0] = 0x00; ++ buff[1] = 0xff; ++ buff[2] = 0x00; ++ } ++ } ++ DEBUG(">>>>>> mmcpy vi frame %ld\n", _get_time_us() - start); ++ ++ start = _get_time_us(); ++ DEBUG("Push..width:%d height:%d data_size:%d format:%d\r\n", img_w, img_h, show_img_size, img_fmt); ++ mmf_vo_frame_push_with_fit(layer, vo_ch, show_img, show_img_size, img_w, img_h, format, fit); ++ DEBUG(">>>>>> flush vo frame %ld\n", _get_time_us() - start); ++ ++ // static int cnt = 0; ++ // if (cnt ++ > 10) { ++ // save_buff_to_file("480_480.yuv", show_img, show_img_size); ++ // DEBUG("Save to snapshot.yuv\r\n"); ++ // system("sync"); ++ // exit_flag = 1; ++ // } ++ ++ DEBUG(">>>>>> flush time %ld ms\n", (_get_time_us() - start2) / 1000); ++ start2 = _get_time_us(); ++ // PAUSE(); ++ } ++ UNUSED(save_buff_to_file); ++ free(show_img); ++ } ++ ++ mmf_del_vo_channel(layer, vo_ch); ++ mmf_del_vi_channel(vi_ch); ++ mmf_vi_deinit(); ++ mmf_deinit(); ++ return 0; ++} ++ ++static int _test_region(void) ++{ ++ signal(SIGINT, sig_handle); ++ signal(SIGTERM, sig_handle); ++ ++#if 1 ++ if (0 != mmf_init()) { ++ DEBUG("mmf_init failed!\r\n"); ++ return -1; ++ } ++ ++ int img_w = 552, img_h = 368, fit = 0, img_fmt = PIXEL_FORMAT_RGB_888; //PIXEL_FORMAT_NV21 or PIXEL_FORMAT_RGB_888 ++ int vo_w = 552, vo_h = 368; ++ int vi_ch = mmf_get_vi_unused_channel(); ++ if (0 != mmf_vi_init()) { ++ DEBUG("mmf_vi_init failed!\r\n"); ++ mmf_deinit(); ++ return -1; ++ } ++ if (0 != mmf_add_vi_channel(vi_ch, img_w, img_h, img_fmt)) { ++ DEBUG("mmf_add_vi_channel failed!\r\n"); ++ mmf_deinit(); ++ return -1; ++ } ++ ++ int layer = 0; ++ int vo_ch = mmf_get_vo_unused_channel(layer); ++ if (0 != mmf_add_vo_channel_with_fit(layer, vo_ch, vo_w, vo_h, img_fmt, fit)) { ++ DEBUG("mmf_add_vo_channel_with_fit failed!\r\n"); ++ mmf_del_vi_channel(vi_ch); ++ mmf_deinit(); ++ return -1; ++ } ++ ++ int rgn_ch = 0, rgn_w = 200, rgn_h = 100, rgn_x = 0, rgn_y = 0; ++ rgn_ch = mmf_get_region_unused_channel(); ++ if (0 != mmf_add_region_channel(rgn_ch, OVERLAY_RGN, CVI_ID_VPSS, 1, vo_ch, rgn_x, rgn_y, rgn_w, rgn_h, PIXEL_FORMAT_ARGB_8888)) { ++ DEBUG("mmf_add_region_channel failed!\r\n"); ++ exit_flag = 1; ++ } ++ ++ int rgn_ch2 = mmf_get_region_unused_channel(); ++ if (0 != mmf_add_region_channel(rgn_ch2, OVERLAY_RGN, CVI_ID_VPSS, 0, vi_ch, rgn_x + 100, rgn_y + 100, rgn_w, rgn_h, PIXEL_FORMAT_ARGB_8888)) { ++ DEBUG("mmf_add_region_channel failed!\r\n"); ++ exit_flag = 1; ++ } ++ ++ struct timeval tv; ++ uint64_t start, start2, end; ++ void *data; ++ int data_size, width, height, format; ++#ifndef DEBUG_EN ++ UNUSED(start2); ++#endif ++ ++ // first snap, do nothing ++ if (0 == mmf_vi_frame_pop(vi_ch, &data, &data_size, &width, &height, &format)) { ++ mmf_vo_frame_push_with_fit(layer, vo_ch, data, data_size, width, height, format, fit); ++ mmf_vi_frame_free(vi_ch); ++ } ++ ++ while (!exit_flag) { ++ int show_img_size = 0; ++ if (img_fmt == PIXEL_FORMAT_RGB_888) ++ show_img_size = img_w * img_h * 3; ++ else ++ show_img_size = img_w * img_h * 3 / 2; ++ ++ uint8_t *show_img = malloc(show_img_size); ++ if (!show_img) { ++ DEBUG("Malloc failed!\r\n"); ++ exit_flag = 1; ++ } ++ ++ gettimeofday(&tv, NULL); ++ start = tv.tv_usec + tv.tv_sec * 1000000; ++ start2 = start; ++ if (0 == mmf_vi_frame_pop(vi_ch, &data, &data_size, &width, &height, &format)) { ++ gettimeofday(&tv, NULL); ++ end = tv.tv_usec + tv.tv_sec * 1000000; ++ DEBUG(">>>>>> pop vi frame %ld\n", end - start); ++ start = end; ++ ++ DEBUG("Pop..width:%d height:%d data_size:%d format:%d\r\n", width, height, data_size, format); ++ if (img_w % DEFAULT_ALIGN != 0) { ++ switch (img_fmt) { ++ case PIXEL_FORMAT_RGB_888: ++ for (int h = 0; h < img_h; h ++) { ++ memcpy(show_img + h * img_w * 3, (uint8_t *)data + h * width * 3, img_w * 3); ++ } ++ break; ++ case PIXEL_FORMAT_NV21: ++ for (int h = 0; h < img_h * 3 / 2; h ++) { ++ memcpy(show_img + h * img_w, (uint8_t *)data + h * width, img_w); ++ } ++ break; ++ default:break; ++ } ++ } else { ++ memcpy(show_img, data, data_size); ++ } ++ ++ gettimeofday(&tv, NULL); ++ end = tv.tv_usec + tv.tv_sec * 1000000; ++ DEBUG(">>>>>> mmcpy vi frame %ld\n", end - start); ++ start = end; ++ ++ mmf_vi_frame_free(vi_ch); ++ ++ { ++ start = _get_time_us(); ++ uint8_t *rgn_data = (uint8_t *)_prepare_image(rgn_w, rgn_h, PIXEL_FORMAT_ARGB_8888); ++ DEBUG("memcpy rgn_data use: %ld us\n", _get_time_us() - start); ++ ++ { ++ memset(rgn_data, 0xff, rgn_w * rgn_h * 4); ++ uint8_t *new_rgn_data = (uint8_t *)rgn_data; ++ for (int h = 0; h < 50; h ++) { ++ for (int w = 0; w < 50; w ++) { ++ new_rgn_data[rgn_w * h * 4 + w * 4 + 0] = 0x00; ++ new_rgn_data[rgn_w * h * 4 + w * 4 + 1] = 0xff; ++ new_rgn_data[rgn_w * h * 4 + w * 4 + 2] = 0x00; ++ new_rgn_data[rgn_w * h * 4 + w * 4 + 3] = 0x55; ++ } ++ } ++ } ++ ++ start = _get_time_us(); ++ mmf_region_frame_push(rgn_ch, rgn_data, rgn_w * rgn_h * 4); ++ DEBUG("_mmf_region_frame_push use: %ld us\n", _get_time_us() - start); ++ ++ ++ start = _get_time_us(); ++ void *data; ++ int width, height, format; ++ assert(0 == mmf_region_get_canvas(rgn_ch2, &data, &width, &height, &format)); ++ // memcpy(data, rgn_data, rgn_w * rgn_h * 4); ++ memset(data, 0xff, rgn_w * rgn_h * 4); ++ uint8_t *new_rgn_data = (uint8_t *)data; ++ for (int h = 0; h < height; h ++) { ++ for (int w = 0; w < width; w ++) { ++ new_rgn_data[width * h * 4 + w * 4 + 0] = 0x00; ++ new_rgn_data[width * h * 4 + w * 4 + 1] = 0xff; ++ new_rgn_data[width * h * 4 + w * 4 + 2] = 0x00; ++ new_rgn_data[width * h * 4 + w * 4 + 3] = 0x55; ++ } ++ } ++ assert(0 == mmf_region_update_canvas(rgn_ch2)); ++ DEBUG("mmf_region_update_canvas use: %ld us\n", _get_time_us() - start); ++ free(rgn_data); ++ } ++ DEBUG("Push..width:%d height:%d data_size:%d format:%d\r\n", img_w, img_h, show_img_size, img_fmt); ++ mmf_vo_frame_push_with_fit(layer, vo_ch, show_img, show_img_size, img_w, img_h, format, fit); ++ ++ gettimeofday(&tv, NULL); ++ end = tv.tv_usec + tv.tv_sec * 1000000; ++ DEBUG(">>>>>> flush vo frame %ld\n", end - start); ++ ++ gettimeofday(&tv, NULL); ++ end = tv.tv_usec + tv.tv_sec * 1000000; ++ DEBUG(">>>>>> flush time %ld\n", (end - start2) / 1000); ++ // PAUSE(); ++ } ++ UNUSED(save_buff_to_file); ++ free(show_img); ++ } ++ ++ mmf_del_region_channel(rgn_ch); ++ mmf_del_region_channel(rgn_ch2); ++ mmf_del_vo_channel(layer, vo_ch); ++ mmf_del_vi_channel(vi_ch); ++ mmf_deinit(); ++ return 0; ++#else ++ if (0 != mmf_init()) { ++ DEBUG("mmf_init failed!\r\n"); ++ return -1; ++ } ++ ++ if (0 != mmf_vi_init()) { ++ DEBUG("mmf_vi_init failed!\r\n"); ++ mmf_deinit(); ++ return -1; ++ } ++ ++ int img_w = 552, img_h = 368, fit = 0, img_fmt = PIXEL_FORMAT_NV21; //PIXEL_FORMAT_NV21 or PIXEL_FORMAT_RGB_888 ++ int vo_w = 552, vo_h = 368; ++ int vi_ch = mmf_get_vi_unused_channel(); ++ if (0 != mmf_add_vi_channel(vi_ch, img_w, img_h, img_fmt)) { ++ DEBUG("mmf_add_vi_channel failed!\r\n"); ++ mmf_deinit(); ++ return -1; ++ } ++ ++ int video_layer = 0; ++ int vo_video_ch = mmf_get_vo_unused_channel(video_layer); ++ if (0 != mmf_add_vo_channel_with_fit(video_layer, vo_video_ch, vo_w, vo_h, img_fmt, fit)) { ++ DEBUG("mmf_add_vo_channel_with_fit failed!\r\n"); ++ mmf_del_vi_channel(vi_ch); ++ mmf_deinit(); ++ return -1; ++ } ++ ++ int osd_layer = 1; ++ int osd_img_fmt = PIXEL_FORMAT_ARGB_8888; ++ int vo_osd_ch = mmf_get_vo_unused_channel(osd_layer); ++ if (0 != mmf_add_vo_channel_with_fit(osd_layer, vo_osd_ch, vo_w, vo_h, osd_img_fmt, fit)) { ++ DEBUG("mmf_add_vo_channel_with_fit failed!\r\n"); ++ mmf_del_vo_channel(video_layer, vo_video_ch); ++ mmf_del_vi_channel(vi_ch); ++ mmf_deinit(); ++ return -1; ++ } ++ ++ uint64_t start, last_loop_us = 0; ++ void *data; ++ int data_size, width, height, format; ++ ++ // first snap, do nothing ++ if (0 == mmf_vi_frame_pop(vi_ch, &data, &data_size, &width, &height, &format)) { ++ mmf_vo_frame_push_with_fit(video_layer, vo_video_ch, data, data_size, width, height, format, fit); ++ mmf_vi_frame_free(vi_ch); ++ } ++ ++ { ++ uint8_t *rgn_data = _prepare_image(vo_w, vo_h, PIXEL_FORMAT_ARGB_8888); ++ start = _get_time_us(); ++ mmf_vo_frame_push_with_fit(osd_layer, vo_osd_ch, rgn_data, vo_w * vo_h * 4, img_w, img_h, osd_img_fmt, fit); ++ DEBUG("osd frame push use: %ld us\n", _get_time_us() - start); ++ free(rgn_data); ++ } ++ last_loop_us = _get_time_us(); ++ while (!exit_flag) { ++ int show_img_size = 0; ++ if (img_fmt == PIXEL_FORMAT_RGB_888) ++ show_img_size = img_w * img_h * 3; ++ else ++ show_img_size = img_w * img_h * 3 / 2; ++ ++ uint8_t *show_img = malloc(show_img_size); ++ if (!show_img) { ++ DEBUG("Malloc failed!\r\n"); ++ exit_flag = 1; ++ } ++ ++ start = _get_time_us(); ++ if (0 == mmf_vi_frame_pop(vi_ch, &data, &data_size, &width, &height, &format)) { ++ DEBUG("vi pop frame\n(width:%d height:%d data_size:%d format:%d) use: %ld us\n", width, height, data_size, format, _get_time_us() - start); ++ ++ start = _get_time_us(); ++ if (img_w % DEFAULT_ALIGN != 0) { ++ switch (img_fmt) { ++ case PIXEL_FORMAT_RGB_888: ++ for (int h = 0; h < img_h; h ++) { ++ memcpy(show_img + h * img_w * 3, (uint8_t *)data + h * width * 3, img_w * 3); ++ } ++ break; ++ case PIXEL_FORMAT_NV21: ++ for (int h = 0; h < img_h * 3 / 2; h ++) { ++ memcpy(show_img + h * img_w, (uint8_t *)data + h * width, img_w); ++ } ++ break; ++ default:break; ++ } ++ } else { ++ memcpy(show_img, data, data_size); ++ } ++ DEBUG("vi memcpy use: %ld us\n", _get_time_us() - start); ++ ++ mmf_vi_frame_free(vi_ch); ++ ++ if (img_fmt == PIXEL_FORMAT_RGB_888) { ++ for (int i = 0; i < img_h; i ++) { ++ uint8_t *buff = &show_img[(i * img_w + i) * 3]; ++ buff[0] = 0xff; ++ buff[1] = 0x00; ++ buff[2] = 0x00; ++ } ++ for (int i = 0; i < img_h; i ++) { ++ uint8_t *buff = &show_img[(i * img_w + i + img_w - img_h) * 3]; ++ buff[0] = 0x00; ++ buff[1] = 0xff; ++ buff[2] = 0x00; ++ } ++ } ++ ++ { ++ uint8_t *rgn_data = _prepare_image(vo_w, vo_h, PIXEL_FORMAT_ARGB_8888); ++ start = _get_time_us(); ++ mmf_vo_frame_push_with_fit(osd_layer, vo_osd_ch, rgn_data, vo_w * vo_h * 4, img_w, img_h, osd_img_fmt, fit); ++ DEBUG("osd frame push use: %ld us\n", _get_time_us() - start); ++ free(rgn_data); ++ } ++ DEBUG("Push..width:%d height:%d data_size:%d format:%d\r\n", img_w, img_h, show_img_size, img_fmt); ++ ++ start = _get_time_us(); ++ if (0 != mmf_vo_frame_push_with_fit(video_layer, vo_video_ch, show_img, show_img_size, img_w, img_h, format, fit)) { ++ DEBUG("mmf_vo_frame_push_with_fit failed!\r\n"); ++ exit_flag = 1; ++ } ++ DEBUG("video frame push use: %ld us\n", _get_time_us() - start); ++ // PAUSE(); ++ } ++ UNUSED(save_buff_to_file); ++ free(show_img); ++ ++ DEBUG("loop use: %ld us\n", _get_time_us() - last_loop_us); ++ last_loop_us = _get_time_us(); ++ } ++ ++ mmf_del_vo_channel(osd_layer, vo_osd_ch); ++ mmf_del_vo_channel(video_layer, vo_video_ch); ++ mmf_del_vi_channel(vi_ch); ++ mmf_deinit(); ++ return 0; ++#endif ++} ++ ++static int _test_venc_jpg(void) ++{ ++ signal(SIGINT, sig_handle); ++ signal(SIGTERM, sig_handle); ++ ++#if 1 ++ int img_w = 2560, img_h = 1440, fit = 0, img_fmt = PIXEL_FORMAT_NV21; //PIXEL_FORMAT_NV21 or PIXEL_FORMAT_RGB_888 ++ // int img_w = 640, img_h = 480, fit = 0, img_fmt = PIXEL_FORMAT_RGB_888; //PIXEL_FORMAT_NV21 or PIXEL_FORMAT_RGB_888 ++ ++#if 0 ++ uint8_t *filebuf = _prepare_image(img_w, img_h, img_fmt); ++ uint32_t filelen; ++ if (img_fmt == PIXEL_FORMAT_RGB_888) ++ filelen = img_w * img_h * 3; ++ else ++ filelen = img_w * img_h * 3 / 2; ++#endif ++ int show_w = 552, show_h = 368; ++ ++ DEBUG("in w:%d h:%d fmt:%d\r\n", img_w, img_h, img_fmt); ++ DEBUG("out w:%d h:%d fmt:%d\r\n", show_w, show_h, img_fmt); ++#endif ++ ++ mmf_init(); ++ ++ if (0 != mmf_vi_init()) { ++ DEBUG("mmf_vi_init failed!\r\n"); ++ mmf_deinit(); ++ return -1; ++ } ++ ++ int vi_ch = mmf_get_vi_unused_channel(); ++ if (0 != mmf_add_vi_channel(vi_ch, img_w, img_h, img_fmt)) { ++ DEBUG("mmf_add_vi_channel failed!\r\n"); ++ mmf_deinit(); ++ return -1; ++ } ++ ++ int enc_ch = 0; ++ if (0 != mmf_enc_jpg_init(enc_ch, img_w, img_h, img_fmt, 80)) { ++ DEBUG("mmf_enc_jpg_init failed!\r\n"); ++ return -1; ++ } ++ ++ int layer = 0; ++ int vo_ch = mmf_get_vo_unused_channel(layer); ++ if (0 != mmf_add_vo_channel_with_fit(layer, vo_ch, show_w, show_h, img_fmt, fit)) { ++ DEBUG("mmf_add_vo_channel_with_fit failed!\r\n"); ++ mmf_del_vi_channel(vi_ch); ++ mmf_deinit(); ++ return -1; ++ } ++ ++ int loop_count = 0; ++ int fail_count = 0; ++ uint64_t start = _get_time_us(); ++#ifndef DEBUG_EN ++ UNUSED(start); ++#endif ++#if 1 ++ while (!exit_flag) { ++ // pop last push frame ++ uint8_t *data; ++ int data_size; ++ void *vi_data; ++ int vi_data_size, width, height, format; ++ if (0 != mmf_vi_frame_pop(vi_ch, &vi_data, &vi_data_size, &width, &height, &format)) { ++ fail_count++; ++ if (fail_count > 30) ++ break; ++ continue; ++ } ++ printf("Pop..width:%d height:%d data_size:%d format:%d\r\n", width, height, data_size, format); ++ start = _get_time_us(); ++ if (0 != mmf_enc_jpg_push(enc_ch, vi_data, width, height, format)) { ++ printf("mmf_enc_jpg_push failed!\r\n"); ++ } ++ DEBUG(">>>>>>>>>>>>>>>>[%s][%d] use %ld us\r\n", __func__, __LINE__, _get_time_us() - start); ++ start = _get_time_us(); ++ if (!mmf_enc_jpg_pop(enc_ch, &data, &data_size)) { ++ DEBUG(">>>>>>>>>>>>>>>>[%s][%d] use %ld us\r\n", __func__, __LINE__, _get_time_us() - start); ++ ++ if ((loop_count < 60) && data_size) { ++ char fn[32]; ++ sprintf(fn, "venc_stream%d.jpg", loop_count); ++ save_buff_to_file(fn, data, data_size); ++ loop_count++; ++ } ++ ++ start = _get_time_us(); ++ if (0 != mmf_enc_jpg_free(enc_ch)) { ++ ++ DEBUG("mmf_enc_jpg_free failed!\r\n"); ++ } ++ DEBUG(">>>>>>>>>>>>>>>>[%s][%d] use %ld us\r\n", __func__, __LINE__, _get_time_us() - start); ++ } ++ ++ start = _get_time_us(); ++ mmf_vi_frame_free(vi_ch); ++ DEBUG("use %ld us\r\n", _get_time_us() - start); ++ if (loop_count >= 60) ++ break; ++ } ++#elif 1 ++ { ++ if (0 != mmf_enc_jpg_init(enc_ch, img_w, img_h, img_fmt, 80)) { ++ DEBUG("mmf_enc_jpg_init failed!\r\n"); ++ return -1; ++ } ++ DEBUG(">>>>>>>>>>>>>>>>[%s][%d] use %ld us\r\n", __func__, __LINE__, _get_time_us() - start); ++ ++ ++ while (!exit_flag) { ++ start = _get_time_us(); ++ if (0 != mmf_enc_jpg_push(enc_ch, filebuf, img_w, img_h, img_fmt)) { ++ DEBUG("mmf_enc_jpg_push failed!\r\n"); ++ } ++ DEBUG(">>>>>>>>>>>>>>>>[%s][%d] use %ld us\r\n", __func__, __LINE__, _get_time_us() - start); ++ ++ uint8_t *data; ++ int data_size; ++ start = _get_time_us(); ++ if (0 != mmf_enc_jpg_pop(enc_ch, &data, &data_size)) { ++ DEBUG("mmf_enc_jpg_pop failed!\r\n"); ++ } ++ DEBUG(">>>>>>>>>>>>>>>>[%s][%d] use %ld us\r\n", __func__, __LINE__, _get_time_us() - start); ++ ++ save_buff_to_file("venc_stream.jpg", data, data_size); ++ ++ start = _get_time_us(); ++ if (0 != mmf_enc_jpg_free(enc_ch)) { ++ DEBUG("mmf_enc_jpg_free failed!\r\n"); ++ } ++ DEBUG(">>>>>>>>>>>>>>>>[%s][%d] use %ld us\r\n", __func__, __LINE__, _get_time_us() - start); ++ } ++ start = _get_time_us(); ++ if (0 != mmf_enc_jpg_deinit(enc_ch)) { ++ DEBUG("mmf_enc_jpg_deinit failed!\r\n"); ++ } ++ DEBUG(">>>>>>>>>>>>>>>>[%s][%d] use %ld us\r\n", __func__, __LINE__, _get_time_us() - start); ++ } ++#else ++ while (!exit_flag) { ++ { ++ void *data; ++ int data_size, width, height, format; ++ if (0 == mmf_vi_frame_pop(vi_ch, &data, &data_size, &width, &height, &format)) { ++ DEBUG("Pop..width:%d height:%d data_size:%d format:%d\r\n", width, height, data_size, format); ++ mmf_vi_frame_free(vi_ch); ++ } ++ } ++ ++ { ++ start = _get_time_us(); ++ if (0 != mmf_enc_jpg_push(enc_ch, filebuf, img_w, img_h, img_fmt)) { ++ DEBUG("mmf_enc_jpg_push failed!\r\n"); ++ } ++ DEBUG(">>>>>>>>>>>>>>>>[%s][%d] use %ld us\r\n", __func__, __LINE__, _get_time_us() - start); ++ ++ uint8_t *data; ++ int data_size; ++ start = _get_time_us(); ++ if (0 != mmf_enc_jpg_pop(enc_ch, &data, &data_size)) { ++ DEBUG("mmf_enc_jpg_pop failed!\r\n"); ++ } ++ DEBUG(">>>>>>>>>>>>>>>>[%s][%d] use %ld us\r\n", __func__, __LINE__, _get_time_us() - start); ++ ++ // save_buff_to_file("venc_stream.jpg", data, data_size); ++ start = _get_time_us();DEBUG(">>>>>>>>>>>>>>>>[%s][%d] use %ld us\r\n", __func__, __LINE__, _get_time_us() - start); ++ if (0 != mmf_enc_jpg_free(enc_ch)) { ++ DEBUG("mmf_enc_jpg_free failed!\r\n"); ++ } ++ DEBUG(">>>>>>>>>>>>>>>>[%s][%d] use %ld us\r\n", __func__, __LINE__, _get_time_us() - start); ++ // break; ++ } ++ ++ { ++ mmf_vo_frame_push_with_fit(layer, vo_ch, filebuf, filelen, img_w, img_h, img_fmt, fit); ++ usleep(33 * 1000); ++ } ++ } ++#endif ++ ++ mmf_del_vo_channel(layer, vo_ch); ++ ++ if (0 != mmf_enc_jpg_deinit(enc_ch)) { ++ DEBUG("mmf_enc_jpg_deinit failed!\r\n"); ++ } ++ ++ mmf_del_vi_channel(vi_ch); ++ mmf_vi_deinit(); ++ mmf_deinit(); ++ return 0; ++} ++ ++ ++static VIDEO_FRAME_INFO_S *_mmf_alloc_frame(SIZE_S stSize, PIXEL_FORMAT_E enPixelFormat) ++{ ++ VIDEO_FRAME_INFO_S *pstVideoFrame; ++ VIDEO_FRAME_S *pstVFrame; ++ VB_BLK blk; ++ VB_CAL_CONFIG_S stVbCfg; ++ ++ pstVideoFrame = (VIDEO_FRAME_INFO_S *)calloc(sizeof(*pstVideoFrame), 1); ++ if (pstVideoFrame == NULL) { ++ SAMPLE_PRT("Failed to allocate VIDEO_FRAME_INFO_S\n"); ++ return NULL; ++ } ++ ++ memset(&stVbCfg, 0, sizeof(stVbCfg)); ++ VENC_GetPicBufferConfig(stSize.u32Width, ++ stSize.u32Height, ++ enPixelFormat, ++ DATA_BITWIDTH_8, ++ COMPRESS_MODE_NONE, ++ &stVbCfg); ++ ++ pstVFrame = &pstVideoFrame->stVFrame; ++ ++ pstVFrame->enCompressMode = COMPRESS_MODE_NONE; ++ pstVFrame->enPixelFormat = enPixelFormat; ++ pstVFrame->enVideoFormat = VIDEO_FORMAT_LINEAR; ++ pstVFrame->enColorGamut = COLOR_GAMUT_BT709; ++ pstVFrame->u32Width = stSize.u32Width; ++ pstVFrame->u32Height = stSize.u32Height; ++ pstVFrame->u32TimeRef = 0; ++ pstVFrame->u64PTS = 0; ++ pstVFrame->enDynamicRange = DYNAMIC_RANGE_SDR8; ++ ++ if (pstVFrame->u32Width % VENC_ALIGN_W) { ++ SAMPLE_PRT("u32Width is not algined to %d\n", VENC_ALIGN_W); ++ } ++ ++ blk = CVI_VB_GetBlock(VB_INVALID_POOLID, stVbCfg.u32VBSize); ++ if (blk == VB_INVALID_HANDLE) { ++ SAMPLE_PRT("Can't acquire vb block\n"); ++ free(pstVideoFrame); ++ return NULL; ++ } ++ ++ pstVideoFrame->u32PoolId = CVI_VB_Handle2PoolId(blk); ++ pstVFrame->u64PhyAddr[0] = CVI_VB_Handle2PhysAddr(blk); ++ pstVFrame->u32Stride[0] = stVbCfg.u32MainStride; ++ pstVFrame->u32Length[0] = stVbCfg.u32MainYSize; ++ pstVFrame->pu8VirAddr[0] = (CVI_U8 *)CVI_SYS_MmapCache(pstVFrame->u64PhyAddr[0], pstVFrame->u32Length[0]); ++ ++ if (stVbCfg.plane_num > 1) { ++ pstVFrame->u64PhyAddr[1] = ALIGN(pstVFrame->u64PhyAddr[0] + stVbCfg.u32MainYSize, stVbCfg.u16AddrAlign); ++ pstVFrame->u32Stride[1] = stVbCfg.u32CStride; ++ pstVFrame->u32Length[1] = stVbCfg.u32MainCSize; ++ pstVFrame->pu8VirAddr[1] = (CVI_U8 *)CVI_SYS_MmapCache(pstVFrame->u64PhyAddr[1], pstVFrame->u32Length[1]); ++ } ++ ++ if (stVbCfg.plane_num > 2) { ++ pstVFrame->u64PhyAddr[2] = ALIGN(pstVFrame->u64PhyAddr[1] + stVbCfg.u32MainCSize, stVbCfg.u16AddrAlign); ++ pstVFrame->u32Stride[2] = stVbCfg.u32CStride; ++ pstVFrame->u32Length[2] = stVbCfg.u32MainCSize; ++ pstVFrame->pu8VirAddr[2] = (CVI_U8 *)CVI_SYS_MmapCache(pstVFrame->u64PhyAddr[2], pstVFrame->u32Length[2]); ++ } ++ ++ // CVI_VENC_TRACE("phy addr(%#llx, %#llx, %#llx), Size %x\n", (long long)pstVFrame->u64PhyAddr[0] ++ // , (long long)pstVFrame->u64PhyAddr[1], (long long)pstVFrame->u64PhyAddr[2], stVbCfg.u32VBSize); ++ // CVI_VENC_TRACE("vir addr(%p, %p, %p), Size %x\n", pstVFrame->pu8VirAddr[0] ++ // , pstVFrame->pu8VirAddr[1], pstVFrame->pu8VirAddr[2], stVbCfg.u32MainSize); ++ ++ return pstVideoFrame; ++} ++ ++static CVI_S32 _mmf_free_frame(VIDEO_FRAME_INFO_S *pstVideoFrame) ++{ ++ VIDEO_FRAME_S *pstVFrame = &pstVideoFrame->stVFrame; ++ VB_BLK blk; ++ ++ if (pstVFrame->pu8VirAddr[0]) ++ CVI_SYS_Munmap((CVI_VOID *)pstVFrame->pu8VirAddr[0], pstVFrame->u32Length[0]); ++ if (pstVFrame->pu8VirAddr[1]) ++ CVI_SYS_Munmap((CVI_VOID *)pstVFrame->pu8VirAddr[1], pstVFrame->u32Length[1]); ++ if (pstVFrame->pu8VirAddr[2]) ++ CVI_SYS_Munmap((CVI_VOID *)pstVFrame->pu8VirAddr[2], pstVFrame->u32Length[2]); ++ ++ blk = CVI_VB_PhysAddr2Handle(pstVFrame->u64PhyAddr[0]); ++ if (blk != VB_INVALID_HANDLE) { ++ CVI_VB_ReleaseBlock(blk); ++ } ++ ++ free(pstVideoFrame); ++ ++ return CVI_SUCCESS; ++} ++ ++ ++// static void _mmf_dump_venc_h265_vui(VENC_H265_VUI_S *venc_h265_vui) ++// { ++// printf("venc_h265_vui->stVuiAspectRatio.aspect_ratio_info_present_flag = %d\n", venc_h265_vui->stVuiAspectRatio.aspect_ratio_info_present_flag); ++// printf("venc_h265_vui->stVuiAspectRatio.aspect_ratio_idc = %d\n", venc_h265_vui->stVuiAspectRatio.aspect_ratio_idc); ++// printf("venc_h265_vui->stVuiAspectRatio.overscan_info_present_flag = %d\n", venc_h265_vui->stVuiAspectRatio.overscan_info_present_flag); ++// printf("venc_h265_vui->stVuiAspectRatio.overscan_appropriate_flag = %d\n", venc_h265_vui->stVuiAspectRatio.overscan_appropriate_flag); ++// printf("venc_h265_vui->stVuiAspectRatio.sar_width = %d\n", venc_h265_vui->stVuiAspectRatio.sar_width); ++// printf("venc_h265_vui->stVuiAspectRatio.sar_height = %d\n", venc_h265_vui->stVuiAspectRatio.sar_height); ++ ++// printf("venc_h265_vui->stVuiTimeInfo.timing_info_present_flag = %d\n", venc_h265_vui->stVuiTimeInfo.timing_info_present_flag); ++// printf("venc_h265_vui->stVuiTimeInfo.num_units_in_tick = %d\n", venc_h265_vui->stVuiTimeInfo.num_units_in_tick); ++// printf("venc_h265_vui->stVuiTimeInfo.time_scale = %d\n", venc_h265_vui->stVuiTimeInfo.time_scale); ++// printf("venc_h265_vui->stVuiTimeInfo.num_ticks_poc_diff_one_minus1 = %d\n", venc_h265_vui->stVuiTimeInfo.num_ticks_poc_diff_one_minus1); ++ ++// printf("venc_h265_vui->stVuiVideoSignal.video_signal_type_present_flag = %d\n", venc_h265_vui->stVuiVideoSignal.video_signal_type_present_flag); ++// printf("venc_h265_vui->stVuiVideoSignal.video_format = %d\n", venc_h265_vui->stVuiVideoSignal.video_format); ++// printf("venc_h265_vui->stVuiVideoSignal.video_full_range_flag = %d\n", venc_h265_vui->stVuiVideoSignal.video_full_range_flag); ++// printf("venc_h265_vui->stVuiVideoSignal.colour_description_present_flag = %d\n", venc_h265_vui->stVuiVideoSignal.colour_description_present_flag); ++// printf("venc_h265_vui->stVuiVideoSignal.colour_primaries = %d\n", venc_h265_vui->stVuiVideoSignal.colour_primaries); ++// printf("venc_h265_vui->stVuiVideoSignal.transfer_characteristics = %d\n", venc_h265_vui->stVuiVideoSignal.transfer_characteristics); ++// printf("venc_h265_vui->stVuiVideoSignal.matrix_coefficients = %d\n", venc_h265_vui->stVuiVideoSignal.matrix_coefficients); ++ ++// printf("venc_h265_vui->stVuiBitstreamRestric.bitstream_restriction_flag = %d\n", venc_h265_vui->stVuiBitstreamRestric.bitstream_restriction_flag); ++// } ++ ++// static void _mmf_dump_venc_rc_param(VENC_RC_PARAM_S *venc_rc_param) ++// { ++// printf("venc_rc_param->u32ThrdI[%ld] = [", sizeof(venc_rc_param->u32ThrdI) / sizeof(CVI_U32)); ++// for (size_t i = 0; i < sizeof(venc_rc_param->u32ThrdI) / sizeof(CVI_U32); i ++) { ++// printf("%d, ", venc_rc_param->u32ThrdI[i]); ++// } ++// printf("]\n"); ++ ++// printf("venc_rc_param->u32ThrdP[%ld] = [", sizeof(venc_rc_param->u32ThrdP) / sizeof(CVI_U32)); ++// for (size_t i = 0; i < sizeof(venc_rc_param->u32ThrdP) / sizeof(CVI_U32); i ++) { ++// printf("%d, ", venc_rc_param->u32ThrdP[i]); ++// } ++// printf("]\n"); ++ ++// printf("venc_rc_param->u32ThrdB[%ld] = [", sizeof(venc_rc_param->u32ThrdB) / sizeof(CVI_U32)); ++// for (size_t i = 0; i < sizeof(venc_rc_param->u32ThrdB) / sizeof(CVI_U32); i ++) { ++// printf("%d, ", venc_rc_param->u32ThrdB[i]); ++// } ++// printf("]\n"); ++ ++// printf("venc_rc_param->u32DirectionThrd:%d\n", venc_rc_param->u32DirectionThrd); ++// printf("venc_rc_param->u32RowQpDelta:%d\n", venc_rc_param->u32RowQpDelta); ++// printf("venc_rc_param->s32FirstFrameStartQp:%d\n", venc_rc_param->s32FirstFrameStartQp); ++// printf("venc_rc_param->s32InitialDelay:%d\n", venc_rc_param->s32InitialDelay); ++// printf("venc_rc_param->u32ThrdLv:%d\n", venc_rc_param->u32ThrdLv); ++// printf("venc_rc_param->bBgEnhanceEn:%d\n", venc_rc_param->bBgEnhanceEn); ++// printf("venc_rc_param->s32BgDeltaQp:%d\n", venc_rc_param->s32BgDeltaQp); ++// printf("venc_rc_param->u32RowQpDelta:%d\n", venc_rc_param->u32RowQpDelta); ++ ++// printf("venc_rc_param->stParamH264Cbr.u32MinIprop:%d\n", venc_rc_param->stParamH264Cbr.u32MinIprop); ++// printf("venc_rc_param->stParamH264Cbr.u32MaxIprop:%d\n", venc_rc_param->stParamH264Cbr.u32MaxIprop); ++// printf("venc_rc_param->stParamH264Cbr.u32MaxQp:%d\n", venc_rc_param->stParamH264Cbr.u32MaxQp); ++// printf("venc_rc_param->stParamH264Cbr.u32MinQp:%d\n", venc_rc_param->stParamH264Cbr.u32MinQp); ++// printf("venc_rc_param->stParamH264Cbr.u32MaxIQp:%d\n", venc_rc_param->stParamH264Cbr.u32MaxIQp); ++// printf("venc_rc_param->stParamH264Cbr.u32MinIQp:%d\n", venc_rc_param->stParamH264Cbr.u32MinIQp); ++// printf("venc_rc_param->stParamH264Cbr.s32MaxReEncodeTimes:%d\n", venc_rc_param->stParamH264Cbr.s32MaxReEncodeTimes); ++// printf("venc_rc_param->stParamH264Cbr.bQpMapEn:%d\n", venc_rc_param->stParamH264Cbr.bQpMapEn); ++ ++// printf("venc_rc_param->stParamH265Cbr.u32MinIprop:%d\n", venc_rc_param->stParamH265Cbr.u32MinIprop); ++// printf("venc_rc_param->stParamH265Cbr.u32MaxIprop:%d\n", venc_rc_param->stParamH265Cbr.u32MaxIprop); ++// printf("venc_rc_param->stParamH265Cbr.u32MaxQp:%d\n", venc_rc_param->stParamH265Cbr.u32MaxQp); ++// printf("venc_rc_param->stParamH265Cbr.u32MinQp:%d\n", venc_rc_param->stParamH265Cbr.u32MinQp); ++// printf("venc_rc_param->stParamH265Cbr.u32MaxIQp:%d\n", venc_rc_param->stParamH265Cbr.u32MaxIQp); ++// printf("venc_rc_param->stParamH265Cbr.u32MinIQp:%d\n", venc_rc_param->stParamH265Cbr.u32MinIQp); ++// printf("venc_rc_param->stParamH265Cbr.s32MaxReEncodeTimes:%d\n", venc_rc_param->stParamH265Cbr.s32MaxReEncodeTimes); ++// printf("venc_rc_param->stParamH265Cbr.bQpMapEn:%d\n", venc_rc_param->stParamH265Cbr.bQpMapEn); ++// printf("venc_rc_param->stParamH265Cbr.enQpMapMode:%d\n", venc_rc_param->stParamH265Cbr.enQpMapMode); ++ ++// } ++ ++// static void _mmf_dump_venc_framelost(VENC_FRAMELOST_S *venc_framelost) ++// { ++// printf("venc_framelost->bFrmLostOpen:%d\n", venc_framelost->bFrmLostOpen); ++// printf("venc_framelost->u32FrmLostBpsThr:%d\n", venc_framelost->u32FrmLostBpsThr); ++// printf("venc_framelost->enFrmLostMode:%d\n", venc_framelost->enFrmLostMode); ++// printf("venc_framelost->u32EncFrmGaps:%d\n", venc_framelost->u32EncFrmGaps); ++// } ++ ++// static void _mmf_dump_venc_attr(VENC_ATTR_S *venc_attr) ++// { ++// printf("venc_attr->enType = %d\n", venc_attr->enType); ++// printf("venc_attr->u32MaxPicWidth = %d\n", venc_attr->u32MaxPicWidth); ++// printf("venc_attr->u32MaxPicHeight = %d\n", venc_attr->u32MaxPicHeight); ++// printf("venc_attr->u32BufSize = %d\n", venc_attr->u32BufSize); ++// printf("venc_attr->u32Profile = %d\n", venc_attr->u32Profile); ++// printf("venc_attr->bByFrame = %d\n", venc_attr->bByFrame); ++// printf("venc_attr->u32PicWidth = %d\n", venc_attr->u32PicWidth); ++// printf("venc_attr->u32PicHeight = %d\n", venc_attr->u32PicHeight); ++// printf("venc_attr->bSingleCore = %d\n", venc_attr->bSingleCore); ++// printf("venc_attr->bEsBufQueueEn = %d\n", venc_attr->bEsBufQueueEn); ++// printf("venc_attr->bIsoSendFrmEn = %d\n", venc_attr->bIsoSendFrmEn); ++// } ++ ++// static void _mmf_dump_venc_gop_attr(VENC_GOP_ATTR_S *venc_gop_attr) ++// { ++// printf("venc_gop_attr->enGopMode = %d\n", venc_gop_attr->enGopMode); ++// switch (venc_gop_attr->enGopMode) { ++// case VENC_GOPMODE_NORMALP: ++// printf("venc_gop_attr->stNormalP.s32IPQpDelta = %d\n", venc_gop_attr->stNormalP.s32IPQpDelta); ++// break; ++// default: ++// printf("unknown gop mode:%d\n", venc_gop_attr->enGopMode); ++// break; ++// } ++// } ++ ++// static void _mmf_dump_venc_rc_attr(VENC_RC_ATTR_S *venc_rc_attr) ++// { ++// printf("venc_rc_attr->enRcMode = %d\n", venc_rc_attr->enRcMode); ++// switch (venc_rc_attr->enRcMode) { ++// case VENC_RC_MODE_H264CBR: ++// printf("venc_rc_attr->stH264Cbr.u32Gop = %d\n", venc_rc_attr->stH264Cbr.u32Gop); ++// printf("venc_rc_attr->stH264Cbr.u32StatTime = %d\n", venc_rc_attr->stH264Cbr.u32StatTime); ++// printf("venc_rc_attr->stH264Cbr.u32SrcFrameRate = %d\n", venc_rc_attr->stH264Cbr.u32SrcFrameRate); ++// printf("venc_rc_attr->stH264Cbr.fr32DstFrameRate = %d\n", venc_rc_attr->stH264Cbr.fr32DstFrameRate); ++// printf("venc_rc_attr->stH264Cbr.u32BitRate = %d\n", venc_rc_attr->stH264Cbr.u32BitRate); ++// printf("venc_rc_attr->stH264Cbr.bVariFpsEn = %d\n", venc_rc_attr->stH264Cbr.bVariFpsEn); ++// break; ++// case VENC_RC_MODE_MJPEGCBR: ++// printf("venc_rc_attr->stMjpegCbr.u32StatTime = %d\n", venc_rc_attr->stMjpegCbr.u32StatTime); ++// printf("venc_rc_attr->stMjpegCbr.u32SrcFrameRate = %d\n", venc_rc_attr->stMjpegCbr.u32SrcFrameRate); ++// printf("venc_rc_attr->stMjpegCbr.fr32DstFrameRate = %d\n", venc_rc_attr->stMjpegCbr.fr32DstFrameRate); ++// printf("venc_rc_attr->stMjpegCbr.u32BitRate = %d\n", venc_rc_attr->stMjpegCbr.u32BitRate); ++// printf("venc_rc_attr->stMjpegCbr.bVariFpsEn = %d\n", venc_rc_attr->stMjpegCbr.bVariFpsEn); ++// break; ++// case VENC_RC_MODE_H265CBR: ++// printf("venc_rc_attr->stH265Cbr.u32Gop = %d\n", venc_rc_attr->stH265Cbr.u32Gop); ++// printf("venc_rc_attr->stH265Cbr.u32StatTime = %d\n", venc_rc_attr->stH265Cbr.u32StatTime); ++// printf("venc_rc_attr->stH265Cbr.u32SrcFrameRate = %d\n", venc_rc_attr->stH265Cbr.u32SrcFrameRate); ++// printf("venc_rc_attr->stH265Cbr.fr32DstFrameRate = %d\n", venc_rc_attr->stH265Cbr.fr32DstFrameRate); ++// printf("venc_rc_attr->stH265Cbr.u32BitRate = %d\n", venc_rc_attr->stH265Cbr.u32BitRate); ++// printf("venc_rc_attr->stH265Cbr.bVariFpsEn = %d\n", venc_rc_attr->stH265Cbr.bVariFpsEn); ++// break; ++// default: ++// printf("unknown rc mode:%d\n", venc_rc_attr->enRcMode); ++// break; ++// } ++// } ++ ++// static void _mmf_dump_venc_ch_attr(VENC_CHN_ATTR_S *venc_chn_attr) ++// { ++// _mmf_dump_venc_attr(&venc_chn_attr->stVencAttr); ++// _mmf_dump_venc_gop_attr(&venc_chn_attr->stGopAttr); ++// _mmf_dump_venc_rc_attr(&venc_chn_attr->stRcAttr); ++// } ++ ++int mmf_enc_h264_init(int ch, int w, int h) ++{ ++ mmf_venc_cfg_t cfg = { ++ .type = 2, //1, h265, 2, h264 ++ .w = w, ++ .h = h, ++ .fmt = PIXEL_FORMAT_NV21, ++ .jpg_quality = 0, // unused ++ .gop = 50, ++ .intput_fps = 30, ++ .output_fps = 30, ++ .bitrate = 3000, ++ }; ++ ++ return mmf_add_venc_channel(ch, &cfg); ++} ++ ++int test_mmf_venc_init(int ch, int w, int h) ++{ ++ if (rtsp_server_type == 2) ++ return mmf_enc_h264_init(ch, w, h); ++ else ++ return mmf_enc_h265_init(ch, w, h); ++} ++ ++static int _test_venc_h265(void) ++{ ++ uint8_t *filebuf = NULL; ++ uint32_t filelen; ++ (void)filelen; ++#if 1 ++ int img_w = 2560, img_h = 1440, fit = 0, img_fmt = PIXEL_FORMAT_NV21; //PIXEL_FORMAT_NV21 or PIXEL_FORMAT_RGB_888 ++ // int img_w = 2560, img_h = 1440, fit = 0, img_fmt = PIXEL_FORMAT_RGB_888; //PIXEL_FORMAT_NV21 or PIXEL_FORMAT_RGB_888 ++ (void)fit; ++ filebuf = _prepare_image(img_w, img_h, img_fmt); ++ if (img_fmt == PIXEL_FORMAT_RGB_888) ++ filelen = img_w * img_h * 3; ++ else ++ filelen = img_w * img_h * 3 / 2; ++ ++ DEBUG("in w:%d h:%d fmt:%d\r\n", img_w, img_h, img_fmt); ++#endif ++ ++ mmf_init(); ++ ++ if (0 != mmf_vi_init()) { ++ DEBUG("mmf_vi_init failed!\r\n"); ++ mmf_deinit(); ++ return -1; ++ } ++ ++ int ch = 0; ++ if (test_mmf_venc_init(ch, img_w, img_h)) { ++ printf("test_mmf_venc_init failed\n"); ++ return -1; ++ } ++ ++#if 0 ++ while (!exit_flag) { ++ mmf_stream_t stream; ++ if (!mmf_venc_pop(ch, &stream)) { ++ for (int i = 0; i < stream.count; i ++) { ++ printf("[%d] stream.data:%p stream.len:%d\n", i, stream.data[i], stream.data_size[i]); ++ } ++ ++ if (mmf_venc_free(ch)) { ++ printf("mmf_venc_free failed\n"); ++ goto _exit; ++ } ++ } ++ ++ if (mmf_venc_push(ch, filebuf, img_w, img_h, img_fmt)) { ++ printf("mmf_venc_push failed\n"); ++ goto _exit; ++ } ++ } ++#else ++ while (!exit_flag) { ++ if (mmf_venc_push(ch, filebuf, img_w, img_h, img_fmt)) { ++ printf("mmf_venc_push failed\n"); ++ goto _exit; ++ } ++ ++ mmf_stream_t stream; ++ if (mmf_venc_pop(ch, &stream)) { ++ printf("mmf_venc_pop failed\n"); ++ goto _exit; ++ } ++ ++ { ++ for (int i = 0; i < stream.count; i ++) { ++ printf("[%d] stream.data:%p stream.len:%d\n", i, stream.data[i], stream.data_size[i]); ++ } ++ ++ // static FILE *fp = NULL; ++ // static int file_num = 0; ++ // static int file_duration = 100; ++ // if (fp == NULL) { ++ // printf("open file\n"); ++ // fp = fopen("venc_stream.h265", "wb"); ++ // if (fp == NULL) { ++ // printf("open file failed\n"); ++ // goto _exit; ++ // } ++ // } ++ ++ // for (int i = 0; i < stream.count; i++) { ++ // fwrite(stream.data[i], stream.data_size[i], 1, fp); ++ // } ++ ++ // if (++ file_num >= file_duration) { ++ // printf("close file\n"); ++ // fclose(fp); ++ // fp = NULL; ++ // file_num = 0; ++ // exit_flag = 1; ++ // } ++ } ++ ++ if (mmf_venc_free(ch)) { ++ printf("mmf_venc_free failed\n"); ++ goto _exit; ++ } ++ } ++#endif ++ ++ if (mmf_del_venc_channel(ch)) { ++ printf("mmf_del_venc_channel failed\n"); ++ return -1; ++ } ++_exit: ++ mmf_deinit(); ++ return 0; ++} ++ ++static int _test_vi_venc_h265(void) ++{ ++ uint8_t *filebuf = NULL; ++ uint32_t filelen; ++ (void)filebuf; ++ (void)filelen; ++#if 1 ++ int img_w = 2560, img_h = 1440, fit = 0, img_fmt = PIXEL_FORMAT_NV21; //PIXEL_FORMAT_NV21 or PIXEL_FORMAT_RGB_888 ++ // int img_w = 2560, img_h = 1440, fit = 0, img_fmt = PIXEL_FORMAT_RGB_888; //PIXEL_FORMAT_NV21 or PIXEL_FORMAT_RGB_888 ++ (void)fit; ++ filebuf = _prepare_image(img_w, img_h, img_fmt); ++ if (img_fmt == PIXEL_FORMAT_RGB_888) ++ filelen = img_w * img_h * 3; ++ else ++ filelen = img_w * img_h * 3 / 2; ++ ++ DEBUG("in w:%d h:%d fmt:%d\r\n", img_w, img_h, img_fmt); ++#endif ++ ++ mmf_init(); ++ ++ int ch = 0; ++ if (test_mmf_venc_init(ch, img_w, img_h)) { ++ printf("test_mmf_venc_init failed\n"); ++ return -1; ++ } ++ ++ if (0 != mmf_vi_init()) { ++ DEBUG("mmf_vi_init failed!\r\n"); ++ mmf_deinit(); ++ return -1; ++ } ++ ++ int vi_ch = mmf_get_vi_unused_channel(); ++ if (0 != mmf_add_vi_channel(vi_ch, img_w, img_h, img_fmt)) { ++ DEBUG("mmf_add_vi_channel failed!\r\n"); ++ mmf_deinit(); ++ return -1; ++ } ++ ++ uint64_t start = _get_time_us(); ++ uint64_t last_loop_us = start; ++#ifndef DEBUG_EN ++ UNUSED(start); UNUSED(last_loop_us); ++#endif ++ while (!exit_flag) { ++ void *data; ++ int data_size, width, height, format; ++ ++ start = _get_time_us(); ++ if (mmf_vi_frame_pop(vi_ch, &data, &data_size, &width, &height, &format)) { ++ continue; ++ } ++ DEBUG("use %ld us\r\n", _get_time_us() - start); ++ ++ start = _get_time_us(); ++ if (mmf_venc_push(ch, data, img_w, img_h, img_fmt)) { ++ printf("mmf_venc_push failed\n"); ++ goto _exit; ++ } ++ DEBUG("use %ld us\r\n", _get_time_us() - start); ++ ++ start = _get_time_us(); ++ mmf_stream_t stream; ++ if (mmf_venc_pop(ch, &stream)) { ++ printf("mmf_venc_pop failed\n"); ++ goto _exit; ++ } ++ DEBUG("use %ld us\r\n", _get_time_us() - start); ++ ++ start = _get_time_us(); ++ { ++ for (int i = 0; i < stream.count; i ++) { ++ printf("[%d] stream.data:%p stream.len:%d\n", i, stream.data[i], stream.data_size[i]); ++ } ++ ++ static FILE *fp = NULL; ++ static int file_num = 0; ++ static int file_duration = -1; ++ if (fp == NULL) { ++ printf("open file\n"); ++ fp = fopen("venc_stream.h265", "wb"); ++ if (fp == NULL) { ++ printf("open file failed\n"); ++ goto _exit; ++ } ++ } ++ ++ for (int i = 0; i < stream.count; i++) { ++ fwrite(stream.data[i], stream.data_size[i], 1, fp); ++ } ++ ++ if (file_duration != -1 && ++ file_num >= file_duration) { ++ printf("close file\n"); ++ fclose(fp); ++ fp = NULL; ++ file_num = 0; ++ exit_flag = 1; ++ } else if (exit_flag) { ++ printf("close file\n"); ++ fclose(fp); ++ fp = NULL; ++ } ++ } ++ DEBUG("use %ld us\r\n", _get_time_us() - start); ++ ++ start = _get_time_us(); ++ if (mmf_venc_free(ch)) { ++ printf("mmf_venc_free failed\n"); ++ goto _exit; ++ } ++ DEBUG("use %ld us\r\n", _get_time_us() - start); ++ ++ start = _get_time_us(); ++ mmf_vi_frame_free(vi_ch); ++ DEBUG("use %ld us\r\n", _get_time_us() - start); ++ ++ DEBUG("use %ld us\r\n", _get_time_us() - last_loop_us); ++ last_loop_us = _get_time_us(); ++ } ++ ++ if (mmf_del_venc_channel(ch)) { ++ printf("mmf_del_venc_channel failed\n"); ++ return -1; ++ } ++_exit: ++ mmf_deinit(); ++ return 0; ++} ++ ++static int _test_vi_venc_h26x_rtsp(void); ++ ++static int _test_rtsp_h264(void) ++{ ++ rtsp_server_type = 2; ++ return _test_vi_venc_h26x_rtsp(); ++} ++ ++ ++static int _test_vi_venc_h264(void) ++{ ++ uint8_t *filebuf = NULL; ++ uint32_t filelen; ++ (void)filelen; ++#if 1 ++ int img_w = 1280, img_h = 720, fit = 0, img_fmt = PIXEL_FORMAT_NV21; //PIXEL_FORMAT_NV21 or PIXEL_FORMAT_RGB_888 ++ // int img_w = 2560, img_h = 1440, fit = 0, img_fmt = PIXEL_FORMAT_NV21; //PIXEL_FORMAT_NV21 or PIXEL_FORMAT_RGB_888 ++ // int img_w = 2560, img_h = 1440, fit = 0, img_fmt = PIXEL_FORMAT_RGB_888; //PIXEL_FORMAT_NV21 or PIXEL_FORMAT_RGB_888 ++ (void)fit; ++ filebuf = _prepare_image(img_w, img_h, img_fmt); ++ if (img_fmt == PIXEL_FORMAT_RGB_888) ++ filelen = img_w * img_h * 3; ++ else ++ filelen = img_w * img_h * 3 / 2; ++ ++ DEBUG("in w:%d h:%d fmt:%d\r\n", img_w, img_h, img_fmt); ++#endif ++ ++ mmf_init(); ++ ++ if (0 != mmf_vi_init()) { ++ DEBUG("mmf_vi_init failed!\r\n"); ++ mmf_deinit(); ++ return -1; ++ } ++ ++#if 1 ++ { ++ CVI_S32 s32Ret = CVI_SUCCESS; ++ int ch = 0, w = img_w, h = img_h; ++ uint64_t start = _get_time_us(); ++ { ++ if (img_fmt != PIXEL_FORMAT_NV21) { ++ printf("Only support PIXEL_FORMAT_NV21!\r\n"); ++ return -1; ++ } ++ VENC_CHN_ATTR_S stVencChnAttr; ++ memset(&stVencChnAttr, 0, sizeof(VENC_CHN_ATTR_S)); ++ stVencChnAttr.stVencAttr.enType = PT_H264; ++ stVencChnAttr.stVencAttr.u32MaxPicWidth = w; ++ stVencChnAttr.stVencAttr.u32MaxPicHeight = h; ++ stVencChnAttr.stVencAttr.u32BufSize = 1024 * 1024; // 1024Kb ++ stVencChnAttr.stVencAttr.bByFrame = 1; ++ stVencChnAttr.stVencAttr.u32PicWidth = w; ++ stVencChnAttr.stVencAttr.u32PicHeight = h; ++ stVencChnAttr.stVencAttr.bEsBufQueueEn = CVI_TRUE; ++ stVencChnAttr.stVencAttr.bIsoSendFrmEn = CVI_TRUE; ++ stVencChnAttr.stGopAttr.enGopMode = VENC_GOPMODE_NORMALP; ++ stVencChnAttr.stGopAttr.stNormalP.s32IPQpDelta = 2; ++ stVencChnAttr.stRcAttr.enRcMode = VENC_RC_MODE_H264CBR; ++ stVencChnAttr.stRcAttr.stH264Cbr.u32Gop = 50; ++ stVencChnAttr.stRcAttr.stH264Cbr.u32StatTime = 2; ++ stVencChnAttr.stRcAttr.stH264Cbr.u32SrcFrameRate = 30; ++ stVencChnAttr.stRcAttr.stH264Cbr.fr32DstFrameRate = 30; ++ stVencChnAttr.stRcAttr.stH264Cbr.u32BitRate = 3000; ++ stVencChnAttr.stRcAttr.stH264Cbr.bVariFpsEn = 0; ++ s32Ret = CVI_VENC_CreateChn(ch, &stVencChnAttr); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("CVI_VENC_CreateChn [%d] failed with %d\n", ch, s32Ret); ++ return s32Ret; ++ } ++ ++ VENC_RECV_PIC_PARAM_S stRecvParam; ++ stRecvParam.s32RecvPicNum = -1; ++ s32Ret = CVI_VENC_StartRecvFrame(ch, &stRecvParam); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("CVI_VENC_StartRecvPic failed with %d\n", s32Ret); ++ return CVI_FAILURE; ++ } ++ ++ { ++ VENC_H264_TRANS_S h264Trans = {0}; ++ s32Ret = CVI_VENC_GetH264Trans(ch, &h264Trans); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("CVI_VENC_GetH264Trans failed with %d\n", s32Ret); ++ return s32Ret; ++ } ++ //h264Trans.cb_qp_offset = 0; ++ //h264Trans.cr_qp_offset = 0; ++ h264Trans.chroma_qp_index_offset = 0; ++ s32Ret = CVI_VENC_SetH264Trans(ch, &h264Trans); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("CVI_VENC_SetH264Trans failed with %d\n", s32Ret); ++ return s32Ret; ++ } ++ } ++ ++ { ++ VENC_H264_VUI_S h264Vui = {0}; ++ s32Ret = CVI_VENC_GetH264Vui(ch, &h264Vui); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("CVI_VENC_GetH264Vui failed with %d\n", s32Ret); ++ return s32Ret; ++ } ++ ++ h264Vui.stVuiAspectRatio.aspect_ratio_info_present_flag = 0; ++ h264Vui.stVuiAspectRatio.aspect_ratio_idc = 1; ++ h264Vui.stVuiAspectRatio.overscan_info_present_flag = 0; ++ h264Vui.stVuiAspectRatio.overscan_appropriate_flag = 0; ++ h264Vui.stVuiAspectRatio.sar_width = 1; ++ h264Vui.stVuiAspectRatio.sar_height = 1; ++ h264Vui.stVuiTimeInfo.timing_info_present_flag = 1; ++ h264Vui.stVuiTimeInfo.num_units_in_tick = 1; ++ h264Vui.stVuiTimeInfo.time_scale = 30; ++ //h264Vui.stVuiTimeInfo.num_ticks_poc_diff_one_minus1 = 1; ++ h264Vui.stVuiVideoSignal.video_signal_type_present_flag = 0; ++ h264Vui.stVuiVideoSignal.video_format = 5; ++ h264Vui.stVuiVideoSignal.video_full_range_flag = 0; ++ h264Vui.stVuiVideoSignal.colour_description_present_flag = 0; ++ h264Vui.stVuiVideoSignal.colour_primaries = 2; ++ h264Vui.stVuiVideoSignal.transfer_characteristics = 2; ++ h264Vui.stVuiVideoSignal.matrix_coefficients = 2; ++ h264Vui.stVuiBitstreamRestric.bitstream_restriction_flag = 0; ++ ++ // _mmf_dump_venc_h264_vui(&h264Vui); ++ ++ s32Ret = CVI_VENC_SetH264Vui(ch, &h264Vui); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("CVI_VENC_SetH264Vui failed with %d\n", s32Ret); ++ return s32Ret; ++ } ++ } ++ ++ // rate control ++ { ++ VENC_RC_PARAM_S stRcParam; ++ s32Ret = CVI_VENC_GetRcParam(ch, &stRcParam); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("CVI_VENC_GetRcParam failed with %d\n", s32Ret); ++ return s32Ret; ++ } ++ stRcParam.s32FirstFrameStartQp = 35; ++ stRcParam.stParamH264Cbr.u32MinIprop = 1; ++ stRcParam.stParamH264Cbr.u32MaxIprop = 10; ++ stRcParam.stParamH264Cbr.u32MaxQp = 51; ++ stRcParam.stParamH264Cbr.u32MinQp = 20; ++ stRcParam.stParamH264Cbr.u32MaxIQp = 51; ++ stRcParam.stParamH264Cbr.u32MinIQp = 20; ++ ++ // _mmf_dump_venc_rc_param(&stRcParam); ++ ++ s32Ret = CVI_VENC_SetRcParam(ch, &stRcParam); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("CVI_VENC_SetRcParam failed with %d\n", s32Ret); ++ return s32Ret; ++ } ++ } ++ ++ // frame lost set ++ { ++ VENC_FRAMELOST_S stFL; ++ s32Ret = CVI_VENC_GetFrameLostStrategy(ch, &stFL); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("CVI_VENC_GetFrameLostStrategy failed with %d\n", s32Ret); ++ return s32Ret; ++ } ++ stFL.enFrmLostMode = FRMLOST_PSKIP; ++ ++ // _mmf_dump_venc_framelost(&stFL); ++ ++ s32Ret = CVI_VENC_SetFrameLostStrategy(ch, &stFL); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("CVI_VENC_SetFrameLostStrategy failed with %d\n", s32Ret); ++ return s32Ret; ++ } ++ } ++ } ++ printf("==============================[%s][%d] use %ld us\r\n", __func__, __LINE__, _get_time_us() - start); ++ ++ while (!exit_flag) { ++ start = _get_time_us(); ++ { ++ SIZE_S stSize = {(CVI_U32)w, (CVI_U32)h}; ++ PIXEL_FORMAT_E format = (PIXEL_FORMAT_E)img_fmt; ++ VIDEO_FRAME_INFO_S* frame = _mmf_alloc_frame(stSize, (PIXEL_FORMAT_E)format); ++ if (!frame) { ++ printf("Alloc frame failed!\r\n"); ++ return -1; ++ } ++ uint64_t start2 = _get_time_us(); ++ switch (format) { ++ case PIXEL_FORMAT_NV21: ++ { ++ memcpy(frame->stVFrame.pu8VirAddr[0], filebuf, w * h); ++ memcpy(frame->stVFrame.pu8VirAddr[1], filebuf + w * h, w * h / 2); ++ } ++ break; ++ default: return -1; ++ } ++ printf("==============================[%s][%d] use %ld us\r\n", __func__, __LINE__, _get_time_us() - start2); ++ ++ s32Ret = CVI_VENC_SendFrame(ch, frame, 1000); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("CVI_VENC_GetStream failed with %#x\n", s32Ret); ++ return s32Ret; ++ } ++ ++ _mmf_free_frame(frame); ++ } ++ printf("==============================[%s][%d] use %ld us\r\n", __func__, __LINE__, _get_time_us() - start); ++ ++ start = _get_time_us(); ++ { ++ int fd = CVI_VENC_GetFd(ch); ++ if (fd < 0) { ++ printf("CVI_VENC_GetFd failed with %d\n", fd); ++ goto _exit; ++ } ++ ++ fd_set readFds; ++ struct timeval timeoutVal; ++ ++ FD_ZERO(&readFds); ++ FD_SET(fd, &readFds); ++ timeoutVal.tv_sec = 0; ++ timeoutVal.tv_usec = 80*1000; ++ s32Ret = select(fd + 1, &readFds, NULL, NULL, &timeoutVal); ++ if (s32Ret < 0) { ++ if (errno == EINTR) { ++ printf("VencChn(%d) select failed!\n", ch); ++ goto _exit; ++ } ++ } else if (s32Ret == 0) { ++ printf("VencChn(%d) select timeout!\n", ch); ++ goto _exit; ++ } ++ ++ VENC_STREAM_S frame = {0}; ++ frame.pstPack = (VENC_PACK_S *)malloc(sizeof(VENC_PACK_S) * 8); ++ if (!frame.pstPack) { ++ printf("malloc failed!\r\n"); ++ return -1; ++ } ++ ++ // ISP_EXP_INFO_S stExpInfo; ++ // memset(&stExpInfo, 0, sizeof(stExpInfo)); ++ // CVI_ISP_QueryExposureInfo(0, &stExpInfo); ++ // CVI_S32 timeout = (1000 * 2) / (stExpInfo.u32Fps / 100); //u32Fps = fps * 100 ++ CVI_S32 timeout = 100; ++ s32Ret = CVI_VENC_GetStream(ch, &frame, timeout); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("CVI_VENC_GetStream failed with %#x\n", s32Ret); ++ free(frame.pstPack); ++ return s32Ret; ++ } ++ ++ printf("frame.u32PackCount = %d frame.pstPack[0].u32Len:%d\n", frame.u32PackCount, frame.u32PackCount ? frame.pstPack[0].u32Len : 0); ++ if ((1 == frame.u32PackCount) && (frame.pstPack[0].u32Len > 512 * 1024)) { ++ printf("size is over 512K\n"); ++ } else { ++ printf("get new frame\n"); ++ for (CVI_U32 i = 0; i < frame.u32PackCount; i++) { ++ printf("[%d] frame.pstPack.pu8Addr:%p frame.pstPac.u32Len:%d dataPtr:%p dataLen:%d\n", ++ i, frame.pstPack[i].pu8Addr, frame.pstPack[i].u32Len, frame.pstPack[i].pu8Addr - frame.pstPack[i].u32Offset, frame.pstPack[i].u32Len - frame.pstPack[i].u32Offset); ++ } ++ { ++ // check file exit ++ static FILE *fp = NULL; ++ static int file_num = 0; ++ static int file_duration = 100; ++ { ++ if (fp == NULL) { ++ fp = fopen("venc_stream.h264", "wb"); ++ if (fp == NULL) { ++ printf("open file failed\n"); ++ goto _release_venc; ++ } ++ } ++ ++ for (CVI_U32 i = 0; i < frame.u32PackCount; i++) { ++ fwrite(frame.pstPack[i].pu8Addr + frame.pstPack[i].u32Offset, frame.pstPack[i].u32Len - frame.pstPack[i].u32Offset, 1, fp); ++ } ++ ++ if (++ file_num >= file_duration) { ++ printf("close file\n"); ++ fclose(fp); ++ fp = NULL; ++ file_num = 0; ++ goto _release_venc; ++ } ++ } ++ } ++ // save_buff_to_file("venc_stream.jpg", ++ // frame.pstPack[0].pu8Addr, frame.pstPack[0].u32Len); ++ } ++ ++ free(frame.pstPack); ++ s32Ret = CVI_VENC_ReleaseStream(ch, &frame); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("CVI_VENC_ReleaseStream failed with %#x\n", s32Ret); ++ return s32Ret; ++ } ++ } ++ printf("==============================[%s][%d] use %ld us\r\n", __func__, __LINE__, _get_time_us() - start); ++ } ++_release_venc: ++ start = _get_time_us(); ++ { ++ s32Ret = CVI_VENC_StopRecvFrame(ch); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("CVI_VENC_StopRecvPic failed with %d\n", s32Ret); ++ } ++ ++ s32Ret = CVI_VENC_ResetChn(ch); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("CVI_VENC_ResetChn vechn[%d] failed with %#x!\n", ++ ch, s32Ret); ++ } ++ ++ s32Ret = CVI_VENC_DestroyChn(ch); ++ if (s32Ret != CVI_SUCCESS) { ++ printf("CVI_VENC_DestroyChn [%d] failed with %d\n", ch, s32Ret); ++ } ++ } ++ printf("==============================[%s][%d] use %ld us\r\n", __func__, __LINE__, _get_time_us() - start); ++ } ++#endif ++_exit: ++ mmf_deinit(); ++ return 0; ++} ++ ++static inline const uint8_t* search_start_code(const uint8_t* ptr, const uint8_t* end) ++{ ++ for(const uint8_t *p = ptr; p + 3 < end; p++) ++ { ++ if(0x00 == p[0] && 0x00 == p[1] && (0x01 == p[2] || (0x00==p[2] && 0x01==p[3]))) ++ return p; ++ } ++ return end; ++} ++ ++static void* _rtsp_user_thread(void *args) ++{ ++ (void)args; ++ uint8_t *m_ptr = NULL; ++ size_t m_capacity = 0; ++ uint64_t timestamp = 0; ++ const char *file = "test.h265"; ++ FILE* fp = fopen(file, "rb"); ++ if(fp) { ++ fseek(fp, 0, SEEK_END); ++ m_capacity = ftell(fp); ++ fseek(fp, 0, SEEK_SET); ++ ++ m_ptr = (uint8_t*)malloc(m_capacity); ++ fread(m_ptr, 1, m_capacity, fp); ++ fclose(fp); ++ } ++ ++ uint64_t last_loop_us = _get_time_us(); ++ while (1) { ++ const uint8_t* end = m_ptr + m_capacity; ++ const uint8_t* nalu = search_start_code(m_ptr, end); ++ const uint8_t* p = nalu; ++ while (p < end) { ++ const unsigned char* pn = search_start_code(p + 4, end); ++ size_t bytes = pn - nalu; ++ ++ rtsp_send_memory_data(timestamp, (uint8_t *)nalu, bytes); ++ ++ nalu = pn; ++ p = pn; ++ ++ usleep(40 * 1000); ++ timestamp += (_get_time_us() - last_loop_us) / 1000; ++ last_loop_us = _get_time_us(); ++ } ++ } ++ ++ return NULL; ++} ++ ++static int _test_rtsp_h26x(void) ++{ ++ pthread_t pthread_id; ++ pthread_create(&pthread_id, NULL, _rtsp_user_thread, NULL); ++ ++ rtsp_server_init(NULL, 8554); ++ rtsp_memory_server_start(rtsp_server_type); ++ ++ printf("rtsp://%s:%d/live\n", rtsp_get_server_ip(), rtsp_get_server_port()); ++ ++ while (!exit_flag) { ++ ++ usleep(30 * 1000); ++ } ++ ++ rtsp_server_deinit(); ++ return 0; ++} ++ ++ ++static int _test_vi_venc_h26x_rtsp(void) ++{ ++ if (0 != rtsp_server_init(NULL, 8554)) { ++ printf("rtsp server init\n"); ++ return 0; ++ } ++ ++ if (0 != rtsp_memory_server_start(rtsp_server_type)) { ++ printf("rtsp server start\n"); ++ return 0; ++ } ++ ++ if (0 != mmf_init()) { ++ printf("mmf deinit\n"); ++ return 0; ++ } ++ ++ int img_w = 2560, img_h = 1440, img_fps = 30, fit = 0, img_fmt = PIXEL_FORMAT_NV21; ++ (void)fit; ++ int ch = 0; ++ mmf_vi_get_max_size(&img_w, &img_h); ++ char *sensor_name = mmf_get_sensor_name(); ++ printf("sensor %s max size %dx%d\n", sensor_name, img_w, img_h); ++ if (!strcmp(sensor_name, "lt6911")) { ++ img_w = 1280; img_h = 720; img_fps = 60; ++ } ++ if (test_mmf_venc_init(ch, img_w, img_h)) { ++ printf("test_mmf_venc_init failed\n"); ++ return -1; ++ } ++ ++ uint8_t *filebuf = _prepare_image(img_w, img_h, img_fmt); ++ ++ if (0 != mmf_vi_init()) { ++ DEBUG("mmf_vi_init failed!\r\n"); ++ mmf_deinit(); ++ return -1; ++ } ++ ++ int vi_ch = mmf_get_vi_unused_channel(); ++ if (0 != mmf_add_vi_channel_v2(vi_ch, img_w, img_h, img_fmt, img_fps, 2, !true, !true, 2, 3)) { ++ DEBUG("mmf_add_vi_channel failed!\r\n"); ++ mmf_deinit(); ++ return -1; ++ } ++ ++ mmf_vi_set_pop_timeout(100); ++ ++ printf("rtsp://%s:%d/live\n", rtsp_get_server_ip(), rtsp_get_server_port()); ++ ++ uint64_t start = _get_time_us(); ++ uint64_t last_loop_us = start; ++ uint64_t timestamp = 0; ++ int last_vi_pop = -1; ++ exit_flag = 0; ++ while (!exit_flag) { ++ void *data; ++ int data_size, width, height, format; ++ ++ if (!last_vi_pop) { ++ start = _get_time_us(); ++ mmf_vi_frame_free(vi_ch); ++ DEBUG("use %ld us\r\n", _get_time_us() - start); ++ } ++ ++ start = _get_time_us(); ++ int vi_ret = mmf_vi_frame_pop(vi_ch, &data, &data_size, &width, &height, &format); ++ if (vi_ret != last_vi_pop) { ++ uint64_t vi_stamp = timestamp; ++ vi_stamp += (_get_time_us() - last_loop_us) / 1000; ++ printf("[%.6ld.%.3ld] %s\n", vi_stamp / 1000, vi_stamp % 1000, ++ vi_ret ? "no input signal" : "got input signal"); ++ mmf_del_venc_channel(ch); ++ test_mmf_venc_init(ch, img_w, img_h); ++ last_vi_pop = vi_ret; ++ } ++ if (vi_ret) ++ data = filebuf; ++ DEBUG("use %ld us\r\n", _get_time_us() - start); ++ ++ start = _get_time_us(); ++ if (mmf_venc_push(ch, data, img_w, img_h, img_fmt)) { ++ printf("mmf_venc_push failed\n"); ++ goto _exit; ++ } ++ DEBUG("use %ld us\r\n", _get_time_us() - start); ++ ++ start = _get_time_us(); ++ mmf_stream_t stream; ++ if (mmf_venc_pop(ch, &stream)) { ++ printf("mmf_venc_pop failed\n"); ++ goto _exit; ++ } ++ DEBUG("use %ld us\r\n", _get_time_us() - start); ++ ++ start = _get_time_us(); ++ { ++ int stream_size = 0; ++ for (int i = 0; i < stream.count; i ++) { ++ DEBUG("[%d] stream.data:%p stream.len:%d\n", i, stream.data[i], stream.data_size[i]); ++ stream_size += stream.data_size[i]; ++ } ++ ++ if (stream.count > 1) { ++ uint8_t *stream_buffer = (uint8_t *)malloc(stream_size); ++ if (stream_buffer) { ++ int copy_length = 0; ++ for (int i = 0; i < stream.count; i ++) { ++ memcpy(stream_buffer + copy_length, stream.data[i], stream.data_size[i]); ++ copy_length += stream.data_size[i]; ++ } ++ rtsp_send_memory_data(timestamp, stream_buffer, copy_length); ++ free(stream_buffer); ++ } else { ++ DEBUG("malloc failed!\r\n"); ++ } ++ } else if (stream.count == 1) { ++ rtsp_send_memory_data(timestamp, (uint8_t *)stream.data[0], stream.data_size[0]); ++ } ++ } ++ DEBUG("use %ld us\r\n", _get_time_us() - start); ++ ++ start = _get_time_us(); ++ if (mmf_venc_free(ch)) { ++ printf("mmf_venc_free failed\n"); ++ goto _exit; ++ } ++ DEBUG("use %ld us\r\n", _get_time_us() - start); ++ ++ DEBUG("use %ld us\r\n", _get_time_us() - last_loop_us); ++ timestamp += (_get_time_us() - last_loop_us) / 1000; ++ last_loop_us = _get_time_us(); ++ } ++ ++ if (mmf_del_venc_channel(ch)) { ++ printf("mmf_del_venc_channel failed\n"); ++ return -1; ++ } ++ ++ if (0 != rtsp_server_deinit()) { ++ printf("rtsp server deinit\n"); ++ return 0; ++ } ++_exit: ++ mmf_del_vi_channel(vi_ch); ++ mmf_vi_deinit(); ++ if (0 != mmf_deinit()) { ++ printf("mmf deinit\n"); ++ } ++ free(filebuf); ++ return 0; ++} ++ ++static int _test_rtsp_h265(void) ++{ ++ rtsp_server_type = 1; ++ return _test_rtsp_h26x(); ++} ++ ++static int _test_vi_venc_h265_rtsp(void) ++{ ++ rtsp_server_type = 1; ++ return _test_vi_venc_h26x_rtsp(); ++} ++ ++static int _test_multiple_vi(void) ++{ ++ signal(SIGINT, sig_handle); ++ signal(SIGTERM, sig_handle); ++ ++ int img_w = 2560, img_h = 1440, fit = 2, img_fmt = PIXEL_FORMAT_NV21; //PIXEL_FORMAT_NV21 or PIXEL_FORMAT_RGB_888 ++ int img_w2 = 640, img_h2 = 480, img_fmt2 = PIXEL_FORMAT_RGB_888; //PIXEL_FORMAT_NV21 or PIXEL_FORMAT_RGB_888 ++ ++ if (0 != mmf_init()) { ++ DEBUG("mmf_init failed!\r\n"); ++ return -1; ++ } ++ ++ if (0 != mmf_vi_init()) { ++ DEBUG("mmf_vi_init failed!\r\n"); ++ mmf_deinit(); ++ return -1; ++ } ++ ++ int vi_ch = mmf_get_vi_unused_channel(); ++ if (0 != mmf_add_vi_channel(vi_ch, img_w, img_h, img_fmt)) { ++ DEBUG("mmf_add_vi_channel failed!\r\n"); ++ mmf_deinit(); ++ return -1; ++ } ++ ++ int vi_ch2 = mmf_get_vi_unused_channel(); ++ if (0 != mmf_add_vi_channel(vi_ch2, img_w2, img_h2, img_fmt2)) { ++ DEBUG("mmf_add_vi_channel failed!\r\n"); ++ mmf_del_vi_channel(vi_ch); ++ mmf_deinit(); ++ return -1; ++ } ++ ++ int layer = 0; ++ int vo_ch = mmf_get_vo_unused_channel(layer); ++ if (0 != mmf_add_vo_channel_with_fit(layer, vo_ch, 552, 368, img_fmt, fit)) { ++ DEBUG("mmf_add_vo_channel_with_fit failed!\r\n"); ++ mmf_del_vi_channel(vi_ch); ++ mmf_deinit(); ++ return -1; ++ } ++ ++ uint64_t start, start2 = 0; ++ void *data, *data2; ++ int data_size, width, height, format; ++ int data_size2, width2, height2, format2; ++#ifndef DEBUG_EN ++ UNUSED(start); UNUSED(start2); ++#endif ++ ++ int show_img_size = 0; ++ if (img_fmt == PIXEL_FORMAT_RGB_888) ++ show_img_size = img_w * img_h * 3; ++ else ++ show_img_size = img_w * img_h * 3 / 2; ++ ++ uint8_t *show_img = malloc(show_img_size); ++ if (!show_img) { ++ DEBUG("Malloc failed!\r\n"); ++ exit_flag = 1; ++ } ++ while (!exit_flag) { ++ start = _get_time_us(); ++ if (mmf_vi_frame_pop(vi_ch, &data, &data_size, &width, &height, &format)) { ++ continue; ++ } ++ ++ if (mmf_vi_frame_pop(vi_ch2, &data2, &data_size2, &width2, &height2, &format2)) { ++ mmf_vi_frame_free(vi_ch); ++ continue; ++ } ++ ++ DEBUG("[0]Pop..width:%d height:%d data_size:%d format:%d\r\n", width, height, data_size, format); ++ DEBUG("[1]Pop..width:%d height:%d data_size:%d format:%d\r\n", width2, height2, data_size2, format2); ++ start = _get_time_us(); ++ if (width % DEFAULT_ALIGN != 0) { ++ switch (img_fmt) { ++ case PIXEL_FORMAT_RGB_888: ++ for (int h = 0; h < img_h; h ++) { ++ memcpy(show_img + h * img_w * 3, (uint8_t *)data + h * width * 3, img_w * 3); ++ } ++ break; ++ case PIXEL_FORMAT_NV21: ++ for (int h = 0; h < img_h * 3 / 2; h ++) { ++ memcpy(show_img + h * img_w, (uint8_t *)data + h * width, img_w); ++ } ++ break; ++ default:break; ++ } ++ } else { ++ memcpy(show_img, data, data_size); ++ } ++ ++ mmf_vi_frame_free(vi_ch); ++ mmf_vi_frame_free(vi_ch2); ++ ++ if (img_fmt == PIXEL_FORMAT_RGB_888) { ++ for (int i = 0; i < img_h; i ++) { ++ uint8_t *buff = &show_img[(i * img_w + i) * 3]; ++ buff[0] = 0xff; ++ buff[1] = 0x00; ++ buff[2] = 0x00; ++ } ++ for (int i = 0; i < img_h; i ++) { ++ uint8_t *buff = &show_img[(i * img_w + i + img_w - img_h) * 3]; ++ buff[0] = 0x00; ++ buff[1] = 0xff; ++ buff[2] = 0x00; ++ } ++ } ++ DEBUG(">>>>>> mmcpy vi frame %ld\n", _get_time_us() - start); ++ ++ start = _get_time_us(); ++ DEBUG("Push..width:%d height:%d data_size:%d format:%d\r\n", img_w, img_h, show_img_size, img_fmt); ++ mmf_vo_frame_push_with_fit(layer, vo_ch, show_img, show_img_size, img_w, img_h, format, fit); ++ DEBUG(">>>>>> flush vo frame %ld\n", _get_time_us() - start); ++ ++ DEBUG(">>>>>> flush time %ld ms\n", (_get_time_us() - start2) / 1000); ++ start2 = _get_time_us(); ++ } ++ ++ mmf_del_vo_channel(layer, vo_ch); ++ mmf_del_vi_channel(vi_ch); ++ mmf_del_vi_channel(vi_ch2); ++ mmf_deinit(); ++ return 0; ++} ++ ++static int _test_vi_region_venc_h26x_rtsp(void) ++{ ++ if (0 != rtsp_server_init(NULL, 8554)) { ++ printf("rtsp server init\n"); ++ return 0; ++ } ++ ++ if (0 != rtsp_memory_server_start(rtsp_server_type)) { ++ printf("rtsp server start\n"); ++ return 0; ++ } ++ ++ if (0 != mmf_init()) { ++ printf("mmf deinit\n"); ++ return 0; ++ } ++ ++ // int img_w = 1920, img_h = 1080, fit = 2, img_fmt = PIXEL_FORMAT_NV21; ++ // int img_w2 = 1920, img_h2 = 1080, img_fmt2 = PIXEL_FORMAT_NV21; //PIXEL_FORMAT_NV21 or PIXEL_FORMAT_RGB_888 ++ int img_w = 1280, img_h = 720, fit = 2, img_fmt = PIXEL_FORMAT_NV21; ++ int img_w2 = 640, img_h2 = 480, img_fmt2 = PIXEL_FORMAT_RGB_888; //PIXEL_FORMAT_NV21 or PIXEL_FORMAT_RGB_888 ++ ++ (void)fit; ++ int ch = 0; ++ if (test_mmf_venc_init(ch, img_w, img_h)) { ++ printf("test_mmf_venc_init failed\n"); ++ return -1; ++ } ++ ++ if (0 != mmf_vi_init()) { ++ DEBUG("mmf_vi_init failed!\r\n"); ++ mmf_deinit(); ++ return -1; ++ } ++ ++ int vi_ch = mmf_get_vi_unused_channel(); ++ mmf_set_vi_hmirror(vi_ch, true); ++ mmf_set_vi_vflip(vi_ch, true); ++ if (0 != mmf_add_vi_channel(vi_ch, img_w, img_h, img_fmt)) { ++ DEBUG("mmf_add_vi_channel failed!\r\n"); ++ mmf_deinit(); ++ return -1; ++ } ++ ++ int vi_ch2 = mmf_get_vi_unused_channel(); ++ if (0 != mmf_add_vi_channel(vi_ch2, img_w2, img_h2, img_fmt2)) { ++ DEBUG("mmf_add_vi_channel failed!\r\n"); ++ mmf_del_vi_channel(vi_ch); ++ mmf_deinit(); ++ return -1; ++ } ++ ++ mmf_vi_set_pop_timeout(100); ++ ++ int layer = 0; ++ int vo_ch = mmf_get_vo_unused_channel(layer); ++ // if (0 != mmf_add_vo_channel_with_fit(layer, vo_ch, 552, 368, img_fmt, fit)) { ++ if (0 != mmf_add_vo_channel_with_fit(layer, vo_ch, 832, 480, img_fmt, fit)) { ++ DEBUG("mmf_add_vo_channel_with_fit failed!\r\n"); ++ mmf_del_vi_channel(vi_ch); ++ mmf_del_vi_channel(vi_ch2); ++ mmf_deinit(); ++ return -1; ++ } ++ ++ // int rgn_ch = 0, rgn_w = 200, rgn_h = 100, rgn_x = 0, rgn_y = 0, rgn_fmt = PIXEL_FORMAT_ARGB_8888; ++ // rgn_ch = mmf_get_region_unused_channel(); ++ // if (0 != mmf_add_region_channel(rgn_ch, OVERLAY_RGN, CVI_ID_VPSS, 0, vi_ch, rgn_x, rgn_y, rgn_w, rgn_h, rgn_fmt)) { ++ // DEBUG("mmf_add_region_channel failed!\r\n"); ++ // exit_flag = 1; ++ // } ++ ++ // uint8_t *rgn_test_img = (uint8_t *)_prepare_image(rgn_w, rgn_h, rgn_fmt); ++ // if (!rgn_test_img) { ++ // DEBUG("Malloc failed!\r\n"); ++ // exit_flag = 1; ++ // } ++ ++ printf("rtsp://%s:%d/live\n", rtsp_get_server_ip(), rtsp_get_server_port()); ++ ++ char ipdata[30]; ++ sprintf(ipdata, "rtsp://%s:%d/live\n", rtsp_get_server_ip(), rtsp_get_server_port()); ++ int fd = -1; ++ remove("/root/rtsp_ip_addr.txt"); ++ fd = open("/root/rtsp_ip_addr.txt", O_WRONLY | O_CREAT, 0777); ++ if (fd <= 2) { ++ DEBUG("Open filed, fd = %d\r\n", fd); ++ } ++ ++ int res = 0; ++ if ((res = write(fd, ipdata, 30)) < 0) { ++ DEBUG("Write failed"); ++ close(fd); ++ } ++ close(fd); ++ ++ show_ip_on_oled(ipdata); ++ ++ uint8_t *filebuf = _prepare_image(img_w, img_h, img_fmt); ++ uint8_t *filebuf2 = _prepare_image(img_w2, img_h2, img_fmt2); ++ uint64_t start = _get_time_us(); ++ uint64_t last_loop_us = start; ++ uint64_t timestamp = 0; ++ uint8_t frame_count = 0; ++ int last_vi_pop = -1; ++ ++ void *data, *data2; ++ int data_size, width, height, format; ++ int data_size2, width2, height2, format2; ++ ++ int show_img_size = 0; ++ if (img_fmt2 == PIXEL_FORMAT_RGB_888) ++ show_img_size = img_w * img_h * 3; ++ else ++ show_img_size = img_w * img_h * 3 / 2; ++ ++ uint8_t *show_img = malloc(show_img_size); ++ if (!show_img) { ++ DEBUG("Malloc failed!\r\n"); ++ exit_flag = 1; ++ } ++ exit_flag = 0; ++ while (!exit_flag) { ++ if(frame_count < 100) ++ frame_count ++; ++ ++ start = _get_time_us(); ++ mmf_stream_t stream; ++ if (!mmf_venc_pop(ch, &stream)) { ++ DEBUG("use %ld us\r\n", _get_time_us() - start); ++ ++ start = _get_time_us(); ++ { ++ int stream_size = 0; ++ for (int i = 0; i < stream.count; i ++) { ++ // printf("[%d] stream.data:%p stream.len:%d\n", i, stream.data[i], stream.data_size[i]); ++ stream_size += stream.data_size[i]; ++ } ++ ++ if (stream.count > 1) { ++ uint8_t *stream_buffer = (uint8_t *)malloc(stream_size); ++ if (stream_buffer) { ++ int copy_length = 0; ++ for (int i = 0; i < stream.count; i ++) { ++ memcpy(stream_buffer + copy_length, stream.data[i], stream.data_size[i]); ++ copy_length += stream.data_size[i]; ++ } ++ rtsp_send_memory_data(timestamp, stream_buffer, copy_length); ++ free(stream_buffer); ++ } else { ++ DEBUG("malloc failed!\r\n"); ++ } ++ } else if (stream.count == 1) { ++ rtsp_send_memory_data(timestamp, (uint8_t *)stream.data[0], stream.data_size[0]); ++ } ++ } ++ DEBUG("use %ld us\r\n", _get_time_us() - start); ++ ++ start = _get_time_us(); ++ if (mmf_venc_free(ch)) { ++ printf("mmf_venc_free failed\n"); ++ goto _exit; ++ } ++ DEBUG("use %ld us\r\n", _get_time_us() - start); ++ } ++ ++ if (!last_vi_pop) { ++ start = _get_time_us(); ++ mmf_vi_frame_free(vi_ch); ++ DEBUG("use %ld us\r\n", _get_time_us() - start); ++ } ++ ++ start = _get_time_us(); ++ int vi_ret = mmf_vi_frame_pop(vi_ch, &data, &data_size, &width, &height, &format); ++ if (vi_ret != last_vi_pop) { ++ uint64_t vi_stamp = timestamp; ++ vi_stamp += (_get_time_us() - last_loop_us) / 1000; ++ printf("[%.6ld.%.3ld] %s\n", vi_stamp / 1000, vi_stamp % 1000, ++ vi_ret ? "no input signal" : "got input signal"); ++ mmf_del_venc_channel(ch); ++ test_mmf_venc_init(ch, img_w, img_h); ++ last_vi_pop = vi_ret; ++ } ++ if (vi_ret) ++ data = filebuf; ++ DEBUG("use %ld us\r\n", _get_time_us() - start); ++ ++ start = _get_time_us(); ++ int vi_ret2 = vi_ret; ++ if (!vi_ret) ++ vi_ret2 = mmf_vi_frame_pop(vi_ch2, &data2, &data_size2, &width2, &height2, &format2); ++ if (vi_ret2) ++ data2 = filebuf2; ++ DEBUG("use %ld us\r\n", _get_time_us() - start); ++ ++ start = _get_time_us(); ++ if (mmf_venc_push(ch, data, img_w, img_h, img_fmt)) { ++ printf("mmf_venc_push failed\n"); ++ goto _exit; ++ } ++ DEBUG("use %ld us\r\n", _get_time_us() - start); ++ ++ ++ start = _get_time_us(); ++ if (width2 % DEFAULT_ALIGN != 0) { ++ switch (img_fmt2) { ++ case PIXEL_FORMAT_RGB_888: ++ for (int h = 0; h < img_h2; h ++) { ++ memcpy(show_img + h * img_w2 * 3, (uint8_t *)data2 + h * width * 3, img_w2 * 3); ++ } ++ break; ++ case PIXEL_FORMAT_NV21: ++ for (int h = 0; h < img_h2 * 3 / 2; h ++) { ++ memcpy(show_img + h * img_w2, (uint8_t *)data2 + h * width, img_w2); ++ } ++ break; ++ default:break; ++ } ++ } else { ++ memcpy(show_img, data, data_size); ++ } ++ DEBUG("use %ld us\r\n", _get_time_us() - start); ++ ++ if(frame_count == 99){ ++ save_buff_to_file("rtsp_stream.jpg", data, data_size); ++ } ++ ++ if (!vi_ret2) { ++ start = _get_time_us(); ++ mmf_vi_frame_free(vi_ch2); ++ DEBUG("use %ld us\r\n", _get_time_us() - start); ++ } ++ ++ // start = _get_time_us(); ++ // if (0 != mmf_region_frame_push(rgn_ch, rgn_test_img, rgn_w * rgn_h * 4)) { ++ // DEBUG("mmf_region_frame_push failed!\r\n"); ++ // } ++ // DEBUG("use %ld us\r\n", _get_time_us() - start); ++ ++ start = _get_time_us(); ++ DEBUG("Push..width:%d height:%d data_size:%d format:%d\r\n", img_w2, img_h2, show_img_size, img_fmt2); ++ mmf_vo_frame_push_with_fit(layer, vo_ch, show_img, show_img_size, img_w, img_h, img_fmt, fit); ++ DEBUG(">>>>>> flush vo frame %ld\n", _get_time_us() - start); ++ ++ DEBUG("use %ld us\r\n", _get_time_us() - last_loop_us); ++ timestamp += (_get_time_us() - last_loop_us) / 1000; ++ last_loop_us = _get_time_us(); ++ } ++ ++ // if (0 != mmf_del_region_channel(rgn_ch)) { ++ // DEBUG("mmf_region_bind failed!\r\n"); ++ // exit_flag = 1; ++ // } ++ ++ if (mmf_del_venc_channel(ch)) { ++ printf("mmf_del_venc_channel failed\n"); ++ return -1; ++ } ++ ++ if (0 != rtsp_server_deinit()) { ++ printf("rtsp server deinit\n"); ++ return 0; ++ } ++_exit: ++ if (0 != mmf_deinit()) { ++ printf("mmf deinit\n"); ++ } ++ free(filebuf2); ++ free(filebuf); ++ close_oled(); ++ return 0; ++ ++} ++ ++static int _test_vi_region_venc_h265_rtsp(void) ++{ ++ rtsp_server_type = 1; ++ return _test_vi_region_venc_h26x_rtsp(); ++} ++ ++static int _test_i2c_oled(void) ++{ ++ char * chat_str = "rtsp://xxx.xxx.xxx.xxx:8554/live"; ++ ++ show_ip_on_oled(chat_str); ++ return 0; ++} ++ ++int test_pre_init(void) ++{ ++ signal(SIGINT, sig_handle); ++ signal(SIGTERM, sig_handle); ++ signal(SIGSEGV, exit_handle); ++ signal(SIGKILL, exit_handle); ++ signal(SIGFPE, exit_handle); ++ signal(SIGILL, exit_handle); ++ signal(SIGABRT, exit_handle); ++ return 0; ++} ++ ++int test_vo_only(void) ++{ ++ return _test_vo_only(); ++} ++ ++int test_vi_only(void) ++{ ++ return _test_vi_only(); ++} ++ ++int test_vio(void) ++{ ++ return _test_vio(); ++} ++ ++int test_region(void) ++{ ++ return _test_region(); ++} ++ ++int test_venc_jpg(void) ++{ ++ return _test_venc_jpg(); ++} ++ ++int test_venc_h265(void) ++{ ++ return _test_venc_h265(); ++} ++ ++int test_vi_venc_h265(void) ++{ ++ return _test_vi_venc_h265(); ++} ++ ++int test_rtsp_h264(void) ++{ ++ return _test_rtsp_h264(); ++} ++ ++int test_vi_venc_h264(void) ++{ ++ return _test_vi_venc_h264(); ++} ++ ++int test_rtsp_h265(void) ++{ ++ return _test_rtsp_h265(); ++} ++ ++int test_vi_venc_h265_rtsp(void) ++{ ++ return _test_vi_venc_h265_rtsp(); ++} ++ ++int test_multiple_vi(void) ++{ ++ return _test_multiple_vi(); ++} ++ ++int test_vi_region_venc_h265_rtsp(void) ++{ ++ return _test_vi_region_venc_h265_rtsp(); ++} ++ ++int test_i2c_oled(void) ++{ ++ return _test_i2c_oled(); ++} +diff --git a/sample/test_mmf/sample_vio.h b/sample/test_mmf/sample_vio.h +new file mode 100644 +index 0000000..460be17 +--- /dev/null ++++ b/sample/test_mmf/sample_vio.h +@@ -0,0 +1,46 @@ ++/* ++ * Copyright (C) Cvitek Co., Ltd. 2019-2020. All rights reserved. ++ * ++ * File Name: sample_vio.h ++ * Description: ++ */ ++ ++#ifndef __SAMPLE_VIO_H__ ++#define __SAMPLE_VIO_H__ ++ ++#ifdef __cplusplus ++#if __cplusplus ++extern "C" { ++#endif ++#endif /* End of #ifdef __cplusplus */ ++ ++#include ++ ++CVI_S32 SAMPLE_IMX327_N5_VI_VPSS_ONLINE_TEST(void); ++CVI_S32 SAMPLE_IMX327_N5_TEST(void); ++CVI_S32 SAMPLE_PICO640_TEST(void); ++CVI_S32 SAMPLE_MM308M2_TEST(void); ++CVI_S32 SAMPLE_N5_TEST(void); ++CVI_S32 SAMPLE_MCS369Q_TEST(void); ++CVI_S32 SAMPLE_MCS369_TEST(void); ++CVI_S32 SAMPLE_VIO_TWO_DEV_VO(void); ++CVI_S32 SAMPLE_VI_VPSS_SLT(CVI_S32 frmNum, char *filename); ++CVI_S32 SAMPLE_VIO_VoRotation(void); ++CVI_S32 SAMPLE_VIO_ViVpssAspectRatio(void); ++CVI_S32 SAMPLE_VIO_ViRotation(void); ++CVI_S32 SAMPLE_VIO_VpssRotation(void); ++CVI_S32 SAMPLE_VIO_VpssFileIO(SIZE_S stSize); ++CVI_S32 SAMPLE_VIO_VpssCombine2File(SIZE_S stSize); ++CVI_S32 SAMPLE_PR2100_TEST(void); ++CVI_S32 SAMPLE_IMX335_PR2020_OFFLINE_ONLINE_TEST(void); ++CVI_S32 SAMPLE_IMX307_PR2020_OFFLINE_ONLINE_TEST(void); ++CVI_S32 SAMPLE_IMX307_ONTHEFLY_ONLINE_SC_TEST(void); ++CVI_S32 SAMPLE_VO_LVDS_TEST(void); ++ ++#ifdef __cplusplus ++#if __cplusplus ++} ++#endif ++#endif /* End of #ifdef __cplusplus */ ++ ++#endif /* End of #ifndef __SAMPLE_VIO_H__*/ +diff --git a/sample/test_mmf/sample_vio_main.c b/sample/test_mmf/sample_vio_main.c +new file mode 100644 +index 0000000..dd7cbad +--- /dev/null ++++ b/sample/test_mmf/sample_vio_main.c +@@ -0,0 +1,139 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "sample_comm.h" ++#include "sample_vio.h" ++#include "cvi_sys.h" ++#include ++ ++void SAMPLE_VIO_HandleSig(CVI_S32 signo) ++{ ++ signal(SIGINT, SIG_IGN); ++ signal(SIGTERM, SIG_IGN); ++ ++ if (SIGINT == signo || SIGTERM == signo) { ++ //todo for release ++ SAMPLE_PRT("Program termination abnormally\n"); ++ } ++ exit(-1); ++} ++ ++void SAMPLE_VIO_Usage(char *sPrgNm) ++{ ++ printf("Usage : %s \n", sPrgNm); ++ printf("index:\n"); ++ printf("\t 0) test vo only.\n"); ++ printf("\t 1) test vi only.\n"); ++ printf("\t 2) test vi vo.\n"); ++ printf("\t 3) test region.\n"); ++ printf("\t 4) test venc jpg.\n"); ++ printf("\t 5) test venc h265.\n"); ++ printf("\t 6) test vi venc h265.\n"); ++ printf("\t 7) test rtsp h264.\n"); ++ printf("\t 8) test venc h264.\n"); ++ printf("\t 9) test rtsp h265.\n"); ++ printf("\t 10) test vi venc h265 rtsp.\n"); ++ printf("\t 11) test multiple vi.\n"); ++ printf("\t 12) test vi venc region h265 rtsp.\n"); ++ printf("\t 13) test i2c oled.\n"); ++} ++ ++int main(int argc, char *argv[]) ++{ ++ CVI_S32 s32Ret = CVI_FAILURE; ++ CVI_S32 s32Index; ++ ++ if (argc < 2) { ++ SAMPLE_VIO_Usage(argv[0]); ++ return CVI_FAILURE; ++ } ++ ++ if (!strncmp(argv[1], "-h", 2)) { ++ SAMPLE_VIO_Usage(argv[0]); ++ return CVI_SUCCESS; ++ } ++ ++ extern int test_pre_init(void); ++ extern int test_vo_only(void); ++ extern int test_vi_only(void); ++ extern int test_vio(void); ++ extern int test_region(void); ++ extern int test_venc_jpg(void); ++ extern int test_venc_h265(void); ++ extern int test_vi_venc_h265(void); ++ extern int test_rtsp_h264(void); ++ extern int test_vi_venc_h264(void); ++ extern int test_rtsp_h265(void); ++ extern int test_vi_venc_h265_rtsp(void); ++ extern int test_multiple_vi(void); ++ extern int test_vi_region_venc_h265_rtsp(void); ++ extern int test_i2c_oled(void); ++ ++ test_pre_init(); ++ ++ s32Index = atoi(argv[1]); ++ switch (s32Index) { ++ case 0: ++ s32Ret = test_vo_only(); ++ break; ++ case 1: ++ s32Ret = test_vi_only(); ++ break; ++ case 2: ++ s32Ret = test_vio(); ++ break; ++ case 3: ++ s32Ret = test_region(); ++ break; ++ case 4: ++ s32Ret = test_venc_jpg(); ++ break; ++ case 5: ++ s32Ret = test_venc_h265(); ++ break; ++ case 6: ++ s32Ret = test_vi_venc_h265(); ++ break; ++ case 7: ++ s32Ret = test_rtsp_h264(); ++ break; ++ case 8: ++ s32Ret = test_vi_venc_h264(); ++ break; ++ case 9: ++ s32Ret = test_rtsp_h265(); ++ break; ++ case 10: ++ s32Ret = test_vi_venc_h265_rtsp(); ++ break; ++ case 11: ++ s32Ret = test_multiple_vi(); ++ break; ++ case 12: ++ s32Ret = test_vi_region_venc_h265_rtsp(); ++ break; ++ case 13: ++ s32Ret = test_i2c_oled(); ++ break; ++ default: ++ SAMPLE_PRT("the index %d is invaild!\n", s32Index); ++ SAMPLE_VIO_Usage(argv[0]); ++ return CVI_FAILURE; ++ } ++ ++ if (s32Ret == CVI_SUCCESS) ++ SAMPLE_PRT("sample_vio exit success!\n"); ++ else ++ SAMPLE_PRT("sample_vio exit abnormally!\n"); ++ ++ return s32Ret; ++} +-- +2.34.1 + diff --git a/configs/common/patches/middleware/0005-sample-fix-test_mmf.patch b/configs/common/patches/middleware/0005-sample-fix-test_mmf.patch new file mode 100644 index 0000000..576b0a8 --- /dev/null +++ b/configs/common/patches/middleware/0005-sample-fix-test_mmf.patch @@ -0,0 +1,106 @@ +From 7cb5d00ce68e71f99cf22d92bc64b78fbed71b91 Mon Sep 17 00:00:00 2001 +From: scpcom +Date: Sat, 8 Mar 2025 04:44:09 +0100 +Subject: [PATCH] sample: fix test_mmf + +--- + sample/test_mmf/Makefile | 9 +++++++-- + sample/test_mmf/maix_mmf/sophgo_middleware.c | 10 +++++++++- + 2 files changed, 16 insertions(+), 3 deletions(-) + +diff --git a/sample/test_mmf/Makefile b/sample/test_mmf/Makefile +index c0b7b4b..c10a866 100644 +--- a/sample/test_mmf/Makefile ++++ b/sample/test_mmf/Makefile +@@ -12,7 +12,8 @@ INCS = -I$(MW_INC) -I$(ISP_INC) -I../common/ -I$(KERNEL_INC) -I$(MW_INC)/linux - + SRCS_CPP += $(wildcard $(SDIR)/rtsp_server/src/*.cpp) + + CFLAGS += -I$(SDIR)/rtsp_server/inc +-CPPFLAGS += -I$(SDIR)/media_server-1.0.x/include \ ++CPPFLAGS += $(subst -std=gnu11,-std=gnu++11, $(CFLAGS)) \ ++-I$(SDIR)/media_server-1.0.x/include \ + -I$(SDIR)/media_server-1.0.x/media-server/librtsp/include \ + -I$(SDIR)/media_server-1.0.x/media-server/librtsp/source/server \ + -I$(SDIR)/media_server-1.0.x/sdk/include \ +@@ -101,9 +102,13 @@ $(COMMON_DIR)/%.o: $(COMMON_DIR)/%.c + @echo [$(notdir $(CC))] $(notdir $@) + + $(SDIR)/%.o: $(SDIR)/%.c +- @$(CC) $(DEPFLAGS) $(CFLAGS) $(EXTRA_CFLAGS) -o $@ -c $< ++ @$(CC) $(DEPFLAGS) $(filter-out -Werror, $(CFLAGS)) $(EXTRA_CFLAGS) -o $@ -c $< + @echo [$(notdir $(CC))] $(notdir $@) + ++$(SDIR)/%.o: $(SDIR)/%.cpp ++ @$(CXX) $(DEPFLAGS) $(filter-out -Werror, $(CPPFLAGS)) $(EXTRA_CFLAGS) -o $@ -c $< ++ @echo [$(notdir $(CXX))] $(notdir $@) ++ + $(TARGET): mmflibs $(COMM_OBJ) $(OBJS) $(ISP_OBJ) $(MW_LIB)/libvenc.a $(MW_LIB)/libsys.a + @$(CXX) -o $@ -Wl,--start-group $(OBJS) $(COMM_OBJS) -lsys $(MW_LIB)/libsys.a -Wl,--end-group -lmaix_mmf $(ELFFLAGS) $(EXTRA_LDFLAGS) + @echo -e $(BLUE)[LINK]$(END)[$(notdir $(CXX))] $(notdir $@) +diff --git a/sample/test_mmf/maix_mmf/sophgo_middleware.c b/sample/test_mmf/maix_mmf/sophgo_middleware.c +index db370d0..08d578c 100644 +--- a/sample/test_mmf/maix_mmf/sophgo_middleware.c ++++ b/sample/test_mmf/maix_mmf/sophgo_middleware.c +@@ -442,7 +442,7 @@ static int _free_leak_memory_of_ion(void) + if (strcmp(buffer_name, "VI_DMA_BUF") + && strcmp(buffer_name, "ISP_SHARED_BUFFER_0")) + continue; +- struct sys_ion_data2 ion_data; ++ struct sys_ion_data ion_data; + + alloc_buf_size = atoi(alloc_buf_size_str); + phy_addr = (unsigned int)strtol(phy_addr_str, NULL, 16); +@@ -1149,7 +1149,9 @@ char* mmf_get_sensor_name(void) + snprintf(name, sizeof(name), "gcore_gc2083"); + return name; + case GCORE_GC4653_MIPI_4M_30FPS_10BIT: ++#if 0 + case GCORE_GC4653_MIPI_720P_60FPS_10BIT: ++#endif + snprintf(name, sizeof(name), "gcore_gc4653"); + return name; + case SMS_SC035GS_MIPI_480P_120FPS_12BIT: +@@ -1161,9 +1163,11 @@ char* mmf_get_sensor_name(void) + case OV_OS04A10_MIPI_4M_1440P_30FPS_12BIT: + snprintf(name, sizeof(name), "ov_os04a10"); + return name; ++#if defined(SENSOR_OV_OV2685) + case GCORE_OV2685_MIPI_1600x1200_30FPS_10BIT: + snprintf(name, sizeof(name), "ov_ov2685"); + return name; ++#endif + case OV_OV5647_MIPI_2M_30FPS_10BIT: + snprintf(name, sizeof(name), "ov_ov5647"); + return name; +@@ -5248,10 +5252,12 @@ void mmf_vi_set_pop_timeout(int ms) + priv.vi_pop_timeout = ms; + } + ++#if 0 + int mmf_vi_channel_set_windowing(int ch, int x, int y, int w, int h) + { + return -1; + } ++#endif + + int mmf_get_again(int ch, uint32_t *gain) + { +@@ -5340,6 +5346,7 @@ int mmf_set_ispdgain(int ch, uint32_t gain) + return 0; + } + ++#if 0 + int mmf_set_wb_mode(int ch, int mode) + { + return -1; +@@ -5349,6 +5356,7 @@ int mmf_get_wb_mode(int ch) + { + return 0; + } ++#endif + + int mmf_init0(uint32_t param, ...) + { +-- +2.34.1 + diff --git a/configs/common/patches/middleware/0006-disable-vi_dbg_handler.patch b/configs/common/patches/middleware/0006-disable-vi_dbg_handler.patch new file mode 100644 index 0000000..ddb5487 --- /dev/null +++ b/configs/common/patches/middleware/0006-disable-vi_dbg_handler.patch @@ -0,0 +1,29 @@ +From 195a74a964e3fcef09614f1d354dd4d3c43b684e Mon Sep 17 00:00:00 2001 +From: lxowalle +Date: Mon, 14 Oct 2024 15:21:27 +0800 +Subject: [PATCH] * disable vi_dbg_handler + +--- + modules/vi/src/cvi_vi.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/modules/vi/src/cvi_vi.c b/modules/vi/src/cvi_vi.c +index fd8585f..e0f092a 100644 +--- a/modules/vi/src/cvi_vi.c ++++ b/modules/vi/src/cvi_vi.c +@@ -1519,7 +1519,11 @@ CVI_S32 CVI_VI_EnableChn(VI_PIPE ViPipe, VI_CHN ViChn) + pthread_attr_setschedparam(&attr, ¶m); + pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED); + +- pthread_create(&gViDbgTH.vi_dbg_thread, &attr, (void *)vi_dbg_handler, NULL); ++ setenv("VI_DBG_HANDLER_ENABLE", "0", 0); ++ char *value = getenv("VI_DBG_HANDLER_ENABLE"); ++ if (atoi(value)) { ++ pthread_create(&gViDbgTH.vi_dbg_thread, &attr, (void *)vi_dbg_handler, NULL); ++ } + } + } + +-- +2.34.1 + diff --git a/configs/common/patches/middleware/0007-disable-vi_dbg_handler-2.patch b/configs/common/patches/middleware/0007-disable-vi_dbg_handler-2.patch new file mode 100644 index 0000000..992266c --- /dev/null +++ b/configs/common/patches/middleware/0007-disable-vi_dbg_handler-2.patch @@ -0,0 +1,28 @@ +From 43535c5beeeacb96eda3602bad1d0caf9566bcbe Mon Sep 17 00:00:00 2001 +From: lxowalle +Date: Mon, 14 Oct 2024 17:35:14 +0800 +Subject: [PATCH] * disable vi_dbg_handler 2 + +--- + modules/vi/src/cvi_vi.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/modules/vi/src/cvi_vi.c b/modules/vi/src/cvi_vi.c +index e0f092a..2062446 100644 +--- a/modules/vi/src/cvi_vi.c ++++ b/modules/vi/src/cvi_vi.c +@@ -1573,7 +1573,10 @@ CVI_S32 CVI_VI_DisableChn(VI_PIPE ViPipe, VI_CHN ViChn) + return CVI_ERR_VI_FAILED_NOT_ENABLED; + } + +- pthread_join(gViDbgTH.vi_dbg_thread, NULL); ++ char *value = getenv("VI_DBG_HANDLER_ENABLE"); ++ if (atoi(value)) { ++ pthread_join(gViDbgTH.vi_dbg_thread, NULL); ++ } + + s32Ret = _cvi_vi_freeIonBuf(); + if (s32Ret != CVI_SUCCESS) { +-- +2.34.1 + diff --git a/configs/common/patches/middleware/0008-modules-isp_bin-add-hack-for-legacy-cvi_sdr_bin.patch b/configs/common/patches/middleware/0008-modules-isp_bin-add-hack-for-legacy-cvi_sdr_bin.patch new file mode 100644 index 0000000..91aedd6 --- /dev/null +++ b/configs/common/patches/middleware/0008-modules-isp_bin-add-hack-for-legacy-cvi_sdr_bin.patch @@ -0,0 +1,164 @@ +From eada0ace3da40cf83f1375ae457695a8a014b36a Mon Sep 17 00:00:00 2001 +From: scpcom +Date: Tue, 11 Feb 2025 01:06:05 +0100 +Subject: [PATCH] modules: isp_bin: add hack for legacy cvi_sdr_bin + +--- + modules/isp/cv181x/isp_bin/src/isp_3a_bin.c | 7 ++++- + modules/isp/cv181x/isp_bin/src/isp_3a_bin.h | 2 +- + modules/isp/cv181x/isp_bin/src/isp_bin.c | 34 +++++++++++++++++---- + 3 files changed, 35 insertions(+), 8 deletions(-) + +diff --git a/modules/isp/cv181x/isp_bin/src/isp_3a_bin.c b/modules/isp/cv181x/isp_bin/src/isp_3a_bin.c +index 3978b6b..5d7d9a5 100644 +--- a/modules/isp/cv181x/isp_bin/src/isp_3a_bin.c ++++ b/modules/isp/cv181x/isp_bin/src/isp_3a_bin.c +@@ -214,7 +214,7 @@ CVI_S32 isp_3aBinAttr_get_parambuf(VI_PIPE ViPipe, CVI_U8 *buffer) + return CVI_SUCCESS; + } + +-CVI_S32 isp_3aBinAttr_set_param(VI_PIPE ViPipe, CVI_U8 **binPtr) ++CVI_S32 isp_3aBinAttr_set_param(VI_PIPE ViPipe, CVI_U8 **binPtr, CVI_BOOL bStats) + { + // AE + ISP_WDR_EXPOSURE_ATTR_S stWDRExpAttr = { 0 }; +@@ -298,6 +298,11 @@ CVI_S32 isp_3aBinAttr_set_param(VI_PIPE ViPipe, CVI_U8 **binPtr) + (*binPtr) += sizeof(ISP_AWB_Calibration_Gain_S_EX); + CVI_ISP_SetWBCalibrationEx(ViPipe, &stWBCalibEx); + ++ if (!bStats) { ++ printf("%s: CVI_ISP_SetStatisticsConfig skipped.\n", __func__); ++ return CVI_SUCCESS; ++ } ++ + ISP_STATISTICS_CFG_S stStatCfg = {0}; + + memcpy(&stStatCfg, (*binPtr), sizeof(ISP_STATISTICS_CFG_S)); +diff --git a/modules/isp/cv181x/isp_bin/src/isp_3a_bin.h b/modules/isp/cv181x/isp_bin/src/isp_3a_bin.h +index 54df28b..d30f778 100644 +--- a/modules/isp/cv181x/isp_bin/src/isp_3a_bin.h ++++ b/modules/isp/cv181x/isp_bin/src/isp_3a_bin.h +@@ -21,7 +21,7 @@ extern "C" { + CVI_S32 isp_3aBinAttr_get_size(VI_PIPE ViPipe, CVI_U32 *size); + CVI_S32 isp_3aBinAttr_get_param(VI_PIPE ViPipe, FILE *fp); + CVI_S32 isp_3aBinAttr_get_parambuf(VI_PIPE ViPipe, CVI_U8 *buffer); +-CVI_S32 isp_3aBinAttr_set_param(VI_PIPE ViPipe, CVI_U8 **binPtr); ++CVI_S32 isp_3aBinAttr_set_param(VI_PIPE ViPipe, CVI_U8 **binPtr, CVI_BOOL bStats); + CVI_S32 isp_3aJsonAttr_set_param(VI_PIPE ViPipe, ISP_3A_Parameter_Structures *stPtr); + CVI_S32 isp_3aJsonAttr_get_param(VI_PIPE ViPipe, ISP_3A_Parameter_Structures *stPtr); + +diff --git a/modules/isp/cv181x/isp_bin/src/isp_bin.c b/modules/isp/cv181x/isp_bin/src/isp_bin.c +index a653fd7..159c529 100644 +--- a/modules/isp/cv181x/isp_bin/src/isp_bin.c ++++ b/modules/isp/cv181x/isp_bin/src/isp_bin.c +@@ -112,12 +112,13 @@ static CVI_S32 isp_bin_getBinSizeImp(VI_PIPE ViPipe, CVI_U32 *binSize); + static CVI_S32 isp_bin_getBinParamImp(VI_PIPE ViPipe, CVI_U8 *addr, CVI_U32 binSize); + static CVI_S32 isp_bin_setBinParamImp(VI_PIPE ViPipe, FILE *fp); + static CVI_S32 isp_bin_setBinParamImptobuf(VI_PIPE ViPipe, unsigned char *buffer); +-static CVI_S32 isp_bin_checkMd5(VI_PIPE ViPipe, CVI_U8 *addr, CVI_U32 binSize); ++static CVI_S32 isp_bin_checkMd5(VI_PIPE ViPipe, CVI_U8 *addr, CVI_U32 binSize, CVI_U32 *pBinPad); + static CVI_S32 isp_bin_checkBinVersion(CVI_U8 *addr, CVI_U32 binSize); + static CVI_S32 isp_get_paramstruct(VI_PIPE ViPipe, ISP_Parameter_Structures *pstParaBuf); + static CVI_S32 isp_set_paramstruct(VI_PIPE ViPipe, ISP_Parameter_Structures *pstParaBuf); + + static ISP_BIN_BYPASS g_binBypassParams = {0}; ++static CVI_CHAR g_pqBinMd5[BIN_MD5_SIZE] = { 0 }; + + CVI_S32 header_bin_getBinSize(CVI_U32 *binSize) + { +@@ -421,10 +422,11 @@ static CVI_S32 isp_bin_getBinSizeImp(VI_PIPE ViPipe, CVI_U32 *binSize) + static CVI_S32 isp_bin_getBinParamImp(VI_PIPE ViPipe, CVI_U8 *addr, CVI_U32 binSize) + { + CVI_S32 ret = CVI_SUCCESS; ++ CVI_U32 binPad = 0; + CVI_U8 *buf_ofs = addr; + CVI_BIN_HEADER *pstHeader = (CVI_BIN_HEADER *)buf_ofs; + +- if (isp_bin_checkMd5(ViPipe, addr, binSize) != CVI_SUCCESS) { ++ if (isp_bin_checkMd5(ViPipe, addr, binSize, &binPad) != CVI_SUCCESS) { + CVI_TRACE_ISP_BIN(LOG_WARNING, "section[CVI_BIN_ID_ISP%d] Md5 not matched\n", ViPipe); + return CVI_FAILURE; + } +@@ -434,7 +436,7 @@ static CVI_S32 isp_bin_getBinParamImp(VI_PIPE ViPipe, CVI_U8 *addr, CVI_U32 binS + + isp_set_paramstruct(ViPipe, (ISP_Parameter_Structures *)buf_ofs); + buf_ofs += sizeof(ISP_Parameter_Structures); +- isp_3aBinAttr_set_param(ViPipe, &buf_ofs); ++ isp_3aBinAttr_set_param(ViPipe, &buf_ofs, !binPad); + + CVI_TRACE_ISP_BIN(LOG_DEBUG, "apply bin setting to %d\n", ViPipe); + +@@ -479,10 +481,11 @@ static CVI_S32 isp_bin_setBinParamImptobuf(VI_PIPE ViPipe, unsigned char *buffer + return ret; + } + +-static CVI_S32 isp_bin_checkMd5(VI_PIPE ViPipe, CVI_U8 *addr, CVI_U32 binSize) ++static CVI_S32 isp_bin_checkMd5(VI_PIPE ViPipe, CVI_U8 *addr, CVI_U32 binSize, CVI_U32 *pBinPad) + { + CVI_S32 ret = CVI_SUCCESS; + CVI_U32 size = 0; ++ CVI_U32 binPad = 0; + CVI_CHAR binCommitId[BIN_COMMIT_SIZE]; + CVI_CHAR binGerrit[BIN_GERRIT_SIZE]; + CVI_CHAR curMd5[BIN_MD5_SIZE] = { 0 }; +@@ -494,6 +497,18 @@ static CVI_S32 isp_bin_checkMd5(VI_PIPE ViPipe, CVI_U8 *addr, CVI_U32 binSize) + bin_get_repo_info(binGerrit, binCommitId, curMd5); + + if (strcmp(binMd5, curMd5)) { ++ if(!strcmp(binMd5, "")) { ++ strncpy(binMd5, g_pqBinMd5, BIN_MD5_SIZE); ++ } ++ if (!strcmp(curMd5, "9b60189725b5bcb970ec86e4bbdbf600") && ++ !strcmp(binMd5, "d6db2297ddfd44e8252c1f3f888f47b2")) { ++ strncpy(binMd5, curMd5, BIN_MD5_SIZE); ++ binPad = 248; ++ } ++ } ++ ++ if (strcmp(binMd5, curMd5)) { ++ printf("pqbin md5 mismatch, mwMd5:%s != pqBinMd5:%s\n", curMd5, binMd5); + CVI_TRACE_ISP_BIN(LOG_ERR, "%s%s%s", + "md5 mismatch means that you will read json in PQBIN, ", + "but the disadvantage is that the boot speed is slightly reduced. ", +@@ -503,7 +518,8 @@ static CVI_S32 isp_bin_checkMd5(VI_PIPE ViPipe, CVI_U8 *addr, CVI_U32 binSize) + ret = CVI_FAILURE; + } else { + isp_bin_getBinSizeImp(ViPipe, &size); +- if (size != binSize) { ++ if (size != binSize && size != binSize + binPad) { ++ printf("vi(%d), Bin Size not matched(%u vs %u)\n", ViPipe, size, binSize); + CVI_TRACE_ISP_BIN(LOG_ERR, "vi(%d), Bin Size not matched(%u vs %u),", ViPipe, size, binSize); + CVI_TRACE_ISP_BIN(LOG_ERR, "%s%s", + "Size mismatch means that someone added the pqbin structure ", +@@ -514,6 +530,10 @@ static CVI_S32 isp_bin_checkMd5(VI_PIPE ViPipe, CVI_U8 *addr, CVI_U32 binSize) + } + } + ++ if (pBinPad) { ++ *pBinPad = binPad; ++ } ++ + return ret; + } + +@@ -594,6 +614,8 @@ static CVI_S32 isp_bin_checkBinVersion(CVI_U8 *addr, CVI_U32 binSize) + "tool Version:", toolVersion, "mode:", pqbinMode); + printf("********************************************************************************\n"); + ++ strncpy(g_pqBinMd5, binMd5, BIN_MD5_SIZE); ++ + // check sensor + for (CVI_U8 i = 0; i < sensorInfo.num; ++i) { + if (strcmp(sensorInfo.name[i], sensorName[i]) != 0) { +@@ -605,7 +627,7 @@ static CVI_S32 isp_bin_checkBinVersion(CVI_U8 *addr, CVI_U32 binSize) + + //check md5 + if (strcmp(binMd5, ISP_BIN_MD5)) { +- printf("pqbin md5 mismatch, mwMd5:%s != pqBinMd5:%s", ISP_BIN_MD5, binMd5); ++ printf("pqbin md5 mismatch, mwMd5:%s != pqBinMd5:%s\n", ISP_BIN_MD5, binMd5); + return CVI_SUCCESS; + } + +-- +2.34.1 + diff --git a/configs/common/patches/osdrv/0001-licheervnano-osdrv-interdrv-vi-disable-vi_motion_lev.patch b/configs/common/patches/osdrv/0001-licheervnano-osdrv-interdrv-vi-disable-vi_motion_lev.patch new file mode 100644 index 0000000..5026725 --- /dev/null +++ b/configs/common/patches/osdrv/0001-licheervnano-osdrv-interdrv-vi-disable-vi_motion_lev.patch @@ -0,0 +1,312 @@ +From 27d5e9ac04ef9485fc67eeef4fe5c4df1782ac02 Mon Sep 17 00:00:00 2001 +From: scpcom +Date: Sat, 21 Sep 2024 01:58:24 +0200 +Subject: [PATCH] licheervnano: osdrv/interdrv/vi: disable vi_motion_level_calc + for backward compatibility + +--- + interdrv/cvi_vc_drv/module/src/enc_ctx.c | 4 ++++ + .../vcodec/sample/main_enc_cvitest.c | 4 ++++ + interdrv/dwa/chip/cv181x/mesh.c | 2 ++ + .../include/chip/cv181x/uapi/linux/vi_uapi.h | 4 ++++ + interdrv/include/common/kapi/base_ctx.h | 8 ++++++++ + interdrv/include/common/kapi/vi_cb.h | 2 ++ + interdrv/vi/chip/cv181x/vi.c | 10 ++++++++++ + interdrv/vi/chip/cv181x/vi.h | 2 ++ + interdrv/vpss/common/vpss.c | 20 +++++++++++++++++++ + 9 files changed, 56 insertions(+) + +diff --git a/interdrv/cvi_vc_drv/module/src/enc_ctx.c b/interdrv/cvi_vc_drv/module/src/enc_ctx.c +index 7cefb42..9d028a3 100644 +--- a/interdrv/cvi_vc_drv/module/src/enc_ctx.c ++++ b/interdrv/cvi_vc_drv/module/src/enc_ctx.c +@@ -1026,7 +1026,11 @@ static CVI_S32 vidEnc_enc_one_pic(CVI_VOID *ctx, + || pEncCtx->base.rcMode == RC_MODE_AVBR) { + if (blk && (indexFrameDisplay & 0xffffff00)) { + pPicCfg->picMotionLevel = blk->buf.motion_lv; ++#ifdef WANT_VI_MOTION_LEVEL_CALC + pPicCfg->picDciLv = blk->buf.dci_lv; ++#else ++ pPicCfg->picDciLv = 0; ++#endif + pPicCfg->picMotionMap = mtable; + pPicCfg->picMotionMapSize = MO_TBL_SIZE; + memcpy(mtable, blk->buf.motion_table, MO_TBL_SIZE); +diff --git a/interdrv/cvi_vc_drv/vcodec/sample/main_enc_cvitest.c b/interdrv/cvi_vc_drv/vcodec/sample/main_enc_cvitest.c +index 112d13f..3e6b093 100644 +--- a/interdrv/cvi_vc_drv/vcodec/sample/main_enc_cvitest.c ++++ b/interdrv/cvi_vc_drv/vcodec/sample/main_enc_cvitest.c +@@ -2848,7 +2848,11 @@ void cviCopyMotionMap(void *handle, cviEncOnePicCfg *pPicCfg, void *phandle) + mlv_info->vpss_grp = 0; + cvi_vc_get_motion_tbl((void *) mlv_info); + pPicCfg->picMotionLevel = mlv_info->m_lv_i.mlv_i.mlv_i_level; ++#ifdef WANT_VI_MOTION_LEVEL_CALC + pPicCfg->picDciLv = mlv_info->m_lv_i.dci_lv; ++#else ++ pPicCfg->picDciLv = 0; ++#endif + pPicCfg->picMotionMapSize = MO_TBL_SIZE; + memcpy(pPicCfg->picMotionMap, mlv_info->m_lv_i.mlv_i.mlv_i_table, MO_TBL_SIZE); + } +diff --git a/interdrv/dwa/chip/cv181x/mesh.c b/interdrv/dwa/chip/cv181x/mesh.c +index 5ad6e81..82fc6b1 100644 +--- a/interdrv/dwa/chip/cv181x/mesh.c ++++ b/interdrv/dwa/chip/cv181x/mesh.c +@@ -148,7 +148,9 @@ static int init_ldc_param(const struct vb_s *vb_in, struct vb_s *vb_out, + vb_out->buf.u64PTS = stTask->stImgOut.stVFrame.u64PTS; + vb_out->buf.frm_num = vb_in->buf.frm_num; + vb_out->buf.motion_lv = vb_in->buf.motion_lv; ++#ifdef WANT_VI_MOTION_LEVEL_CALC + vb_out->buf.dci_lv = vb_in->buf.dci_lv; ++#endif + memcpy(vb_out->buf.motion_table, vb_in->buf.motion_table, + MO_TBL_SIZE); + +diff --git a/interdrv/include/chip/cv181x/uapi/linux/vi_uapi.h b/interdrv/include/chip/cv181x/uapi/linux/vi_uapi.h +index 7ba86f1..85d1fa1 100644 +--- a/interdrv/include/chip/cv181x/uapi/linux/vi_uapi.h ++++ b/interdrv/include/chip/cv181x/uapi/linux/vi_uapi.h +@@ -204,7 +204,11 @@ struct vi_event { + #endif + }; + ++#ifdef WANT_VI_MOTION_LEVEL_CALC + #define MO_TBL_SIZE 2048 ++#else ++#define MO_TBL_SIZE 256 ++#endif + /* + * Configure the structure of motion information. + */ +diff --git a/interdrv/include/common/kapi/base_ctx.h b/interdrv/include/common/kapi/base_ctx.h +index b85cc42..45cbc48 100644 +--- a/interdrv/include/common/kapi/base_ctx.h ++++ b/interdrv/include/common/kapi/base_ctx.h +@@ -78,7 +78,11 @@ typedef uint64_t VB_BLK; + (var) = (tvar)) + #endif + ++#ifdef WANT_VI_MOTION_LEVEL_CALC + #define MO_TBL_SIZE 2048 ++#else ++#define MO_TBL_SIZE 256 ++#endif + + union vb_ctrl_cfg { + struct cvi_vb_blk_info vb_blk_info; +@@ -97,8 +101,10 @@ struct mlv_i_s { + + struct mlv_wrap_i_s { + struct mlv_i_s mlv_i; ++#ifdef WANT_VI_MOTION_LEVEL_CALC + u32 dci_lv; + u8 raw_num; ++#endif + }; + + struct mod_ctx_s { +@@ -131,7 +137,9 @@ struct cvi_buffer { + + uint8_t motion_lv; + uint8_t motion_table[MO_TBL_SIZE]; ++#ifdef WANT_VI_MOTION_LEVEL_CALC + uint32_t dci_lv; ++#endif + + uint32_t flags; //bit 0: drop frame + uint32_t sequence; +diff --git a/interdrv/include/common/kapi/vi_cb.h b/interdrv/include/common/kapi/vi_cb.h +index e4df8d3..626d089 100644 +--- a/interdrv/include/common/kapi/vi_cb.h ++++ b/interdrv/include/common/kapi/vi_cb.h +@@ -12,7 +12,9 @@ enum VI_CB_CMD { + VI_CB_SET_VIVPSSMODE, + VI_CB_RESET_ISP, + VI_CB_GDC_OP_DONE = DWA_CB_GDC_OP_DONE, ++#ifdef WANT_VI_MOTION_LEVEL_CALC + VI_CB_MOTION_CALC, ++#endif + VI_CB_MAX + }; + +diff --git a/interdrv/vi/chip/cv181x/vi.c b/interdrv/vi/chip/cv181x/vi.c +index a0d7936..809ba08 100644 +--- a/interdrv/vi/chip/cv181x/vi.c ++++ b/interdrv/vi/chip/cv181x/vi.c +@@ -6027,6 +6027,7 @@ int vi_cb(void *dev, enum ENUM_MODULES_ID caller, u32 cmd, void *arg) + rc = 0; + break; + } ++#ifdef WANT_VI_MOTION_LEVEL_CALC + case VI_CB_MOTION_CALC: + { + struct mlv_wrap_i_s *mlv = (struct mlv_wrap_i_s *)arg; +@@ -6038,6 +6039,7 @@ int vi_cb(void *dev, enum ENUM_MODULES_ID caller, u32 cmd, void *arg) + } + break; + } ++#endif + default: + break; + } +@@ -6063,6 +6065,7 @@ static void _vi_timeout_chk(struct cvi_vi_dev *vdev) + } + } + ++#ifdef WANT_VI_MOTION_LEVEL_CALC + #define VC_GRID_SIZE (64) + #define MAX_MOTION_LEVEL (255) + +@@ -6198,6 +6201,7 @@ static void vi_dci_calc(struct cvi_vi_dev *vdev, enum cvi_isp_raw raw_num, uint3 + if (dci_means) + *dci_lv = 511 - *dci_lv / dci_means; + } ++#endif + + #ifdef VI_PROFILE + static void _vi_update_chnRealFrameRate(VI_CHN_STATUS_S *pstViChnStatus) +@@ -6296,10 +6300,16 @@ static int _vi_event_handler_thread(void * arg) + } + + if (!gViCtx->pipeAttr[chn.s32ChnId].bYuvBypassPath) { ++#ifdef WANT_VI_MOTION_LEVEL_CALC + vi_motion_level_calc(vdev, b.raw_id, vb->buf.motion_table, &vb->buf.motion_lv); + vi_dci_calc(vdev, b.raw_id, &vb->buf.dci_lv); ++#else ++ vi_fill_mlv_info(vb, 0, NULL, true); ++#endif + vi_fill_dis_info(vb); ++#ifdef WANT_VI_MOTION_LEVEL_CALC + vi_motion_dbg(vdev, vb); ++#endif + } + + // TODO: extchn only support works on original frame without GDC effect. +diff --git a/interdrv/vi/chip/cv181x/vi.h b/interdrv/vi/chip/cv181x/vi.h +index 6801fd2..84c642a 100644 +--- a/interdrv/vi/chip/cv181x/vi.h ++++ b/interdrv/vi/chip/cv181x/vi.h +@@ -1530,9 +1530,11 @@ static int _vi_clk_ctrl(struct cvi_vi_dev *vdev, u8 enable); + #endif + static inline void vi_err_wake_up_th(struct cvi_vi_dev *vdev, enum cvi_isp_raw err_raw); + static inline void _post_rgbmap_update(struct isp_ctx *ctx, const enum cvi_isp_raw raw_num, const u32 frm_num); ++#ifdef WANT_VI_MOTION_LEVEL_CALC + static void vi_motion_level_calc(struct cvi_vi_dev *vdev, enum cvi_isp_raw raw_num, + uint8_t *motion_table, uint8_t *motion_lv); + static void vi_dci_calc(struct cvi_vi_dev *vdev, enum cvi_isp_raw raw_num, uint32_t *dci_lv); ++#endif + void _postraw_outbuf_enq(struct cvi_vi_dev *vdev, const enum cvi_isp_raw raw_num); + void isp_fill_rgbmap(struct isp_ctx *ctx, enum cvi_isp_raw raw_num, const u8 chn_num); + struct cvi_isp_buf *_cvi_isp_next_buf(struct cvi_vi_dev *vdev, const u8 chn_num); +diff --git a/interdrv/vpss/common/vpss.c b/interdrv/vpss/common/vpss.c +index 6cba04b..6c972e1 100644 +--- a/interdrv/vpss/common/vpss.c ++++ b/interdrv/vpss/common/vpss.c +@@ -573,6 +573,7 @@ static CVI_BOOL vpss_enable_handler_ctx(struct vpss_handler_ctx *ctx) + return CVI_FALSE; + } + ++#ifdef WANT_VI_MOTION_LEVEL_CALC + static CVI_VOID _vpss_offline_set_mlv_info(struct vb_s *vb_in, struct cvi_buffer *buf, + struct cvi_vpss_ctx *ctx, VPSS_CHN VpssChn) + { +@@ -628,6 +629,7 @@ static CVI_VOID _vpss_offline_set_mlv_info(struct vb_s *vb_in, struct cvi_buffer + } + } + } ++#endif + + static CVI_VOID _vpss_fill_cvi_buffer(MMF_CHN_S chn, struct vb_s *grp_vb_in, + uint64_t phy_addr, struct cvi_buffer *buf, struct cvi_vpss_ctx *ctx) +@@ -663,10 +665,14 @@ static CVI_VOID _vpss_fill_cvi_buffer(MMF_CHN_S chn, struct vb_s *grp_vb_in, + buf->u64PTS = grp_vb_in->buf.u64PTS; + buf->frm_num = grp_vb_in->buf.frm_num; + buf->motion_lv = grp_vb_in->buf.motion_lv; ++#ifdef WANT_VI_MOTION_LEVEL_CALC + buf->dci_lv = grp_vb_in->buf.dci_lv; ++#endif + memcpy(buf->motion_table, grp_vb_in->buf.motion_table, MO_TBL_SIZE); + ++#ifdef WANT_VI_MOTION_LEVEL_CALC + _vpss_offline_set_mlv_info(grp_vb_in, buf, ctx, chn.s32ChnId); ++#endif + } + } + +@@ -1127,6 +1133,7 @@ static void hw_reset(VPSS_GRP VpssGrp, struct cvi_vpss_ctx *ctx) + static CVI_VOID _vpss_online_set_mlv_info(struct vb_s *blk, struct cvi_vpss_ctx *ctx, VPSS_CHN VpssChn) + { + CVI_U8 snr_num = blk->buf.dev_num; ++#ifdef WANT_VI_MOTION_LEVEL_CALC + CVI_U32 x, y; + CVI_U32 fractional_bits = 8; + CVI_U32 x_scale, y_scale; +@@ -1135,11 +1142,15 @@ static CVI_VOID _vpss_online_set_mlv_info(struct vb_s *blk, struct cvi_vpss_ctx + CVI_U32 out_ctu_w, out_ctu_h; + CVI_U32 opposite; + CVI_U8 temp; ++#endif + + blk->buf.motion_lv = g_mlv_i[snr_num].mlv_i.mlv_i_level; ++#ifdef WANT_VI_MOTION_LEVEL_CALC + blk->buf.dci_lv = g_mlv_i[snr_num].dci_lv; ++#endif + memcpy(blk->buf.motion_table, g_mlv_i[snr_num].mlv_i.mlv_i_table, sizeof(blk->buf.motion_table)); + ++#ifdef WANT_VI_MOTION_LEVEL_CALC + in_ctu_w = ALIGN(ctx->stGrpAttr.u32MaxW, 64) >> 6; + in_ctu_h = ALIGN(ctx->stGrpAttr.u32MaxH, 64) >> 6; + out_ctu_w = ALIGN(ctx->stChnCfgs[VpssChn].stChnAttr.u32Width, 64) >> 6; +@@ -1182,6 +1193,7 @@ static CVI_VOID _vpss_online_set_mlv_info(struct vb_s *blk, struct cvi_vpss_ctx + } + } + } ++#endif + } + + static CVI_S32 _vpss_online_get_dpcm_wr_crop(CVI_U8 snr_num, +@@ -2528,7 +2540,9 @@ static CVI_VOID vpss_handle_online_frame_done(struct vpss_handler_ctx *ctx, VPSS + CVI_U8 u8ChnMask; + struct vb_s *vb; + CVI_BOOL vc_sbm_enabled = _is_vc_sbm_enabled(workingGrp, vpss_ctx); ++#ifdef WANT_VI_MOTION_LEVEL_CALC + static struct mlv_wrap_i_s m_w_i; ++#endif + + vpssCtx[workingGrp]->stGrpWorkStatus.u32RecvCnt++; + u8ChnMask = _vpss_get_chn_mask_by_dev(workingGrp, ctx->IntMask[workingGrp]); +@@ -2537,9 +2551,11 @@ static CVI_VOID vpss_handle_online_frame_done(struct vpss_handler_ctx *ctx, VPSS + VpssChn = 0; + mutex_lock(&vpssCtx[workingGrp]->lock); + ++#ifdef WANT_VI_MOTION_LEVEL_CALC + m_w_i.raw_num = workingGrp; + _vpss_call_cb(E_MODULE_VI, VI_CB_MOTION_CALC, &m_w_i); + vpss_set_mlv_info(workingGrp, &m_w_i); ++#endif + + do { + if (vpss_ctx->stChnCfgs[VpssChn].stBufWrap.bEnable && +@@ -5230,7 +5246,9 @@ CVI_VOID vpss_set_mlv_info(CVI_U8 snr_num, struct mlv_wrap_i_s *p_m_lv_i) + return; + } + g_mlv_i[snr_num].mlv_i.mlv_i_level = p_m_lv_i->mlv_i.mlv_i_level; ++#ifdef WANT_VI_MOTION_LEVEL_CALC + g_mlv_i[snr_num].dci_lv = p_m_lv_i->dci_lv; ++#endif + memcpy(g_mlv_i[snr_num].mlv_i.mlv_i_table, p_m_lv_i->mlv_i.mlv_i_table, + sizeof(g_mlv_i[snr_num].mlv_i.mlv_i_table)); + } +@@ -5242,7 +5260,9 @@ CVI_VOID vpss_get_mlv_info(CVI_U8 snr_num, struct mlv_wrap_i_s *p_m_lv_i) + return; + } + p_m_lv_i->mlv_i.mlv_i_level = g_mlv_i[snr_num].mlv_i.mlv_i_level; ++#ifdef WANT_VI_MOTION_LEVEL_CALC + p_m_lv_i->dci_lv = g_mlv_i[snr_num].dci_lv; ++#endif + memcpy(p_m_lv_i->mlv_i.mlv_i_table, g_mlv_i[snr_num].mlv_i.mlv_i_table, + sizeof(g_mlv_i[snr_num].mlv_i.mlv_i_table)); + } +-- +2.34.1 + diff --git a/configs/common/patches/osdrv/0002-licheervnano-osdrv-interdrv-vi-remove-obsolete-vi_fi.patch b/configs/common/patches/osdrv/0002-licheervnano-osdrv-interdrv-vi-remove-obsolete-vi_fi.patch new file mode 100644 index 0000000..f42bffe --- /dev/null +++ b/configs/common/patches/osdrv/0002-licheervnano-osdrv-interdrv-vi-remove-obsolete-vi_fi.patch @@ -0,0 +1,26 @@ +From cd94ea2d2052a1826be96adef9d1868b53bce5c1 Mon Sep 17 00:00:00 2001 +From: scpcom +Date: Sun, 22 Sep 2024 20:14:14 +0200 +Subject: [PATCH] licheervnano: osdrv/interdrv/vi: remove obsolete + vi_fill_mlv_info call + +--- + interdrv/vi/chip/cv181x/vi.c | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/interdrv/vi/chip/cv181x/vi.c b/interdrv/vi/chip/cv181x/vi.c +index 809ba08..72f29a1 100644 +--- a/interdrv/vi/chip/cv181x/vi.c ++++ b/interdrv/vi/chip/cv181x/vi.c +@@ -6303,8 +6303,6 @@ static int _vi_event_handler_thread(void * arg) + #ifdef WANT_VI_MOTION_LEVEL_CALC + vi_motion_level_calc(vdev, b.raw_id, vb->buf.motion_table, &vb->buf.motion_lv); + vi_dci_calc(vdev, b.raw_id, &vb->buf.dci_lv); +-#else +- vi_fill_mlv_info(vb, 0, NULL, true); + #endif + vi_fill_dis_info(vb); + #ifdef WANT_VI_MOTION_LEVEL_CALC +-- +2.34.1 + diff --git a/configs/common/patches/osdrv/0003-update.patch b/configs/common/patches/osdrv/0003-update.patch new file mode 100644 index 0000000..10e7a61 --- /dev/null +++ b/configs/common/patches/osdrv/0003-update.patch @@ -0,0 +1,96 @@ +From 08fd439f1f289ea4b7454a02c4f00db150925f87 Mon Sep 17 00:00:00 2001 +From: Lu Hui +Date: Thu, 14 Mar 2024 11:52:41 +0800 +Subject: [PATCH] update + +--- + interdrv/vi/chip/cv181x/vi.c | 3 ++- + interdrv/vo/chip/cv181x/vo.c | 3 ++- + interdrv/vo/common/vo_common.h | 8 ++++---- + interdrv/vpss/chip/cv181x/vpss_core.c | 3 ++- + interdrv/vpss/common/vpss_debug.h | 8 ++++---- + 5 files changed, 14 insertions(+), 11 deletions(-) + +diff --git a/interdrv/vi/chip/cv181x/vi.c b/interdrv/vi/chip/cv181x/vi.c +index 8fd07b2..6d77f57 100644 +--- a/interdrv/vi/chip/cv181x/vi.c ++++ b/interdrv/vi/chip/cv181x/vi.c +@@ -52,7 +52,8 @@ + /******************************************************* + * Global variables + ******************************************************/ +-u32 vi_log_lv = VI_ERR | VI_WARN | VI_NOTICE | VI_INFO | VI_DBG; ++//u32 vi_log_lv = VI_ERR | VI_WARN | VI_NOTICE | VI_INFO | VI_DBG; ++u32 vi_log_lv = 0; + module_param(vi_log_lv, int, 0644); + + +diff --git a/interdrv/vo/chip/cv181x/vo.c b/interdrv/vo/chip/cv181x/vo.c +index 7e3bbed..5f6e2d2 100644 +--- a/interdrv/vo/chip/cv181x/vo.c ++++ b/interdrv/vo/chip/cv181x/vo.c +@@ -43,7 +43,8 @@ + /******************************************************* + * Global variables + ******************************************************/ +-u32 vo_log_lv = CVI_DBG_WARN; ++//u32 vo_log_lv = CVI_DBG_WARN; ++u32 vo_log_lv = 0; + int smooth; + int debug; + int job_init; +diff --git a/interdrv/vo/common/vo_common.h b/interdrv/vo/common/vo_common.h +index 395288f..6c918ee 100644 +--- a/interdrv/vo/common/vo_common.h ++++ b/interdrv/vo/common/vo_common.h +@@ -14,10 +14,10 @@ extern u32 vo_log_lv; + #define _reg_write(addr, data) writel(data, (void __iomem *)addr) + + #define CVI_DBG_ERR 1 /* error conditions */ +-#define CVI_DBG_WARN 2 /* warning conditions */ +-#define CVI_DBG_NOTICE 3 /* normal but significant condition */ +-#define CVI_DBG_INFO 4 /* informational */ +-#define CVI_DBG_DEBUG 5 /* debug-level messages */ ++#define CVI_DBG_WARN 5 /* warning conditions */ ++#define CVI_DBG_NOTICE 0xf /* normal but significant condition */ ++#define CVI_DBG_INFO 0xff /* informational */ ++#define CVI_DBG_DEBUG 0xfff /* debug-level messages */ + + #if defined(CONFIG_CVI_LOG) + #define CVI_TRACE_VO(level, fmt, ...) \ +diff --git a/interdrv/vpss/chip/cv181x/vpss_core.c b/interdrv/vpss/chip/cv181x/vpss_core.c +index 3fac4f5..d235881 100644 +--- a/interdrv/vpss/chip/cv181x/vpss_core.c ++++ b/interdrv/vpss/chip/cv181x/vpss_core.c +@@ -35,7 +35,8 @@ + #include "sclr_test.h" + + +-u32 vpss_log_lv = CVI_DBG_WARN; ++//u32 vpss_log_lv = CVI_DBG_WARN; ++u32 vpss_log_lv = 0; + int single_vb; + int debug; + int vip_clk_freq; +diff --git a/interdrv/vpss/common/vpss_debug.h b/interdrv/vpss/common/vpss_debug.h +index 2b14d2d..6bb7b17 100644 +--- a/interdrv/vpss/common/vpss_debug.h ++++ b/interdrv/vpss/common/vpss_debug.h +@@ -6,10 +6,10 @@ + extern u32 vpss_log_lv; + + #define CVI_DBG_ERR 1 /* error conditions */ +-#define CVI_DBG_WARN 2 /* warning conditions */ +-#define CVI_DBG_NOTICE 3 /* normal but significant condition */ +-#define CVI_DBG_INFO 4 /* informational */ +-#define CVI_DBG_DEBUG 5 /* debug-level messages */ ++#define CVI_DBG_WARN 3 /* warning conditions */ ++#define CVI_DBG_NOTICE 7 /* normal but significant condition */ ++#define CVI_DBG_INFO 0xf /* informational */ ++#define CVI_DBG_DEBUG 0xff /* debug-level messages */ + + #if defined(CONFIG_CVI_LOG) + #define CVI_TRACE_VPSS(level, fmt, ...) \ +-- +2.34.1 + diff --git a/configs/common/patches/osdrv/0004-licheervnano-osdrv-interdrv-vpss-disable-tile-mode-f.patch b/configs/common/patches/osdrv/0004-licheervnano-osdrv-interdrv-vpss-disable-tile-mode-f.patch new file mode 100644 index 0000000..a8b8042 --- /dev/null +++ b/configs/common/patches/osdrv/0004-licheervnano-osdrv-interdrv-vpss-disable-tile-mode-f.patch @@ -0,0 +1,47 @@ +From 91babab1b3c793492dc21dd2af7a048d107fd023 Mon Sep 17 00:00:00 2001 +From: scpcom +Date: Sat, 21 Sep 2024 02:01:59 +0200 +Subject: [PATCH] licheervnano: osdrv/interdrv/vpss: disable tile mode for + backward compatibility + +--- + interdrv/vpss/chip/cv181x/chip.mk | 2 +- + interdrv/vpss/chip/cv181x/vpss_core.c | 2 ++ + 2 files changed, 3 insertions(+), 1 deletion(-) + +diff --git a/interdrv/vpss/chip/cv181x/chip.mk b/interdrv/vpss/chip/cv181x/chip.mk +index 781343a..0d83e22 100644 +--- a/interdrv/vpss/chip/cv181x/chip.mk ++++ b/interdrv/vpss/chip/cv181x/chip.mk +@@ -1,7 +1,7 @@ + CONFIG_SCLR_TEST = 0 + CONFIG_CVI_LOG = 1 + CONFIG_REG_DUMP = 1 +-CONFIG_TILE_MODE = 1 ++CONFIG_TILE_MODE = 0 + CONFIG_RGN_EX = 0 + + $(CVIARCH_L)_vpss-objs += chip/$(CVIARCH_L)/vip_img.o +diff --git a/interdrv/vpss/chip/cv181x/vpss_core.c b/interdrv/vpss/chip/cv181x/vpss_core.c +index d235881..fc07edf 100644 +--- a/interdrv/vpss/chip/cv181x/vpss_core.c ++++ b/interdrv/vpss/chip/cv181x/vpss_core.c +@@ -441,6 +441,7 @@ static void cvi_img_device_run(struct cvi_img_vdev *idev, bool sc_need_check[]) + idev->job_flags |= TRANS_RUNNING; + //spin_unlock_irqrestore(&dev->job_lock, flags); + ++#if defined(CONFIG_TILE_MODE) + if (idev->is_tile) { + is_left_tile = !idev->is_work_on_r_tile; + if (!idev->is_work_on_r_tile) { +@@ -474,6 +475,7 @@ static void cvi_img_device_run(struct cvi_img_vdev *idev, bool sc_need_check[]) + } + } + } ++#endif + + + sclr_img_checksum_en(idev->img_type, true); +-- +2.34.1 + diff --git a/configs/duo256/linux/defconfig b/configs/duo256/linux/defconfig index 2d09e77..f30d04f 100644 --- a/configs/duo256/linux/defconfig +++ b/configs/duo256/linux/defconfig @@ -4,15 +4,16 @@ CONFIG_POSIX_MQUEUE=y CONFIG_GENERIC_IRQ_DEBUGFS=y CONFIG_NO_HZ_IDLE=y CONFIG_HIGH_RES_TIMERS=y +CONFIG_PREEMPT=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=15 CONFIG_CGROUPS=y CONFIG_MEMCG=y CONFIG_BLK_CGROUP=y -CONFIG_CGROUP_SCHED=y +# CONFIG_CGROUP_SCHED is not set CONFIG_CFS_BANDWIDTH=y -CONFIG_RT_GROUP_SCHED=y +# CONFIG_RT_GROUP_SCHED is not set CONFIG_CGROUP_PIDS=y CONFIG_CGROUP_DEVICE=y CONFIG_NAMESPACES=y @@ -1353,6 +1354,7 @@ CONFIG_TMP006=m CONFIG_TMP007=m CONFIG_TSYS01=m CONFIG_TSYS02D=m +CONFIG_PWM=y CONFIG_PWM_CVITEK=m CONFIG_SIFIVE_PLIC=y CONFIG_ANDROID=y @@ -1486,5 +1488,7 @@ CONFIG_DYNAMIC_DEBUG=y CONFIG_DEBUG_FS=y # CONFIG_DEBUG_MISC is not set # CONFIG_SCHED_DEBUG is not set +# CONFIG_DEBUG_PREEMPT is not set +# CONFIG_RCU_TRACE is not set # CONFIG_FTRACE is not set # CONFIG_RUNTIME_TESTING_MENU is not set diff --git a/configs/duo256/memmap.py b/configs/duo256/memmap.py index 545af06..63baece 100755 --- a/configs/duo256/memmap.py +++ b/configs/duo256/memmap.py @@ -40,10 +40,10 @@ class MemoryMap: # ================= # Multimedia buffer. Used by u-boot/kernel/FreeRTOS # ================= - ION_SIZE = 0 * SIZE_1M - H26X_BITSTREAM_SIZE = 0 * SIZE_1M + ION_SIZE = 63 * SIZE_1M + H26X_BITSTREAM_SIZE = 2 * SIZE_1M H26X_ENC_BUFF_SIZE = 0 - ISP_MEM_BASE_SIZE = 0 * SIZE_1M + ISP_MEM_BASE_SIZE = 20 * SIZE_1M FREERTOS_RESERVED_ION_SIZE = H26X_BITSTREAM_SIZE + H26X_ENC_BUFF_SIZE + ISP_MEM_BASE_SIZE # ION after FreeRTOS @@ -58,7 +58,7 @@ class MemoryMap: # Boot logo is after the ION buffer # Framebuffer uses boot logo's reserved memory - BOOTLOGO_SIZE = 1800 * SIZE_1K + BOOTLOGO_SIZE = 5632 * SIZE_1K BOOTLOGO_ADDR = ION_ADDR - BOOTLOGO_SIZE FRAMEBUFFER_SIZE = BOOTLOGO_SIZE FRAMEBUFFER_ADDR = BOOTLOGO_ADDR diff --git a/configs/duo256/settings.mk b/configs/duo256/settings.mk index 28fd960..5faf3c2 100644 --- a/configs/duo256/settings.mk +++ b/configs/duo256/settings.mk @@ -8,4 +8,6 @@ PARTITION_FILE=partition_sd.xml STORAGE_TYPE=sd PACKAGES += " duo-pinmux" + +IMAGE_ADDITIONS += "load-systemko" #IMAGE_ADDITIONS += "aic8800-firmware" \ No newline at end of file diff --git a/configs/duos/linux/defconfig b/configs/duos/linux/defconfig index 2d09e77..f30d04f 100644 --- a/configs/duos/linux/defconfig +++ b/configs/duos/linux/defconfig @@ -4,15 +4,16 @@ CONFIG_POSIX_MQUEUE=y CONFIG_GENERIC_IRQ_DEBUGFS=y CONFIG_NO_HZ_IDLE=y CONFIG_HIGH_RES_TIMERS=y +CONFIG_PREEMPT=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=15 CONFIG_CGROUPS=y CONFIG_MEMCG=y CONFIG_BLK_CGROUP=y -CONFIG_CGROUP_SCHED=y +# CONFIG_CGROUP_SCHED is not set CONFIG_CFS_BANDWIDTH=y -CONFIG_RT_GROUP_SCHED=y +# CONFIG_RT_GROUP_SCHED is not set CONFIG_CGROUP_PIDS=y CONFIG_CGROUP_DEVICE=y CONFIG_NAMESPACES=y @@ -1353,6 +1354,7 @@ CONFIG_TMP006=m CONFIG_TMP007=m CONFIG_TSYS01=m CONFIG_TSYS02D=m +CONFIG_PWM=y CONFIG_PWM_CVITEK=m CONFIG_SIFIVE_PLIC=y CONFIG_ANDROID=y @@ -1486,5 +1488,7 @@ CONFIG_DYNAMIC_DEBUG=y CONFIG_DEBUG_FS=y # CONFIG_DEBUG_MISC is not set # CONFIG_SCHED_DEBUG is not set +# CONFIG_DEBUG_PREEMPT is not set +# CONFIG_RCU_TRACE is not set # CONFIG_FTRACE is not set # CONFIG_RUNTIME_TESTING_MENU is not set diff --git a/configs/duos/memmap.py b/configs/duos/memmap.py index 1303eba..c9b3176 100755 --- a/configs/duos/memmap.py +++ b/configs/duos/memmap.py @@ -40,10 +40,10 @@ class MemoryMap: # ================= # Multimedia buffer. Used by u-boot/kernel/FreeRTOS # ================= - ION_SIZE = 0 * SIZE_1M - H26X_BITSTREAM_SIZE = 0 * SIZE_1M + ION_SIZE = 74 * SIZE_1M + H26X_BITSTREAM_SIZE = 2 * SIZE_1M H26X_ENC_BUFF_SIZE = 0 - ISP_MEM_BASE_SIZE = 0 * SIZE_1M + ISP_MEM_BASE_SIZE = 20 * SIZE_1M FREERTOS_RESERVED_ION_SIZE = H26X_BITSTREAM_SIZE + H26X_ENC_BUFF_SIZE + ISP_MEM_BASE_SIZE # ION after FreeRTOS @@ -58,7 +58,7 @@ class MemoryMap: # Boot logo is after the ION buffer # Framebuffer uses boot logo's reserved memory - BOOTLOGO_SIZE = 1800 * SIZE_1K + BOOTLOGO_SIZE = 5632 * SIZE_1K BOOTLOGO_ADDR = ION_ADDR - BOOTLOGO_SIZE FRAMEBUFFER_SIZE = BOOTLOGO_SIZE FRAMEBUFFER_ADDR = BOOTLOGO_ADDR diff --git a/configs/duos/settings.mk b/configs/duos/settings.mk index 78bf404..09bd1af 100644 --- a/configs/duos/settings.mk +++ b/configs/duos/settings.mk @@ -9,6 +9,7 @@ PARTITION_FILE=partition_$(STORAGE_TYPE).xml PACKAGES += " duo-pinmux wireless-regdb wpasupplicant cvi-pinmux-cv181x bluez" +IMAGE_ADDITIONS += "load-systemko" IMAGE_ADDITIONS += "aic8800-firmware" IMAGE_ADDITIONS += "ethernet-leds" IMAGE_ADDITIONS += "usb-switch" diff --git a/configs/licheervnano/dts/sg2002_licheervnano_sd.dts b/configs/licheervnano/dts/cv181x_licheervnano_sd.dts similarity index 92% rename from configs/licheervnano/dts/sg2002_licheervnano_sd.dts rename to configs/licheervnano/dts/cv181x_licheervnano_sd.dts index 49dd8a5..3f4907a 100644 --- a/configs/licheervnano/dts/sg2002_licheervnano_sd.dts +++ b/configs/licheervnano/dts/cv181x_licheervnano_sd.dts @@ -1,8 +1,8 @@ /dts-v1/; -#include "sg200x_base_riscv.dtsi" -#include "sg200x_asic_qfn.dtsi" -#include "sg200x_asic_sd.dtsi" -#include "sg200x_default_memmap.dtsi" +#include "cv181x_base_riscv.dtsi" +#include "cv181x_asic_qfn.dtsi" +#include "cv181x_asic_sd.dtsi" +#include "cv181x_default_memmap.dtsi" #include #include @@ -43,15 +43,19 @@ /delete-property/ mute-gpio-r; }; +&mipi_rx { + snsr-reset = <&porte 1 GPIO_ACTIVE_LOW>; +}; + &soc_thermal_0 { cooling-maps { map0 { trip = <&soc_thermal_trip_0>; - cooling-device = <&cooling THERMAL_NO_LIMIT 1>; + cooling-device = <&cv181x_cooling THERMAL_NO_LIMIT 1>; }; map1 { trip = <&soc_thermal_trip_1>; - cooling-device = <&cooling THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + cooling-device = <&cv181x_cooling THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; }; }; }; diff --git a/configs/licheervnano/linux/defconfig b/configs/licheervnano/linux/defconfig index 2d09e77..f30d04f 100644 --- a/configs/licheervnano/linux/defconfig +++ b/configs/licheervnano/linux/defconfig @@ -4,15 +4,16 @@ CONFIG_POSIX_MQUEUE=y CONFIG_GENERIC_IRQ_DEBUGFS=y CONFIG_NO_HZ_IDLE=y CONFIG_HIGH_RES_TIMERS=y +CONFIG_PREEMPT=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=15 CONFIG_CGROUPS=y CONFIG_MEMCG=y CONFIG_BLK_CGROUP=y -CONFIG_CGROUP_SCHED=y +# CONFIG_CGROUP_SCHED is not set CONFIG_CFS_BANDWIDTH=y -CONFIG_RT_GROUP_SCHED=y +# CONFIG_RT_GROUP_SCHED is not set CONFIG_CGROUP_PIDS=y CONFIG_CGROUP_DEVICE=y CONFIG_NAMESPACES=y @@ -1353,6 +1354,7 @@ CONFIG_TMP006=m CONFIG_TMP007=m CONFIG_TSYS01=m CONFIG_TSYS02D=m +CONFIG_PWM=y CONFIG_PWM_CVITEK=m CONFIG_SIFIVE_PLIC=y CONFIG_ANDROID=y @@ -1486,5 +1488,7 @@ CONFIG_DYNAMIC_DEBUG=y CONFIG_DEBUG_FS=y # CONFIG_DEBUG_MISC is not set # CONFIG_SCHED_DEBUG is not set +# CONFIG_DEBUG_PREEMPT is not set +# CONFIG_RCU_TRACE is not set # CONFIG_FTRACE is not set # CONFIG_RUNTIME_TESTING_MENU is not set diff --git a/configs/licheervnano/memmap.py b/configs/licheervnano/memmap.py index 1554541..63baece 100755 --- a/configs/licheervnano/memmap.py +++ b/configs/licheervnano/memmap.py @@ -40,10 +40,10 @@ class MemoryMap: # ================= # Multimedia buffer. Used by u-boot/kernel/FreeRTOS # ================= - ION_SIZE = 0 * SIZE_1M - H26X_BITSTREAM_SIZE = 0 * SIZE_1M + ION_SIZE = 63 * SIZE_1M + H26X_BITSTREAM_SIZE = 2 * SIZE_1M H26X_ENC_BUFF_SIZE = 0 - ISP_MEM_BASE_SIZE = 0 * SIZE_1M + ISP_MEM_BASE_SIZE = 20 * SIZE_1M FREERTOS_RESERVED_ION_SIZE = H26X_BITSTREAM_SIZE + H26X_ENC_BUFF_SIZE + ISP_MEM_BASE_SIZE # ION after FreeRTOS @@ -58,7 +58,7 @@ class MemoryMap: # Boot logo is after the ION buffer # Framebuffer uses boot logo's reserved memory - BOOTLOGO_SIZE = 8000 * SIZE_1K + BOOTLOGO_SIZE = 5632 * SIZE_1K BOOTLOGO_ADDR = ION_ADDR - BOOTLOGO_SIZE FRAMEBUFFER_SIZE = BOOTLOGO_SIZE FRAMEBUFFER_ADDR = BOOTLOGO_ADDR diff --git a/configs/licheervnano/patches/fsbl/0002-add-debug-mode.patch b/configs/licheervnano/patches/fsbl/0002-add-debug-mode.patch.old similarity index 83% rename from configs/licheervnano/patches/fsbl/0002-add-debug-mode.patch rename to configs/licheervnano/patches/fsbl/0002-add-debug-mode.patch.old index c7dc265..b61f95d 100644 --- a/configs/licheervnano/patches/fsbl/0002-add-debug-mode.patch +++ b/configs/licheervnano/patches/fsbl/0002-add-debug-mode.patch.old @@ -4,13 +4,13 @@ Date: Thu, 18 Apr 2024 13:38:27 +0000 Subject: [PATCH] add debug mode --- - plat/sg200x/bl2/bl2_opt.c | 15 +++++++++++++++ + plat/cv180x/bl2/bl2_opt.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) -diff --git a/plat/sg200x/bl2/bl2_opt.c b/plat/sg200x/bl2/bl2_opt.c +diff --git a/plat/cv180x/bl2/bl2_opt.c b/plat/cv180x/bl2/bl2_opt.c index c73fa55..013d5de 100644 ---- a/plat/sg200x/bl2/bl2_opt.c -+++ b/plat/sg200x/bl2/bl2_opt.c +--- a/plat/cv180x/bl2/bl2_opt.c ++++ b/plat/cv180x/bl2/bl2_opt.c @@ -419,6 +419,21 @@ retry_from_flash: switch_rtc_mode_2nd_stage(); diff --git a/configs/licheervnano/patches/middleware/0001-sample-common-sample_common_sensor.c-fix-sensor-pixe.patch b/configs/licheervnano/patches/middleware/0001-sample-common-sample_common_sensor.c-fix-sensor-pixe.patch new file mode 100644 index 0000000..e7e606b --- /dev/null +++ b/configs/licheervnano/patches/middleware/0001-sample-common-sample_common_sensor.c-fix-sensor-pixe.patch @@ -0,0 +1,27 @@ +From 223cde97bfdc1482ebf6791c4e1f9d9d2e28507a Mon Sep 17 00:00:00 2001 +From: Lu Hui +Date: Tue, 20 Feb 2024 11:25:12 +0800 +Subject: [PATCH] sample/common/sample_common_sensor.c: fix sensor pixel format + +--- + sample/common/sample_common_sensor.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/sample/common/sample_common_sensor.c b/sample/common/sample_common_sensor.c +index 7ce8cb4..120ff09 100644 +--- a/sample/common/sample_common_sensor.c ++++ b/sample/common/sample_common_sensor.c +@@ -1034,7 +1034,9 @@ CVI_S32 SAMPLE_COMM_SNS_GetIspAttrBySns(SAMPLE_SNS_TYPE_E enSnsType, ISP_PUB_ATT + case GCORE_GC4653_SLAVE_MIPI_4M_30FPS_10BIT: + case TECHPOINT_TP2850_MIPI_2M_30FPS_8BIT: + case TECHPOINT_TP2850_MIPI_4M_30FPS_8BIT: +- pstPubAttr->enBayer = BAYER_GRBG; ++ // on licheervnano ++ pstPubAttr->enBayer = BAYER_RGGB; ++ //pstPubAttr->enBayer = BAYER_GRBG; + break; + default: + pstPubAttr->enBayer = BAYER_BGGR; +-- +2.34.1 + diff --git a/configs/licheervnano/patches/middleware/0002-update.patch b/configs/licheervnano/patches/middleware/0002-update.patch new file mode 100644 index 0000000..53fae1e --- /dev/null +++ b/configs/licheervnano/patches/middleware/0002-update.patch @@ -0,0 +1,36 @@ +From 9abe8151ed6e38caf0928890fee30157d3c51e5d Mon Sep 17 00:00:00 2001 +From: Lu Hui +Date: Sun, 7 Apr 2024 09:41:20 +0800 +Subject: [PATCH] update + +--- + sample/common/sample_common_sensor.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/sample/common/sample_common_sensor.c b/sample/common/sample_common_sensor.c +index 120ff09..4cff919 100644 +--- a/sample/common/sample_common_sensor.c ++++ b/sample/common/sample_common_sensor.c +@@ -745,6 +745,9 @@ CVI_S32 SAMPLE_COMM_SNS_GetDevAttr(SAMPLE_SNS_TYPE_E enSnsType, VI_DEV_ATTR_S *p + case GCORE_GC1084_SLAVE2_MIPI_1M_30FPS_10BIT: + case GCORE_GC4653_MIPI_4M_30FPS_10BIT: + case GCORE_GC4653_SLAVE_MIPI_4M_30FPS_10BIT: ++ // omnivision ++ case OV_OS04A10_MIPI_4M_1440P_30FPS_12BIT: ++ case OV_OS04A10_MIPI_4M_1440P_30FPS_10BIT_WDR2TO1: + case TECHPOINT_TP2850_MIPI_2M_30FPS_8BIT: + case TECHPOINT_TP2850_MIPI_4M_30FPS_8BIT: + pstViDevAttr->enBayerFormat = BAYER_FORMAT_GR; +@@ -1032,6 +1035,9 @@ CVI_S32 SAMPLE_COMM_SNS_GetIspAttrBySns(SAMPLE_SNS_TYPE_E enSnsType, ISP_PUB_ATT + case GCORE_GC1084_SLAVE2_MIPI_1M_30FPS_10BIT: + case GCORE_GC4653_MIPI_4M_30FPS_10BIT: + case GCORE_GC4653_SLAVE_MIPI_4M_30FPS_10BIT: ++ // omnivision ++ case OV_OS04A10_MIPI_4M_1440P_30FPS_12BIT: ++ case OV_OS04A10_MIPI_4M_1440P_30FPS_10BIT_WDR2TO1: + case TECHPOINT_TP2850_MIPI_2M_30FPS_8BIT: + case TECHPOINT_TP2850_MIPI_4M_30FPS_8BIT: + // on licheervnano +-- +2.34.1 + diff --git a/configs/licheervnano/patches/middleware/0003-Added-support-for-OA04A10-SC035GS-LT6911-and-the-new.patch b/configs/licheervnano/patches/middleware/0003-Added-support-for-OA04A10-SC035GS-LT6911-and-the-new.patch new file mode 100644 index 0000000..8034d0e --- /dev/null +++ b/configs/licheervnano/patches/middleware/0003-Added-support-for-OA04A10-SC035GS-LT6911-and-the-new.patch @@ -0,0 +1,102 @@ +From 6bc93f08f76660b9afcec1e535035a8a7a5c234b Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?=E6=9F=90=E6=9D=B0=E5=90=8C=E5=AD=A6?= <1220627966@qq.com> +Date: Wed, 15 May 2024 00:00:53 -0700 +Subject: [PATCH] Added support for OA04A10, SC035GS, LT6911, and the new + 5-inch LCD + +Added support for OA04A10, SC035GS, LT6911, and the new 5-inch display +--- + include/cvi_sys.h | 10 + + modules/sys/src/cvi_sys.c | 16 + + sample/common/sample_common_platform.c | 2 +- + sample/common/sample_common_sensor.c | 6 +- + 903 files changed, 138988 insertions(+), 3 deletions(-) + +diff --git a/include/cvi_sys.h b/include/cvi_sys.h +index 339738a..f4ca7cd 100644 +--- a/include/cvi_sys.h ++++ b/include/cvi_sys.h +@@ -360,6 +360,16 @@ CVI_S32 CVI_SYS_StartThermalThread(void); + CVI_S32 CVI_SYS_StopThermalThread(void); + + ++struct sys_ion_data2 { ++ __u32 size; ++ __u32 cached; ++ __u32 dmabuf_fd; ++ __u64 addr_p; ++ __u8 name[32]; ++}; ++ ++int ionFree2(struct sys_ion_data2 *para); ++ + #ifdef __cplusplus + #if __cplusplus + } +diff --git a/modules/sys/src/cvi_sys.c b/modules/sys/src/cvi_sys.c +index 45f685a..bee85f3 100644 +--- a/modules/sys/src/cvi_sys.c ++++ b/modules/sys/src/cvi_sys.c +@@ -650,6 +650,22 @@ int ionFree(struct sys_ion_data *para) + return CVI_SUCCESS; + } + ++int ionFree2(struct sys_ion_data2 *para) ++{ ++ CVI_S32 fd = -1; ++ CVI_S32 ret = CVI_SUCCESS; ++ ++ if ((fd = get_sys_fd()) == -1) ++ return CVI_ERR_SYS_NOTREADY; ++ ++ ret = ioctl(fd, SYS_ION_FREE, para); ++ if (ret < 0) { ++ printf("ioctl SYS_ION_ALLOC failed\n"); ++ } ++ ++ return CVI_SUCCESS; ++} ++ + static CVI_S32 _SYS_IonAlloc(CVI_U64 *pu64PhyAddr, CVI_VOID **ppVirAddr, + CVI_U32 u32Len, CVI_BOOL cached, const CVI_CHAR *name) + { +diff --git a/sample/common/sample_common_platform.c b/sample/common/sample_common_platform.c +index a4c2eaf..5b93047 100644 +--- a/sample/common/sample_common_platform.c ++++ b/sample/common/sample_common_platform.c +@@ -238,7 +238,7 @@ CVI_S32 SAMPLE_PLAT_VPSS_INIT(VPSS_GRP VpssGrp, SIZE_S stSizeIn, SIZE_S stSizeOu + + stVpssGrpAttr.stFrameRate.s32SrcFrameRate = -1; + stVpssGrpAttr.stFrameRate.s32DstFrameRate = -1; +- stVpssGrpAttr.enPixelFormat = SAMPLE_PIXEL_FORMAT; ++ stVpssGrpAttr.enPixelFormat = SAMPLE_PIXEL_FORMAT; // PIXEL_FORMAT_YUYV / SAMPLE_PIXEL_FORMAT / PIXEL_FORMAT_UYVY / PIXEL_FORMAT_YUV_400 + stVpssGrpAttr.u32MaxW = stSizeIn.u32Width; + stVpssGrpAttr.u32MaxH = stSizeIn.u32Height; + stVpssGrpAttr.u8VpssDev = 0; +diff --git a/sample/common/sample_common_sensor.c b/sample/common/sample_common_sensor.c +index 4cff919..4e4e237 100644 +--- a/sample/common/sample_common_sensor.c ++++ b/sample/common/sample_common_sensor.c +@@ -750,7 +750,8 @@ CVI_S32 SAMPLE_COMM_SNS_GetDevAttr(SAMPLE_SNS_TYPE_E enSnsType, VI_DEV_ATTR_S *p + case OV_OS04A10_MIPI_4M_1440P_30FPS_10BIT_WDR2TO1: + case TECHPOINT_TP2850_MIPI_2M_30FPS_8BIT: + case TECHPOINT_TP2850_MIPI_4M_30FPS_8BIT: +- pstViDevAttr->enBayerFormat = BAYER_FORMAT_GR; ++ // pstViDevAttr->enBayerFormat = BAYER_FORMAT_RG; ++ pstViDevAttr->enBayerFormat = BAYER_FORMAT_GB; + break; + case SOI_K06_MIPI_4M_25FPS_10BIT: + pstViDevAttr->enBayerFormat = BAYER_FORMAT_GB; +@@ -1041,7 +1042,8 @@ CVI_S32 SAMPLE_COMM_SNS_GetIspAttrBySns(SAMPLE_SNS_TYPE_E enSnsType, ISP_PUB_ATT + case TECHPOINT_TP2850_MIPI_2M_30FPS_8BIT: + case TECHPOINT_TP2850_MIPI_4M_30FPS_8BIT: + // on licheervnano +- pstPubAttr->enBayer = BAYER_RGGB; ++ pstPubAttr->enBayer = BAYER_BGGR; ++ // pstPubAttr->enBayer = BAYER_RGGB; + //pstPubAttr->enBayer = BAYER_GRBG; + break; + default: +-- +2.34.1 + diff --git a/configs/licheervnano/patches/middleware/0004-Fix-the-problem-of-GC4653-color-anomaly.patch b/configs/licheervnano/patches/middleware/0004-Fix-the-problem-of-GC4653-color-anomaly.patch new file mode 100644 index 0000000..a73d65d --- /dev/null +++ b/configs/licheervnano/patches/middleware/0004-Fix-the-problem-of-GC4653-color-anomaly.patch @@ -0,0 +1,35 @@ +From 6822f93acacc7eab351bfb4d6195be51899ed1a6 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?=E6=9F=90=E6=9D=B0=E5=90=8C=E5=AD=A6?= <1220627966@qq.com> +Date: Mon, 27 May 2024 19:38:37 -0700 +Subject: [PATCH] Fix the problem of GC4653 color anomaly + +--- + sample/common/sample_common_sensor.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/sample/common/sample_common_sensor.c b/sample/common/sample_common_sensor.c +index 4e4e237..db9cad5 100644 +--- a/sample/common/sample_common_sensor.c ++++ b/sample/common/sample_common_sensor.c +@@ -745,6 +745,9 @@ CVI_S32 SAMPLE_COMM_SNS_GetDevAttr(SAMPLE_SNS_TYPE_E enSnsType, VI_DEV_ATTR_S *p + case GCORE_GC1084_SLAVE2_MIPI_1M_30FPS_10BIT: + case GCORE_GC4653_MIPI_4M_30FPS_10BIT: + case GCORE_GC4653_SLAVE_MIPI_4M_30FPS_10BIT: ++ pstViDevAttr->enBayerFormat = BAYER_FORMAT_RG; ++ // pstViDevAttr->enBayerFormat = BAYER_FORMAT_GB; ++ break; + // omnivision + case OV_OS04A10_MIPI_4M_1440P_30FPS_12BIT: + case OV_OS04A10_MIPI_4M_1440P_30FPS_10BIT_WDR2TO1: +@@ -1036,6 +1039,8 @@ CVI_S32 SAMPLE_COMM_SNS_GetIspAttrBySns(SAMPLE_SNS_TYPE_E enSnsType, ISP_PUB_ATT + case GCORE_GC1084_SLAVE2_MIPI_1M_30FPS_10BIT: + case GCORE_GC4653_MIPI_4M_30FPS_10BIT: + case GCORE_GC4653_SLAVE_MIPI_4M_30FPS_10BIT: ++ pstPubAttr->enBayer = BAYER_RGGB; ++ break; + // omnivision + case OV_OS04A10_MIPI_4M_1440P_30FPS_12BIT: + case OV_OS04A10_MIPI_4M_1440P_30FPS_10BIT_WDR2TO1: +-- +2.34.1 + diff --git a/configs/licheervnano/patches/sensorsupportlist/0001-v2-component-isp-sensor-sg200x-gcore_gc4653-add-supp.patch b/configs/licheervnano/patches/sensorsupportlist/0001-v2-component-isp-sensor-sg200x-gcore_gc4653-add-supp.patch new file mode 100644 index 0000000..fba3b84 --- /dev/null +++ b/configs/licheervnano/patches/sensorsupportlist/0001-v2-component-isp-sensor-sg200x-gcore_gc4653-add-supp.patch @@ -0,0 +1,419 @@ +From 57cacce3f83d5cd699ebfb787e77f01301613a09 Mon Sep 17 00:00:00 2001 +From: Lu Hui +Date: Mon, 19 Feb 2024 19:10:36 +0800 +Subject: [PATCH 01/12] v2: component: isp: sensor: sg200x: gcore_gc4653: add + support for licheervnano + +--- + sensor/cv182x/gcore_gc4653/gc4653_cmos.c | 35 +- + .../cv182x/gcore_gc4653/gc4653_cmos_param.h | 6 +- + .../cv182x/gcore_gc4653/gc4653_sensor_ctl.c | 311 ++++++++---------- + 3 files changed, 179 insertions(+), 173 deletions(-) + +diff --git a/sensor/cv182x/gcore_gc4653/gc4653_cmos.c b/sensor/cv182x/gcore_gc4653/gc4653_cmos.c +index 4f6e2b6..b7ae8b8 100644 +--- a/sensor/cv182x/gcore_gc4653/gc4653_cmos.c ++++ b/sensor/cv182x/gcore_gc4653/gc4653_cmos.c +@@ -42,7 +42,8 @@ ISP_SNS_STATE_S *g_pastGc4653[VI_MAX_PIPE_NUM] = {CVI_NULL}; + #define GC4653_SENSOR_RESET_CTX(dev) (g_pastGc4653[dev] = CVI_NULL) + + ISP_SNS_COMMBUS_U g_aunGc4653_BusInfo[VI_MAX_PIPE_NUM] = { +- [0] = { .s8I2cDev = 3}, ++ // for licheervnano ++ [0] = { .s8I2cDev = 4}, + [1 ... VI_MAX_PIPE_NUM - 1] = { .s8I2cDev = -1} + }; + +@@ -474,9 +475,35 @@ static CVI_S32 cmos_get_wdr_size(VI_PIPE ViPipe, ISP_SNS_ISP_INFO_S *pstIspCfg) + + static CVI_S32 cmos_set_wdr_mode(VI_PIPE ViPipe, CVI_U8 u8Mode) + { +- UNUSED(ViPipe); +- UNUSED(u8Mode); +- CVI_TRACE_SNS(CVI_DBG_ERR, "Unsupport sensor mode!\n"); ++ //UNUSED(ViPipe); ++ //UNUSED(u8Mode); ++ ++ ISP_SNS_STATE_S *pstSnsState = CVI_NULL; ++ ++ GC4653_SENSOR_GET_CTX(ViPipe, pstSnsState); ++ CMOS_CHECK_POINTER(pstSnsState); ++ ++ pstSnsState->bSyncInit = CVI_FALSE; ++ ++ switch (u8Mode) { ++ case WDR_MODE_NONE: ++ pstSnsState->u8ImgMode = GC4653_MODE_2560X1440P30; ++ pstSnsState->enWDRMode = WDR_MODE_NONE; ++ pstSnsState->u32FLStd = g_astGc4653_mode[pstSnsState->u8ImgMode].u32VtsDef; ++ syslog(LOG_INFO, "WDR_MODE_NONE\n"); ++ break; ++ ++ case WDR_MODE_2To1_LINE: ++ default: ++ CVI_TRACE_SNS(CVI_DBG_ERR, "Unsupport sensor mode!\n"); ++ return CVI_FAILURE; ++ } ++ ++ pstSnsState->au32FL[0] = pstSnsState->u32FLStd; ++ pstSnsState->au32FL[1] = pstSnsState->au32FL[0]; ++ memset(pstSnsState->au32WDRIntTime, 0, sizeof(pstSnsState->au32WDRIntTime)); ++ ++ //CVI_TRACE_SNS(CVI_DBG_ERR, "Unsupport sensor mode!\n"); + return CVI_SUCCESS; + } + +diff --git a/sensor/cv182x/gcore_gc4653/gc4653_cmos_param.h b/sensor/cv182x/gcore_gc4653/gc4653_cmos_param.h +index c932e32..30c40f4 100644 +--- a/sensor/cv182x/gcore_gc4653/gc4653_cmos_param.h ++++ b/sensor/cv182x/gcore_gc4653/gc4653_cmos_param.h +@@ -198,13 +198,13 @@ struct combo_dev_attr_s gc4653_rx_attr = { + .mac_clk = RX_MAC_CLK_200M, + .mipi_attr = { + .raw_data_type = RAW_DATA_10BIT, +- .lane_id = {2, 1, 3, -1, -1}, +- .pn_swap = {1, 1, 1, 0, 0}, ++ .lane_id = {2, 1, 0, -1, -1}, ++ .pn_swap = {0, 0, 0, 0, 0}, + .wdr_mode = CVI_MIPI_WDR_MODE_NONE, + }, + .mclk = { + .cam = 0, +- .freq = CAMPLL_FREQ_27M, ++ .freq = CAMPLL_FREQ_24M, + }, + .devno = 0, + }; +diff --git a/sensor/cv182x/gcore_gc4653/gc4653_sensor_ctl.c b/sensor/cv182x/gcore_gc4653/gc4653_sensor_ctl.c +index 8d01a6a..525cfd9 100644 +--- a/sensor/cv182x/gcore_gc4653/gc4653_sensor_ctl.c ++++ b/sensor/cv182x/gcore_gc4653/gc4653_sensor_ctl.c +@@ -22,7 +22,7 @@ + + static void gc4653_linear_1440p30_init(VI_PIPE ViPipe); + +-CVI_U8 gc4653_i2c_addr = 0x10; ++CVI_U8 gc4653_i2c_addr = 0x29; + const CVI_U32 gc4653_addr_byte = 2; + const CVI_U32 gc4653_data_byte = 1; + static int g_fd[VI_MAX_PIPE_NUM] = {[0 ... (VI_MAX_PIPE_NUM - 1)] = -1}; +@@ -213,172 +213,151 @@ void gc4653_exit(VI_PIPE ViPipe) + + static void gc4653_linear_1440p30_init(VI_PIPE ViPipe) + { +- delay_ms(10); +- /****system****/ + gc4653_write_register(ViPipe, 0x03fe, 0xf0); +- gc4653_write_register(ViPipe, 0x03fe, 0x00); +- gc4653_write_register(ViPipe, 0x0317, 0x00); +- gc4653_write_register(ViPipe, 0x0320, 0x77); +- gc4653_write_register(ViPipe, 0x0324, 0xc8); +- gc4653_write_register(ViPipe, 0x0325, 0x06); +- gc4653_write_register(ViPipe, 0x0326, 0x60); +- gc4653_write_register(ViPipe, 0x0327, 0x03); +- gc4653_write_register(ViPipe, 0x0334, 0x40); +- gc4653_write_register(ViPipe, 0x0336, 0x60); +- gc4653_write_register(ViPipe, 0x0337, 0x82); +- gc4653_write_register(ViPipe, 0x0315, 0x25); +- gc4653_write_register(ViPipe, 0x031c, 0xc6); +- /****************************************/ +- /*frame structure*/ +- /****************************************/ +- gc4653_write_register(ViPipe, 0x0287, 0x18); +- gc4653_write_register(ViPipe, 0x0084, 0x00); +- gc4653_write_register(ViPipe, 0x0087, 0x50); +- gc4653_write_register(ViPipe, 0x029d, 0x08); +- gc4653_write_register(ViPipe, 0x0290, 0x00); +- /**********AHD 30 other need change ******************/ +- gc4653_write_register(ViPipe, 0x0340, 0x05); +- gc4653_write_register(ViPipe, 0x0341, 0xdc); +- gc4653_write_register(ViPipe, 0x0345, 0x06); +- gc4653_write_register(ViPipe, 0x034b, 0xb0); +- gc4653_write_register(ViPipe, 0x0352, 0x08); +- gc4653_write_register(ViPipe, 0x0354, 0x08); +- /****************************************/ +- /*ANALOG CIRCUIT*/ +- /****************************************/ +- gc4653_write_register(ViPipe, 0x02d1, 0xe0); +- gc4653_write_register(ViPipe, 0x0223, 0xf2); +- gc4653_write_register(ViPipe, 0x0238, 0xa4); +- gc4653_write_register(ViPipe, 0x02ce, 0x7f); +- gc4653_write_register(ViPipe, 0x0232, 0xc4); +- gc4653_write_register(ViPipe, 0x02d3, 0x05); +- gc4653_write_register(ViPipe, 0x0243, 0x06); +- gc4653_write_register(ViPipe, 0x02ee, 0x30); +- gc4653_write_register(ViPipe, 0x026f, 0x70); +- gc4653_write_register(ViPipe, 0x0257, 0x09); +- gc4653_write_register(ViPipe, 0x0211, 0x02); +- gc4653_write_register(ViPipe, 0x0219, 0x09); +- gc4653_write_register(ViPipe, 0x023f, 0x2d); +- gc4653_write_register(ViPipe, 0x0518, 0x00); +- gc4653_write_register(ViPipe, 0x0519, 0x01); +- gc4653_write_register(ViPipe, 0x0515, 0x08); +- gc4653_write_register(ViPipe, 0x02d9, 0x3f); +- gc4653_write_register(ViPipe, 0x02da, 0x02); +- gc4653_write_register(ViPipe, 0x02db, 0xe8); +- gc4653_write_register(ViPipe, 0x02e6, 0x20); +- gc4653_write_register(ViPipe, 0x021b, 0x10); +- gc4653_write_register(ViPipe, 0x0252, 0x22); +- gc4653_write_register(ViPipe, 0x024e, 0x22); +- gc4653_write_register(ViPipe, 0x02c4, 0x01); +- gc4653_write_register(ViPipe, 0x021d, 0x17); +- gc4653_write_register(ViPipe, 0x024a, 0x01); +- gc4653_write_register(ViPipe, 0x02ca, 0x02); +- gc4653_write_register(ViPipe, 0x0262, 0x10); +- gc4653_write_register(ViPipe, 0x029a, 0x20); +- gc4653_write_register(ViPipe, 0x021c, 0x0e); +- gc4653_write_register(ViPipe, 0x0298, 0x03); +- gc4653_write_register(ViPipe, 0x029c, 0x00); +- gc4653_write_register(ViPipe, 0x027e, 0x14); +- gc4653_write_register(ViPipe, 0x02c2, 0x10); +- gc4653_write_register(ViPipe, 0x0540, 0x20); +- gc4653_write_register(ViPipe, 0x0546, 0x01); +- gc4653_write_register(ViPipe, 0x0548, 0x01); +- gc4653_write_register(ViPipe, 0x0544, 0x01); +- gc4653_write_register(ViPipe, 0x0242, 0x1b); +- gc4653_write_register(ViPipe, 0x02c0, 0x1b); +- gc4653_write_register(ViPipe, 0x02c3, 0x20); +- gc4653_write_register(ViPipe, 0x02e4, 0x10); +- gc4653_write_register(ViPipe, 0x022e, 0x00); +- gc4653_write_register(ViPipe, 0x027b, 0x3f); +- gc4653_write_register(ViPipe, 0x0269, 0x0f); +- gc4653_write_register(ViPipe, 0x02d2, 0x40); +- gc4653_write_register(ViPipe, 0x027c, 0x08); +- gc4653_write_register(ViPipe, 0x023a, 0x2e); +- gc4653_write_register(ViPipe, 0x0245, 0xce); +- gc4653_write_register(ViPipe, 0x0530, 0x20); +- gc4653_write_register(ViPipe, 0x0531, 0x02); +- gc4653_write_register(ViPipe, 0x0228, 0x50); +- gc4653_write_register(ViPipe, 0x02ab, 0x00); +- gc4653_write_register(ViPipe, 0x0250, 0x00); +- gc4653_write_register(ViPipe, 0x0221, 0x50); +- gc4653_write_register(ViPipe, 0x02ac, 0x00); +- gc4653_write_register(ViPipe, 0x02a5, 0x02); +- gc4653_write_register(ViPipe, 0x0260, 0x0b); +- gc4653_write_register(ViPipe, 0x0216, 0x04); +- gc4653_write_register(ViPipe, 0x0299, 0x1C); +- gc4653_write_register(ViPipe, 0x02bb, 0x0d); +- gc4653_write_register(ViPipe, 0x02a3, 0x02); +- gc4653_write_register(ViPipe, 0x02a4, 0x02); +- gc4653_write_register(ViPipe, 0x021e, 0x02); +- gc4653_write_register(ViPipe, 0x024f, 0x08); +- gc4653_write_register(ViPipe, 0x028c, 0x08); +- gc4653_write_register(ViPipe, 0x0532, 0x3f); +- gc4653_write_register(ViPipe, 0x0533, 0x02); +- gc4653_write_register(ViPipe, 0x0277, 0xc0); +- gc4653_write_register(ViPipe, 0x0276, 0xc0); +- gc4653_write_register(ViPipe, 0x0239, 0xc0); +- /*exp*/ +- gc4653_write_register(ViPipe, 0x0202, 0x05); +- gc4653_write_register(ViPipe, 0x0203, 0x46); +- /*gain*/ +- gc4653_write_register(ViPipe, 0x0205, 0xc0); +- gc4653_write_register(ViPipe, 0x02b0, 0x68); +- /*dpc*/ +- gc4653_write_register(ViPipe, 0x0002, 0xa9); +- gc4653_write_register(ViPipe, 0x0004, 0x01); +- /*dark_sun*/ +- gc4653_write_register(ViPipe, 0x021a, 0x98); +- gc4653_write_register(ViPipe, 0x0266, 0xa0); +- gc4653_write_register(ViPipe, 0x0020, 0x01); +- gc4653_write_register(ViPipe, 0x0021, 0x03); +- gc4653_write_register(ViPipe, 0x0022, 0x00); +- gc4653_write_register(ViPipe, 0x0023, 0x04); +- /****************************************/ +- /*mipi*/ +- /****************************************/ +- /*********** AHD 30 ******************/ +- /*30fps*/ +- gc4653_write_register(ViPipe, 0x0342, 0x06); +- gc4653_write_register(ViPipe, 0x0343, 0x40); +- /*30fps*/ +- gc4653_write_register(ViPipe, 0x03fe, 0x10); +- gc4653_write_register(ViPipe, 0x03fe, 0x00); +- gc4653_write_register(ViPipe, 0x0106, 0x78); +- gc4653_write_register(ViPipe, 0x0108, 0x0c); +- gc4653_write_register(ViPipe, 0x0114, 0x01); +- gc4653_write_register(ViPipe, 0x0115, 0x12); +- gc4653_write_register(ViPipe, 0x0180, 0x46); +- gc4653_write_register(ViPipe, 0x0181, 0x30); +- gc4653_write_register(ViPipe, 0x0182, 0x05); +- gc4653_write_register(ViPipe, 0x0185, 0x01); +- gc4653_write_register(ViPipe, 0x03fe, 0x10); +- gc4653_write_register(ViPipe, 0x03fe, 0x00); +- gc4653_write_register(ViPipe, 0x0100, 0x09); +- // 0x008e = 0x00, which means disabling bayer transformation when flip/mirroring +- //gc4653_write_register(ViPipe, 0x008e, 0x00); +- //fix FPN +- gc4653_write_register(ViPipe, 0x0277, 0x38); +- gc4653_write_register(ViPipe, 0x0276, 0xc0); +- gc4653_write_register(ViPipe, 0x000f, 0x10); +- gc4653_write_register(ViPipe, 0x0059, 0x00);//close dither +- //otp +- gc4653_write_register(ViPipe, 0x0080, 0x02); +- gc4653_write_register(ViPipe, 0x0097, 0x0a); +- gc4653_write_register(ViPipe, 0x0098, 0x10); +- gc4653_write_register(ViPipe, 0x0099, 0x05); +- gc4653_write_register(ViPipe, 0x009a, 0xb0); +- gc4653_write_register(ViPipe, 0x0317, 0x08); +- gc4653_write_register(ViPipe, 0x0a67, 0x80); +- gc4653_write_register(ViPipe, 0x0a70, 0x03); +- gc4653_write_register(ViPipe, 0x0a82, 0x00); +- gc4653_write_register(ViPipe, 0x0a83, 0x10); +- gc4653_write_register(ViPipe, 0x0a80, 0x2b); +- gc4653_write_register(ViPipe, 0x05be, 0x00); +- gc4653_write_register(ViPipe, 0x05a9, 0x01); +- gc4653_write_register(ViPipe, 0x0313, 0x80); +- gc4653_write_register(ViPipe, 0x05be, 0x01); +- gc4653_write_register(ViPipe, 0x0317, 0x00); +- gc4653_write_register(ViPipe, 0x0a67, 0x00); ++ gc4653_write_register(ViPipe, 0x03fe, 0x00); ++ gc4653_write_register(ViPipe, 0x0317, 0x00); ++ gc4653_write_register(ViPipe, 0x0320, 0x77); ++ gc4653_write_register(ViPipe, 0x0324, 0xc8); ++ gc4653_write_register(ViPipe, 0x0325, 0x06); ++ gc4653_write_register(ViPipe, 0x0326, 0x6c); ++ gc4653_write_register(ViPipe, 0x0327, 0x03); ++ gc4653_write_register(ViPipe, 0x0334, 0x40); ++ gc4653_write_register(ViPipe, 0x0336, 0x6c); ++ gc4653_write_register(ViPipe, 0x0337, 0x82); ++ gc4653_write_register(ViPipe, 0x0315, 0x25); ++ gc4653_write_register(ViPipe, 0x031c, 0xc6); ++ gc4653_write_register(ViPipe, 0x0287, 0x18); ++ gc4653_write_register(ViPipe, 0x0084, 0x00); ++ gc4653_write_register(ViPipe, 0x0087, 0x50); ++ gc4653_write_register(ViPipe, 0x029d, 0x08); ++ gc4653_write_register(ViPipe, 0x0290, 0x00); ++ gc4653_write_register(ViPipe, 0x0340, 0x05); ++ gc4653_write_register(ViPipe, 0x0341, 0xdc); ++ gc4653_write_register(ViPipe, 0x0345, 0x06); ++ gc4653_write_register(ViPipe, 0x034b, 0xb0); ++ ++ gc4653_write_register(ViPipe, 0x0352, 0x06); ++ gc4653_write_register(ViPipe, 0x0354, 0x07); ++ gc4653_write_register(ViPipe, 0x02d1, 0xe0); ++ gc4653_write_register(ViPipe, 0x0223, 0xf2); ++ gc4653_write_register(ViPipe, 0x0238, 0xa4); ++ gc4653_write_register(ViPipe, 0x02ce, 0x7f); ++ gc4653_write_register(ViPipe, 0x0232, 0xc4); ++ gc4653_write_register(ViPipe, 0x02d3, 0x05); ++ gc4653_write_register(ViPipe, 0x0243, 0x06); ++ gc4653_write_register(ViPipe, 0x02ee, 0x30); ++ gc4653_write_register(ViPipe, 0x026f, 0x70); ++ gc4653_write_register(ViPipe, 0x0257, 0x09); ++ gc4653_write_register(ViPipe, 0x0211, 0x02); ++ gc4653_write_register(ViPipe, 0x0219, 0x09); ++ gc4653_write_register(ViPipe, 0x023f, 0x2d); ++ gc4653_write_register(ViPipe, 0x0518, 0x00); ++ gc4653_write_register(ViPipe, 0x0519, 0x1e); ++ gc4653_write_register(ViPipe, 0x0515, 0x30); ++ gc4653_write_register(ViPipe, 0x02d9, 0x5c); ++ gc4653_write_register(ViPipe, 0x02da, 0x02); ++ gc4653_write_register(ViPipe, 0x02db, 0xe8); ++ gc4653_write_register(ViPipe, 0x02e6, 0x20); ++ gc4653_write_register(ViPipe, 0x021b, 0x10); ++ gc4653_write_register(ViPipe, 0x0252, 0x22); ++ gc4653_write_register(ViPipe, 0x024e, 0x22); ++ gc4653_write_register(ViPipe, 0x02c4, 0x01); ++ gc4653_write_register(ViPipe, 0x021d, 0x17); ++ gc4653_write_register(ViPipe, 0x024a, 0x01); ++ gc4653_write_register(ViPipe, 0x02ca, 0x02); ++ gc4653_write_register(ViPipe, 0x0262, 0x10); ++ gc4653_write_register(ViPipe, 0x029a, 0x20); ++ gc4653_write_register(ViPipe, 0x021c, 0x0e); ++ gc4653_write_register(ViPipe, 0x0298, 0x03); ++ gc4653_write_register(ViPipe, 0x029c, 0x00); ++ gc4653_write_register(ViPipe, 0x027e, 0x14); ++ gc4653_write_register(ViPipe, 0x02c2, 0x10); ++ gc4653_write_register(ViPipe, 0x0540, 0x20); ++ gc4653_write_register(ViPipe, 0x0546, 0x01); ++ gc4653_write_register(ViPipe, 0x0548, 0x01); ++ gc4653_write_register(ViPipe, 0x0544, 0x01); ++ gc4653_write_register(ViPipe, 0x0242, 0x1b); ++ gc4653_write_register(ViPipe, 0x02c0, 0x1b); ++ gc4653_write_register(ViPipe, 0x02c3, 0x20); ++ gc4653_write_register(ViPipe, 0x02e4, 0x10); ++ gc4653_write_register(ViPipe, 0x022e, 0x00); ++ gc4653_write_register(ViPipe, 0x027b, 0x3f); ++ gc4653_write_register(ViPipe, 0x0269, 0x0f); ++ gc4653_write_register(ViPipe, 0x02d2, 0x40); ++ gc4653_write_register(ViPipe, 0x027c, 0x08); ++ gc4653_write_register(ViPipe, 0x023a, 0x2e); ++ gc4653_write_register(ViPipe, 0x0245, 0xce); ++ gc4653_write_register(ViPipe, 0x0530, 0x20); ++ gc4653_write_register(ViPipe, 0x0531, 0x02); ++ gc4653_write_register(ViPipe, 0x0228, 0x50); ++ gc4653_write_register(ViPipe, 0x02ab, 0x00); ++ gc4653_write_register(ViPipe, 0x0250, 0x00); ++ gc4653_write_register(ViPipe, 0x0221, 0x50); ++ gc4653_write_register(ViPipe, 0x02ac, 0x00); ++ gc4653_write_register(ViPipe, 0x02a5, 0x02); ++ gc4653_write_register(ViPipe, 0x0260, 0x0b); ++ gc4653_write_register(ViPipe, 0x0216, 0x04); ++ gc4653_write_register(ViPipe, 0x0299, 0x1C); ++ gc4653_write_register(ViPipe, 0x02bb, 0x0d); ++ gc4653_write_register(ViPipe, 0x02a3, 0x02); ++ gc4653_write_register(ViPipe, 0x02a4, 0x02); ++ gc4653_write_register(ViPipe, 0x021e, 0x02); ++ gc4653_write_register(ViPipe, 0x024f, 0x08); ++ gc4653_write_register(ViPipe, 0x028c, 0x08); ++ gc4653_write_register(ViPipe, 0x0532, 0x3f); ++ gc4653_write_register(ViPipe, 0x0533, 0x02); ++ gc4653_write_register(ViPipe, 0x0277, 0xc0); ++ gc4653_write_register(ViPipe, 0x0276, 0xc0); ++ gc4653_write_register(ViPipe, 0x0239, 0xc0); ++ gc4653_write_register(ViPipe, 0x0202, 0x05); ++ gc4653_write_register(ViPipe, 0x0203, 0xd0); ++ gc4653_write_register(ViPipe, 0x0205, 0xc0); ++ gc4653_write_register(ViPipe, 0x02b0, 0x68); ++ gc4653_write_register(ViPipe, 0x0002, 0xa9); ++ gc4653_write_register(ViPipe, 0x0004, 0x01); ++ gc4653_write_register(ViPipe, 0x021a, 0x98); ++ gc4653_write_register(ViPipe, 0x0266, 0xa0); ++ gc4653_write_register(ViPipe, 0x0020, 0x01); ++ gc4653_write_register(ViPipe, 0x0021, 0x03); ++ gc4653_write_register(ViPipe, 0x0022, 0x00); ++ gc4653_write_register(ViPipe, 0x0023, 0x04); ++ ++ gc4653_write_register(ViPipe, 0x0342, 0x06); ++ gc4653_write_register(ViPipe, 0x0343, 0x40); ++ gc4653_write_register(ViPipe, 0x03fe, 0x10); ++ gc4653_write_register(ViPipe, 0x03fe, 0x00); ++ gc4653_write_register(ViPipe, 0x0106, 0x78); ++ gc4653_write_register(ViPipe, 0x0108, 0x0c); ++ gc4653_write_register(ViPipe, 0x0114, 0x01); ++ gc4653_write_register(ViPipe, 0x0115, 0x10); //0x12 coninute mode, 0x10 no-continue mode ++ gc4653_write_register(ViPipe, 0x0180, 0x46); ++ gc4653_write_register(ViPipe, 0x0181, 0x30); ++ gc4653_write_register(ViPipe, 0x0182, 0x05); ++ gc4653_write_register(ViPipe, 0x0185, 0x01); ++ gc4653_write_register(ViPipe, 0x03fe, 0x10); ++ gc4653_write_register(ViPipe, 0x03fe, 0x00); ++ gc4653_write_register(ViPipe, 0x000f, 0x00); ++ gc4653_write_register(ViPipe, 0x0100, 0x09); //stream on ++ //otp ++ gc4653_write_register(ViPipe, 0x0080, 0x02); ++ gc4653_write_register(ViPipe, 0x0097, 0x0a); ++ gc4653_write_register(ViPipe, 0x0098, 0x10); ++ gc4653_write_register(ViPipe, 0x0099, 0x05); ++ gc4653_write_register(ViPipe, 0x009a, 0xb0); ++ gc4653_write_register(ViPipe, 0x0317, 0x08); ++ gc4653_write_register(ViPipe, 0x0a67, 0x80); ++ gc4653_write_register(ViPipe, 0x0a70, 0x03); ++ gc4653_write_register(ViPipe, 0x0a82, 0x00); ++ gc4653_write_register(ViPipe, 0x0a83, 0x10); ++ gc4653_write_register(ViPipe, 0x0a80, 0x2b); ++ gc4653_write_register(ViPipe, 0x05be, 0x00); ++ gc4653_write_register(ViPipe, 0x05a9, 0x01); ++ gc4653_write_register(ViPipe, 0x0313, 0x80); ++ gc4653_write_register(ViPipe, 0x05be, 0x01); ++ gc4653_write_register(ViPipe, 0x0317, 0x00); ++ gc4653_write_register(ViPipe, 0x0a67, 0x00); ++ ++ gc4653_write_register(ViPipe, 0x0000, 0x00); // end flag + + gc4653_default_reg_init(ViPipe); + delay_ms(10); +-- +2.34.1 + diff --git a/configs/licheervnano/patches/sensorsupportlist/0002-20240319.patch b/configs/licheervnano/patches/sensorsupportlist/0002-20240319.patch new file mode 100644 index 0000000..13850a1 --- /dev/null +++ b/configs/licheervnano/patches/sensorsupportlist/0002-20240319.patch @@ -0,0 +1,27 @@ +From a59515687eeeae73ff5b2067c3b5d0e629f33b0b Mon Sep 17 00:00:00 2001 +From: Lu Hui +Date: Tue, 19 Mar 2024 16:54:57 +0800 +Subject: [PATCH 02/12] 20240319 + +--- + sensor/cv182x/gcore_gc4653/gc4653_cmos_param.h | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/sensor/cv182x/gcore_gc4653/gc4653_cmos_param.h b/sensor/cv182x/gcore_gc4653/gc4653_cmos_param.h +index 30c40f4..c4dec7d 100644 +--- a/sensor/cv182x/gcore_gc4653/gc4653_cmos_param.h ++++ b/sensor/cv182x/gcore_gc4653/gc4653_cmos_param.h +@@ -198,7 +198,10 @@ struct combo_dev_attr_s gc4653_rx_attr = { + .mac_clk = RX_MAC_CLK_200M, + .mipi_attr = { + .raw_data_type = RAW_DATA_10BIT, ++ // alpha board + .lane_id = {2, 1, 0, -1, -1}, ++ // beta board ++ //.lane_id = {4, 3, 2, -1, -1}, + .pn_swap = {0, 0, 0, 0, 0}, + .wdr_mode = CVI_MIPI_WDR_MODE_NONE, + }, +-- +2.34.1 + diff --git a/configs/licheervnano/patches/sensorsupportlist/0003-update-for-beta-board.patch b/configs/licheervnano/patches/sensorsupportlist/0003-update-for-beta-board.patch new file mode 100644 index 0000000..c07f1df --- /dev/null +++ b/configs/licheervnano/patches/sensorsupportlist/0003-update-for-beta-board.patch @@ -0,0 +1,28 @@ +From a4cfd56ef791a38e3cbc45b3d0772377ba33b563 Mon Sep 17 00:00:00 2001 +From: Lu +Date: Tue, 26 Mar 2024 09:39:28 +0800 +Subject: [PATCH 03/12] update, for beta board + +--- + sensor/cv182x/gcore_gc4653/gc4653_cmos_param.h | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/sensor/cv182x/gcore_gc4653/gc4653_cmos_param.h b/sensor/cv182x/gcore_gc4653/gc4653_cmos_param.h +index c4dec7d..0dc377c 100644 +--- a/sensor/cv182x/gcore_gc4653/gc4653_cmos_param.h ++++ b/sensor/cv182x/gcore_gc4653/gc4653_cmos_param.h +@@ -199,9 +199,9 @@ struct combo_dev_attr_s gc4653_rx_attr = { + .mipi_attr = { + .raw_data_type = RAW_DATA_10BIT, + // alpha board +- .lane_id = {2, 1, 0, -1, -1}, ++ //.lane_id = {2, 1, 0, -1, -1}, + // beta board +- //.lane_id = {4, 3, 2, -1, -1}, ++ .lane_id = {4, 3, 2, -1, -1}, + .pn_swap = {0, 0, 0, 0, 0}, + .wdr_mode = CVI_MIPI_WDR_MODE_NONE, + }, +-- +2.34.1 + diff --git a/configs/licheervnano/patches/sensorsupportlist/0004-update.patch b/configs/licheervnano/patches/sensorsupportlist/0004-update.patch new file mode 100644 index 0000000..ffe24d2 --- /dev/null +++ b/configs/licheervnano/patches/sensorsupportlist/0004-update.patch @@ -0,0 +1,25 @@ +From 1d37cf3396ee36f7b3d77fddebeb5da7779763bb Mon Sep 17 00:00:00 2001 +From: Lu Hui +Date: Sun, 7 Apr 2024 09:41:20 +0800 +Subject: [PATCH 04/12] update + +--- + sensor/cv182x/ov_os04a10/os04a10_cmos_param.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sensor/cv182x/ov_os04a10/os04a10_cmos_param.h b/sensor/cv182x/ov_os04a10/os04a10_cmos_param.h +index 2f71974..4052a94 100644 +--- a/sensor/cv182x/ov_os04a10/os04a10_cmos_param.h ++++ b/sensor/cv182x/ov_os04a10/os04a10_cmos_param.h +@@ -211,7 +211,7 @@ struct combo_dev_attr_s os04a10_rx_attr = { + .mac_clk = RX_MAC_CLK_400M, + .mipi_attr = { + .raw_data_type = RAW_DATA_12BIT, +- .lane_id = {0, 1, 2, 3, 4}, ++ .lane_id = {2, 1, 3, 0, 4}, + .wdr_mode = CVI_MIPI_WDR_MODE_VC, + .dphy = { + .enable = 1, +-- +2.34.1 + diff --git a/configs/licheervnano/patches/sensorsupportlist/0005-Added-support-for-OA04A10-SC035GS-LT6911-and-the-new.patch b/configs/licheervnano/patches/sensorsupportlist/0005-Added-support-for-OA04A10-SC035GS-LT6911-and-the-new.patch new file mode 100644 index 0000000..43ec312 --- /dev/null +++ b/configs/licheervnano/patches/sensorsupportlist/0005-Added-support-for-OA04A10-SC035GS-LT6911-and-the-new.patch @@ -0,0 +1,228 @@ +From 5615b337f641b8e775aad7b0a47cc9ee0edcdb2a Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?=E6=9F=90=E6=9D=B0=E5=90=8C=E5=AD=A6?= <1220627966@qq.com> +Date: Wed, 15 May 2024 00:00:53 -0700 +Subject: [PATCH 05/12] Added support for OA04A10, SC035GS, LT6911, and the new + 5-inch LCD + +Added support for OA04A10, SC035GS, LT6911, and the new 5-inch display +--- + sensor/cv182x/lontium_lt6911/lt6911_cmos.c | 10 +++--- + .../cv182x/lontium_lt6911/lt6911_cmos_param.h | 8 ++--- + .../cv182x/lontium_lt6911/lt6911_sensor_ctl.c | 34 ++++++++++++++++--- + sensor/cv182x/ov_os04a10/os04a10_sensor_ctl.c | 14 ++++++++ + .../cv182x/sms_sc035gs/sc035gs_cmos_param.h | 8 +++-- + .../cv182x/sms_sc035gs/sc035gs_sensor_ctl.c | 13 +++++++ + 6 files changed, 72 insertions(+), 15 deletions(-) + +diff --git a/sensor/cv182x/lontium_lt6911/lt6911_cmos.c b/sensor/cv182x/lontium_lt6911/lt6911_cmos.c +index c704e30..6020987 100644 +--- a/sensor/cv182x/lontium_lt6911/lt6911_cmos.c ++++ b/sensor/cv182x/lontium_lt6911/lt6911_cmos.c +@@ -26,8 +26,8 @@ + + #define LT6911_ID 6911 + +-#define INPUT_WIDTH (1920) +-#define INPUT_HEIGHT (1080) ++#define INPUT_WIDTH (1920) // 1920 1280 800 ++#define INPUT_HEIGHT (1080) // 1080 720 600 + + /**************************************************************************** + * global variables * +@@ -400,6 +400,7 @@ static CVI_S32 sensor_set_init(VI_PIPE ViPipe, ISP_INIT_ATTR_S *pstInitAttr) + + static CVI_S32 sensor_probe(VI_PIPE ViPipe) + { ++ printf("[sensor_prob = lt6911_probe] \n"); + return lt6911_probe(ViPipe); + } + +@@ -418,5 +419,6 @@ ISP_SNS_OBJ_S stSnsLT6911_Obj = { + .pfnGetRxAttr = sensor_rx_attr, + .pfnExpSensorCb = cmos_init_sensor_exp_function, + .pfnExpAeCb = cmos_init_ae_exp_function, +- .pfnSnsProbe = sensor_probe, +-}; +\ No newline at end of file ++ .pfnSnsProbe = sensor_probe, ++}; ++ +diff --git a/sensor/cv182x/lontium_lt6911/lt6911_cmos_param.h b/sensor/cv182x/lontium_lt6911/lt6911_cmos_param.h +index 81f38a5..064141b 100644 +--- a/sensor/cv182x/lontium_lt6911/lt6911_cmos_param.h ++++ b/sensor/cv182x/lontium_lt6911/lt6911_cmos_param.h +@@ -18,8 +18,8 @@ extern "C" { + #include "lt6911_cmos_ex.h" + + // not real time resolution +-#define WIDTH 3840//3840 1920 +-#define HEIGHT 2160//2160 1080 ++#define WIDTH 1920 // 3840 1920 1280 800 ++#define HEIGHT 1080 // 2160 1080 720 600 + + static LT6911_MODE_S g_astLt6911_mode[LT6911_MODE_NUM] = { + [LT6911_MODE_NORMAL] = { +@@ -48,8 +48,8 @@ struct combo_dev_attr_s lt6911_rx_attr = { + .mac_clk = RX_MAC_CLK_600M, + .mipi_attr = { + .raw_data_type = YUV422_8BIT, +- .lane_id = {2, 0, 1, 3, 4}, //3, 0, 1, 2, 4 ; 1, 4, 3, 2, 0 2, 0, 1, 3, 4 3, 1, 2, 4, 0 +- .pn_swap = {1, 1, 1, 1, 1}, ++ .lane_id = {2, 4, 3, 1, 0}, //3, 0, 1, 2, 4 ; 1, 4, 3, 2, 0 2, 0, 1, 3, 4 3, 1, 2, 4, 0 ++ .pn_swap = {0, 0, 0, 0, 0}, + .wdr_mode = CVI_MIPI_WDR_MODE_NONE, + .dphy = { + .enable = 1, +diff --git a/sensor/cv182x/lontium_lt6911/lt6911_sensor_ctl.c b/sensor/cv182x/lontium_lt6911/lt6911_sensor_ctl.c +index 13bb1fc..f5c2f44 100644 +--- a/sensor/cv182x/lontium_lt6911/lt6911_sensor_ctl.c ++++ b/sensor/cv182x/lontium_lt6911/lt6911_sensor_ctl.c +@@ -16,10 +16,11 @@ + #include "cvi_sns_ctrl.h" + #include "lt6911_cmos_ex.h" + +-#define LT6911_I2C_DEV 3 ++ ++#define LT6911_I2C_DEV 4 + #define LT6911_I2C_BANK_ADDR 0xff + +-CVI_U8 lt6911_i2c_addr = 0x2b; ++CVI_U8 lt6911_i2c_addr = 0x56; + const CVI_U32 lt6911_addr_byte = 1; + const CVI_U32 lt6911_data_byte = 1; + static int g_fd[VI_MAX_PIPE_NUM] = {[0 ... (VI_MAX_PIPE_NUM - 1)] = -1}; +@@ -144,6 +145,7 @@ static int lt6911_i2c_read(VI_PIPE ViPipe, int RegAddr) + uint8_t bank = RegAddr >> 8; + uint8_t addr = RegAddr & 0xff; + ++ printf("[lt6911_i2c_read] : addr = %x \n", addr); + lt6911_write_register(ViPipe, LT6911_I2C_BANK_ADDR, bank); + return lt6911_read_register(ViPipe, addr); + } +@@ -153,6 +155,7 @@ static int lt6911_i2c_write(VI_PIPE ViPipe, int RegAddr, int data) + uint8_t bank = RegAddr >> 8; + uint8_t addr = RegAddr & 0xff; + ++ printf("[lt6911_i2c_write] : addr = %x. data = %x \n", addr, data); + lt6911_write_register(ViPipe, LT6911_I2C_BANK_ADDR, bank); + return lt6911_write_register(ViPipe, addr, data); + } +@@ -184,22 +187,43 @@ int lt6911_probe(VI_PIPE ViPipe) + int nVal; + int nVal2; + ++ // PinMUX ++ printf("########### PinMux #######################################################################\n"); ++ system("devmem 0x0300116C 32 0x3"); ++ system("devmem 0x03001170 32 0x3"); ++ system("devmem 0x03001174 32 0x3"); ++ system("devmem 0x03001178 32 0x3"); ++ system("devmem 0x0300117C 32 0x3"); ++ system("devmem 0x03001180 32 0x3"); ++ system("devmem 0x03001184 32 0x3"); ++ system("devmem 0x03001188 32 0x3"); ++ system("devmem 0x0300118C 32 0x3"); ++ system("devmem 0x03001190 32 0x3"); ++ printf("########### PinMux End #######################################################################\n"); ++ + usleep(50); ++ printf("[lt6911_probe] -189 \n"); + if (lt6911_i2c_init(ViPipe) != CVI_SUCCESS) + return CVI_FAILURE; + ++ printf("[lt6911_probe] -195 \n"); + nVal = lt6911_read(ViPipe, LT6911_CHIP_ID_ADDR_H); + nVal2 = lt6911_read(ViPipe, LT6911_CHIP_ID_ADDR_L); + if (nVal < 0 || nVal2 < 0) { +- CVI_TRACE_SNS(CVI_DBG_ERR, "read sensor id error.\n"); +- return nVal; ++ CVI_TRACE_SNS(CVI_DBG_ERR, "read sensor id error. \n"); ++ printf("[lt6911_probe] jump return nVal -198 \n"); ++ // return nVal; + } ++ ++ printf("[lt6911_probe] -201 \n"); + printf("data:%02x %02x\n", nVal, nVal2); + if ((((nVal & 0xFF) << 8) | (nVal2 & 0xFF)) != LT6911_CHIP_ID) { + CVI_TRACE_SNS(CVI_DBG_ERR, "Sensor ID Mismatch! Use the wrong sensor??\n"); +- return CVI_FAILURE; ++ printf("[lt6911_probe] jump return CVI_FAILURE -206 \n"); ++ // return CVI_FAILURE; + } + ++ printf("[lt6911_probe] -208 = exit success \n"); + return CVI_SUCCESS; + } + +diff --git a/sensor/cv182x/ov_os04a10/os04a10_sensor_ctl.c b/sensor/cv182x/ov_os04a10/os04a10_sensor_ctl.c +index 529cbd8..e8bc150 100644 +--- a/sensor/cv182x/ov_os04a10/os04a10_sensor_ctl.c ++++ b/sensor/cv182x/ov_os04a10/os04a10_sensor_ctl.c +@@ -251,6 +251,20 @@ void os04a10_init(VI_PIPE ViPipe) + enWDRMode = g_pastOs04a10[ViPipe]->enWDRMode; + u8ImgMode = g_pastOs04a10[ViPipe]->u8ImgMode; + ++ // PinMUX ++ printf("########### PinMux #######################################################################\n"); ++ system("devmem 0x0300116C 32 0x3"); ++ system("devmem 0x03001170 32 0x3"); ++ system("devmem 0x03001174 32 0x3"); ++ system("devmem 0x03001178 32 0x3"); ++ system("devmem 0x0300117C 32 0x3"); ++ system("devmem 0x03001180 32 0x3"); ++ system("devmem 0x03001184 32 0x3"); ++ system("devmem 0x03001188 32 0x3"); ++ system("devmem 0x0300118C 32 0x3"); ++ system("devmem 0x03001190 32 0x3"); ++ printf("########### PinMux End #######################################################################\n"); ++ + os04a10_i2c_init(ViPipe); + + if (enWDRMode == WDR_MODE_2To1_LINE) { +diff --git a/sensor/cv182x/sms_sc035gs/sc035gs_cmos_param.h b/sensor/cv182x/sms_sc035gs/sc035gs_cmos_param.h +index c85429c..9a1077f 100644 +--- a/sensor/cv182x/sms_sc035gs/sc035gs_cmos_param.h ++++ b/sensor/cv182x/sms_sc035gs/sc035gs_cmos_param.h +@@ -99,9 +99,13 @@ struct combo_dev_attr_s sc035gs_rx_attr = { + .mac_clk = RX_MAC_CLK_200M, + .mipi_attr = { + .raw_data_type = RAW_DATA_12BIT, +- .lane_id = {2, 0, 1, -1, -1}, ++ .lane_id = {4, 3, 2, -1, -1}, ++ .pn_swap = {0, 0, 0, 0, 0}, + .wdr_mode = CVI_MIPI_WDR_MODE_NONE, +- .pn_swap = {1, 1, 1, 0, 0}, ++ .dphy = { ++ .enable = 1, ++ .hs_settle = 8, ++ }, + }, + .mclk = { + .cam = 0, +diff --git a/sensor/cv182x/sms_sc035gs/sc035gs_sensor_ctl.c b/sensor/cv182x/sms_sc035gs/sc035gs_sensor_ctl.c +index 97ba708..5f897ef 100644 +--- a/sensor/cv182x/sms_sc035gs/sc035gs_sensor_ctl.c ++++ b/sensor/cv182x/sms_sc035gs/sc035gs_sensor_ctl.c +@@ -207,6 +207,19 @@ void sc035gs_exit(VI_PIPE ViPipe) + /* 1296P30 and 1296P25 */ + static void sc035gs_linear_1296P30_init(VI_PIPE ViPipe) + { ++ printf("########### PinMux #######################################################################\n"); ++ system("devmem 0x0300116C 32 0x3"); ++ system("devmem 0x03001170 32 0x3"); ++ system("devmem 0x03001174 32 0x3"); ++ system("devmem 0x03001178 32 0x3"); ++ system("devmem 0x0300117C 32 0x3"); ++ system("devmem 0x03001180 32 0x3"); ++ system("devmem 0x03001184 32 0x3"); ++ system("devmem 0x03001188 32 0x3"); ++ system("devmem 0x0300118C 32 0x5"); ++ system("devmem 0x03001190 32 0x3"); ++ printf("########### PinMux End #######################################################################\n"); ++ + sc035gs_write_register(ViPipe, 0x0103, 0x01); + delay_ms(33); + sc035gs_write_register(ViPipe, 0x0100, 0x00); +-- +2.34.1 + diff --git a/configs/licheervnano/patches/sensorsupportlist/0006-Boost-the-SC035-FPS.patch b/configs/licheervnano/patches/sensorsupportlist/0006-Boost-the-SC035-FPS.patch new file mode 100644 index 0000000..6be9162 --- /dev/null +++ b/configs/licheervnano/patches/sensorsupportlist/0006-Boost-the-SC035-FPS.patch @@ -0,0 +1,271 @@ +From 09ed2d682d26b52ca20fc3dad79f22da49be166d Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?=E6=9F=90=E6=9D=B0=E5=90=8C=E5=AD=A6?= <1220627966@qq.com> +Date: Mon, 5 Aug 2024 20:45:14 -0700 +Subject: [PATCH 06/12] Boost the SC035 FPS + +30 - 60fps +--- + .../cv182x/sms_sc035gs/sc035gs_cmos_param.h | 9 +- + .../cv182x/sms_sc035gs/sc035gs_sensor_ctl.c | 209 ++++++++++-------- + 2 files changed, 122 insertions(+), 96 deletions(-) + +diff --git a/sensor/cv182x/sms_sc035gs/sc035gs_cmos_param.h b/sensor/cv182x/sms_sc035gs/sc035gs_cmos_param.h +index 9a1077f..9afac3a 100644 +--- a/sensor/cv182x/sms_sc035gs/sc035gs_cmos_param.h ++++ b/sensor/cv182x/sms_sc035gs/sc035gs_cmos_param.h +@@ -38,8 +38,8 @@ static const SC035GS_MODE_S g_astSC035GS_mode[SC035GS_MODE_NUM] = { + }, + .f32MaxFps = 120, + .f32MinFps = 1.25, /* 515 * 120 / 0xFFFF */ +- .u32HtsDef = 878, +- .u32VtsDef = 683, ++ .u32HtsDef = 1136, // 0x320c/d 036b=878 0470=1136 ++ .u32VtsDef = 528, // 0x320e/f 02ab=683 0210=528 + .stExp[0] = { + .u16Min = 1, + .u16Max = 677 << 4,// (vts - 6) * 16 +@@ -96,9 +96,9 @@ static ISP_CMOS_BLACK_LEVEL_S g_stIspBlcCalibratio = { + + struct combo_dev_attr_s sc035gs_rx_attr = { + .input_mode = INPUT_MODE_MIPI, +- .mac_clk = RX_MAC_CLK_200M, ++ .mac_clk = RX_MAC_CLK_600M, + .mipi_attr = { +- .raw_data_type = RAW_DATA_12BIT, ++ .raw_data_type = RAW_DATA_10BIT, + .lane_id = {4, 3, 2, -1, -1}, + .pn_swap = {0, 0, 0, 0, 0}, + .wdr_mode = CVI_MIPI_WDR_MODE_NONE, +@@ -109,6 +109,7 @@ struct combo_dev_attr_s sc035gs_rx_attr = { + }, + .mclk = { + .cam = 0, ++ // .freq = CAMPLL_FREQ_37P125M, + .freq = CAMPLL_FREQ_24M, + }, + .devno = 0, +diff --git a/sensor/cv182x/sms_sc035gs/sc035gs_sensor_ctl.c b/sensor/cv182x/sms_sc035gs/sc035gs_sensor_ctl.c +index 5f897ef..f948076 100644 +--- a/sensor/cv182x/sms_sc035gs/sc035gs_sensor_ctl.c ++++ b/sensor/cv182x/sms_sc035gs/sc035gs_sensor_ctl.c +@@ -220,100 +220,125 @@ static void sc035gs_linear_1296P30_init(VI_PIPE ViPipe) + system("devmem 0x03001190 32 0x3"); + printf("########### PinMux End #######################################################################\n"); + +- sc035gs_write_register(ViPipe, 0x0103, 0x01); ++ //============================================================================================================================================= ++ // MTK6739 - 60FPS ++ sc035gs_write_register(ViPipe, 0x0103, 0x01); + delay_ms(33); +- sc035gs_write_register(ViPipe, 0x0100, 0x00); +- sc035gs_write_register(ViPipe, 0x36e9, 0x80); +- sc035gs_write_register(ViPipe, 0x36f9, 0x80); +- sc035gs_write_register(ViPipe, 0x3000, 0x00); +- sc035gs_write_register(ViPipe, 0x3001, 0x00); +- sc035gs_write_register(ViPipe, 0x300f, 0x0f); +- sc035gs_write_register(ViPipe, 0x3018, 0x33); +- sc035gs_write_register(ViPipe, 0x3019, 0x0c); +- sc035gs_write_register(ViPipe, 0x301c, 0x78); +- sc035gs_write_register(ViPipe, 0x3031, 0x0a); +- sc035gs_write_register(ViPipe, 0x3037, 0x20); +- sc035gs_write_register(ViPipe, 0x303f, 0x01); +- sc035gs_write_register(ViPipe, 0x320c, 0x03); +- sc035gs_write_register(ViPipe, 0x320d, 0x6e); +- sc035gs_write_register(ViPipe, 0x320e, 0x02); +- sc035gs_write_register(ViPipe, 0x320f, 0xab); +- sc035gs_write_register(ViPipe, 0x3252, 0x02); // 0x1 +- sc035gs_write_register(ViPipe, 0x3253, 0x08); // 0xf8 +- //sc035gs_write_register(ViPipe, 0x3252, 0x02); +- //sc035gs_write_register(ViPipe, 0x3253, 0xa6); +- sc035gs_write_register(ViPipe, 0x3220, 0x10); +- sc035gs_write_register(ViPipe, 0x3250, 0xc0); +- sc035gs_write_register(ViPipe, 0x3251, 0x02); +- sc035gs_write_register(ViPipe, 0x3254, 0x02); +- sc035gs_write_register(ViPipe, 0x3255, 0x07); +- sc035gs_write_register(ViPipe, 0x3304, 0x48); +- sc035gs_write_register(ViPipe, 0x3306, 0x38); +- sc035gs_write_register(ViPipe, 0x3309, 0x68); +- sc035gs_write_register(ViPipe, 0x330b, 0xe0); +- sc035gs_write_register(ViPipe, 0x330c, 0x18); +- sc035gs_write_register(ViPipe, 0x330f, 0x20); +- sc035gs_write_register(ViPipe, 0x3310, 0x10); +- sc035gs_write_register(ViPipe, 0x3314, 0x1e); +- sc035gs_write_register(ViPipe, 0x3315, 0x38); +- sc035gs_write_register(ViPipe, 0x3316, 0x40); +- sc035gs_write_register(ViPipe, 0x3317, 0x10); +- sc035gs_write_register(ViPipe, 0x3329, 0x34); +- sc035gs_write_register(ViPipe, 0x332d, 0x34); +- sc035gs_write_register(ViPipe, 0x332f, 0x38); +- sc035gs_write_register(ViPipe, 0x3335, 0x3c); +- sc035gs_write_register(ViPipe, 0x3344, 0x3c); +- sc035gs_write_register(ViPipe, 0x335b, 0x80); +- sc035gs_write_register(ViPipe, 0x335f, 0x80); +- sc035gs_write_register(ViPipe, 0x3366, 0x06); +- sc035gs_write_register(ViPipe, 0x3385, 0x31); +- sc035gs_write_register(ViPipe, 0x3387, 0x51); +- sc035gs_write_register(ViPipe, 0x3389, 0x01); +- sc035gs_write_register(ViPipe, 0x33b1, 0x03); +- sc035gs_write_register(ViPipe, 0x33b2, 0x06); +- sc035gs_write_register(ViPipe, 0x3621, 0xa4); +- sc035gs_write_register(ViPipe, 0x3622, 0x05); +- sc035gs_write_register(ViPipe, 0x3624, 0x47); +- sc035gs_write_register(ViPipe, 0x3630, 0x46); +- sc035gs_write_register(ViPipe, 0x3631, 0x48); +- sc035gs_write_register(ViPipe, 0x3633, 0x52); +- sc035gs_write_register(ViPipe, 0x3635, 0x18); +- sc035gs_write_register(ViPipe, 0x3636, 0x25); +- sc035gs_write_register(ViPipe, 0x3637, 0x89); +- sc035gs_write_register(ViPipe, 0x3638, 0x0f); +- sc035gs_write_register(ViPipe, 0x3639, 0x08); +- sc035gs_write_register(ViPipe, 0x363a, 0x00); +- sc035gs_write_register(ViPipe, 0x363b, 0x48); +- sc035gs_write_register(ViPipe, 0x363c, 0x06); ++ sc035gs_write_register(ViPipe, 0x0100, 0x00); ++ sc035gs_write_register(ViPipe, 0x3000, 0x00); ++ sc035gs_write_register(ViPipe, 0x3001, 0x00); ++ sc035gs_write_register(ViPipe, 0x300f, 0x0f); ++ sc035gs_write_register(ViPipe, 0x3018, 0x33); ++ sc035gs_write_register(ViPipe, 0x3019, 0xfc); ++ sc035gs_write_register(ViPipe, 0x301c, 0x78); ++ sc035gs_write_register(ViPipe, 0x301f, 0xa2); ++ sc035gs_write_register(ViPipe, 0x3031, 0x0a); ++ sc035gs_write_register(ViPipe, 0x3037, 0x20); ++ sc035gs_write_register(ViPipe, 0x303f, 0x01); ++ ++ // MTK6739 - 60FPS ++ sc035gs_write_register(ViPipe, 0x320c, 0x03); // 852 ++ sc035gs_write_register(ViPipe, 0x320d, 0x54); ++ sc035gs_write_register(ViPipe, 0x320e, 0x02); // 2112 ++ sc035gs_write_register(ViPipe, 0x320f, 0x0e); ++ sc035gs_write_register(ViPipe, 0x3252, 0x02); ++ sc035gs_write_register(ViPipe, 0x3253, 0x08); ++ sc035gs_write_register(ViPipe, 0x3217, 0x00); ++ sc035gs_write_register(ViPipe, 0x3218, 0x00); ++ sc035gs_write_register(ViPipe, 0x3220, 0x10); ++ sc035gs_write_register(ViPipe, 0x3223, 0x48); ++ sc035gs_write_register(ViPipe, 0x3226, 0x74); ++ sc035gs_write_register(ViPipe, 0x3227, 0x07); ++ sc035gs_write_register(ViPipe, 0x323b, 0x00); ++ sc035gs_write_register(ViPipe, 0x3250, 0xf0); ++ sc035gs_write_register(ViPipe, 0x3251, 0x02); ++ sc035gs_write_register(ViPipe, 0x3254, 0x02); ++ sc035gs_write_register(ViPipe, 0x3255, 0x07); ++ sc035gs_write_register(ViPipe, 0x3304, 0x48); ++ sc035gs_write_register(ViPipe, 0x3305, 0x00); ++ sc035gs_write_register(ViPipe, 0x3306, 0x60); ++ sc035gs_write_register(ViPipe, 0x3309, 0x50); ++ sc035gs_write_register(ViPipe, 0x330a, 0x00); ++ sc035gs_write_register(ViPipe, 0x330b, 0xc0); ++ sc035gs_write_register(ViPipe, 0x330c, 0x18); ++ sc035gs_write_register(ViPipe, 0x330f, 0x40); ++ sc035gs_write_register(ViPipe, 0x3310, 0x10); ++ sc035gs_write_register(ViPipe, 0x3314, 0x1e); ++ sc035gs_write_register(ViPipe, 0x3315, 0x30); ++ sc035gs_write_register(ViPipe, 0x3316, 0x68); ++ sc035gs_write_register(ViPipe, 0x3317, 0x1b); ++ sc035gs_write_register(ViPipe, 0x3329, 0x5c); ++ sc035gs_write_register(ViPipe, 0x332d, 0x5c); ++ sc035gs_write_register(ViPipe, 0x332f, 0x60); ++ sc035gs_write_register(ViPipe, 0x3335, 0x64); ++ sc035gs_write_register(ViPipe, 0x3344, 0x64); ++ sc035gs_write_register(ViPipe, 0x335b, 0x80); ++ sc035gs_write_register(ViPipe, 0x335f, 0x80); ++ sc035gs_write_register(ViPipe, 0x3366, 0x06); ++ sc035gs_write_register(ViPipe, 0x3385, 0x31); ++ sc035gs_write_register(ViPipe, 0x3387, 0x39); ++ sc035gs_write_register(ViPipe, 0x3389, 0x01); ++ sc035gs_write_register(ViPipe, 0x33b1, 0x03); ++ sc035gs_write_register(ViPipe, 0x33b2, 0x06); ++ sc035gs_write_register(ViPipe, 0x33bd, 0xe0); ++ sc035gs_write_register(ViPipe, 0x33bf, 0x10); ++ sc035gs_write_register(ViPipe, 0x3621, 0xa4); ++ sc035gs_write_register(ViPipe, 0x3622, 0x05); ++ sc035gs_write_register(ViPipe, 0x3624, 0x47); ++ sc035gs_write_register(ViPipe, 0x3630, 0x4a); ++ sc035gs_write_register(ViPipe, 0x3631, 0x58); ++ sc035gs_write_register(ViPipe, 0x3633, 0x52); ++ sc035gs_write_register(ViPipe, 0x3635, 0x03); ++ sc035gs_write_register(ViPipe, 0x3636, 0x25); ++ sc035gs_write_register(ViPipe, 0x3637, 0x8a); ++ sc035gs_write_register(ViPipe, 0x3638, 0x0f); ++ sc035gs_write_register(ViPipe, 0x3639, 0x08); ++ sc035gs_write_register(ViPipe, 0x363a, 0x00); ++ sc035gs_write_register(ViPipe, 0x363b, 0x48); ++ sc035gs_write_register(ViPipe, 0x363c, 0x86); + sc035gs_write_register(ViPipe, 0x363d, 0x00); +- sc035gs_write_register(ViPipe, 0x363e, 0xf8); +- sc035gs_write_register(ViPipe, 0x3640, 0x00); +- sc035gs_write_register(ViPipe, 0x3641, 0x01); +- sc035gs_write_register(ViPipe, 0x36ea, 0x3b); +- sc035gs_write_register(ViPipe, 0x36eb, 0x0e); +- sc035gs_write_register(ViPipe, 0x36ec, 0x1e); +- sc035gs_write_register(ViPipe, 0x36ed, 0x33); +- sc035gs_write_register(ViPipe, 0x36fa, 0x3a); +- sc035gs_write_register(ViPipe, 0x36fc, 0x01); +- sc035gs_write_register(ViPipe, 0x3908, 0x91); +- sc035gs_write_register(ViPipe, 0x3d08, 0x01); +- sc035gs_write_register(ViPipe, 0x3e01, 0x14); +- sc035gs_write_register(ViPipe, 0x3e02, 0x80); +- sc035gs_write_register(ViPipe, 0x3e06, 0x0c); +- sc035gs_write_register(ViPipe, 0x4500, 0x59); +- sc035gs_write_register(ViPipe, 0x4501, 0xc4); +- sc035gs_write_register(ViPipe, 0x4603, 0x00); +- sc035gs_write_register(ViPipe, 0x4809, 0x01); +- sc035gs_write_register(ViPipe, 0x4837, 0x37); +- sc035gs_write_register(ViPipe, 0x5011, 0x00); +- sc035gs_write_register(ViPipe, 0x36e9, 0x00); +- sc035gs_write_register(ViPipe, 0x36f9, 0x00); +- sc035gs_default_reg_init(ViPipe); +- sc035gs_write_register(ViPipe, 0x0100, 0x01); +- delay_ms(18); +- sc035gs_write_register(ViPipe, 0x4418, 0x08); +- sc035gs_write_register(ViPipe, 0x4419, 0x8e); +- delay_ms(100); ++ sc035gs_write_register(ViPipe, 0x363e, 0xf8); ++ sc035gs_write_register(ViPipe, 0x3640, 0x00); ++ sc035gs_write_register(ViPipe, 0x3641, 0x01); ++ sc035gs_write_register(ViPipe, 0x36e9, 0x80); ++ sc035gs_write_register(ViPipe, 0x36ea, 0x37); ++ sc035gs_write_register(ViPipe, 0x36eb, 0x0e); ++ sc035gs_write_register(ViPipe, 0x36ec, 0x1e); ++ sc035gs_write_register(ViPipe, 0x36ed, 0x23); ++ sc035gs_write_register(ViPipe, 0x36f9, 0x80); ++ sc035gs_write_register(ViPipe, 0x36fa, 0x37); ++ sc035gs_write_register(ViPipe, 0x36fb, 0x00); ++ sc035gs_write_register(ViPipe, 0x36fc, 0x02); ++ sc035gs_write_register(ViPipe, 0x36fd, 0x03); ++ sc035gs_write_register(ViPipe, 0x3908, 0x91); ++ sc035gs_write_register(ViPipe, 0x391b, 0x81); ++ sc035gs_write_register(ViPipe, 0x3d08, 0x01); ++ sc035gs_write_register(ViPipe, 0x3e01, 0x83); ++ sc035gs_write_register(ViPipe, 0x3e02, 0x80); ++ sc035gs_write_register(ViPipe, 0x3e03, 0x2b); ++ sc035gs_write_register(ViPipe, 0x3e06, 0x0c); ++ sc035gs_write_register(ViPipe, 0x3f04, 0x03); ++ sc035gs_write_register(ViPipe, 0x3f05, 0x34); ++ sc035gs_write_register(ViPipe, 0x4500, 0x59); ++ sc035gs_write_register(ViPipe, 0x4501, 0xc4); ++ sc035gs_write_register(ViPipe, 0x4603, 0x00); ++ sc035gs_write_register(ViPipe, 0x4800, 0x64); ++ sc035gs_write_register(ViPipe, 0x4809, 0x01); ++ sc035gs_write_register(ViPipe, 0x4810, 0x00); ++ sc035gs_write_register(ViPipe, 0x4811, 0x01); ++ sc035gs_write_register(ViPipe, 0x4837, 0x26); ++ sc035gs_write_register(ViPipe, 0x5011, 0x00); ++ sc035gs_write_register(ViPipe, 0x5988, 0x02); ++ sc035gs_write_register(ViPipe, 0x598e, 0x03); ++ sc035gs_write_register(ViPipe, 0x598f, 0x01); ++ sc035gs_write_register(ViPipe, 0x36e9, 0x24); ++ sc035gs_write_register(ViPipe, 0x36f9, 0x20); ++ sc035gs_write_register(ViPipe, 0x0100, 0x01); ++ delay_ms(20); ++ sc035gs_write_register(ViPipe, 0x4418, 0x0a); ++ sc035gs_write_register(ViPipe, 0x363d, 0x10); ++ sc035gs_write_register(ViPipe, 0x4419, 0x80); ++ + + printf("ViPipe:%d,===SC035GS 480P 120fps 12bit LINE Init OK!===\n", ViPipe); + } +-- +2.34.1 + diff --git a/configs/licheervnano/patches/sensorsupportlist/0007-lt6911-os04a10-sc035gs-include-stdlib.h.patch b/configs/licheervnano/patches/sensorsupportlist/0007-lt6911-os04a10-sc035gs-include-stdlib.h.patch new file mode 100644 index 0000000..ce5913d --- /dev/null +++ b/configs/licheervnano/patches/sensorsupportlist/0007-lt6911-os04a10-sc035gs-include-stdlib.h.patch @@ -0,0 +1,50 @@ +From 84315e0011de40c06f82a789fca97864c0bd1ac3 Mon Sep 17 00:00:00 2001 +From: scpcom +Date: Sat, 8 Mar 2025 07:55:18 +0100 +Subject: [PATCH] lt6911/os04a10/sc035gs: include stdlib.h + +--- + sensor/cv182x/lontium_lt6911/lt6911_sensor_ctl.c | 1 + + sensor/cv182x/ov_os04a10/os04a10_sensor_ctl.c | 1 + + sensor/cv182x/sms_sc035gs/sc035gs_sensor_ctl.c | 1 + + 3 files changed, 3 insertions(+) + +diff --git a/sensor/cv182x/lontium_lt6911/lt6911_sensor_ctl.c b/sensor/cv182x/lontium_lt6911/lt6911_sensor_ctl.c +index f5c2f44..13387e3 100644 +--- a/sensor/cv182x/lontium_lt6911/lt6911_sensor_ctl.c ++++ b/sensor/cv182x/lontium_lt6911/lt6911_sensor_ctl.c +@@ -4,6 +4,7 @@ + #include + #include + #include ++#include + #include + #include + #include +diff --git a/sensor/cv182x/ov_os04a10/os04a10_sensor_ctl.c b/sensor/cv182x/ov_os04a10/os04a10_sensor_ctl.c +index e8bc150..ceda1ee 100644 +--- a/sensor/cv182x/ov_os04a10/os04a10_sensor_ctl.c ++++ b/sensor/cv182x/ov_os04a10/os04a10_sensor_ctl.c +@@ -4,6 +4,7 @@ + #include + #include + #include ++#include + #include + #include + #include +diff --git a/sensor/cv182x/sms_sc035gs/sc035gs_sensor_ctl.c b/sensor/cv182x/sms_sc035gs/sc035gs_sensor_ctl.c +index f948076..46b19eb 100644 +--- a/sensor/cv182x/sms_sc035gs/sc035gs_sensor_ctl.c ++++ b/sensor/cv182x/sms_sc035gs/sc035gs_sensor_ctl.c +@@ -4,6 +4,7 @@ + #include + #include + #include ++#include + #include + #include + #include +-- +2.34.1 + diff --git a/configs/licheervnano/settings.mk b/configs/licheervnano/settings.mk index 9e5bb3d..eace9a4 100644 --- a/configs/licheervnano/settings.mk +++ b/configs/licheervnano/settings.mk @@ -1,5 +1,5 @@ -CHIP=sg200x -UBOOT_CHIP=sg2002 +CHIP=cv181x +UBOOT_CHIP=cv181x UBOOT_BOARD=licheervnano_sd BOOT_CPU=riscv ARCH=riscv @@ -9,4 +9,5 @@ STORAGE_TYPE=sd PACKAGES += " wireless-regdb wpasupplicant cvi-pinmux-cv181x" +IMAGE_ADDITIONS += "load-systemko" IMAGE_ADDITIONS += "aic8800-firmware" \ No newline at end of file diff --git a/configs/licheervnano/u-boot/defconfig b/configs/licheervnano/u-boot/defconfig index a480236..797b15f 100644 --- a/configs/licheervnano/u-boot/defconfig +++ b/configs/licheervnano/u-boot/defconfig @@ -79,4 +79,5 @@ CONFIG_CVI_SOUND_DRIVERS=y CONFIG_SPI=y CONFIG_LZ4=y CONFIG_LZMA=y +CONFIG_TARGET_CVITEK_CV181X=y # CONFIG_TOOLS_LIBCRYPTO is not set diff --git a/configs/settings.mk b/configs/settings.mk index 58ce76d..5fd0abb 100644 --- a/configs/settings.mk +++ b/configs/settings.mk @@ -1,5 +1,8 @@ -KERNELREV="2" -FSBLVERSION=1.0.0 -PACKAGES="ca-certificates debian-archive-keyring dosfstools binutils file tree sudo bash-completion u-boot-menu openssh-server network-manager dnsmasq-base libpam-systemd ppp libengine-pkcs11-openssl iptables systemd-timesyncd vim usbutils parted exfatprogs systemd-sysv i2c-tools net-tools ethtool avahi-utils sudo gnupg rsync gpiod u-boot-tools libubootenv-tool" +KERNELREV="4" +FSBLVERSION=1.1.0 +OSDRVVERSION=2024.10.14 +MIDDLEWAREVERSION=2024.10.14 +PACKAGES="busybox-static ca-certificates debian-archive-keyring dosfstools binutils file tree sudo bash-completion u-boot-menu openssh-server network-manager dnsmasq-base libpam-systemd ppp libengine-pkcs11-openssl iptables systemd-timesyncd vim usbutils parted exfatprogs systemd-sysv i2c-tools net-tools ethtool avahi-utils sudo gnupg rsync gpiod u-boot-tools libubootenv-tool" -IMAGE_ADDITIONS="usb-gadget" \ No newline at end of file +IMAGE_ADDITIONS="usb-gadget" +IMAGE_ADDITIONS+="sensor-config" \ No newline at end of file diff --git a/scripts/Dockerfile b/scripts/Dockerfile index 35d0404..d3bbbad 100644 --- a/scripts/Dockerfile +++ b/scripts/Dockerfile @@ -14,7 +14,8 @@ RUN apt-get update \ git gperf kmod libexpat-dev \ libgmp-dev libmpc-dev libmpfr-dev libssl-dev \ libtool mmdebstrap openssl parted \ - patchutils python3 python3-dev python3-distutils \ + patchutils python3 python3-dev \ + python-is-python3 python3-jinja2 pkg-config xxd \ python3-setuptools swig gnupg \ systemd-container texinfo zlib1g-dev wget arch-test \ linux-image-generic genimage joe mc zip \ diff --git a/scripts/Makefile b/scripts/Makefile index 37e02c4..640fff6 100644 --- a/scripts/Makefile +++ b/scripts/Makefile @@ -9,6 +9,41 @@ reset:=$(shell tput sgr0) BUILDDIR := /build/ +DEB_ARCH = riscv64 + +GIT_CLONE_OPTS = --shallow-since=2020-03-12 + +OSDRV_ENV = CHIP_ARCH=CV181X \ +CVIARCH=CV181X \ +SDK_VER=musl_riscv64 \ +CROSS_COMPILE_MUSL_RISCV64=/host-tools/gcc/riscv64-linux-musl-x86_64/bin/riscv64-unknown-linux-musl- \ +CONFIG_ARCH=riscv \ +CONFIG_CROSS_COMPILE_KERNEL="/host-tools/gcc/riscv64-linux-musl-x86_64/bin/riscv64-unknown-linux-musl-" \ +CONFIG_CP_EXT_WIRELESS=y + +SENSOR_ENV = CONFIG_SENSOR_GCORE_GC2083=y \ +CONFIG_SENSOR_GCORE_GC4653=y \ +CONFIG_SENSOR_OV_OS04A10=y \ +CONFIG_SENSOR_OV_OV2685=y \ +CONFIG_SENSOR_OV_OV5647=y \ +CONFIG_SENSOR_SMS_SC035GS=y \ +CONFIG_SENSOR_LONTIUM_LT6911=y + +MIDDLEWARE_ENV = $(OSDRV_ENV) $(SENSOR_ENV) + +KO_DIRS = drivers/i2c \ +drivers/input/touchscreen \ +drivers/media/usb/gspca \ +drivers/net/usb \ +drivers/net/wireless \ +drivers/pwm \ +drivers/rtc \ +drivers/spi \ +drivers/video/backlight \ +fs/efivarfs \ +net/ipv4 \ +net/wireless + ifndef BOARD $(error $(red)BOARD is not set$(reset)) endif @@ -35,11 +70,24 @@ $(info $(blue)Packages: $(_PACKAGES)$(reset)) NPROCS := $(shell nproc) +define copy_header_action + @cp -r $(BUILDDIR)/osdrv/interdrv/include/chip/cv181x/uapi/linux/* ${1}/linux/ + @cp -r $(BUILDDIR)/osdrv/interdrv/include/common/uapi/linux/* ${1}/linux/ + @cp $(BUILDDIR)/kernel/drivers/staging/android/uapi/ion.h ${1}/linux/ + @cp $(BUILDDIR)/kernel/drivers/staging/android/uapi/ion_cvitek.h ${1}/linux/ + @cp $(BUILDDIR)/kernel/include/uapi/linux/dma-buf.h ${1}/linux/ +endef + +define copy_ko_action + @mkdir -p $(BUILDDIR)/osdrv/ko + $(foreach kodir, $(KO_DIRS), find ${1}/lib/modules/*/kernel/$(kodir) -name '*.ko' -exec cp -f {} $(BUILDDIR)/osdrv/ko/ \; ;) +endef + $(BUILDDIR)/linux-prepare-checkout-stamp: @echo "$(COLOUR_GREEN)Checking out Kernel for $(BOARD)$(END_COLOUR)" @mkdir -p $(BUILDDIR) - @git clone -b sg200x-dev --depth 7 https://github.com/sophgo/linux_5.10.git /build/kernel - @cd $(BUILDDIR)/kernel && git checkout 8b8fbf8 + @git clone -b sg200x-dev $(GIT_CLONE_OPTS) https://github.com/sophgo/linux_5.10.git /build/kernel + @cd $(BUILDDIR)/kernel && git checkout e6ead53 @touch $@ $(BUILDDIR)/linux-prepare-patch-stamp: $(BUILDDIR)/linux-prepare-checkout-stamp @@ -65,6 +113,7 @@ $(BUILDDIR)/linux-compile-stamp: $(BUILDDIR)/linux-prepare-configure-stamp @sed -i 's/packagename=linux-image.*/packagename=linux-image-$(BOARD)/' $(BUILDDIR)/kernel/scripts/package/mkdebian @sed -i 's/packagename=linux-image-$$version/packagename=linux-image-$(BOARD)-$$version/' $(BUILDDIR)/kernel/scripts/package/builddeb @cd $(BUILDDIR)/kernel && KCFLAGS=-Wno-attribute-alias ARCH=riscv CROSS_COMPILE="/host-tools/gcc/riscv64-linux-musl-x86_64/bin/riscv64-unknown-linux-musl-" KDEB_SOURCENAME=linux-$(BOARD) $(MAKE) -j$(NPROCS) O=$(BUILDDIR)/kernel/ bindeb-pkg + @cd $(BUILDDIR)/kernel && KCFLAGS=-Wno-attribute-alias ARCH=riscv CROSS_COMPILE="/host-tools/gcc/riscv64-linux-musl-x86_64/bin/riscv64-unknown-linux-musl-" KDEB_SOURCENAME=linux-$(BOARD) $(MAKE) -j$(NPROCS) O=$(BUILDDIR)/kernel/ modules_install INSTALL_MOD_PATH=$(BUILDDIR)/kernel/modules headers_install INSTALL_HDR_PATH=$(BUILDDIR)/kernel/riscv/usr @cp $(BUILDDIR)/*.deb /output/ @touch $@ @@ -76,10 +125,147 @@ linux-clean: @rm -f $(BUILDDIR)/linux-*.deb +$(BUILDDIR)/osdrv-prepare-checkout-stamp: + @echo "$(COLOUR_GREEN)Checking out OSdrv for $(BOARD)$(END_COLOUR)" + @mkdir -p $(BUILDDIR) + @git clone -b sg200x-dev $(GIT_CLONE_OPTS) https://github.com/sophgo/osdrv.git /build/osdrv + @cd $(BUILDDIR)/osdrv && git checkout 28215f2 + @touch $@ + +$(BUILDDIR)/osdrv-prepare-patch-stamp: $(BUILDDIR)/osdrv-prepare-checkout-stamp $(BUILDDIR)/linux-compile-stamp + @echo "$(COLOUR_GREEN)Patching OSdrv for $(BOARD)$(END_COLOUR)" + $(call copy_ko_action, $(BUILDDIR)/kernel/modules) + @$(foreach file, $(wildcard /configs/common/patches/osdrv/*.patch), cd $(BUILDDIR)/osdrv && git apply --ignore-whitespace $(file);) + @$(foreach file, $(wildcard /configs/$(BOARD)/patches/osdrv/*.patch), cd $(BUILDDIR)/osdrv && git apply --ignore-whitespace $(file);) + @touch $@ + +$(BUILDDIR)/osdrv-prepare-configure-stamp: $(BUILDDIR)/osdrv-prepare-patch-stamp + @echo "$(COLOUR_GREEN)Configuring OSdrv for $(BOARD)$(END_COLOUR)" + @touch $@ + +$(BUILDDIR)/osdrv-compile-stamp: $(BUILDDIR)/osdrv-prepare-configure-stamp + @echo "$(COLOUR_GREEN)Building OSdrv for $(BOARD)$(END_COLOUR)" + @cd $(BUILDDIR)/osdrv && $(OSDRV_ENV) $(MAKE) KERNEL_DIR=$(BUILDDIR)/kernel INSTALL_DIR=$(BUILDDIR)/osdrv/ko all + @touch $@ + +$(BUILDDIR)/osdrv-package-stamp: $(BUILDDIR)/osdrv-compile-stamp + @echo "$(COLOUR_GREEN)Packaging OSdrv for $(BOARD)$(END_COLOUR)" + @$(eval KERNELRELEASE=$(shell basename $(BUILDDIR)/kernel/debian/linux-headers/usr/share/doc/linux-headers-* | cut -d '-' -f 3-)) + @mkdir -p $(BUILDDIR)/package/cvitek-osdrv-$(BOARD)-$(KERNELRELEASE) + @cp -r /builder/deb/cvitek-osdrv/* $(BUILDDIR)/package/cvitek-osdrv-$(BOARD)-$(KERNELRELEASE)/ + @mkdir -pv $(BUILDDIR)/package/cvitek-osdrv-$(BOARD)-$(KERNELRELEASE)/mnt/system/ko/$(KERNELRELEASE)/ + @cp -p $(BUILDDIR)/osdrv/ko/*.ko $(BUILDDIR)/package/cvitek-osdrv-$(BOARD)-$(KERNELRELEASE)/mnt/system/ko/$(KERNELRELEASE)/ + @rm -f $(BUILDDIR)/package/cvitek-osdrv-$(BOARD)-$(KERNELRELEASE)/mnt/system/ko/$(KERNELRELEASE)/$(CHIP)_clock_cooling.ko + @rm -f $(BUILDDIR)/package/cvitek-osdrv-$(BOARD)-$(KERNELRELEASE)/mnt/system/ko/$(KERNELRELEASE)/$(CHIP)_pwm.ko + @rm -f $(BUILDDIR)/package/cvitek-osdrv-$(BOARD)-$(KERNELRELEASE)/mnt/system/ko/$(KERNELRELEASE)/$(CHIP)_rtc.ko + @rm -f $(BUILDDIR)/package/cvitek-osdrv-$(BOARD)-$(KERNELRELEASE)/mnt/system/ko/$(KERNELRELEASE)/$(CHIP)_saradc.ko + @rm -f $(BUILDDIR)/package/cvitek-osdrv-$(BOARD)-$(KERNELRELEASE)/mnt/system/ko/$(KERNELRELEASE)/$(CHIP)_wdt.ko + @mkdir -pv $(BUILDDIR)/package/cvitek-osdrv-$(BOARD)-$(KERNELRELEASE)/mnt/system/ko/$(KERNELRELEASE)/3rd/ + @cp -p $(BUILDDIR)/osdrv/ko/3rd/*.ko $(BUILDDIR)/package/cvitek-osdrv-$(BOARD)-$(KERNELRELEASE)/mnt/system/ko/$(KERNELRELEASE)/3rd/ + @sed -i 's/Version: 1.0.0/Version: $(OSDRVVERSION)-$(KERNELRELEASE)/' $(BUILDDIR)/package/cvitek-osdrv-$(BOARD)-$(KERNELRELEASE)/DEBIAN/control + @sed -i 's/Package: cvitek-osdrv/Package: cvitek-osdrv-$(BOARD)-$(KERNELRELEASE)/' $(BUILDDIR)/package/cvitek-osdrv-$(BOARD)-$(KERNELRELEASE)/DEBIAN/control + @cd $(BUILDDIR)/package/ && dpkg-deb --build cvitek-osdrv-$(BOARD)-$(KERNELRELEASE) cvitek-osdrv-$(BOARD)-$(KERNELRELEASE)_$(OSDRVVERSION)-$(KERNELRELEASE)_$(DEB_ARCH).deb + @cp $(BUILDDIR)/package/cvitek-osdrv-$(BOARD)-$(KERNELRELEASE)_$(OSDRVVERSION)-$(KERNELRELEASE)_$(DEB_ARCH).deb /output/ + @touch $@ + +osdrv: $(BUILDDIR)/osdrv-package-stamp + +osdrv-clean: + @rm -rf $(BUILDDIR)/osdrv + @rm -f $(BUILDDIR)/osdrv-*-stamp + + +$(BUILDDIR)/middleware-prepare-checkout-stamp: + @echo "$(COLOUR_GREEN)Checking out Middleware for $(BOARD)$(END_COLOUR)" + @mkdir -p $(BUILDDIR) + @git clone -b sg200x-dev $(GIT_CLONE_OPTS) --recursive https://github.com/sophgo/cvi_mpi.git /build/middleware + @cd $(BUILDDIR)/middleware && git checkout ebaaf1b + @git clone -b sg200x-dev $(GIT_CLONE_OPTS) --recursive https://github.com/sophgo/SensorSupportList.git /build/middleware/component/isp + @cd $(BUILDDIR)/middleware/component/isp && git checkout 7e900fc + @mkdir -p $(BUILDDIR)/middleware/sample/test_mmf + @git clone -b maixcdk $(GIT_CLONE_OPTS) --recursive https://github.com/scpcom/ireader $(BUILDDIR)/middleware/sample/test_mmf/media_server-1.0.x + @cd $(BUILDDIR)/middleware/sample/test_mmf/media_server-1.0.x && git checkout 06cf95b + @touch $@ + +$(BUILDDIR)/middleware-prepare-patch-stamp: $(BUILDDIR)/middleware-prepare-checkout-stamp $(BUILDDIR)/osdrv-compile-stamp + @echo "$(COLOUR_GREEN)Patching Middleware for $(BOARD)$(END_COLOUR)" + mkdir -pv $(BUILDDIR)/kernel/riscv/usr/include/linux/ + $(call copy_header_action, $(BUILDDIR)/kernel/riscv/usr/include) + @$(foreach file, $(wildcard /configs/common/patches/middleware/*.patch), cd $(BUILDDIR)/middleware && git apply --ignore-whitespace $(file);) + @$(foreach file, $(wildcard /configs/$(BOARD)/patches/middleware/*.patch), cd $(BUILDDIR)/middleware && git apply --ignore-whitespace $(file);) + @$(foreach file, $(wildcard /configs/common/patches/sensorsupportlist/*.patch), cd $(BUILDDIR)/middleware/component/isp && git apply --ignore-whitespace $(file);) + @$(foreach file, $(wildcard /configs/$(BOARD)/patches/sensorsupportlist/*.patch), cd $(BUILDDIR)/middleware/component/isp && git apply --ignore-whitespace $(file);) + sed -i 's|$$(ROOT_DIR)/../host-tools|/host-tools|g' $(BUILDDIR)/middleware/Makefile.param + sed -i 's|^include $$(BUILD_PATH)/.config|-include $$(BUILD_PATH)/.config|g' $(BUILDDIR)/middleware/Makefile.param + sed -i 's|^include $$(BUILD_PATH)/.config|-include $$(BUILD_PATH)/.config|g' $(BUILDDIR)/middleware/component/isp/Makefile + sed -i 's|^include $$(BUILD_PATH)/.config|-include $$(BUILD_PATH)/.config|g' $(BUILDDIR)/middleware/component/isp/common/Makefile + sed -i 's|^include $$(BUILD_PATH)/.config|-include $$(BUILD_PATH)/.config|g' $(BUILDDIR)/middleware/sample/common/Makefile + [ -e $(BUILDDIR)/middleware/sample/mipi_tx ] || sed -i 's|cp -f sample/mipi_tx/sample_dsi|#cp -f sample/mipi_tx/sample_dsi|g' $(BUILDDIR)/middleware/Makefile + [ -e $(BUILDDIR)/middleware/sample/cipher ] || sed -i 's|cp -f sample/cipher/sample_cipher|#cp -f sample/cipher/sample_cipher|g' $(BUILDDIR)/middleware/Makefile + [ -e $(BUILDDIR)/middleware/sample/cvg ] || sed -i 's|cp -f sample/cvg/sample_cvg|#cp -f sample/cvg/sample_cvg|g' $(BUILDDIR)/middleware/Makefile + sed -i 's|@cp -f modules/venc/vc_lib/bin/|#@cp -f modules/venc/vc_lib/bin/|g' $(BUILDDIR)/middleware/Makefile + @touch $@ + +$(BUILDDIR)/middleware-prepare-configure-stamp: $(BUILDDIR)/middleware-prepare-patch-stamp + @echo "$(COLOUR_GREEN)Configuring Middleware for $(BOARD)$(END_COLOUR)" + @touch $@ + +$(BUILDDIR)/middleware-compile-stamp: $(BUILDDIR)/middleware-prepare-configure-stamp + @echo "$(COLOUR_GREEN)Building Middleware for $(BOARD)$(END_COLOUR)" + @cd $(BUILDDIR)/middleware && $(MIDDLEWARE_ENV) $(MAKE) KERNEL_DIR=$(BUILDDIR)/kernel all + @mkdir -pv $(BUILDDIR)/middleware/install/system/ + @cd $(BUILDDIR)/middleware && $(MIDDLEWARE_ENV) $(MAKE) KERNEL_DIR=$(BUILDDIR)/kernel install DESTDIR=$(BUILDDIR)/middleware/install/system + @touch $@ + +$(BUILDDIR)/middleware-package-stamp: $(BUILDDIR)/middleware-compile-stamp + @echo "$(COLOUR_GREEN)Packaging Middleware for $(BOARD)$(END_COLOUR)" + @mkdir -p $(BUILDDIR)/package/cvitek-middleware-$(BOARD)-$(MIDDLEWAREVERSION) + @cp -r /builder/deb/cvitek-middleware/* $(BUILDDIR)/package/cvitek-middleware-$(BOARD)-$(MIDDLEWAREVERSION)/ + @mkdir -pv $(BUILDDIR)/package/cvitek-middleware-$(BOARD)-$(MIDDLEWAREVERSION)/mnt/system/ + @rsync -avpPxH $(BUILDDIR)/middleware/install/system/ $(BUILDDIR)/package/cvitek-middleware-$(BOARD)-$(MIDDLEWAREVERSION)/mnt/system/ + @sed -i 's/Version: 1.0.0/Version: $(MIDDLEWAREVERSION)/' $(BUILDDIR)/package/cvitek-middleware-$(BOARD)-$(MIDDLEWAREVERSION)/DEBIAN/control + @sed -i 's/Package: cvitek-middleware/Package: cvitek-middleware-$(BOARD)/' $(BUILDDIR)/package/cvitek-middleware-$(BOARD)-$(MIDDLEWAREVERSION)/DEBIAN/control + @cd $(BUILDDIR)/package/ && dpkg-deb --build cvitek-middleware-$(BOARD)-$(MIDDLEWAREVERSION) $(BUILDDIR)/package/cvitek-middleware-$(BOARD)_$(MIDDLEWAREVERSION)_$(DEB_ARCH).deb + @cp $(BUILDDIR)/package/cvitek-middleware-$(BOARD)_$(MIDDLEWAREVERSION)_$(DEB_ARCH).deb /output/ + @touch $@ + +middleware: $(BUILDDIR)/middleware-package-stamp + +middleware-clean: + @rm -rf $(BUILDDIR)/middleware + @rm -f $(BUILDDIR)/middleware-*-stamp + + +$(BUILDDIR)/vcodec-firmware-prepare-checkout-stamp: + @echo "$(COLOUR_GREEN)Checking out vcodec-firmware for $(BOARD)$(END_COLOUR)" + @mkdir -p $(BUILDDIR)/vcodec-firmware + @cd $(BUILDDIR)/vcodec-firmware && wget -N https://github.com/sophgo/ramdisk/raw/8bf2a7446007a2ce02aba56622303a7a5906f91c/rootfs/common_musl_riscv64/usr/share/fw_vcodec/coda980.bin + @cd $(BUILDDIR)/vcodec-firmware && wget -N https://github.com/sophgo/ramdisk/raw/8bf2a7446007a2ce02aba56622303a7a5906f91c/rootfs/common_musl_riscv64/usr/share/fw_vcodec/monet.bin + @touch $@ + +$(BUILDDIR)/vcodec-firmware-package-stamp: $(BUILDDIR)/vcodec-firmware-prepare-checkout-stamp + @echo "$(COLOUR_GREEN)Packaging vcodec-firmware for $(BOARD)$(END_COLOUR)" + @mkdir -p $(BUILDDIR)/package/firmware-vcodec-$(CHIP)-$(MIDDLEWAREVERSION) + @cp -r /builder/deb/firmware-vcodec-cv181x/* $(BUILDDIR)/package/firmware-vcodec-$(CHIP)-$(MIDDLEWAREVERSION)/ + @mkdir -pv $(BUILDDIR)/package/firmware-vcodec-$(CHIP)-$(MIDDLEWAREVERSION)/usr/share/fw_vcodec/ + @rsync -avpPxH $(BUILDDIR)/vcodec-firmware/ $(BUILDDIR)/package/firmware-vcodec-$(CHIP)-$(MIDDLEWAREVERSION)/usr/share/fw_vcodec/ + @sed -i 's/Version: 1.0.0/Version: $(MIDDLEWAREVERSION)/' $(BUILDDIR)/package/firmware-vcodec-$(CHIP)-$(MIDDLEWAREVERSION)/DEBIAN/control + @sed -i 's/Package: firmware-vcodec-cv181x/Package: firmware-vcodec-$(CHIP)/' $(BUILDDIR)/package/firmware-vcodec-$(CHIP)-$(MIDDLEWAREVERSION)/DEBIAN/control + @cd $(BUILDDIR)/package/ && dpkg-deb --build firmware-vcodec-$(CHIP)-$(MIDDLEWAREVERSION) firmware-vcodec-$(CHIP)_$(MIDDLEWAREVERSION)_$(DEB_ARCH).deb + @cp $(BUILDDIR)/package/firmware-vcodec-$(CHIP)_$(MIDDLEWAREVERSION)_$(DEB_ARCH).deb /output/ + @touch $@ + +vcodec-firmware: $(BUILDDIR)/vcodec-firmware-package-stamp + +vcodec-firmware-clean: + @rm -rf $(BUILDDIR)/vcodec-firmware + @rm -f $(BUILDDIR)/vcodec-firmware-*-stamp + + $(BUILDDIR)/uboot-prepare-checkout-stamp: @echo "$(COLOUR_GREEN)Checking out U-Boot for $(BOARD)$(END_COLOUR)" @mkdir -p $(BUILDDIR) - @git clone --depth 1 https://github.com/sophgo/u-boot-2021.10.git $(BUILDDIR)/u-boot + @git clone $(GIT_CLONE_OPTS) https://github.com/sophgo/u-boot-2021.10.git $(BUILDDIR)/u-boot @cd $(BUILDDIR)/u-boot && git checkout 4a21b6b @touch $@ @@ -100,13 +286,13 @@ $(BUILDDIR)/uboot-prepare-patch-stamp: $(BUILDDIR)/uboot-prepare-checkout-stamp $(BUILDDIR)/uboot-prepare-configure-stamp: $(BUILDDIR)/uboot-prepare-patch-stamp @echo "$(COLOUR_GREEN)Configuring U-Boot for $(BOARD)$(END_COLOUR)" - @cd $(BUILDDIR)/u-boot/ && $(MAKE) -j$(NPROCS) BOARD=cv181x CONFIG_USE_DEFAULT_ENV=y STORAGE_TYPE=$(STORAGE_TYPE) CHIP=$(UBOOT_CHIP) CVIBOARD=$(UBOOT_BOARD) CROSS_COMPILE="/host-tools/gcc/riscv64-linux-musl-x86_64/bin/riscv64-unknown-linux-musl-" $(BOARD)_defconfig + cd $(BUILDDIR)/u-boot/ && $(MAKE) -j$(NPROCS) BOARD=cv181x CONFIG_USE_DEFAULT_ENV=y STORAGE_TYPE=$(STORAGE_TYPE) CHIP=$(UBOOT_CHIP) CVIBOARD=$(UBOOT_BOARD) CROSS_COMPILE="/host-tools/gcc/riscv64-linux-musl-x86_64/bin/riscv64-unknown-linux-musl-" $(BOARD)_defconfig @touch $@ $(BUILDDIR)/uboot-compile-stamp: $(BUILDDIR)/uboot-prepare-configure-stamp @echo "$(COLOUR_GREEN)Building U-Boot for $(BOARD)$(END_COLOUR)" - @cd $(BUILDDIR)/u-boot/ && $(MAKE) -j$(NPROCS) BOARD=cv181x CONFIG_USE_DEFAULT_ENV=y STORAGE_TYPE=$(STORAGE_TYPE) CHIP=$(UBOOT_CHIP) CVIBOARD=$(UBOOT_BOARD) CROSS_COMPILE="/host-tools/gcc/riscv64-linux-musl-x86_64/bin/riscv64-unknown-linux-musl-" - @cd $(BUILDDIR)/u-boot/ && $(MAKE) -j$(NPROCS) BOARD=cv181x CONFIG_USE_DEFAULT_ENV=y STORAGE_TYPE=$(STORAGE_TYPE) CHIP=$(UBOOT_CHIP) CVIBOARD=$(UBOOT_BOARD) CROSS_COMPILE="/host-tools/gcc/riscv64-linux-musl-x86_64/bin/riscv64-unknown-linux-musl-" u-boot-initial-env + cd $(BUILDDIR)/u-boot/ && $(MAKE) -j$(NPROCS) BOARD=cv181x CONFIG_USE_DEFAULT_ENV=y STORAGE_TYPE=$(STORAGE_TYPE) CHIP=$(UBOOT_CHIP) CVIBOARD=$(UBOOT_BOARD) CROSS_COMPILE="/host-tools/gcc/riscv64-linux-musl-x86_64/bin/riscv64-unknown-linux-musl-" + cd $(BUILDDIR)/u-boot/ && $(MAKE) -j$(NPROCS) BOARD=cv181x CONFIG_USE_DEFAULT_ENV=y STORAGE_TYPE=$(STORAGE_TYPE) CHIP=$(UBOOT_CHIP) CVIBOARD=$(UBOOT_BOARD) CROSS_COMPILE="/host-tools/gcc/riscv64-linux-musl-x86_64/bin/riscv64-unknown-linux-musl-" u-boot-initial-env @cp $(BUILDDIR)/u-boot/u-boot.bin $(BUILDDIR) @cp $(BUILDDIR)/u-boot/u-boot.dtb $(BUILDDIR) @cp $(BUILDDIR)/u-boot/u-boot-initial-env $(BUILDDIR) @@ -122,7 +308,7 @@ uboot-clean: $(BUILDDIR)/opensbi-prepare-checkout-stamp: @echo "$(COLOUR_GREEN)Checking out OpenSBI for $(BOARD)$(END_COLOUR)" @mkdir -p $(BUILDDIR) - @git clone -b sg200x-dev --depth 4 https://github.com/sophgo/opensbi.git $(BUILDDIR)/opensbi + @git clone -b sg200x-dev $(GIT_CLONE_OPTS) https://github.com/sophgo/opensbi.git $(BUILDDIR)/opensbi @cd $(BUILDDIR)/opensbi && git checkout 216793f # git clone https://github.com/riscv-software-src/opensbi.git $(BUILDDIR)/opensbi # @cd $(BUILDDIR)/opensbi && git checkout a2b255b @@ -151,14 +337,14 @@ opensbi-clean: $(BUILDDIR)/fsbl-prepare-checkout-stamp: @echo "$(COLOUR_GREEN)Checking out FSBL for $(BOARD)$(END_COLOUR)" @mkdir -p $(BUILDDIR) - @git clone -b sg200x-dev --depth 1 https://github.com/sophgo/fsbl.git $(BUILDDIR)/fsbl - @cd $(BUILDDIR)/fsbl && git checkout 15a84c5 + @git clone -b sg200x-dev $(GIT_CLONE_OPTS) https://github.com/sophgo/fsbl.git $(BUILDDIR)/fsbl + @cd $(BUILDDIR)/fsbl && git checkout 2039113 @touch $@ $(BUILDDIR)/fsbl-prepare-patch-stamp: $(BUILDDIR)/fsbl-prepare-checkout-stamp @echo "$(COLOUR_GREEN)Patching FSBL for $(BOARD)$(END_COLOUR)" - @$(foreach file, $(wildcard /configs/common/patches/fsbl/*.patch), cd $(BUILDDIR)/fsbl && git apply --ignore-whitespace $(file);) - @$(foreach file, $(wildcard /configs/$(BOARD)/patches/fsbl/*.patch), cd $(BUILDDIR)/fsbl && git apply --ignore-whitespace $(file);) + $(foreach file, $(wildcard /configs/common/patches/fsbl/*.patch), cd $(BUILDDIR)/fsbl && git apply --ignore-whitespace $(file);) + $(foreach file, $(wildcard /configs/$(BOARD)/patches/fsbl/*.patch), cd $(BUILDDIR)/fsbl && git apply --ignore-whitespace $(file);) @python3 /builder/python/mmap_conv.py --type h /configs/$(BOARD)/memmap.py $(BUILDDIR)/fsbl/plat/$(CHIP)/include/cvi_board_memmap.h @printf '\163\000\120\020\157\360\337\377' > $(BUILDDIR)/fsbl/blank.bin @touch $@ @@ -197,14 +383,17 @@ $(BUILDDIR)/image-prepare-stamp: @rm -rf /rootfs/ @-rm $(addon-targets) @mkdir -p /rootfs/ - @curl -v -L https://sophgo.my-ho.st:8443/public-key.asc -o $(BUILDDIR)/public-key.asc - @apt-key add $(BUILDDIR)/public-key.asc - @mmdebstrap -v --architectures=riscv64 --include="$(_PACKAGES)" sid "/rootfs/" "deb http://deb.debian.org/debian/ sid main" "deb https://sophgo.my-ho.st:8443/ debian sophgo" + @curl -v -L https://sophgo.my-ho.st/public-key.asc -o $(BUILDDIR)/public-key.asc + @mmdebstrap -v --architectures=riscv64 --include="$(_PACKAGES)" sid "/rootfs/" "deb http://deb.debian.org/debian/ sid main" "deb [signed-by=$(BUILDDIR)/public-key.asc] https://sophgo.my-ho.st:8443/ debian sophgo" @touch $@ -$(BUILDDIR)/image-addons-stamp: $(BUILDDIR)/image-prepare-stamp $(BUILDDIR)/fsbl-package-stamp $(BUILDDIR)/linux-compile-stamp $(addon-targets) +$(BUILDDIR)/image-addons-stamp: $(BUILDDIR)/image-prepare-stamp $(BUILDDIR)/fsbl-package-stamp $(BUILDDIR)/linux-compile-stamp $(BUILDDIR)/osdrv-package-stamp $(BUILDDIR)/middleware-package-stamp $(BUILDDIR)/vcodec-firmware-package-stamp $(addon-targets) + @[ -e /rootfs/usr/bin/devmem ] || ln -s busybox /rootfs/usr/bin/devmem @echo "$(COLOUR_GREEN)Copying Deb files for installation on $(BOARD)$(END_COLOUR)" @cp /output/cvitek-fsbl-$(BOARD)-*.deb /rootfs/tmp/install/ + @cp /output/cvitek-osdrv-*$(BOARD)*.deb /rootfs/tmp/install/ + @cp /output/cvitek-middleware-*$(BOARD)*.deb /rootfs/tmp/install/ + @cp /output/firmware-vcodec-$(CHIP)*.deb /rootfs/tmp/install/ @cp /output/linux-image-$(BOARD)-*.deb /rootfs/tmp/install/ @cp /output/linux-headers-*.deb /rootfs/tmp/install/ @cp /output/linux-libc-dev*.deb /rootfs/tmp/install/ @@ -258,6 +447,6 @@ image-clean: image-clean-customize: @rm -f $(BUILDDIR)/image-customize-stamp -clean: opensbi-clean uboot-clean linux-clean fsbl-clean +clean: opensbi-clean uboot-clean linux-clean osdrv-clean middleware-clean fsbl-clean -.PHONY: image clean opensbi uboot linux fsbl fsbl-clean uboot-clean linux-clean opensbi-clean +.PHONY: image clean opensbi uboot linux osdrv middleware fsbl fsbl-clean uboot-clean linux-clean opensbi-clean diff --git a/scripts/addons/load-systemko/addon.mk b/scripts/addons/load-systemko/addon.mk new file mode 100644 index 0000000..bcef331 --- /dev/null +++ b/scripts/addons/load-systemko/addon.mk @@ -0,0 +1,9 @@ +$(BUILDDIR)/load-systemko-stamp: + @echo "$(COLOUR_GREEN)Installing load-systemko for $(BOARD)$(END_COLOUR)" + @mkdir -pv /rootfs/etc/init.d/ + @cp -a addons/load-systemko/load-systemko.sh /rootfs/etc/init.d/ + @chmod +x /rootfs/etc/init.d/load-systemko.sh + @cp -a addons/load-systemko/load-systemko*.service /rootfs/etc/systemd/system/ + @mkdir -p /rootfs/tmp/install/ + @echo " load-systemko" >> /rootfs/tmp/install/systemd-enable + @touch $@ diff --git a/scripts/addons/load-systemko/load-systemko.service b/scripts/addons/load-systemko/load-systemko.service new file mode 100644 index 0000000..0dcff84 --- /dev/null +++ b/scripts/addons/load-systemko/load-systemko.service @@ -0,0 +1,11 @@ +[Unit] +Description=Load System Modules +Before=network.target +StartLimitIntervalSec=0 + +[Service] +Type=oneshot +ExecStart=sh /etc/init.d/load-systemko.sh start + +[Install] +WantedBy=multi-user.target diff --git a/scripts/addons/load-systemko/load-systemko.sh b/scripts/addons/load-systemko/load-systemko.sh new file mode 100755 index 0000000..26f83b9 --- /dev/null +++ b/scripts/addons/load-systemko/load-systemko.sh @@ -0,0 +1,44 @@ +#!/bin/sh + +if [ "$1" = "start" ] +then + KERNELRELEASE=$(uname -r) + + rmmod hynitron_touch + rmmod spi_gpio + rmmod spi_bitbang + rmmod i2c_gpio + rmmod i2c_algo_bit + rmmod cvitek_remoteproc + rmmod cvitek_mailbox + + . /etc/profile + printf "load kernel module: " + cd /mnt/system/ko/${KERNELRELEASE}/ + insmod cv181x_sys.ko + insmod cv181x_base.ko + insmod cv181x_rtos_cmdqu.ko + insmod cv181x_fast_image.ko + insmod cvi_mipi_rx.ko + insmod snsr_i2c.ko + insmod cv181x_vi.ko + insmod cv181x_vpss.ko + insmod cv181x_dwa.ko + insmod cv181x_vo.ko +# insmod cv181x_mipi_tx.ko + insmod cv181x_rgn.ko +# insmod cv181x_wdt.ko +# insmod cv181x_clock_cooling.ko + insmod cv181x_tpu.ko + insmod cv181x_vcodec.ko + insmod cv181x_jpeg.ko + insmod cvi_vc_driver.ko MaxVencChnNum=9 MaxVdecChnNum=9 +# insmod cv181x_rtc.ko + insmod cv181x_ive.ko + insmod cv181x_mon.ko +# insmod cv181x_pwm.ko +# insmod cv181x_saradc.ko + insmod cvi_wiegand.ko + echo "OK" + exit 0 +fi diff --git a/scripts/addons/sensor-config/addon.mk b/scripts/addons/sensor-config/addon.mk new file mode 100644 index 0000000..f288322 --- /dev/null +++ b/scripts/addons/sensor-config/addon.mk @@ -0,0 +1,38 @@ +$(BUILDDIR)/sensor-config-package-stamp: + @echo "$(COLOUR_GREEN)Packaging sensor-config for $(BOARD)$(END_COLOUR)" + @mkdir -p $(BUILDDIR)/package/sensor-config-$(BOARD)-$(MIDDLEWAREVERSION) + @cp -r /builder/deb/sensor-config/* $(BUILDDIR)/package/sensor-config-$(BOARD)-$(MIDDLEWAREVERSION)/ + @mkdir -pv $(BUILDDIR)/package/sensor-config-$(BOARD)-$(MIDDLEWAREVERSION)/etc/init.d/ + @cp -a addons/sensor-config/sensor-config.sh $(BUILDDIR)/package/sensor-config-$(BOARD)-$(MIDDLEWAREVERSION)/etc/init.d/ + @chmod +x $(BUILDDIR)/package/sensor-config-$(BOARD)-$(MIDDLEWAREVERSION)/etc/init.d/sensor-config.sh + @mkdir -pv $(BUILDDIR)/package/sensor-config-$(BOARD)-$(MIDDLEWAREVERSION)/etc/systemd/system/ + @cp -a addons/sensor-config/sensor-config*.service $(BUILDDIR)/package/sensor-config-$(BOARD)-$(MIDDLEWAREVERSION)/etc/systemd/system/ + @mkdir -pv $(BUILDDIR)/package/sensor-config-$(BOARD)-$(MIDDLEWAREVERSION)/mnt/cfg/param/ + @rsync -avpPxH addons/sensor-config/overlay/mnt/cfg/param/ $(BUILDDIR)/package/sensor-config-$(BOARD)-$(MIDDLEWAREVERSION)/mnt/cfg/param/ + @rm -f $(BUILDDIR)/package/sensor-config-$(BOARD)-$(MIDDLEWAREVERSION)/mnt/cfg/param/cvi_sdr_bin + @mkdir -pv $(BUILDDIR)/package/sensor-config-$(BOARD)-$(MIDDLEWAREVERSION)/mnt/data/ + @rsync -avpPxH addons/sensor-config/overlay/mnt/data/ $(BUILDDIR)/package/sensor-config-$(BOARD)-$(MIDDLEWAREVERSION)/mnt/data/ + @rm -f $(BUILDDIR)/package/sensor-config-$(BOARD)-$(MIDDLEWAREVERSION)/mnt/data/sensor_cfg.ini + @sed -i 's/Version: 1.0.0/Version: $(MIDDLEWAREVERSION)/' $(BUILDDIR)/package/sensor-config-$(BOARD)-$(MIDDLEWAREVERSION)/DEBIAN/control + @sed -i 's/Package: sensor-config/Package: sensor-config-$(BOARD)/' $(BUILDDIR)/package/sensor-config-$(BOARD)-$(MIDDLEWAREVERSION)/DEBIAN/control + @cd $(BUILDDIR)/package/ && dpkg-deb --build sensor-config-$(BOARD)-$(MIDDLEWAREVERSION) sensor-config-$(BOARD)_$(MIDDLEWAREVERSION)_$(DEB_ARCH).deb + @cp $(BUILDDIR)/package/sensor-config-$(BOARD)_$(MIDDLEWAREVERSION)_$(DEB_ARCH).deb /output/ + @mkdir -p /rootfs/tmp/install/ + @cp /output/sensor-config-*.deb /rootfs/tmp/install/ + @touch $@ + +$(BUILDDIR)/sensor-config-stamp: $(BUILDDIR)/sensor-config-package-stamp + @echo "$(COLOUR_GREEN)Installing sensor-config for $(BOARD)$(END_COLOUR)" + @mkdir -pv /rootfs/boot/ + @[ "$(BOARD)" = "licheervnano" ] || touch /rootfs/boot/epsilon + @mkdir -pv /rootfs/mnt/cfg/param/ + @mkdir -pv /rootfs/mnt/data/ + @if [ "$(BOARD)" = "licheervnano" ]; then \ + cp -p addons/sensor-config/overlay/mnt/cfg/param/sipeed_gc4653_30fps_202403261356.bin /rootfs/mnt/cfg/param/cvi_sdr_bin ; \ + elif [ "$(BOARD)" = "duo256" ]; then \ + cp -p addons/sensor-config/overlay/mnt/cfg/param/cvi_sdr_bin_GC2083 /rootfs/mnt/cfg/param/cvi_sdr_bin && \ + cp -p addons/sensor-config/overlay/mnt/data/sensor_cfg_GC2083.ini /rootfs/mnt/data/sensor_cfg.ini ; \ + fi + @mkdir -p /rootfs/tmp/install/ + @echo " sensor-config" >> /rootfs/tmp/install/systemd-enable + @touch $@ diff --git a/scripts/addons/sensor-config/overlay/mnt/cfg/param/cvi_sdr_bin.os04a10 b/scripts/addons/sensor-config/overlay/mnt/cfg/param/cvi_sdr_bin.os04a10 new file mode 100644 index 0000000..24a3c34 Binary files /dev/null and b/scripts/addons/sensor-config/overlay/mnt/cfg/param/cvi_sdr_bin.os04a10 differ diff --git a/scripts/addons/sensor-config/overlay/mnt/cfg/param/cvi_sdr_bin.ov2685 b/scripts/addons/sensor-config/overlay/mnt/cfg/param/cvi_sdr_bin.ov2685 new file mode 100644 index 0000000..c52f4a6 Binary files /dev/null and b/scripts/addons/sensor-config/overlay/mnt/cfg/param/cvi_sdr_bin.ov2685 differ diff --git a/scripts/addons/sensor-config/overlay/mnt/cfg/param/cvi_sdr_bin_GC2083 b/scripts/addons/sensor-config/overlay/mnt/cfg/param/cvi_sdr_bin_GC2083 new file mode 100644 index 0000000..a44ed2d Binary files /dev/null and b/scripts/addons/sensor-config/overlay/mnt/cfg/param/cvi_sdr_bin_GC2083 differ diff --git a/scripts/addons/sensor-config/overlay/mnt/cfg/param/cvi_sdr_bin_OV5647.bin b/scripts/addons/sensor-config/overlay/mnt/cfg/param/cvi_sdr_bin_OV5647.bin new file mode 100644 index 0000000..2c65bfd Binary files /dev/null and b/scripts/addons/sensor-config/overlay/mnt/cfg/param/cvi_sdr_bin_OV5647.bin differ diff --git a/scripts/addons/sensor-config/overlay/mnt/cfg/param/sipeed_gc4653_30fps_202403261356.bin b/scripts/addons/sensor-config/overlay/mnt/cfg/param/sipeed_gc4653_30fps_202403261356.bin new file mode 100644 index 0000000..eca6526 Binary files /dev/null and b/scripts/addons/sensor-config/overlay/mnt/cfg/param/sipeed_gc4653_30fps_202403261356.bin differ diff --git a/scripts/addons/sensor-config/overlay/mnt/data/sensor_cfg.ini.LT b/scripts/addons/sensor-config/overlay/mnt/data/sensor_cfg.ini.LT new file mode 100644 index 0000000..cfa5691 --- /dev/null +++ b/scripts/addons/sensor-config/overlay/mnt/data/sensor_cfg.ini.LT @@ -0,0 +1,34 @@ +[source] + +;type = SOURCE_USER_FE + +dev_num = 1 + +; section for sensor + +[sensor] + +; sensor name +name = LONTIUM_LT6911_2M_60FPS_8BIT + +bus_id = 4 + +sns_i2c_addr = ff + +mipi_dev = 0 + +lane_id = 2, 4, 3, 1, 0 + +pn_swap = 0, 0, 0, 0, 0 + +mclk_en = 0 + +mclk = 0 + +;port = 0 + +;pin = 2 + +;pol = 1 + +fps = 60 diff --git a/scripts/addons/sensor-config/overlay/mnt/data/sensor_cfg.ini.OA b/scripts/addons/sensor-config/overlay/mnt/data/sensor_cfg.ini.OA new file mode 100755 index 0000000..e6299a2 --- /dev/null +++ b/scripts/addons/sensor-config/overlay/mnt/data/sensor_cfg.ini.OA @@ -0,0 +1,34 @@ +[source] + +;type = SOURCE_USER_FE + +dev_num = 1 + +; section for sensor + +[sensor] + +; sensor name +name = OV_OS04A10_MIPI_4M_1440P_30FPS_12BIT + +bus_id = 4 + +sns_i2c_addr = 36 + +mipi_dev = 0 + +lane_id = 2, 1, 3, 0, 4 + +pn_swap = 0, 0, 0, 0, 0 + +mclk_en = 0 + +mclk = 0 + +;port = 0 + +;pin = 2 + +;pol = 1 + +;fps = 30 diff --git a/scripts/addons/sensor-config/overlay/mnt/data/sensor_cfg.ini.SC035 b/scripts/addons/sensor-config/overlay/mnt/data/sensor_cfg.ini.SC035 new file mode 100755 index 0000000..bbcad58 --- /dev/null +++ b/scripts/addons/sensor-config/overlay/mnt/data/sensor_cfg.ini.SC035 @@ -0,0 +1,34 @@ +[source] + +;type = SOURCE_USER_FE + +dev_num = 1 + +; section for sensor + +[sensor] + +; sensor name +name = SMS_SC035GS_MIPI_480P_120FPS_12BIT + +bus_id = 4 + +sns_i2c_addr = 30 + +mipi_dev = 0 + +lane_id = 4, 3, 2, -1, -1 + +pn_swap = 0, 0, 0, 0, 0 + +mclk_en = 1 + +mclk = 1 + +;port = 0 + +;pin = 2 + +;pol = 1 + +;fps = 30 diff --git a/scripts/addons/sensor-config/overlay/mnt/data/sensor_cfg.ini.alpha b/scripts/addons/sensor-config/overlay/mnt/data/sensor_cfg.ini.alpha new file mode 100644 index 0000000..c1f4c08 --- /dev/null +++ b/scripts/addons/sensor-config/overlay/mnt/data/sensor_cfg.ini.alpha @@ -0,0 +1,34 @@ +[source] + +;type = SOURCE_USER_FE + +dev_num = 1 + +; section for sensor + +[sensor] + +; sensor name +name = GCORE_GC4653_MIPI_4M_30FPS_10BIT + +bus_id = 4 + +sns_i2c_addr = 29 + +mipi_dev = 0 + +lane_id = 2, 1, 0, -1, -1 + +pn_swap = 0, 0, 0, 0, 0 + +mclk_en = 1 + +mclk = 0 + +;port = 0 + +;pin = 2 + +;pol = 1 + +;fps = 30 diff --git a/scripts/addons/sensor-config/overlay/mnt/data/sensor_cfg.ini.beta b/scripts/addons/sensor-config/overlay/mnt/data/sensor_cfg.ini.beta new file mode 100644 index 0000000..20e6a3a --- /dev/null +++ b/scripts/addons/sensor-config/overlay/mnt/data/sensor_cfg.ini.beta @@ -0,0 +1,34 @@ +[source] + +;type = SOURCE_USER_FE + +dev_num = 1 + +; section for sensor + +[sensor] + +; sensor name +name = GCORE_GC4653_MIPI_4M_30FPS_10BIT + +bus_id = 4 + +sns_i2c_addr = 29 + +mipi_dev = 0 + +lane_id = 4, 3, 2, -1, -1 + +pn_swap = 0, 0, 0, 0, 0 + +mclk_en = 1 + +mclk = 1 + +;port = 0 + +;pin = 2 + +;pol = 1 + +;fps = 30 diff --git a/scripts/addons/sensor-config/overlay/mnt/data/sensor_cfg_GC2083.ini b/scripts/addons/sensor-config/overlay/mnt/data/sensor_cfg_GC2083.ini new file mode 100644 index 0000000..940fa5d --- /dev/null +++ b/scripts/addons/sensor-config/overlay/mnt/data/sensor_cfg_GC2083.ini @@ -0,0 +1,14 @@ +;section for source +[source] +;type = SOURCE_USER_FE +dev_num = 1 +;section for sensor +[sensor] +;sensor name +name = GCORE_GC2083_MIPI_2M_30FPS_10BIT +;bus/i2c dev number +bus_id = 2 +sns_i2c_addr = 37 +mipi_dev = 0 +lane_id = 1, 0, 2, -1, -1 +pn_swap = 0, 0, 0, 0, 0 diff --git a/scripts/addons/sensor-config/overlay/mnt/data/sensor_cfg_OV5647.ini b/scripts/addons/sensor-config/overlay/mnt/data/sensor_cfg_OV5647.ini new file mode 100644 index 0000000..7b4d4e8 --- /dev/null +++ b/scripts/addons/sensor-config/overlay/mnt/data/sensor_cfg_OV5647.ini @@ -0,0 +1,14 @@ +;section for source +[source] +;type = SOURCE_USER_FE +dev_num = 1 +;section for sensor +[sensor] +;sensor name +name = OV_OV5647_MIPI_2M_30FPS_10BIT +;bus/i2c dev number +bus_id = 2 +sns_i2c_addr = 36 +mipi_dev = 0 +lane_id = 1, 0, 2, -1, -1 +pn_swap = 0, 0, 0, 0, 0 diff --git a/scripts/addons/sensor-config/sensor-config.service b/scripts/addons/sensor-config/sensor-config.service new file mode 100644 index 0000000..51f0ef7 --- /dev/null +++ b/scripts/addons/sensor-config/sensor-config.service @@ -0,0 +1,13 @@ +[Unit] +Description=Configure Sensor +After=load-systemko.service +Before=device-key.service +Before=network.target +StartLimitIntervalSec=0 + +[Service] +Type=oneshot +ExecStart=busybox sh /etc/init.d/sensor-config.sh start + +[Install] +WantedBy=multi-user.target diff --git a/scripts/addons/sensor-config/sensor-config.sh b/scripts/addons/sensor-config/sensor-config.sh new file mode 100755 index 0000000..001eed9 --- /dev/null +++ b/scripts/addons/sensor-config/sensor-config.sh @@ -0,0 +1,57 @@ +#!/bin/sh + +if [ "$1" = "start" ] +then + . /etc/profile + printf "copy sensor config file: " + if [ -e /boot/alpha ] + then + if [ ! -e /mnt/data/sensor_cfg.ini ] + then + cp /mnt/data/sensor_cfg.ini.alpha /mnt/data/sensor_cfg.ini + fi + if [ $(cat /mnt/data/sensor_cfg.ini | wc -l) -eq 0 ] + then + cp /mnt/data/sensor_cfg.ini.beta /mnt/data/sensor_cfg.ini + fi + # MIPI RX 4N PINMUX MCLK0 + devmem 0x0300116C 32 0x5 + # MIPI RX 0N PINMUX MIPIP RX 0N + devmem 0x0300118C 32 0x3 + echo " alpha " + elif [ -e /boot/epsilon ] + then + if [ ! -e /mnt/data/sensor_cfg.ini ] + then + cp /mnt/data/sensor_cfg.ini.alpha /mnt/data/sensor_cfg.ini + fi + if [ $(cat /mnt/data/sensor_cfg.ini | wc -l) -eq 0 ] + then + cp /mnt/data/sensor_cfg.ini.beta /mnt/data/sensor_cfg.ini + fi + # MIPI RX 4N PINMUX no change + # + # MIPI RX 0N PINMUX no change + # + echo " epsilon " + else + if [ ! -e /mnt/data/sensor_cfg.ini ] + then + cp /mnt/data/sensor_cfg.ini.beta /mnt/data/sensor_cfg.ini + fi + if [ $(cat /mnt/data/sensor_cfg.ini | wc -l) -eq 0 ] + then + cp /mnt/data/sensor_cfg.ini.beta /mnt/data/sensor_cfg.ini + fi + # MIPI RX 4N PINMUX MIPI RX 4N + devmem 0x0300116C 32 0x3 + # MIPI RX 0N PINMUX MCLK1 + devmem 0x0300118C 32 0x5 + echo -n " beta " + fi + if [ -e /boot/kvmtest ] + then + cp /mnt/data/sensor_cfg.ini.LT /mnt/data/sensor_cfg.ini + fi + echo "OK" +fi diff --git a/scripts/deb/cvitek-fsbl/DEBIAN/control b/scripts/deb/cvitek-fsbl/DEBIAN/control index a8e6317..ecb5261 100644 --- a/scripts/deb/cvitek-fsbl/DEBIAN/control +++ b/scripts/deb/cvitek-fsbl/DEBIAN/control @@ -2,5 +2,5 @@ Package: cvitek-fsbl Architecture: riscv64 Maintainer: @fishwaldo Priority: optional -Version: 1.0.0 +Version: 1.1.0 Description: First Stage Boot Loader for the CV18xx and SG200X series of RISC-V SoC's diff --git a/scripts/deb/cvitek-middleware/DEBIAN/control b/scripts/deb/cvitek-middleware/DEBIAN/control new file mode 100644 index 0000000..0b89fd7 --- /dev/null +++ b/scripts/deb/cvitek-middleware/DEBIAN/control @@ -0,0 +1,6 @@ +Package: cvitek-middleware +Architecture: riscv64 +Maintainer: @scpcom +Priority: optional +Version: 1.0.0 +Description: Middleware for the CV18xx and SG200X series of RISC-V SoC's diff --git a/scripts/deb/cvitek-osdrv/DEBIAN/control b/scripts/deb/cvitek-osdrv/DEBIAN/control new file mode 100644 index 0000000..e22fe91 --- /dev/null +++ b/scripts/deb/cvitek-osdrv/DEBIAN/control @@ -0,0 +1,6 @@ +Package: cvitek-osdrv +Architecture: riscv64 +Maintainer: @scpcom +Priority: optional +Version: 1.0.0 +Description: OS drivers for the CV18xx and SG200X series of RISC-V SoC's diff --git a/scripts/deb/firmware-vcodec-cv181x/DEBIAN/control b/scripts/deb/firmware-vcodec-cv181x/DEBIAN/control new file mode 100644 index 0000000..3d9ed97 --- /dev/null +++ b/scripts/deb/firmware-vcodec-cv181x/DEBIAN/control @@ -0,0 +1,6 @@ +Package: firmware-vcodec-cv181x +Architecture: riscv64 +Maintainer: @scpcom +Priority: optional +Version: 1.0.0 +Description: vcodec-firmware for the CV18xx and SG200X series of RISC-V SoC's diff --git a/scripts/deb/sensor-config/DEBIAN/control b/scripts/deb/sensor-config/DEBIAN/control new file mode 100644 index 0000000..4844ca1 --- /dev/null +++ b/scripts/deb/sensor-config/DEBIAN/control @@ -0,0 +1,6 @@ +Package: sensor-config +Architecture: riscv64 +Maintainer: @scpcom +Priority: optional +Version: 1.0.0 +Description: sensor-config for the CV18xx and SG200X series of RISC-V SoC's diff --git a/scripts/setup_rootfs.sh b/scripts/setup_rootfs.sh index 96ca5bf..d902fab 100755 --- a/scripts/setup_rootfs.sh +++ b/scripts/setup_rootfs.sh @@ -144,7 +144,9 @@ fi rm -rf /etc/apt/sources.list.d/multistrap-debian.list -apt-key add /tmp/install/public-key.asc +#apt-key add /tmp/install/public-key.asc +gpg --dearmor /tmp/install/public-key.asc +cp /tmp/install/public-key.asc.gpg /etc/apt/trusted.gpg.d/sophgo-myho-st.gpg cat > /etc/apt/sources.list <